From dccc54b674a634288a181d0bc12a53cd2384f99d Mon Sep 17 00:00:00 2001
From: Xilin Jia <6257601+XilinJia@users.noreply.github.com>
Date: Sun, 3 Nov 2024 13:02:29 +0100
Subject: [PATCH] 6.13.3 commit
---
.github/workflows/runEmulatorTests.sh | 11 ----
CONTRIBUTING.md | 19 -------
app/build.gradle | 4 +-
.../main/assets/LICENSE_ANDROID_ICONIFY.txt | 18 ------
app/src/main/assets/licenses.xml | 2 +-
.../main/kotlin/ac/mdiq/podcini/PodciniApp.kt | 4 +-
.../service/DownloadServiceInterfaceImpl.kt | 11 ++--
.../podcini/net/feed/FeedUpdateManager.kt | 10 ++--
.../mdiq/podcini/net/feed/LocalFeedUpdater.kt | 10 ++--
.../ac/mdiq/podcini/net/sync/SyncService.kt | 13 ++---
.../podcini/net/sync/wifi/WifiSyncService.kt | 12 ++--
.../playback/PlaybackServiceStarter.kt | 4 +-
.../podcini/playback/ServiceStatusHandler.kt | 4 +-
.../mdiq/podcini/playback/base/InTheatre.kt | 8 +--
.../podcini/playback/base/LocalMediaPlayer.kt | 8 ++-
.../playback/service/PlaybackService.kt | 8 +--
.../service/QuickSettingsTileService.kt | 4 +-
.../podcini/preferences/OpmlBackupAgent.kt | 4 +-
.../podcini/preferences/PreferenceUpgrader.kt | 4 +-
.../ImportExportPreferencesFragment.kt | 4 +-
.../fragments/PlaybackPreferencesFragment.kt | 11 ++--
.../fragments/SwipePreferencesFragment.kt | 12 ++--
.../SynchronizationPreferencesFragment.kt | 10 ++--
.../receiver/ConnectivityActionReceiver.kt | 4 +-
.../podcini/receiver/FeedUpdateReceiver.kt | 4 +-
.../podcini/receiver/MediaButtonReceiver.kt | 4 +-
.../receiver/PowerConnectionReceiver.kt | 4 +-
.../ac/mdiq/podcini/receiver/SPAReceiver.kt | 4 +-
.../storage/algorithms/AutoCleanups.kt | 8 +--
.../storage/algorithms/AutoDownloads.kt | 8 +--
.../mdiq/podcini/storage/database/Episodes.kt | 8 +--
.../ac/mdiq/podcini/storage/database/Feeds.kt | 28 +++------
.../mdiq/podcini/storage/database/Queues.kt | 30 +---------
.../podcini/ui/actions/EpisodeActionButton.kt | 22 ++++---
.../ac/mdiq/podcini/ui/actions/SwipeAction.kt | 1 +
.../mdiq/podcini/ui/actions/SwipeActions.kt | 57 +++++++++++++++----
.../mdiq/podcini/ui/activity/MainActivity.kt | 8 +--
.../podcini/ui/activity/OpmlImportActivity.kt | 4 +-
.../ui/activity/SelectSubscriptionActivity.kt | 8 +--
.../ui/activity/ShareReceiverActivity.kt | 6 +-
.../podcini/ui/activity/SplashActivity.kt | 4 +-
.../ui/activity/VideoplayerActivity.kt | 38 ++++++-------
.../starter/VideoPlayerActivityStarter.kt | 5 +-
.../ac/mdiq/podcini/ui/compose/EpisodesVM.kt | 4 +-
.../ac/mdiq/podcini/ui/compose/Feeds.kt | 6 +-
.../podcini/ui/dialog/CustomFeedNameDialog.kt | 5 +-
.../ui/dialog/MediaPlayerErrorDialog.kt | 8 +--
.../podcini/ui/dialog/SleepTimerDialog.kt | 8 +--
.../podcini/ui/dialog/TagSettingsDialog.kt | 4 +-
.../podcini/ui/dialog/VariableSpeedDialog.kt | 15 +++--
.../ui/fragment/AllEpisodesFragment.kt | 8 +--
.../ui/fragment/AudioPlayerFragment.kt | 19 +++----
.../ui/fragment/BaseEpisodesFragment.kt | 8 +--
.../podcini/ui/fragment/DownloadsFragment.kt | 8 +--
.../ui/fragment/EpisodeInfoFragment.kt | 37 ++++++------
.../ui/fragment/FeedEpisodesFragment.kt | 39 ++++++-------
.../podcini/ui/fragment/FeedInfoFragment.kt | 14 ++---
.../ui/fragment/FeedSettingsFragment.kt | 6 +-
.../podcini/ui/fragment/HistoryFragment.kt | 8 +--
.../podcini/ui/fragment/OnlineFeedFragment.kt | 22 ++++---
.../ui/fragment/OnlineSearchFragment.kt | 8 +--
.../podcini/ui/fragment/QueuesFragment.kt | 16 +++---
.../ui/fragment/QuickDiscoveryFragment.kt | 8 +--
.../podcini/ui/fragment/SearchFragment.kt | 16 +++---
.../ui/fragment/SearchResultsFragment.kt | 4 +-
.../ui/fragment/SubscriptionsFragment.kt | 15 ++---
.../ui/statistics/StatisticsFragment.kt | 14 ++---
.../mdiq/podcini/ui/view/ShownotesWebView.kt | 4 +-
.../podcini/util/config/ClientConfigurator.kt | 4 +-
.../main/res/drawable/baseline_comment_24.xml | 5 ++
app/src/main/res/values/strings.xml | 1 +
changelog.md | 10 ++++
.../android/en-US/changelogs/3020289.txt | 2 +-
.../android/en-US/changelogs/3020290.txt | 9 +++
gradle/libs.versions.toml | 22 +++----
75 files changed, 361 insertions(+), 446 deletions(-)
delete mode 100644 .github/workflows/runEmulatorTests.sh
delete mode 100644 app/src/main/assets/LICENSE_ANDROID_ICONIFY.txt
create mode 100644 app/src/main/res/drawable/baseline_comment_24.xml
create mode 100644 fastlane/metadata/android/en-US/changelogs/3020290.txt
diff --git a/.github/workflows/runEmulatorTests.sh b/.github/workflows/runEmulatorTests.sh
deleted file mode 100644
index 4d048a33..00000000
--- a/.github/workflows/runEmulatorTests.sh
+++ /dev/null
@@ -1,11 +0,0 @@
-#!/bin/zsh
-
-set -o pipefail
-
-runTests() {
- ./gradlew connectedPlayDebugAndroidTest connectedDebugAndroidTest \
- -Pandroid.testInstrumentationRunnerArguments.notAnnotation=de.test.podcini.IgnoreOnCi
-}
-
-# Retry tests to make them less flaky
-runTests || runTests || runTests
diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md
index 814c03c4..82fa7905 100644
--- a/CONTRIBUTING.md
+++ b/CONTRIBUTING.md
@@ -53,22 +53,3 @@ Testing and Verifying
--------------------------
As a developer contributing to Podcini, we ask that you test the feature yourself manually and better yet, add unit and functional tests to any feature of bug you fix.
-
-### Running Unit Tests
-
-- `./gradlew :core:testPlayDebugUnitTest`
-
-### Running Integration Tests
-
-#### Using Android Studio
-
-- Create a configuration via 'Run->Edit Configurations...'
-
-
-
-#### Using the command line
-
-- Start an AVD or plug in your phone
-
-- `sh .github/workflows/runTests.sh`
diff --git a/app/build.gradle b/app/build.gradle
index 78166d4d..1fee2d96 100644
--- a/app/build.gradle
+++ b/app/build.gradle
@@ -31,8 +31,8 @@ android {
// testApplicationId "ac.mdiq.podcini.tests"
// testInstrumentationRunner "androidx.test.runner.AndroidJUnitRunner"
- versionCode 3020289
- versionName "6.13.2"
+ versionCode 3020290
+ versionName "6.13.3"
applicationId "ac.mdiq.podcini.R"
def commit = ""
diff --git a/app/src/main/assets/LICENSE_ANDROID_ICONIFY.txt b/app/src/main/assets/LICENSE_ANDROID_ICONIFY.txt
deleted file mode 100644
index 954402c9..00000000
--- a/app/src/main/assets/LICENSE_ANDROID_ICONIFY.txt
+++ /dev/null
@@ -1,18 +0,0 @@
-Copyright 2015 Joan Zapata
-
-Licensed under the Apache License, Version 2.0 (the "License");
-you may not use this file except in compliance with the License.
-You may obtain a copy of the License at
-
- http://www.apache.org/licenses/LICENSE-2.0
-
-Unless required by applicable law or agreed to in writing, software
-distributed under the License is distributed on an "AS IS" BASIS,
-WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-See the License for the specific language governing permissions and
-limitations under the License.
-
-It uses FontAwesome font, licensed under OFL 1.1, which is compatible
-with this library's license.
-
- http://scripts.sil.org/cms/scripts/render_download.php?format=file&media_id=OFL_plaintext&filename=OFL.txt
diff --git a/app/src/main/assets/licenses.xml b/app/src/main/assets/licenses.xml
index cc12699b..92f44463 100644
--- a/app/src/main/assets/licenses.xml
+++ b/app/src/main/assets/licenses.xml
@@ -65,7 +65,7 @@
author="Mike Penz and Peter Gulko"
website="https://github.com/mikepenz/Android-Iconics"
license="Apache 2.0"
- licenseText="LICENSE_ANDROID_ICONIFY.txt" />
+ licenseText="LICENSE_APACHE-2.0.txt" />
= 2
- @UnstableApi
+
override fun doWork(): Result {
Logd(TAG, "starting doWork")
ClientConfigurator.initialize(applicationContext)
@@ -163,7 +160,7 @@ class DownloadServiceInterfaceImpl : DownloadServiceInterface() {
override fun getForegroundInfoAsync(): ListenableFuture {
return Futures.immediateFuture(ForegroundInfo(R.id.notification_downloading, generateProgressNotification()))
}
- @OptIn(UnstableApi::class)
+
private fun performDownload(media: EpisodeMedia, request: DownloadRequest): Result {
Logd(TAG, "starting performDownload")
if (request.destination == null) {
@@ -295,7 +292,7 @@ class DownloadServiceInterfaceImpl : DownloadServiceInterface() {
}
class MediaDownloadedHandler(private val context: Context, var updatedStatus: DownloadResult, private val request: DownloadRequest) : Runnable {
- @UnstableApi override fun run() {
+ override fun run() {
var item = realm.query(Episode::class).query("id == ${request.feedfileId}").first().find()
if (item == null) {
Log.e(TAG, "Could not find downloaded episode object in database")
@@ -356,7 +353,7 @@ class DownloadServiceInterfaceImpl : DownloadServiceInterface() {
return constraints.build()
}
- @OptIn(UnstableApi::class)
+
private fun getRequest(item: Episode): OneTimeWorkRequest.Builder {
Logd(TAG, "starting getRequest")
val workRequest: OneTimeWorkRequest.Builder = OneTimeWorkRequest.Builder(EpisodeDownloadWorker::class.java)
diff --git a/app/src/main/kotlin/ac/mdiq/podcini/net/feed/FeedUpdateManager.kt b/app/src/main/kotlin/ac/mdiq/podcini/net/feed/FeedUpdateManager.kt
index 53486775..58001203 100644
--- a/app/src/main/kotlin/ac/mdiq/podcini/net/feed/FeedUpdateManager.kt
+++ b/app/src/main/kotlin/ac/mdiq/podcini/net/feed/FeedUpdateManager.kt
@@ -39,11 +39,9 @@ import android.content.DialogInterface
import android.content.pm.PackageManager
import android.os.Build
import android.util.Log
-import androidx.annotation.OptIn
import androidx.core.app.ActivityCompat
import androidx.core.app.NotificationCompat
import androidx.core.app.NotificationManagerCompat
-import androidx.media3.common.util.UnstableApi
import androidx.work.*
import androidx.work.Constraints.Builder
import com.google.android.material.dialog.MaterialAlertDialogBuilder
@@ -139,11 +137,11 @@ object FeedUpdateManager {
builder.show()
}
- @OptIn(UnstableApi::class)
+
class FeedUpdateWorker(context: Context, params: WorkerParameters) : Worker(context, params) {
private val notificationManager = NotificationManagerCompat.from(context)
- @UnstableApi
+
override fun doWork(): Result {
ClientConfigurator.initialize(applicationContext)
val feedsToUpdate: MutableList
@@ -200,7 +198,7 @@ object FeedUpdateManager {
override fun getForegroundInfoAsync(): ListenableFuture {
return Futures.immediateFuture(ForegroundInfo(R.id.notification_updating_feeds, createNotification(null)))
}
- @UnstableApi
+
private fun refreshFeeds(feedsToUpdate: MutableList, force: Boolean) {
if (Build.VERSION.SDK_INT >= 33 && ActivityCompat.checkSelfPermission(this.applicationContext,
Manifest.permission.POST_NOTIFICATIONS) != PackageManager.PERMISSION_GRANTED) {
@@ -264,7 +262,7 @@ object FeedUpdateManager {
} catch (e: Throwable) { Logd(TAG, "refreshYoutubeFeed error1 ${e.message}") }
} catch (e: Throwable) { Logd(TAG, "refreshYoutubeFeed error ${e.message}") }
}
- @UnstableApi
+
@Throws(Exception::class)
fun refreshFeed(feed: Feed, force: Boolean) {
val nextPage = (inputData.getBoolean(EXTRA_NEXT_PAGE, false) && feed.nextPageLink != null)
diff --git a/app/src/main/kotlin/ac/mdiq/podcini/net/feed/LocalFeedUpdater.kt b/app/src/main/kotlin/ac/mdiq/podcini/net/feed/LocalFeedUpdater.kt
index aa89b6c7..f7b2991b 100644
--- a/app/src/main/kotlin/ac/mdiq/podcini/net/feed/LocalFeedUpdater.kt
+++ b/app/src/main/kotlin/ac/mdiq/podcini/net/feed/LocalFeedUpdater.kt
@@ -19,7 +19,7 @@ import android.net.Uri
import android.provider.DocumentsContract
import androidx.annotation.VisibleForTesting
import androidx.documentfile.provider.DocumentFile
-import androidx.media3.common.util.UnstableApi
+
import org.apache.commons.io.input.CountingInputStream
import java.io.BufferedInputStream
import java.io.IOException
@@ -33,7 +33,7 @@ object LocalFeedUpdater {
@JvmField
val PREFERRED_FEED_IMAGE_FILENAMES: Array = arrayOf("folder.jpg", "Folder.jpg", "folder.png", "Folder.png")
- @UnstableApi @JvmStatic
+ @JvmStatic
fun updateFeed(feed: Feed, context: Context, updaterProgressListener: UpdaterProgressListener?) {
if (feed.downloadUrl.isNullOrEmpty()) return
try {
@@ -51,7 +51,7 @@ object LocalFeedUpdater {
}
}
- @UnstableApi @JvmStatic
+ @JvmStatic
@VisibleForTesting
@Throws(IOException::class)
fun tryUpdateFeed(feed: Feed, context: Context, folderUri: Uri?, updaterProgressListener: UpdaterProgressListener?) {
@@ -188,7 +188,7 @@ object LocalFeedUpdater {
}
}
- @UnstableApi private fun reportError(feed: Feed, reasonDetailed: String?) {
+ private fun reportError(feed: Feed, reasonDetailed: String?) {
val status = DownloadResult(feed.id, feed.title?:"", DownloadError.ERROR_IO_ERROR, false, reasonDetailed?:"")
LogsAndStats.addDownloadStatus(status)
Feeds.persistFeedLastUpdateFailed(feed, true)
@@ -197,7 +197,7 @@ object LocalFeedUpdater {
/**
* Reports a successful download status.
*/
- @UnstableApi private fun reportSuccess(feed: Feed) {
+ private fun reportSuccess(feed: Feed) {
val status = DownloadResult(feed.id, feed.title?:"", DownloadError.SUCCESS, true, "")
LogsAndStats.addDownloadStatus(status)
Feeds.persistFeedLastUpdateFailed(feed, false)
diff --git a/app/src/main/kotlin/ac/mdiq/podcini/net/sync/SyncService.kt b/app/src/main/kotlin/ac/mdiq/podcini/net/sync/SyncService.kt
index be097f52..bfb432b5 100644
--- a/app/src/main/kotlin/ac/mdiq/podcini/net/sync/SyncService.kt
+++ b/app/src/main/kotlin/ac/mdiq/podcini/net/sync/SyncService.kt
@@ -44,10 +44,8 @@ import android.app.PendingIntent
import android.content.Context
import android.os.Build
import android.util.Log
-import androidx.annotation.OptIn
import androidx.collection.ArrayMap
import androidx.core.app.NotificationCompat
-import androidx.media3.common.util.UnstableApi
import androidx.work.*
import androidx.work.Constraints.Builder
import kotlinx.coroutines.*
@@ -56,13 +54,13 @@ import org.apache.commons.lang3.StringUtils
import java.util.concurrent.ExecutionException
import java.util.concurrent.TimeUnit
-@OptIn(UnstableApi::class)
+
open class SyncService(context: Context, params: WorkerParameters) : Worker(context, params) {
val TAG = this::class.simpleName ?: "Anonymous"
protected val synchronizationQueueStorage = SynchronizationQueueStorage(context)
- @UnstableApi override fun doWork(): Result {
+ override fun doWork(): Result {
Logd(TAG, "doWork() called")
val activeSyncProvider = getActiveSyncProvider() ?: return Result.failure()
Logd(TAG, "doWork() got syn provider")
@@ -104,7 +102,7 @@ open class SyncService(context: Context, params: WorkerParameters) : Worker(cont
}
}
- @UnstableApi @Throws(SyncServiceException::class)
+ @Throws(SyncServiceException::class)
private fun syncSubscriptions(syncServiceImpl: ISyncService) {
Logd(TAG, "syncSubscriptions called")
val lastSync = SynchronizationSettings.lastSubscriptionSynchronizationTimestamp
@@ -160,7 +158,6 @@ open class SyncService(context: Context, params: WorkerParameters) : Worker(cont
SynchronizationSettings.setLastSubscriptionSynchronizationAttemptTimestamp(newTimeStamp)
}
- @UnstableApi
private fun removeFeedWithDownloadUrl(context: Context, downloadUrl: String) {
Logd(TAG, "removeFeedWithDownloadUrl called")
var feedID: Long? = null
@@ -244,7 +241,7 @@ open class SyncService(context: Context, params: WorkerParameters) : Worker(cont
return newTimeStamp
}
- @UnstableApi @Throws(SyncServiceException::class)
+ @Throws(SyncServiceException::class)
private fun syncEpisodeActions(syncServiceImpl: ISyncService) {
Logd(TAG, "syncEpisodeActions called")
var (lastSync, newTimeStamp) = getEpisodeActions(syncServiceImpl)
@@ -277,7 +274,7 @@ open class SyncService(context: Context, params: WorkerParameters) : Worker(cont
return if (idRemove != null) Pair(idRemove, feedItem) else null
}
- @UnstableApi @Synchronized
+ @Synchronized
fun processEpisodeActions(remoteActions: List) {
Logd(TAG, "Processing " + remoteActions.size + " actions")
if (remoteActions.isEmpty()) return
diff --git a/app/src/main/kotlin/ac/mdiq/podcini/net/sync/wifi/WifiSyncService.kt b/app/src/main/kotlin/ac/mdiq/podcini/net/sync/wifi/WifiSyncService.kt
index aa9c3872..9f5a2670 100644
--- a/app/src/main/kotlin/ac/mdiq/podcini/net/sync/wifi/WifiSyncService.kt
+++ b/app/src/main/kotlin/ac/mdiq/podcini/net/sync/wifi/WifiSyncService.kt
@@ -12,17 +12,15 @@ import ac.mdiq.podcini.storage.database.Episodes.getEpisodes
import ac.mdiq.podcini.storage.database.RealmDB.upsertBlk
import ac.mdiq.podcini.storage.model.Episode
import ac.mdiq.podcini.storage.model.EpisodeFilter
-import ac.mdiq.podcini.storage.utils.EpisodeUtil.hasAlmostEnded
import ac.mdiq.podcini.storage.model.EpisodeSortOrder
import ac.mdiq.podcini.storage.model.Rating
-import ac.mdiq.podcini.util.Logd
+import ac.mdiq.podcini.storage.utils.EpisodeUtil.hasAlmostEnded
import ac.mdiq.podcini.util.EventFlow
import ac.mdiq.podcini.util.FlowEvent
+import ac.mdiq.podcini.util.Logd
import android.content.Context
import android.util.Log
-import androidx.annotation.OptIn
import androidx.core.content.ContextCompat.getString
-import androidx.media3.common.util.UnstableApi
import androidx.work.*
import org.apache.commons.lang3.StringUtils
import org.json.JSONArray
@@ -34,7 +32,7 @@ import java.util.*
import java.util.concurrent.TimeUnit
import kotlin.math.min
-@UnstableApi class WifiSyncService(val context: Context, params: WorkerParameters) : SyncService(context, params), ISyncService {
+class WifiSyncService(val context: Context, params: WorkerParameters) : SyncService(context, params), ISyncService {
// val TAG = this::class.simpleName ?: "Anonymous"
@@ -109,7 +107,7 @@ import kotlin.math.min
private var socket: Socket? = null
- @OptIn(UnstableApi::class) override fun login() {
+ override fun login() {
Logd(TAG, "serverIp: $hostIp serverPort: $hostPort $isGuest")
EventFlow.postEvent(FlowEvent.SyncServiceEvent(R.string.sync_status_in_progress, "2"))
if (!isPortInUse(hostPort)) {
@@ -164,7 +162,7 @@ import kotlin.math.min
EventFlow.postEvent(FlowEvent.SyncServiceEvent(R.string.sync_status_in_progress, "5"))
}
- @OptIn(UnstableApi::class) private fun isPortInUse(port: Int): Boolean {
+ private fun isPortInUse(port: Int): Boolean {
val command = "netstat -tlnp"
val process = Runtime.getRuntime().exec(command)
val output = process.inputStream.bufferedReader().use { it.readText() }
diff --git a/app/src/main/kotlin/ac/mdiq/podcini/playback/PlaybackServiceStarter.kt b/app/src/main/kotlin/ac/mdiq/podcini/playback/PlaybackServiceStarter.kt
index 3483229e..ebef792a 100644
--- a/app/src/main/kotlin/ac/mdiq/podcini/playback/PlaybackServiceStarter.kt
+++ b/app/src/main/kotlin/ac/mdiq/podcini/playback/PlaybackServiceStarter.kt
@@ -3,7 +3,7 @@ package ac.mdiq.podcini.playback
import android.content.Context
import android.content.Intent
import androidx.core.content.ContextCompat
-import androidx.media3.common.util.UnstableApi
+
import ac.mdiq.podcini.playback.service.PlaybackService
import ac.mdiq.podcini.storage.model.EpisodeMedia
import ac.mdiq.podcini.playback.base.InTheatre.curEpisode
@@ -14,7 +14,7 @@ import ac.mdiq.podcini.util.Logd
import ac.mdiq.podcini.util.EventFlow
import ac.mdiq.podcini.util.FlowEvent
-@UnstableApi
+
class PlaybackServiceStarter(private val context: Context, private val media: Playable) {
private var shouldStreamThisTime = false
diff --git a/app/src/main/kotlin/ac/mdiq/podcini/playback/ServiceStatusHandler.kt b/app/src/main/kotlin/ac/mdiq/podcini/playback/ServiceStatusHandler.kt
index 1f485b40..2797500e 100644
--- a/app/src/main/kotlin/ac/mdiq/podcini/playback/ServiceStatusHandler.kt
+++ b/app/src/main/kotlin/ac/mdiq/podcini/playback/ServiceStatusHandler.kt
@@ -18,7 +18,7 @@ import android.os.Build
import android.util.Log
import androidx.fragment.app.FragmentActivity
import androidx.lifecycle.lifecycleScope
-import androidx.media3.common.util.UnstableApi
+
import kotlinx.coroutines.Job
import kotlinx.coroutines.flow.collectLatest
import kotlinx.coroutines.launch
@@ -27,7 +27,7 @@ import kotlinx.coroutines.launch
* Communicates with the playback service. GUI classes should use this class to
* control playback instead of communicating with the PlaybackService directly.
*/
-@UnstableApi
+
abstract class ServiceStatusHandler(private val activity: FragmentActivity) {
private var mediaInfoLoaded = false
diff --git a/app/src/main/kotlin/ac/mdiq/podcini/playback/base/InTheatre.kt b/app/src/main/kotlin/ac/mdiq/podcini/playback/base/InTheatre.kt
index 365c306f..b803a29c 100644
--- a/app/src/main/kotlin/ac/mdiq/podcini/playback/base/InTheatre.kt
+++ b/app/src/main/kotlin/ac/mdiq/podcini/playback/base/InTheatre.kt
@@ -11,10 +11,10 @@ import ac.mdiq.podcini.storage.model.CurrentState.Companion.NO_MEDIA_PLAYING
import ac.mdiq.podcini.storage.model.CurrentState.Companion.PLAYER_STATUS_OTHER
import ac.mdiq.podcini.util.Logd
import android.util.Log
-import androidx.annotation.OptIn
-import androidx.media3.common.util.UnstableApi
import io.realm.kotlin.query.Sort
-import kotlinx.coroutines.*
+import kotlinx.coroutines.CoroutineScope
+import kotlinx.coroutines.Dispatchers
+import kotlinx.coroutines.launch
object InTheatre {
val TAG: String = InTheatre::class.simpleName ?: "Anonymous"
@@ -139,7 +139,7 @@ object InTheatre {
}
}
- @OptIn(UnstableApi::class) @JvmStatic
+ @JvmStatic
fun isCurrentlyPlaying(media: EpisodeMedia?): Boolean {
return isCurMedia(media) && PlaybackService.isRunning && MediaPlayerBase.status == PlayerStatus.PLAYING
}
diff --git a/app/src/main/kotlin/ac/mdiq/podcini/playback/base/LocalMediaPlayer.kt b/app/src/main/kotlin/ac/mdiq/podcini/playback/base/LocalMediaPlayer.kt
index 982c8359..79ce5b48 100644
--- a/app/src/main/kotlin/ac/mdiq/podcini/playback/base/LocalMediaPlayer.kt
+++ b/app/src/main/kotlin/ac/mdiq/podcini/playback/base/LocalMediaPlayer.kt
@@ -12,6 +12,7 @@ import ac.mdiq.podcini.playback.base.InTheatre.curQueue
import ac.mdiq.podcini.preferences.UserPreferences.isSkipSilence
import ac.mdiq.podcini.preferences.UserPreferences.prefLowQualityMedia
import ac.mdiq.podcini.preferences.UserPreferences.rewindSecs
+import ac.mdiq.podcini.storage.database.Episodes.setPlayStateSync
import ac.mdiq.podcini.storage.database.RealmDB.runOnIOScope
import ac.mdiq.podcini.storage.model.*
import ac.mdiq.podcini.storage.utils.EpisodeUtil
@@ -324,7 +325,8 @@ class LocalMediaPlayer(context: Context, callback: MediaPlayerCallback) : MediaP
curMedia = playable
if (curMedia is EpisodeMedia) {
val media_ = curMedia as EpisodeMedia
- val item = media_.episodeOrFetch()
+ var item = media_.episodeOrFetch()
+ if (item != null && item.playState < PlayState.INPROGRESS.code) item = runBlocking { setPlayStateSync(PlayState.INPROGRESS.code, item!!, false) }
val eList = if (item?.feed?.preferences?.queue != null) curQueue.episodes else item?.feed?.getVirtualQueueItems() ?: listOf()
curIndexInQueue = EpisodeUtil.indexOfItemWithId(eList, media_.id)
} else curIndexInQueue = -1
@@ -710,7 +712,7 @@ class LocalMediaPlayer(context: Context, callback: MediaPlayerCallback) : MediaP
}
private fun setupPlayerListener() {
- exoplayerListener = object : Player.Listener {
+ exoplayerListener = object : Listener {
override fun onPlaybackStateChanged(playbackState: @State Int) {
Logd(TAG, "onPlaybackStateChanged $playbackState")
when (playbackState) {
@@ -762,7 +764,7 @@ class LocalMediaPlayer(context: Context, callback: MediaPlayerCallback) : MediaP
var exoPlayer: ExoPlayer? = null
- private var exoplayerListener: Player.Listener? = null
+ private var exoplayerListener: Listener? = null
private var audioSeekCompleteListener: java.lang.Runnable? = null
private var audioCompletionListener: java.lang.Runnable? = null
private var audioErrorListener: Consumer? = null
diff --git a/app/src/main/kotlin/ac/mdiq/podcini/playback/service/PlaybackService.kt b/app/src/main/kotlin/ac/mdiq/podcini/playback/service/PlaybackService.kt
index 93d734a5..69add402 100644
--- a/app/src/main/kotlin/ac/mdiq/podcini/playback/service/PlaybackService.kt
+++ b/app/src/main/kotlin/ac/mdiq/podcini/playback/service/PlaybackService.kt
@@ -94,7 +94,7 @@ import androidx.media3.common.MediaItem
import androidx.media3.common.MediaMetadata
import androidx.media3.common.Player.STATE_ENDED
import androidx.media3.common.Player.STATE_IDLE
-import androidx.media3.common.util.UnstableApi
+
import androidx.media3.session.*
import androidx.work.impl.utils.futures.SettableFuture
import com.google.common.collect.ImmutableList
@@ -113,7 +113,7 @@ import kotlin.math.sqrt
/**
* Controls the MediaPlayer that plays a EpisodeMedia-file
*/
-@UnstableApi
+
class PlaybackService : MediaLibraryService() {
private var mediaSession: MediaLibrarySession? = null
@@ -376,7 +376,7 @@ class PlaybackService : MediaLibraryService() {
val isItemdeletable = (!shouldKeepSuperEpisode || (item?.isSUPER != true && item?.playState != PlayState.AGAIN.code && item?.playState != PlayState.FOREVER.code))
if (playable is EpisodeMedia && shouldAutoDelete && isItemdeletable) {
if (playable.localFileAvailable()) item = deleteMediaSync(this@PlaybackService, item!!)
- if (prefDeleteRemovesFromQueue) removeFromQueueSync(null, item!!)
+ if (prefDeleteRemovesFromQueue) removeFromAllQueuesSync( item!!)
} else if (prefRemoveFromQueueMarkedPlayed) removeFromAllQueuesSync(item!!)
}
}
@@ -1247,7 +1247,7 @@ class PlaybackService : MediaLibraryService() {
),
}
- @UnstableApi
+
class CustomMediaNotificationProvider(context: Context) : DefaultMediaNotificationProvider(context) {
override fun addNotificationActions(mediaSession: MediaSession, mediaButtons: ImmutableList,
builder: NotificationCompat.Builder, actionFactory: MediaNotification.ActionFactory): IntArray {
diff --git a/app/src/main/kotlin/ac/mdiq/podcini/playback/service/QuickSettingsTileService.kt b/app/src/main/kotlin/ac/mdiq/podcini/playback/service/QuickSettingsTileService.kt
index b7ae8031..277d270f 100644
--- a/app/src/main/kotlin/ac/mdiq/podcini/playback/service/QuickSettingsTileService.kt
+++ b/app/src/main/kotlin/ac/mdiq/podcini/playback/service/QuickSettingsTileService.kt
@@ -12,9 +12,9 @@ import android.service.quicksettings.Tile
import android.service.quicksettings.TileService
import android.view.KeyEvent
import androidx.annotation.RequiresApi
-import androidx.media3.common.util.UnstableApi
-@UnstableApi
+
+
@RequiresApi(api = Build.VERSION_CODES.N)
class QuickSettingsTileService : TileService() {
override fun onTileAdded() {
diff --git a/app/src/main/kotlin/ac/mdiq/podcini/preferences/OpmlBackupAgent.kt b/app/src/main/kotlin/ac/mdiq/podcini/preferences/OpmlBackupAgent.kt
index ec27d996..cf9806dc 100644
--- a/app/src/main/kotlin/ac/mdiq/podcini/preferences/OpmlBackupAgent.kt
+++ b/app/src/main/kotlin/ac/mdiq/podcini/preferences/OpmlBackupAgent.kt
@@ -16,8 +16,6 @@ import android.content.Context
import android.os.ParcelFileDescriptor
import android.util.Log
import android.widget.Toast
-import androidx.annotation.OptIn
-import androidx.media3.common.util.UnstableApi
import androidx.preference.PreferenceManager
import org.apache.commons.io.IOUtils
import org.xmlpull.v1.XmlPullParserException
@@ -95,7 +93,7 @@ class OpmlBackupAgent : BackupAgentHelper() {
IOUtils.closeQuietly(writer)
}
}
- @OptIn(UnstableApi::class)
+
override fun restoreEntity(data: BackupDataInputStream) {
Logd(TAG, "Backup restore")
if (OPML_ENTITY_KEY != data.key) {
diff --git a/app/src/main/kotlin/ac/mdiq/podcini/preferences/PreferenceUpgrader.kt b/app/src/main/kotlin/ac/mdiq/podcini/preferences/PreferenceUpgrader.kt
index 5f1ffc7e..0a787539 100644
--- a/app/src/main/kotlin/ac/mdiq/podcini/preferences/PreferenceUpgrader.kt
+++ b/app/src/main/kotlin/ac/mdiq/podcini/preferences/PreferenceUpgrader.kt
@@ -4,8 +4,6 @@ import ac.mdiq.podcini.BuildConfig
import ac.mdiq.podcini.util.error.CrashReportWriter.Companion.file
import android.content.Context
import android.content.SharedPreferences
-import androidx.annotation.OptIn
-import androidx.media3.common.util.UnstableApi
import androidx.preference.PreferenceManager
object PreferenceUpgrader {
@@ -28,7 +26,7 @@ object PreferenceUpgrader {
}
}
- @OptIn(UnstableApi::class) private fun upgrade(oldVersion: Int, context: Context) {
+ private fun upgrade(oldVersion: Int, context: Context) {
//New installation
if (oldVersion == -1) return
}
diff --git a/app/src/main/kotlin/ac/mdiq/podcini/preferences/fragments/ImportExportPreferencesFragment.kt b/app/src/main/kotlin/ac/mdiq/podcini/preferences/fragments/ImportExportPreferencesFragment.kt
index 1cd226e1..f41fa22d 100644
--- a/app/src/main/kotlin/ac/mdiq/podcini/preferences/fragments/ImportExportPreferencesFragment.kt
+++ b/app/src/main/kotlin/ac/mdiq/podcini/preferences/fragments/ImportExportPreferencesFragment.kt
@@ -36,13 +36,11 @@ import androidx.activity.result.ActivityResult
import androidx.activity.result.ActivityResultLauncher
import androidx.activity.result.contract.ActivityResultContracts
import androidx.activity.result.contract.ActivityResultContracts.CreateDocument
-import androidx.annotation.OptIn
import androidx.annotation.StringRes
import androidx.core.app.ShareCompat.IntentBuilder
import androidx.core.content.FileProvider
import androidx.documentfile.provider.DocumentFile
import androidx.lifecycle.lifecycleScope
-import androidx.media3.common.util.UnstableApi
import androidx.preference.Preference
import androidx.preference.PreferenceFragmentCompat
import com.google.android.material.dialog.MaterialAlertDialogBuilder
@@ -912,7 +910,7 @@ class ImportExportPreferencesFragment : PreferenceFragmentCompat() {
/** Reads OPML documents. */
object EpisodeProgressReader {
private const val TAG = "EpisodeProgressReader"
- @OptIn(UnstableApi::class)
+
fun readDocument(reader: Reader) {
val jsonString = reader.readText()
val jsonArray = JSONArray(jsonString)
diff --git a/app/src/main/kotlin/ac/mdiq/podcini/preferences/fragments/PlaybackPreferencesFragment.kt b/app/src/main/kotlin/ac/mdiq/podcini/preferences/fragments/PlaybackPreferencesFragment.kt
index 010aaba5..0f37fa2a 100644
--- a/app/src/main/kotlin/ac/mdiq/podcini/preferences/fragments/PlaybackPreferencesFragment.kt
+++ b/app/src/main/kotlin/ac/mdiq/podcini/preferences/fragments/PlaybackPreferencesFragment.kt
@@ -10,7 +10,8 @@ import ac.mdiq.podcini.preferences.UserPreferences.setVideoMode
import ac.mdiq.podcini.preferences.UserPreferences.speedforwardSpeed
import ac.mdiq.podcini.preferences.UserPreferences.videoPlayMode
import ac.mdiq.podcini.ui.activity.PreferenceActivity
-import ac.mdiq.podcini.ui.dialog.*
+import ac.mdiq.podcini.ui.dialog.SkipPreferenceDialog
+import ac.mdiq.podcini.ui.dialog.VariableSpeedDialog
import ac.mdiq.podcini.util.EventFlow
import ac.mdiq.podcini.util.FlowEvent
import android.app.Activity
@@ -21,9 +22,7 @@ import android.os.Bundle
import android.text.Editable
import android.text.InputType
import android.view.LayoutInflater
-import androidx.annotation.OptIn
import androidx.collection.ArrayMap
-import androidx.media3.common.util.UnstableApi
import androidx.preference.ListPreference
import androidx.preference.Preference
import androidx.preference.PreferenceFragmentCompat
@@ -44,7 +43,7 @@ class PlaybackPreferencesFragment : PreferenceFragmentCompat() {
(activity as PreferenceActivity).supportActionBar!!.setTitle(R.string.playback_pref)
}
- @OptIn(UnstableApi::class)
+
private fun setupPlaybackScreen() {
findPreference(Prefs.prefPlaybackSpeedLauncher.name)!!.onPreferenceClickListener = Preference.OnPreferenceClickListener {
VariableSpeedDialog.newInstance(booleanArrayOf(false, false, true),2)?.show(childFragmentManager, null)
@@ -133,7 +132,7 @@ class PlaybackPreferencesFragment : PreferenceFragmentCompat() {
// pref!!.entries = entries
// }
- @UnstableApi
+
class EditFallbackSpeedDialog(activity: Activity) {
val TAG = this::class.simpleName ?: "Anonymous"
private val activityRef = WeakReference(activity)
@@ -159,7 +158,7 @@ class PlaybackPreferencesFragment : PreferenceFragmentCompat() {
}
}
- @UnstableApi
+
class EditForwardSpeedDialog(activity: Activity) {
val TAG = this::class.simpleName ?: "Anonymous"
private val activityRef = WeakReference(activity)
diff --git a/app/src/main/kotlin/ac/mdiq/podcini/preferences/fragments/SwipePreferencesFragment.kt b/app/src/main/kotlin/ac/mdiq/podcini/preferences/fragments/SwipePreferencesFragment.kt
index cfb44faa..0681872f 100644
--- a/app/src/main/kotlin/ac/mdiq/podcini/preferences/fragments/SwipePreferencesFragment.kt
+++ b/app/src/main/kotlin/ac/mdiq/podcini/preferences/fragments/SwipePreferencesFragment.kt
@@ -1,18 +1,16 @@
package ac.mdiq.podcini.preferences.fragments
-import android.os.Bundle
-import androidx.preference.Preference
-import androidx.preference.PreferenceFragmentCompat
import ac.mdiq.podcini.R
import ac.mdiq.podcini.ui.actions.SwipeActions.Companion.showSettingDialog
import ac.mdiq.podcini.ui.activity.PreferenceActivity
-//import ac.mdiq.podcini.ui.dialog.SwipeActionsDialog
import ac.mdiq.podcini.ui.fragment.*
-import androidx.annotation.OptIn
-import androidx.media3.common.util.UnstableApi
+import android.os.Bundle
+import androidx.preference.Preference
+import androidx.preference.PreferenceFragmentCompat
+
class SwipePreferencesFragment : PreferenceFragmentCompat() {
- @OptIn(UnstableApi::class) override fun onCreatePreferences(savedInstanceState: Bundle?, rootKey: String?) {
+ override fun onCreatePreferences(savedInstanceState: Bundle?, rootKey: String?) {
addPreferencesFromResource(R.xml.preferences_swipe)
findPreference(Prefs.prefSwipeQueue.name)?.onPreferenceClickListener = Preference.OnPreferenceClickListener {
diff --git a/app/src/main/kotlin/ac/mdiq/podcini/preferences/fragments/SynchronizationPreferencesFragment.kt b/app/src/main/kotlin/ac/mdiq/podcini/preferences/fragments/SynchronizationPreferencesFragment.kt
index f857ddb5..eb87416e 100644
--- a/app/src/main/kotlin/ac/mdiq/podcini/preferences/fragments/SynchronizationPreferencesFragment.kt
+++ b/app/src/main/kotlin/ac/mdiq/podcini/preferences/fragments/SynchronizationPreferencesFragment.kt
@@ -18,9 +18,9 @@ import ac.mdiq.podcini.net.sync.wifi.WifiSyncService.Companion.hostPort
import ac.mdiq.podcini.net.sync.wifi.WifiSyncService.Companion.startInstantSync
import ac.mdiq.podcini.storage.utils.FileNameGenerator.generateFileName
import ac.mdiq.podcini.ui.activity.PreferenceActivity
-import ac.mdiq.podcini.util.Logd
import ac.mdiq.podcini.util.EventFlow
import ac.mdiq.podcini.util.FlowEvent
+import ac.mdiq.podcini.util.Logd
import android.app.Activity
import android.app.Dialog
import android.content.Context
@@ -39,12 +39,10 @@ import android.view.ViewGroup
import android.view.inputmethod.EditorInfo
import android.view.inputmethod.InputMethodManager
import android.widget.*
-import androidx.annotation.OptIn
import androidx.appcompat.app.AlertDialog
import androidx.core.text.HtmlCompat
import androidx.fragment.app.DialogFragment
import androidx.lifecycle.lifecycleScope
-import androidx.media3.common.util.UnstableApi
import androidx.preference.Preference
import androidx.preference.PreferenceFragmentCompat
import com.google.android.material.dialog.MaterialAlertDialogBuilder
@@ -578,12 +576,12 @@ class SynchronizationPreferencesFragment : PreferenceFragmentCompat() {
}
}
- @OptIn(UnstableApi::class) class WifiAuthenticationFragment : DialogFragment() {
+ class WifiAuthenticationFragment : DialogFragment() {
private var binding: WifiSyncDialogBinding? = null
private var portNum = 0
private var isGuest: Boolean? = null
- @OptIn(UnstableApi::class) override fun onCreateDialog(savedInstanceState: Bundle?): Dialog {
+ override fun onCreateDialog(savedInstanceState: Bundle?): Dialog {
val dialog = MaterialAlertDialogBuilder(requireContext())
dialog.setTitle(R.string.connect_to_peer)
dialog.setNegativeButton(R.string.cancel_label, null)
@@ -626,7 +624,7 @@ class SynchronizationPreferencesFragment : PreferenceFragmentCompat() {
cancelFlowEvents()
super.onDestroy()
}
- @OptIn(UnstableApi::class) override fun onResume() {
+ override fun onResume() {
super.onResume()
val d = dialog as? AlertDialog
if (d != null) {
diff --git a/app/src/main/kotlin/ac/mdiq/podcini/receiver/ConnectivityActionReceiver.kt b/app/src/main/kotlin/ac/mdiq/podcini/receiver/ConnectivityActionReceiver.kt
index 52a8cd9b..23c36745 100644
--- a/app/src/main/kotlin/ac/mdiq/podcini/receiver/ConnectivityActionReceiver.kt
+++ b/app/src/main/kotlin/ac/mdiq/podcini/receiver/ConnectivityActionReceiver.kt
@@ -11,10 +11,10 @@ import android.content.Context
import android.content.Intent
import android.net.ConnectivityManager
import android.util.Log
-import androidx.media3.common.util.UnstableApi
+
class ConnectivityActionReceiver : BroadcastReceiver() {
- @UnstableApi override fun onReceive(context: Context, intent: Intent) {
+ override fun onReceive(context: Context, intent: Intent) {
Log.d(TAG, "onReceive called with action: ${intent.action}")
if (intent.action == ConnectivityManager.CONNECTIVITY_ACTION) {
Logd(TAG, "Received intent")
diff --git a/app/src/main/kotlin/ac/mdiq/podcini/receiver/FeedUpdateReceiver.kt b/app/src/main/kotlin/ac/mdiq/podcini/receiver/FeedUpdateReceiver.kt
index 9f4fe514..7b35352d 100644
--- a/app/src/main/kotlin/ac/mdiq/podcini/receiver/FeedUpdateReceiver.kt
+++ b/app/src/main/kotlin/ac/mdiq/podcini/receiver/FeedUpdateReceiver.kt
@@ -3,7 +3,7 @@ package ac.mdiq.podcini.receiver
import android.content.BroadcastReceiver
import android.content.Context
import android.content.Intent
-import androidx.media3.common.util.UnstableApi
+
import ac.mdiq.podcini.util.config.ClientConfigurator
import ac.mdiq.podcini.net.feed.FeedUpdateManager
import ac.mdiq.podcini.util.Logd
@@ -12,7 +12,7 @@ import ac.mdiq.podcini.util.Logd
* Refreshes all feeds when it receives an intent
*/
class FeedUpdateReceiver : BroadcastReceiver() {
- @UnstableApi
+
override fun onReceive(context: Context, intent: Intent) {
Logd(TAG, "Received intent")
ClientConfigurator.initialize(context)
diff --git a/app/src/main/kotlin/ac/mdiq/podcini/receiver/MediaButtonReceiver.kt b/app/src/main/kotlin/ac/mdiq/podcini/receiver/MediaButtonReceiver.kt
index dc5acebf..39b7afbc 100644
--- a/app/src/main/kotlin/ac/mdiq/podcini/receiver/MediaButtonReceiver.kt
+++ b/app/src/main/kotlin/ac/mdiq/podcini/receiver/MediaButtonReceiver.kt
@@ -9,13 +9,13 @@ import android.os.Build
import android.util.Log
import android.view.KeyEvent
import androidx.core.content.ContextCompat
-import androidx.media3.common.util.UnstableApi
+
/**
* Receives media button events.
*/
class MediaButtonReceiver : BroadcastReceiver() {
- @UnstableApi
+
override fun onReceive(context: Context, intent: Intent) {
Log.d(TAG, "onReceive Received intent: $intent")
Log.d(TAG, "onReceive Action: ${intent.action}")
diff --git a/app/src/main/kotlin/ac/mdiq/podcini/receiver/PowerConnectionReceiver.kt b/app/src/main/kotlin/ac/mdiq/podcini/receiver/PowerConnectionReceiver.kt
index c19f4eee..f0ae49c5 100644
--- a/app/src/main/kotlin/ac/mdiq/podcini/receiver/PowerConnectionReceiver.kt
+++ b/app/src/main/kotlin/ac/mdiq/podcini/receiver/PowerConnectionReceiver.kt
@@ -3,7 +3,7 @@ package ac.mdiq.podcini.receiver
import android.content.BroadcastReceiver
import android.content.Context
import android.content.Intent
-import androidx.media3.common.util.UnstableApi
+
import ac.mdiq.podcini.util.config.ClientConfigurator
import ac.mdiq.podcini.net.download.service.DownloadServiceInterface
import ac.mdiq.podcini.preferences.UserPreferences.isEnableAutodownloadOnBattery
@@ -17,7 +17,7 @@ import android.util.Log
// Since the intent doesn't have the EXTRA_STATUS like the android.com article says it does
// (though it used to)
class PowerConnectionReceiver : BroadcastReceiver() {
- @UnstableApi override fun onReceive(context: Context, intent: Intent) {
+ override fun onReceive(context: Context, intent: Intent) {
val action = intent.action
Log.d(TAG, "onReceive charging intent: $action")
ClientConfigurator.initialize(context)
diff --git a/app/src/main/kotlin/ac/mdiq/podcini/receiver/SPAReceiver.kt b/app/src/main/kotlin/ac/mdiq/podcini/receiver/SPAReceiver.kt
index 0729afd0..d012ce5c 100644
--- a/app/src/main/kotlin/ac/mdiq/podcini/receiver/SPAReceiver.kt
+++ b/app/src/main/kotlin/ac/mdiq/podcini/receiver/SPAReceiver.kt
@@ -12,13 +12,13 @@ import android.content.Context
import android.content.Intent
import android.util.Log
import android.widget.Toast
-import androidx.media3.common.util.UnstableApi
+
/**
* Receives intents from Podcini Single Purpose apps
*/
class SPAReceiver : BroadcastReceiver() {
- @UnstableApi override fun onReceive(context: Context, intent: Intent) {
+ override fun onReceive(context: Context, intent: Intent) {
if (intent.action != ACTION_SP_APPS_QUERY_FEEDS_REPSONSE) return
Log.d(TAG, "onReceive called with action: ${intent.action}")
diff --git a/app/src/main/kotlin/ac/mdiq/podcini/storage/algorithms/AutoCleanups.kt b/app/src/main/kotlin/ac/mdiq/podcini/storage/algorithms/AutoCleanups.kt
index 637f51a3..2f11f318 100644
--- a/app/src/main/kotlin/ac/mdiq/podcini/storage/algorithms/AutoCleanups.kt
+++ b/app/src/main/kotlin/ac/mdiq/podcini/storage/algorithms/AutoCleanups.kt
@@ -16,9 +16,7 @@ import ac.mdiq.podcini.storage.model.PlayState
import ac.mdiq.podcini.util.Logd
import android.content.Context
import android.util.Log
-import androidx.annotation.OptIn
import androidx.annotation.VisibleForTesting
-import androidx.media3.common.util.UnstableApi
import kotlinx.coroutines.runBlocking
import java.util.*
import java.util.concurrent.ExecutionException
@@ -71,7 +69,7 @@ object AutoCleanups {
override fun getReclaimableItems(): Int {
return candidates.size
}
- @OptIn(UnstableApi::class)
+
public override fun performCleanup(context: Context, numToRemove: Int): Int {
var candidates = candidates
// in the absence of better data, we'll sort by item publication date
@@ -125,7 +123,7 @@ object AutoCleanups {
override fun getReclaimableItems(): Int {
return candidates.size
}
- @OptIn(UnstableApi::class) public override fun performCleanup(context: Context, numToRemove: Int): Int {
+ public override fun performCleanup(context: Context, numToRemove: Int): Int {
var candidates = candidates
// in the absence of better data, we'll sort by item publication date
candidates = candidates.sortedWith { lhs: Episode, rhs: Episode ->
@@ -194,7 +192,7 @@ object AutoCleanups {
override fun getReclaimableItems(): Int {
return candidates.size
}
- @OptIn(UnstableApi::class) public override fun performCleanup(context: Context, numToRemove: Int): Int {
+ public override fun performCleanup(context: Context, numToRemove: Int): Int {
val candidates = candidates.toMutableList()
candidates.sortWith { lhs: Episode, rhs: Episode ->
var l = lhs.media!!.playbackCompletionDate
diff --git a/app/src/main/kotlin/ac/mdiq/podcini/storage/algorithms/AutoDownloads.kt b/app/src/main/kotlin/ac/mdiq/podcini/storage/algorithms/AutoDownloads.kt
index 692fa7c8..993e2611 100644
--- a/app/src/main/kotlin/ac/mdiq/podcini/storage/algorithms/AutoDownloads.kt
+++ b/app/src/main/kotlin/ac/mdiq/podcini/storage/algorithms/AutoDownloads.kt
@@ -19,7 +19,7 @@ import android.content.Context
import android.content.Intent
import android.content.IntentFilter
import android.os.BatteryManager
-import androidx.media3.common.util.UnstableApi
+
import io.realm.kotlin.UpdatePolicy
import java.util.concurrent.ExecutorService
import java.util.concurrent.Executors
@@ -48,7 +48,7 @@ object AutoDownloads {
* @param context Used for accessing the DB.
* @return A Future that can be used for waiting for the methods completion.
*/
- @UnstableApi
+
fun autodownloadEpisodeMedia(context: Context, feeds: List? = null): Future<*> {
Logd(TAG, "autodownloadEpisodeMedia")
return autodownloadExec.submit(downloadAlgorithm.autoDownloadEpisodeMedia(context, feeds))
@@ -69,7 +69,7 @@ object AutoDownloads {
* @return A Runnable that will be submitted to an ExecutorService.
*/
// likely not needed
- @UnstableApi
+
open fun autoDownloadEpisodeMedia(context: Context, feeds: List? = null): Runnable? {
return Runnable {}
}
@@ -89,7 +89,7 @@ object AutoDownloads {
class FeedBasedAutoDLAlgorithm : AutoDownloadAlgorithm() {
- @UnstableApi
+
override fun autoDownloadEpisodeMedia(context: Context, feeds: List?): Runnable {
return Runnable {
// true if we should auto download based on network status
diff --git a/app/src/main/kotlin/ac/mdiq/podcini/storage/database/Episodes.kt b/app/src/main/kotlin/ac/mdiq/podcini/storage/database/Episodes.kt
index 2db7128e..dfa80d0d 100644
--- a/app/src/main/kotlin/ac/mdiq/podcini/storage/database/Episodes.kt
+++ b/app/src/main/kotlin/ac/mdiq/podcini/storage/database/Episodes.kt
@@ -31,10 +31,8 @@ import android.app.backup.BackupManager
import android.content.Context
import android.net.Uri
import android.util.Log
-import androidx.annotation.OptIn
import androidx.core.app.NotificationManagerCompat
import androidx.documentfile.provider.DocumentFile
-import androidx.media3.common.util.UnstableApi
import io.realm.kotlin.ext.isManaged
import kotlinx.coroutines.Job
import java.io.File
@@ -102,7 +100,7 @@ object Episodes {
return runOnIOScope {
if (episode.media == null) return@runOnIOScope
val episode_ = deleteMediaSync(context, episode)
- if (prefDeleteRemovesFromQueue) removeFromQueueSync(null, episode_)
+ if (prefDeleteRemovesFromQueue) removeFromAllQueuesSync(episode_)
}
}
@@ -181,7 +179,7 @@ object Episodes {
* Remove the listed episodes and their EpisodeMedia entries.
* Deleting media also removes the download log entries.
*/
- @UnstableApi
+
fun deleteEpisodes(context: Context, episodes: List) : Job {
return runOnIOScope {
val removedFromQueue: MutableList = mutableListOf()
@@ -226,7 +224,7 @@ object Episodes {
* @param episodes the FeedItems.
* @param resetMediaPosition true if this method should also reset the position of the Episode's EpisodeMedia object.
*/
- @OptIn(UnstableApi::class)
+
fun setPlayState(played: Int, resetMediaPosition: Boolean, vararg episodes: Episode) : Job {
Logd(TAG, "setPlayState called")
return runOnIOScope {
diff --git a/app/src/main/kotlin/ac/mdiq/podcini/storage/database/Feeds.kt b/app/src/main/kotlin/ac/mdiq/podcini/storage/database/Feeds.kt
index a1f2043e..dd4c4b46 100644
--- a/app/src/main/kotlin/ac/mdiq/podcini/storage/database/Feeds.kt
+++ b/app/src/main/kotlin/ac/mdiq/podcini/storage/database/Feeds.kt
@@ -161,11 +161,6 @@ object Feeds {
}
fun getFeed(feedId: Long, copy: Boolean = false): Feed? {
-// 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")
-// }
val f = realm.query(Feed::class, "id == $feedId").first().find()
return if (f != null) {
if (copy) realm.copyFromRealm(f)
@@ -348,13 +343,6 @@ object Feeds {
}
}
- fun setRating(feed: Feed, rating: Int) {
- Logd(TAG, "setRating called $rating")
-// return runOnIOScope {
- val result = upsertBlk(feed) { it.rating = rating }
-// }
- }
-
fun updateFeedDownloadURL(original: String, updated: String) : Job {
Logd(TAG, "updateFeedDownloadURL(original: $original, updated: $updated)")
return runOnIOScope {
@@ -678,14 +666,14 @@ object Feeds {
*/
object EpisodeDuplicateGuesser {
// only used in test
- fun seemDuplicates(item1: Episode, item2: Episode): Boolean {
- if (sameAndNotEmpty(item1.identifier, item2.identifier)) return true
- val media1 = item1.media
- val media2 = item2.media
- if (media1 == null || media2 == null) return false
- if (sameAndNotEmpty(media1.getStreamUrl(), media2.getStreamUrl())) return true
- return (titlesLookSimilar(item1, item2) && datesLookSimilar(item1, item2) && durationsLookSimilar(media1, media2) && mimeTypeLooksSimilar(media1, media2))
- }
+// fun seemDuplicates(item1: Episode, item2: Episode): Boolean {
+// if (sameAndNotEmpty(item1.identifier, item2.identifier)) return true
+// val media1 = item1.media
+// val media2 = item2.media
+// if (media1 == null || media2 == null) return false
+// if (sameAndNotEmpty(media1.getStreamUrl(), media2.getStreamUrl())) return true
+// return (titlesLookSimilar(item1, item2) && datesLookSimilar(item1, item2) && durationsLookSimilar(media1, media2) && mimeTypeLooksSimilar(media1, media2))
+// }
private fun sameAndNotEmpty(string1: String?, string2: String?): Boolean {
if (string1.isNullOrEmpty() || string2.isNullOrEmpty()) return false
return string1 == string2
diff --git a/app/src/main/kotlin/ac/mdiq/podcini/storage/database/Queues.kt b/app/src/main/kotlin/ac/mdiq/podcini/storage/database/Queues.kt
index fe35b670..af8e630d 100644
--- a/app/src/main/kotlin/ac/mdiq/podcini/storage/database/Queues.kt
+++ b/app/src/main/kotlin/ac/mdiq/podcini/storage/database/Queues.kt
@@ -17,7 +17,7 @@ import ac.mdiq.podcini.util.EventFlow
import ac.mdiq.podcini.util.FlowEvent
import ac.mdiq.podcini.util.Logd
import android.util.Log
-import androidx.media3.common.util.UnstableApi
+
import kotlinx.coroutines.Job
import java.util.*
@@ -68,11 +68,7 @@ object Queues {
set(location) {
appPrefs.edit().putString(UserPreferences.Prefs.prefEnqueueLocation.name, location.name).apply()
}
-
-// fun queueFromName(name: String): PlayQueue? {
-// return realm.query(PlayQueue::class).query("name == $0", name).first().find()
-// }
-
+
fun getInQueueEpisodeIds(): Set {
Logd(TAG, "getQueueIDList() called")
val queues = realm.query(PlayQueue::class).find()
@@ -192,15 +188,6 @@ object Queues {
}
}
-// /**
-// * Removes a Episode object from the queue.
-// * @param episodes FeedItems that should be removed.
-// */
-// @JvmStatic
-// fun removeFromQueue(vararg episodes: Episode) : Job {
-// return runOnIOScope { removeFromQueueSync(curQueue, *episodes) }
-// }
-
fun removeFromAllQueuesSync(vararg episodes: Episode) {
Logd(TAG, "removeFromAllQueuesSync called ")
val queues = realm.query(PlayQueue::class).find()
@@ -215,7 +202,6 @@ object Queues {
/**
* @param queue_ if null, use curQueue
*/
- @UnstableApi
internal fun removeFromQueueSync(queue_: PlayQueue?, vararg episodes: Episode) {
Logd(TAG, "removeFromQueueSync called ")
if (episodes.isEmpty()) return
@@ -300,18 +286,6 @@ object Queues {
}
}
- /**
- * Changes the position of a Episode in the queue.
- * @param from Source index. Must be in range 0..queue.size()-1.
- * @param to Destination index. Must be in range 0..queue.size()-1.
- * @param broadcastUpdate true if this operation should trigger a QueueUpdateBroadcast. This option should be set to
- * 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())
- */
-// fun moveInQueue(from: Int, to: Int, broadcastUpdate: Boolean) : Job {
-// return runOnIOScope { moveInQueueSync(from, to, broadcastUpdate) }
-// }
-
/**
* Changes the position of a Episode in the queue.
* This function must be run using the ExecutorService (dbExec).
diff --git a/app/src/main/kotlin/ac/mdiq/podcini/ui/actions/EpisodeActionButton.kt b/app/src/main/kotlin/ac/mdiq/podcini/ui/actions/EpisodeActionButton.kt
index 7ab1b860..3401d535 100644
--- a/app/src/main/kotlin/ac/mdiq/podcini/ui/actions/EpisodeActionButton.kt
+++ b/app/src/main/kotlin/ac/mdiq/podcini/ui/actions/EpisodeActionButton.kt
@@ -34,7 +34,6 @@ import android.util.Log
import android.view.KeyEvent
import android.widget.Toast
import androidx.annotation.DrawableRes
-import androidx.annotation.OptIn
import androidx.annotation.StringRes
import androidx.compose.foundation.layout.Arrangement
import androidx.compose.foundation.layout.Row
@@ -53,7 +52,6 @@ import androidx.compose.ui.res.vectorResource
import androidx.compose.ui.unit.dp
import androidx.compose.ui.window.Dialog
import androidx.core.text.HtmlCompat
-import androidx.media3.common.util.UnstableApi
import com.google.android.material.dialog.MaterialAlertDialogBuilder
import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.delay
@@ -144,7 +142,7 @@ abstract class EpisodeActionButton internal constructor(@JvmField var item: Epis
}
}
- @UnstableApi
+
companion object {
// fun forItem(episode: Episode): EpisodeActionButton {
// val media = episode.media ?: return TTSActionButton(episode)
@@ -208,7 +206,7 @@ class CancelDownloadActionButton(item: Episode) : EpisodeActionButton(item) {
return R.drawable.ic_cancel
}
- @UnstableApi
+
override fun onClick(context: Context) {
val media = item.media
if (media != null) DownloadServiceInterface.get()?.cancel(context, media)
@@ -231,7 +229,7 @@ class PlayActionButton(item: Episode) : EpisodeActionButton(item) {
return R.drawable.ic_play_24dp
}
- @UnstableApi
+
override fun onClick(context: Context) {
Logd("PlayActionButton", "onClick called")
val media = item.media
@@ -290,7 +288,7 @@ class DeleteActionButton(item: Episode) : EpisodeActionButton(item) {
override fun getDrawable(): Int {
return R.drawable.ic_delete
}
- @UnstableApi
+
override fun onClick(context: Context) {
LocalDeleteModal.deleteEpisodesWarnLocal(context, listOf(item))
actionState.value = getLabel()
@@ -304,7 +302,7 @@ class NullActionButton(item: Episode) : EpisodeActionButton(item) {
override fun getDrawable(): Int {
return R.drawable.ic_questionmark
}
- @UnstableApi
+
override fun onClick(context: Context) {}
}
@@ -315,7 +313,7 @@ class PauseActionButton(item: Episode) : EpisodeActionButton(item) {
override fun getDrawable(): Int {
return R.drawable.ic_pause
}
- @UnstableApi
+
override fun onClick(context: Context) {
Logd("PauseActionButton", "onClick called")
val media = item.media ?: return
@@ -390,7 +388,7 @@ class StreamActionButton(item: Episode) : EpisodeActionButton(item) {
return R.drawable.ic_stream
}
- @UnstableApi
+
override fun onClick(context: Context) {
if (item.media == null) return
// Logd("StreamActionButton", "item.feed: ${item.feedId}")
@@ -405,7 +403,7 @@ class StreamActionButton(item: Episode) : EpisodeActionButton(item) {
}
class StreamingConfirmationDialog(private val context: Context, private val playable: Playable) {
- @UnstableApi
+
fun show() {
MaterialAlertDialogBuilder(context)
.setTitle(R.string.stream_label)
@@ -447,7 +445,7 @@ class TTSActionButton(item: Episode) : EpisodeActionButton(item) {
return R.drawable.text_to_speech
}
- @OptIn(UnstableApi::class) override fun onClick(context: Context) {
+ override fun onClick(context: Context) {
Logd("TTSActionButton", "onClick called")
if (item.link.isNullOrEmpty()) {
Toast.makeText(context, R.string.episode_has_no_content, Toast.LENGTH_LONG).show()
@@ -577,7 +575,7 @@ class PlayLocalActionButton(item: Episode) : EpisodeActionButton(item) {
override fun getDrawable(): Int {
return R.drawable.ic_play_24dp
}
- @UnstableApi
+
override fun onClick(context: Context) {
Logd("PlayLocalActionButton", "onClick called")
val media = item.media
diff --git a/app/src/main/kotlin/ac/mdiq/podcini/ui/actions/SwipeAction.kt b/app/src/main/kotlin/ac/mdiq/podcini/ui/actions/SwipeAction.kt
index 500d2eb5..d2dfc921 100644
--- a/app/src/main/kotlin/ac/mdiq/podcini/ui/actions/SwipeAction.kt
+++ b/app/src/main/kotlin/ac/mdiq/podcini/ui/actions/SwipeAction.kt
@@ -28,6 +28,7 @@ interface SwipeAction {
NO_ACTION,
COMBO,
RATING,
+ COMMENT,
SET_PLAY_STATE,
ADD_TO_QUEUE,
PUT_TO_QUEUE,
diff --git a/app/src/main/kotlin/ac/mdiq/podcini/ui/actions/SwipeActions.kt b/app/src/main/kotlin/ac/mdiq/podcini/ui/actions/SwipeActions.kt
index d2330f35..79dfd01c 100644
--- a/app/src/main/kotlin/ac/mdiq/podcini/ui/actions/SwipeActions.kt
+++ b/app/src/main/kotlin/ac/mdiq/podcini/ui/actions/SwipeActions.kt
@@ -27,7 +27,6 @@ import android.content.Context
import android.content.SharedPreferences
import android.util.TypedValue
import android.view.ViewGroup
-import androidx.annotation.OptIn
import androidx.compose.foundation.clickable
import androidx.compose.foundation.layout.*
import androidx.compose.foundation.lazy.grid.GridCells
@@ -43,13 +42,13 @@ import androidx.compose.ui.platform.ComposeView
import androidx.compose.ui.platform.LocalContext
import androidx.compose.ui.res.stringResource
import androidx.compose.ui.res.vectorResource
+import androidx.compose.ui.text.input.TextFieldValue
import androidx.compose.ui.text.style.TextAlign
import androidx.compose.ui.unit.dp
import androidx.compose.ui.window.Dialog
import androidx.fragment.app.Fragment
import androidx.lifecycle.DefaultLifecycleObserver
import androidx.lifecycle.LifecycleOwner
-import androidx.media3.common.util.UnstableApi
import com.google.android.material.snackbar.Snackbar
import kotlinx.coroutines.Job
import kotlinx.coroutines.runBlocking
@@ -124,7 +123,6 @@ open class SwipeActions(private val fragment: Fragment, private val tag: String)
override fun getTitle(context: Context): String {
return context.getString(R.string.add_to_queue_label)
}
- @OptIn(UnstableApi::class)
override fun performAction(item: Episode, fragment: Fragment, filter: EpisodeFilter) {
addToQueue(item)
}
@@ -143,7 +141,6 @@ open class SwipeActions(private val fragment: Fragment, private val tag: String)
override fun getTitle(context: Context): String {
return context.getString(R.string.combo_action)
}
- @OptIn(UnstableApi::class)
override fun performAction(item: Episode, fragment: Fragment, filter: EpisodeFilter) {
val composeView = ComposeView(fragment.requireContext()).apply {
setContent {
@@ -195,7 +192,6 @@ open class SwipeActions(private val fragment: Fragment, private val tag: String)
override fun getTitle(context: Context): String {
return context.getString(R.string.delete_episode_label)
}
- @UnstableApi
override fun performAction(item_: Episode, fragment: Fragment, filter: EpisodeFilter) {
var item = item_
if (!item.isDownloaded && item.feed?.isLocalFeed != true) return
@@ -225,7 +221,6 @@ open class SwipeActions(private val fragment: Fragment, private val tag: String)
override fun getTitle(context: Context): String {
return context.getString(R.string.set_rating_label)
}
- @OptIn(UnstableApi::class)
override fun performAction(item: Episode, fragment: Fragment, filter: EpisodeFilter) {
var showChooseRatingDialog by mutableStateOf(true)
val composeView = ComposeView(fragment.requireContext()).apply {
@@ -242,6 +237,46 @@ open class SwipeActions(private val fragment: Fragment, private val tag: String)
}
}
+ class AddCommentSwipeAction : SwipeAction {
+ override fun getId(): String {
+ return ActionTypes.COMMENT.name
+ }
+ override fun getActionIcon(): Int {
+ return R.drawable.baseline_comment_24
+ }
+ override fun getActionColor(): Int {
+ return R.attr.icon_yellow
+ }
+ override fun getTitle(context: Context): String {
+ return context.getString(R.string.add_opinion_label)
+ }
+ override fun performAction(item: Episode, fragment: Fragment, filter: EpisodeFilter) {
+ var showEditComment by mutableStateOf(true)
+ val composeView = ComposeView(fragment.requireContext()).apply {
+ setContent {
+ CustomTheme(fragment.requireContext()) {
+ if (showEditComment) {
+ ChooseRatingDialog(listOf(item)) {
+ showEditComment = false
+ (fragment.view as? ViewGroup)?.removeView(this@apply)
+ }
+ var commentTextState by remember { mutableStateOf(TextFieldValue(item.comment)) }
+ LargeTextEditingDialog(textState = commentTextState, onTextChange = { commentTextState = it },
+ onDismissRequest = {
+ showEditComment = false
+ (fragment.view as? ViewGroup)?.removeView(this@apply)
+ },
+ onSave = {
+ runOnIOScope { upsert(item) { it.comment = commentTextState.text } }
+ })
+ }
+ }
+ }
+ }
+ (fragment.view as? ViewGroup)?.addView(composeView)
+ }
+ }
+
class NoActionSwipeAction : SwipeAction {
override fun getId(): String {
return NO_ACTION.name
@@ -273,7 +308,6 @@ open class SwipeActions(private val fragment: Fragment, private val tag: String)
override fun getTitle(context: Context): String {
return context.getString(R.string.remove_history_label)
}
- @OptIn(UnstableApi::class)
override fun performAction(item: Episode, fragment: Fragment, filter: EpisodeFilter) {
val playbackCompletionDate: Date? = item.media?.playbackCompletionDate
val lastPlayedDate = item.media?.lastPlayedTime
@@ -314,7 +348,6 @@ open class SwipeActions(private val fragment: Fragment, private val tag: String)
override fun getTitle(context: Context): String {
return context.getString(R.string.remove_from_queue_label)
}
- @OptIn(UnstableApi::class)
override fun performAction(item_: Episode, fragment: Fragment, filter: EpisodeFilter) {
val position: Int = curQueue.episodes.indexOf(item_)
var item = item_
@@ -344,8 +377,8 @@ open class SwipeActions(private val fragment: Fragment, private val tag: String)
* @param index Destination index. Must be in range 0..queue.size()
* @throws IndexOutOfBoundsException if index < 0 || index >= queue.size()
*/
- @UnstableApi
- fun addToQueueAt(episode: Episode, index: Int) : Job {
+
+ private fun addToQueueAt(episode: Episode, index: Int) : Job {
return runOnIOScope {
if (curQueue.episodeIds.contains(episode.id)) return@runOnIOScope
if (episode.isNew) setPlayState(PlayState.UNPLAYED.code, false, episode)
@@ -519,7 +552,7 @@ open class SwipeActions(private val fragment: Fragment, private val tag: String)
val swipeActions: List = listOf(
NoActionSwipeAction(), ComboSwipeAction(),
AddToQueueSwipeAction(), PutToQueueSwipeAction(),
- StartDownloadSwipeAction(), SetRatingSwipeAction(),
+ StartDownloadSwipeAction(), SetRatingSwipeAction(), AddCommentSwipeAction(),
SetPlaybackStateSwipeAction(), RemoveFromQueueSwipeAction(),
DeleteSwipeAction(), RemoveFromHistorySwipeAction(),
ShelveSwipeAction(), EraseSwipeAction())
@@ -533,7 +566,7 @@ open class SwipeActions(private val fragment: Fragment, private val tag: String)
return getPrefs(tag, "")
}
- @OptIn(UnstableApi::class) @JvmStatic
+ @JvmStatic
fun getPrefsWithDefaults(tag: String): Actions {
val defaultActions = when (tag) {
QueuesFragment.TAG -> "${NO_ACTION.name},${NO_ACTION.name}"
diff --git a/app/src/main/kotlin/ac/mdiq/podcini/ui/activity/MainActivity.kt b/app/src/main/kotlin/ac/mdiq/podcini/ui/activity/MainActivity.kt
index 71918cc9..e6b674e2 100644
--- a/app/src/main/kotlin/ac/mdiq/podcini/ui/activity/MainActivity.kt
+++ b/app/src/main/kotlin/ac/mdiq/podcini/ui/activity/MainActivity.kt
@@ -69,7 +69,7 @@ import androidx.core.view.WindowInsetsCompat
import androidx.drawerlayout.widget.DrawerLayout
import androidx.fragment.app.Fragment
import androidx.lifecycle.lifecycleScope
-import androidx.media3.common.util.UnstableApi
+
import androidx.media3.session.MediaController
import androidx.media3.session.SessionToken
import androidx.recyclerview.widget.RecyclerView
@@ -89,7 +89,7 @@ import kotlin.math.min
/**
* The activity that is shown when the user launches the app.
*/
-@UnstableApi
+
class MainActivity : CastEnabledActivity() {
private var drawerLayout: DrawerLayout? = null
@@ -178,7 +178,7 @@ class MainActivity : CastEnabledActivity() {
}
private var prevState: Int = 0
- private val bottomSheetCallback: BottomSheetCallback = @UnstableApi object : BottomSheetCallback() {
+ private val bottomSheetCallback: BottomSheetCallback = object : BottomSheetCallback() {
override fun onStateChanged(view: View, state: Int) {
Logd(TAG, "bottomSheet onStateChanged $state ${view.id}")
when (state) {
@@ -214,7 +214,7 @@ class MainActivity : CastEnabledActivity() {
return displayMetrics.widthPixels
}
- @UnstableApi public override fun onCreate(savedInstanceState: Bundle?) {
+ public override fun onCreate(savedInstanceState: Bundle?) {
lastTheme = getNoTitleTheme(this)
setTheme(lastTheme)
diff --git a/app/src/main/kotlin/ac/mdiq/podcini/ui/activity/OpmlImportActivity.kt b/app/src/main/kotlin/ac/mdiq/podcini/ui/activity/OpmlImportActivity.kt
index fe359d38..72b56014 100644
--- a/app/src/main/kotlin/ac/mdiq/podcini/ui/activity/OpmlImportActivity.kt
+++ b/app/src/main/kotlin/ac/mdiq/podcini/ui/activity/OpmlImportActivity.kt
@@ -31,7 +31,7 @@ import androidx.activity.result.contract.ActivityResultContracts
import androidx.appcompat.app.AppCompatActivity
import androidx.core.app.ActivityCompat
import androidx.lifecycle.lifecycleScope
-import androidx.media3.common.util.UnstableApi
+
import com.google.android.material.dialog.MaterialAlertDialogBuilder
import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.launch
@@ -73,7 +73,7 @@ class OpmlImportActivity : AppCompatActivity() {
}
}
- @UnstableApi override fun onCreate(savedInstanceState: Bundle?) {
+ override fun onCreate(savedInstanceState: Bundle?) {
setTheme(getTheme(this))
super.onCreate(savedInstanceState)
supportActionBar?.setDisplayHomeAsUpEnabled(true)
diff --git a/app/src/main/kotlin/ac/mdiq/podcini/ui/activity/SelectSubscriptionActivity.kt b/app/src/main/kotlin/ac/mdiq/podcini/ui/activity/SelectSubscriptionActivity.kt
index 72456277..3802d8d4 100644
--- a/app/src/main/kotlin/ac/mdiq/podcini/ui/activity/SelectSubscriptionActivity.kt
+++ b/app/src/main/kotlin/ac/mdiq/podcini/ui/activity/SelectSubscriptionActivity.kt
@@ -15,13 +15,11 @@ import android.view.View
import android.widget.AdapterView
import android.widget.ArrayAdapter
import android.widget.ListView
-import androidx.annotation.OptIn
import androidx.appcompat.app.AppCompatActivity
import androidx.core.content.pm.ShortcutInfoCompat
import androidx.core.content.pm.ShortcutManagerCompat
import androidx.core.graphics.drawable.IconCompat
import androidx.lifecycle.lifecycleScope
-import androidx.media3.common.util.UnstableApi
import coil.imageLoader
import coil.request.ErrorResult
import coil.request.ImageRequest
@@ -72,7 +70,7 @@ class SelectSubscriptionActivity : AppCompatActivity() {
return result
}
- @UnstableApi private fun addShortcut(feed: Feed, bitmap: Bitmap?) {
+ private fun addShortcut(feed: Feed, bitmap: Bitmap?) {
val intent = Intent(this, MainActivity::class.java)
intent.setAction(Intent.ACTION_MAIN)
intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK or Intent.FLAG_ACTIVITY_CLEAR_TASK)
@@ -100,10 +98,10 @@ class SelectSubscriptionActivity : AppCompatActivity() {
.setHeader("User-Agent", "Mozilla/5.0")
.placeholder(R.color.light_gray)
.listener(object : ImageRequest.Listener {
- @OptIn(UnstableApi::class) override fun onError(request: ImageRequest, throwable: ErrorResult) {
+ override fun onError(request: ImageRequest, throwable: ErrorResult) {
addShortcut(feed, null)
}
- @OptIn(UnstableApi::class) override fun onSuccess(request: ImageRequest, result: SuccessResult) {
+ override fun onSuccess(request: ImageRequest, result: SuccessResult) {
addShortcut(feed, (result.drawable as BitmapDrawable).bitmap)
}
})
diff --git a/app/src/main/kotlin/ac/mdiq/podcini/ui/activity/ShareReceiverActivity.kt b/app/src/main/kotlin/ac/mdiq/podcini/ui/activity/ShareReceiverActivity.kt
index cb800ede..d93037cb 100644
--- a/app/src/main/kotlin/ac/mdiq/podcini/ui/activity/ShareReceiverActivity.kt
+++ b/app/src/main/kotlin/ac/mdiq/podcini/ui/activity/ShareReceiverActivity.kt
@@ -4,8 +4,8 @@ import ac.mdiq.podcini.R
import ac.mdiq.podcini.storage.database.RealmDB.realm
import ac.mdiq.podcini.storage.database.RealmDB.upsertBlk
import ac.mdiq.podcini.storage.model.ShareLog
-import ac.mdiq.podcini.ui.compose.CustomTheme
import ac.mdiq.podcini.ui.compose.ConfirmAddYoutubeEpisode
+import ac.mdiq.podcini.ui.compose.CustomTheme
import ac.mdiq.podcini.util.Logd
import ac.mdiq.vista.extractor.services.youtube.YoutubeParsingHelper.isYoutubeServiceURL
import ac.mdiq.vista.extractor.services.youtube.YoutubeParsingHelper.isYoutubeURL
@@ -15,11 +15,9 @@ import android.net.Uri
import android.os.Bundle
import android.util.Log
import androidx.activity.compose.setContent
-import androidx.annotation.OptIn
import androidx.appcompat.app.AppCompatActivity
import androidx.compose.runtime.mutableStateOf
import androidx.compose.runtime.remember
-import androidx.media3.common.util.UnstableApi
import com.google.android.material.dialog.MaterialAlertDialogBuilder
import java.net.URL
import java.net.URLDecoder
@@ -27,7 +25,7 @@ import java.net.URLDecoder
class ShareReceiverActivity : AppCompatActivity() {
private var sharedUrl: String? = null
- @OptIn(UnstableApi::class) override fun onCreate(savedInstanceState: Bundle?) {
+ override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
Logd(TAG, "intent: $intent")
diff --git a/app/src/main/kotlin/ac/mdiq/podcini/ui/activity/SplashActivity.kt b/app/src/main/kotlin/ac/mdiq/podcini/ui/activity/SplashActivity.kt
index 07875693..e1791e6f 100644
--- a/app/src/main/kotlin/ac/mdiq/podcini/ui/activity/SplashActivity.kt
+++ b/app/src/main/kotlin/ac/mdiq/podcini/ui/activity/SplashActivity.kt
@@ -7,7 +7,7 @@ import android.content.Intent
import android.os.Bundle
import android.view.View
import android.widget.Toast
-import androidx.media3.common.util.UnstableApi
+
import kotlinx.coroutines.CoroutineScope
import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.launch
@@ -18,7 +18,7 @@ import kotlinx.coroutines.withContext
*/
@SuppressLint("CustomSplashScreen")
class SplashActivity : Activity() {
- @UnstableApi override fun onCreate(savedInstanceState: Bundle?) {
+ override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
val content = findViewById(android.R.id.content)
content.viewTreeObserver.addOnPreDrawListener { false } // Keep splash screen active
diff --git a/app/src/main/kotlin/ac/mdiq/podcini/ui/activity/VideoplayerActivity.kt b/app/src/main/kotlin/ac/mdiq/podcini/ui/activity/VideoplayerActivity.kt
index 7a4a21a6..e5afdaab 100644
--- a/app/src/main/kotlin/ac/mdiq/podcini/ui/activity/VideoplayerActivity.kt
+++ b/app/src/main/kotlin/ac/mdiq/podcini/ui/activity/VideoplayerActivity.kt
@@ -64,7 +64,6 @@ import android.widget.EditText
import android.widget.FrameLayout
import android.widget.SeekBar
import android.widget.SeekBar.OnSeekBarChangeListener
-import androidx.annotation.OptIn
import androidx.appcompat.app.AlertDialog
import androidx.appcompat.app.AppCompatActivity
import androidx.compose.runtime.mutableStateOf
@@ -75,7 +74,6 @@ import androidx.fragment.app.DialogFragment
import androidx.fragment.app.Fragment
import androidx.interpolator.view.animation.FastOutSlowInInterpolator
import androidx.lifecycle.lifecycleScope
-import androidx.media3.common.util.UnstableApi
import androidx.window.layout.WindowMetricsCalculator
import com.google.android.material.dialog.MaterialAlertDialogBuilder
import kotlinx.coroutines.Dispatchers
@@ -89,7 +87,7 @@ import kotlin.math.min
/**
* Activity for playing video files.
*/
-@UnstableApi
+
class VideoplayerActivity : CastEnabledActivity() {
private var _binding: VideoplayerActivityBinding? = null
@@ -162,7 +160,7 @@ class VideoplayerActivity : CastEnabledActivity() {
if (::videoEpisodeFragment.isInitialized) videoEpisodeFragment.setForVideoMode()
}
- @UnstableApi
+
override fun onResume() {
super.onResume()
setForVideoMode()
@@ -190,7 +188,7 @@ class VideoplayerActivity : CastEnabledActivity() {
if (!PictureInPictureUtil.isInPictureInPictureMode(this)) compatEnterPictureInPicture()
}
- @UnstableApi
+
override fun onStart() {
super.onStart()
procFlowEvents()
@@ -244,7 +242,7 @@ class VideoplayerActivity : CastEnabledActivity() {
return true
}
- @UnstableApi
+
override fun onPrepareOptionsMenu(menu: Menu): Boolean {
super.onPrepareOptionsMenu(menu)
@@ -426,7 +424,7 @@ class VideoplayerActivity : CastEnabledActivity() {
private val binding get() = _binding!!
private var statusHandler: ServiceStatusHandler? = null
- @UnstableApi override fun onStart() {
+ override fun onStart() {
super.onStart()
statusHandler = object : ServiceStatusHandler(requireActivity()) {
override fun loadMediaInfo() {
@@ -435,7 +433,7 @@ class VideoplayerActivity : CastEnabledActivity() {
}
statusHandler?.init()
}
- @UnstableApi override fun onStop() {
+ override fun onStop() {
super.onStop()
statusHandler?.release()
statusHandler = null
@@ -453,7 +451,7 @@ class VideoplayerActivity : CastEnabledActivity() {
_binding = null
super.onDestroyView()
}
- @UnstableApi private fun setupAudioTracks() {
+ private fun setupAudioTracks() {
val butAudioTracks = binding.audioTracks
if (audioTracks.size < 2 || selectedAudioTrack < 0) {
butAudioTracks.visibility = View.GONE
@@ -476,7 +474,7 @@ class VideoplayerActivity : CastEnabledActivity() {
}
}
- @UnstableApi
+
class VideoEpisodeFragment : Fragment(), OnSeekBarChangeListener {
private var _binding: VideoEpisodeFragmentBinding? = null
private val binding get() = _binding!!
@@ -527,7 +525,7 @@ class VideoplayerActivity : CastEnabledActivity() {
override fun surfaceChanged(holder: SurfaceHolder, format: Int, width: Int, height: Int) {
holder.setFixedSize(width, height)
}
- @UnstableApi
+
override fun surfaceCreated(holder: SurfaceHolder) {
Logd(TAG, "Videoview holder created")
videoSurfaceCreated = true
@@ -549,7 +547,7 @@ class VideoplayerActivity : CastEnabledActivity() {
}
}
- @OptIn(UnstableApi::class)
+
override fun onCreateView(inflater: LayoutInflater, container: ViewGroup?, savedInstanceState: Bundle?): View {
super.onCreateView(inflater, container, savedInstanceState)
Logd(TAG, "fragment onCreateView")
@@ -561,7 +559,7 @@ class VideoplayerActivity : CastEnabledActivity() {
return root
}
- @OptIn(UnstableApi::class)
+
private fun newStatusHandler(): ServiceStatusHandler {
return object : ServiceStatusHandler(requireActivity()) {
override fun updatePlayButton(showPlay: Boolean) {
@@ -586,14 +584,14 @@ class VideoplayerActivity : CastEnabledActivity() {
}
}
- @UnstableApi
+
override fun onStart() {
super.onStart()
onPositionObserverUpdate()
procFlowEvents()
}
- @UnstableApi
+
override fun onStop() {
super.onStop()
cancelFlowEvents()
@@ -689,7 +687,7 @@ class VideoplayerActivity : CastEnabledActivity() {
}
private var loadItemsRunning = false
- @OptIn(UnstableApi::class)
+
private fun loadMediaInfo() {
Logd(TAG, "loadMediaInfo called")
if (curMedia == null) return
@@ -749,7 +747,7 @@ class VideoplayerActivity : CastEnabledActivity() {
}
}
- @UnstableApi
+
private fun setupView() {
showTimeLeft = shouldShowRemainingTime()
Logd(TAG, "setupView showTimeLeft: $showTimeLeft")
@@ -843,19 +841,19 @@ class VideoplayerActivity : CastEnabledActivity() {
})
}
- @UnstableApi
+
fun onRewind() {
playbackService?.mPlayer?.seekDelta(-rewindSecs * 1000)
setupVideoControlsToggler()
}
- @UnstableApi
+
fun onPlayPause() {
playPause()
setupVideoControlsToggler()
}
- @UnstableApi
+
fun onFastForward() {
playbackService?.mPlayer?.seekDelta(fastForwardSecs * 1000)
setupVideoControlsToggler()
diff --git a/app/src/main/kotlin/ac/mdiq/podcini/ui/activity/starter/VideoPlayerActivityStarter.kt b/app/src/main/kotlin/ac/mdiq/podcini/ui/activity/starter/VideoPlayerActivityStarter.kt
index 346711be..e9cd498d 100644
--- a/app/src/main/kotlin/ac/mdiq/podcini/ui/activity/starter/VideoPlayerActivityStarter.kt
+++ b/app/src/main/kotlin/ac/mdiq/podcini/ui/activity/starter/VideoPlayerActivityStarter.kt
@@ -1,18 +1,15 @@
package ac.mdiq.podcini.ui.activity.starter
-
import ac.mdiq.podcini.R
import android.app.PendingIntent
import android.content.Context
import android.content.Intent
-import androidx.annotation.OptIn
-import androidx.media3.common.util.UnstableApi
/**
* Launches the video player activity of the app with specific arguments.
* Does not require a dependency on the actual implementation of the activity.
*/
-@OptIn(UnstableApi::class) class VideoPlayerActivityStarter(private val context: Context) {
+ class VideoPlayerActivityStarter(private val context: Context) {
val intent: Intent = Intent(INTENT)
val pendingIntent: PendingIntent
get() = PendingIntent.getActivity(context, R.id.pending_intent_video_player, intent,
diff --git a/app/src/main/kotlin/ac/mdiq/podcini/ui/compose/EpisodesVM.kt b/app/src/main/kotlin/ac/mdiq/podcini/ui/compose/EpisodesVM.kt
index b1e20bd8..bdf7f648 100644
--- a/app/src/main/kotlin/ac/mdiq/podcini/ui/compose/EpisodesVM.kt
+++ b/app/src/main/kotlin/ac/mdiq/podcini/ui/compose/EpisodesVM.kt
@@ -278,7 +278,7 @@ fun PlayStateDialog(selected: List, onDismissRequest: () -> Unit) {
media = item_.media
if (media != null && hasAlmostEnded && shouldAutoDelete) {
item_ = deleteMediaSync(context, item_)
- if (prefDeleteRemovesFromQueue) removeFromQueueSync(null, item_)
+ if (prefDeleteRemovesFromQueue) removeFromAllQueuesSync(item_)
} else if (prefRemoveFromQueueMarkedPlayed) removeFromAllQueuesSync(item_)
if (item_.feed?.isLocalFeed != true && (isProviderConnected || wifiSyncEnabledKey)) {
val media_: EpisodeMedia? = item_.media
@@ -781,7 +781,7 @@ fun EpisodeLazyColumn(activity: MainActivity, vms: MutableList, feed:
LaunchedEffect(key1 = status, key2 = vm.downloadState) {
if (index >= vms.size) return@LaunchedEffect
if (isDownloading()) vm.dlPercent = dls?.getProgress(vms[index].episode.media?.downloadUrl ?: "") ?: 0
- Logd(TAG, "LaunchedEffect $index isPlayingState: ${vms[index].isPlayingState} ${vms[index].episode.title}")
+ Logd(TAG, "LaunchedEffect $index isPlayingState: ${vms[index].isPlayingState} ${vm.episode.playState} ${vms[index].episode.title}")
Logd(TAG, "LaunchedEffect $index downloadState: ${vms[index].downloadState} ${vm.episode.media?.downloaded} ${vm.dlPercent}")
vm.actionButton = vm.actionButton.forItem(vm.episode)
if (vm.actionButton.getLabel() != actionButton.getLabel()) actionButton = vm.actionButton
diff --git a/app/src/main/kotlin/ac/mdiq/podcini/ui/compose/Feeds.kt b/app/src/main/kotlin/ac/mdiq/podcini/ui/compose/Feeds.kt
index 04b681b8..43a3d2f3 100644
--- a/app/src/main/kotlin/ac/mdiq/podcini/ui/compose/Feeds.kt
+++ b/app/src/main/kotlin/ac/mdiq/podcini/ui/compose/Feeds.kt
@@ -6,6 +6,7 @@ import ac.mdiq.podcini.net.feed.discovery.PodcastSearchResult
import ac.mdiq.podcini.storage.database.Feeds
import ac.mdiq.podcini.storage.database.Feeds.deleteFeedSync
import ac.mdiq.podcini.storage.database.RealmDB.upsert
+import ac.mdiq.podcini.storage.database.RealmDB.upsertBlk
import ac.mdiq.podcini.storage.model.Feed
import ac.mdiq.podcini.storage.model.Feed.Companion.MAX_SYNTHETIC_ID
import ac.mdiq.podcini.storage.model.Rating
@@ -54,7 +55,10 @@ fun ChooseRatingDialog(selected: List, onDismissRequest: () -> Unit) {
Column(modifier = Modifier.padding(16.dp), verticalArrangement = Arrangement.spacedBy(16.dp)) {
for (rating in Rating.entries.reversed()) {
Row(verticalAlignment = Alignment.CenterVertically, modifier = Modifier.padding(4.dp).clickable {
- for (item in selected) Feeds.setRating(item, rating.code)
+ for (item in selected) {
+// Feeds.setRating(item, rating.code)
+ upsertBlk(item) { it.rating = rating.code }
+ }
onDismissRequest()
}) {
Icon(imageVector = ImageVector.vectorResource(id = rating.res), "")
diff --git a/app/src/main/kotlin/ac/mdiq/podcini/ui/dialog/CustomFeedNameDialog.kt b/app/src/main/kotlin/ac/mdiq/podcini/ui/dialog/CustomFeedNameDialog.kt
index 3535e685..f8495bd3 100644
--- a/app/src/main/kotlin/ac/mdiq/podcini/ui/dialog/CustomFeedNameDialog.kt
+++ b/app/src/main/kotlin/ac/mdiq/podcini/ui/dialog/CustomFeedNameDialog.kt
@@ -2,19 +2,16 @@ package ac.mdiq.podcini.ui.dialog
import ac.mdiq.podcini.R
import ac.mdiq.podcini.databinding.EditTextDialogBinding
-import ac.mdiq.podcini.storage.database.RealmDB.unmanaged
import ac.mdiq.podcini.storage.database.RealmDB.upsertBlk
import ac.mdiq.podcini.storage.model.Feed
import android.app.Activity
import android.content.DialogInterface
import android.view.LayoutInflater
-import androidx.annotation.OptIn
import androidx.appcompat.app.AlertDialog
-import androidx.media3.common.util.UnstableApi
import com.google.android.material.dialog.MaterialAlertDialogBuilder
import java.lang.ref.WeakReference
-@OptIn(UnstableApi::class)
+
class CustomFeedNameDialog(activity: Activity, private var feed: Feed) {
private val activityRef: WeakReference = WeakReference(activity)
diff --git a/app/src/main/kotlin/ac/mdiq/podcini/ui/dialog/MediaPlayerErrorDialog.kt b/app/src/main/kotlin/ac/mdiq/podcini/ui/dialog/MediaPlayerErrorDialog.kt
index 65edfa51..d28063b8 100644
--- a/app/src/main/kotlin/ac/mdiq/podcini/ui/dialog/MediaPlayerErrorDialog.kt
+++ b/app/src/main/kotlin/ac/mdiq/podcini/ui/dialog/MediaPlayerErrorDialog.kt
@@ -1,6 +1,8 @@
package ac.mdiq.podcini.ui.dialog
+import ac.mdiq.podcini.R
import ac.mdiq.podcini.ui.activity.MainActivity
+import ac.mdiq.podcini.util.FlowEvent
import android.app.Activity
import android.content.DialogInterface
import android.text.Spannable
@@ -8,12 +10,8 @@ import android.text.SpannableString
import android.text.style.ForegroundColorSpan
import com.google.android.material.bottomsheet.BottomSheetBehavior
import com.google.android.material.dialog.MaterialAlertDialogBuilder
-import ac.mdiq.podcini.R
-import ac.mdiq.podcini.util.FlowEvent
-import androidx.annotation.OptIn
-import androidx.media3.common.util.UnstableApi
-@OptIn(UnstableApi::class)
+
object MediaPlayerErrorDialog {
fun show(activity: Activity, event: FlowEvent.PlayerErrorEvent) {
val errorDialog = MaterialAlertDialogBuilder(activity)
diff --git a/app/src/main/kotlin/ac/mdiq/podcini/ui/dialog/SleepTimerDialog.kt b/app/src/main/kotlin/ac/mdiq/podcini/ui/dialog/SleepTimerDialog.kt
index d881fe58..ba4c2efb 100644
--- a/app/src/main/kotlin/ac/mdiq/podcini/ui/dialog/SleepTimerDialog.kt
+++ b/app/src/main/kotlin/ac/mdiq/podcini/ui/dialog/SleepTimerDialog.kt
@@ -42,7 +42,7 @@ import android.view.inputmethod.InputMethodManager
import android.widget.*
import androidx.fragment.app.DialogFragment
import androidx.lifecycle.lifecycleScope
-import androidx.media3.common.util.UnstableApi
+
import com.google.android.material.dialog.MaterialAlertDialogBuilder
import com.google.android.material.snackbar.Snackbar
import kotlinx.coroutines.Job
@@ -59,17 +59,17 @@ class SleepTimerDialog : DialogFragment() {
private lateinit var etxtTime: EditText
private lateinit var chAutoEnable: CheckBox
- @UnstableApi override fun onStart() {
+ override fun onStart() {
super.onStart()
procFlowEvents()
}
- @UnstableApi override fun onStop() {
+ override fun onStop() {
super.onStop()
cancelFlowEvents()
}
- @UnstableApi override fun onCreateDialog(savedInstanceState: Bundle?): Dialog {
+ override fun onCreateDialog(savedInstanceState: Bundle?): Dialog {
_binding = TimeDialogBinding.inflate(layoutInflater)
val content = binding.root
val builder = MaterialAlertDialogBuilder(requireContext())
diff --git a/app/src/main/kotlin/ac/mdiq/podcini/ui/dialog/TagSettingsDialog.kt b/app/src/main/kotlin/ac/mdiq/podcini/ui/dialog/TagSettingsDialog.kt
index c16e005b..4fa7474a 100644
--- a/app/src/main/kotlin/ac/mdiq/podcini/ui/dialog/TagSettingsDialog.kt
+++ b/app/src/main/kotlin/ac/mdiq/podcini/ui/dialog/TagSettingsDialog.kt
@@ -15,9 +15,7 @@ import android.content.DialogInterface
import android.os.Bundle
import android.view.View
import android.widget.ArrayAdapter
-import androidx.annotation.OptIn
import androidx.fragment.app.DialogFragment
-import androidx.media3.common.util.UnstableApi
import androidx.recyclerview.widget.GridLayoutManager
import com.google.android.material.dialog.MaterialAlertDialogBuilder
@@ -95,7 +93,7 @@ class TagSettingsDialog : DialogFragment() {
super.onDestroyView()
}
- @OptIn(UnstableApi::class) private fun updatePreferencesTags(commonTags: Set) {
+ private fun updatePreferencesTags(commonTags: Set) {
for (i in 0..feedList.size-1) {
val f = feedList[i]
Logd(TAG, "${f.title} $displayedTags")
diff --git a/app/src/main/kotlin/ac/mdiq/podcini/ui/dialog/VariableSpeedDialog.kt b/app/src/main/kotlin/ac/mdiq/podcini/ui/dialog/VariableSpeedDialog.kt
index b0685f9c..595fc7b4 100644
--- a/app/src/main/kotlin/ac/mdiq/podcini/ui/dialog/VariableSpeedDialog.kt
+++ b/app/src/main/kotlin/ac/mdiq/podcini/ui/dialog/VariableSpeedDialog.kt
@@ -1,6 +1,7 @@
package ac.mdiq.podcini.ui.dialog
//import ac.mdiq.podcini.preferences.UserPreferences.videoPlaybackSpeed
+
import ac.mdiq.podcini.R
import ac.mdiq.podcini.databinding.SpeedSelectDialogBinding
import ac.mdiq.podcini.playback.base.InTheatre.curEpisode
@@ -26,9 +27,7 @@ import android.view.LayoutInflater
import android.view.View
import android.view.ViewGroup
import android.widget.CompoundButton
-import androidx.annotation.OptIn
import androidx.lifecycle.lifecycleScope
-import androidx.media3.common.util.UnstableApi
import androidx.recyclerview.widget.GridLayoutManager
import androidx.recyclerview.widget.RecyclerView
import com.google.android.material.bottomsheet.BottomSheetDialogFragment
@@ -43,7 +42,7 @@ import java.text.DecimalFormat
import java.text.DecimalFormatSymbols
import java.util.*
-@OptIn(UnstableApi::class)
+
open class VariableSpeedDialog : BottomSheetDialogFragment() {
private var _binding: SpeedSelectDialogBinding? = null
private val binding get() = _binding!!
@@ -60,7 +59,7 @@ open class VariableSpeedDialog : BottomSheetDialogFragment() {
selectedSpeeds = ArrayList(playbackSpeedArray)
}
- @UnstableApi override fun onStart() {
+ override fun onStart() {
super.onStart()
Logd(TAG, "onStart: playbackService ready: ${playbackService?.isServiceReady()}")
@@ -75,7 +74,7 @@ open class VariableSpeedDialog : BottomSheetDialogFragment() {
updateSpeed(FlowEvent.SpeedChangedEvent(curSpeedFB))
}
- @UnstableApi override fun onStop() {
+ override fun onStop() {
super.onStop()
cancelFlowEvents()
}
@@ -102,7 +101,7 @@ open class VariableSpeedDialog : BottomSheetDialogFragment() {
addCurrentSpeedChip.text = String.format(Locale.getDefault(), "%1$.2f", event.newSpeed)
}
- @UnstableApi override fun onCreateView(inflater: LayoutInflater, container: ViewGroup?, savedInstanceState: Bundle?): View? {
+ override fun onCreateView(inflater: LayoutInflater, container: ViewGroup?, savedInstanceState: Bundle?): View? {
_binding = SpeedSelectDialogBinding.inflate(inflater)
settingCode = (arguments?.getBooleanArray("settingCode") ?: BooleanArray(3) {true})
@@ -144,7 +143,7 @@ open class VariableSpeedDialog : BottomSheetDialogFragment() {
return binding.root
}
- @OptIn(UnstableApi::class) override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
+ override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
super.onViewCreated(view, savedInstanceState)
if (playbackService?.isServiceReady() == false) {
binding.currentAudio.visibility = View.INVISIBLE
@@ -210,7 +209,7 @@ open class VariableSpeedDialog : BottomSheetDialogFragment() {
return ViewHolder(chip)
}
- @UnstableApi override fun onBindViewHolder(holder: ViewHolder, position: Int) {
+ override fun onBindViewHolder(holder: ViewHolder, position: Int) {
val speed = selectedSpeeds[position]
holder.chip.text = String.format(Locale.getDefault(), "%1$.2f", speed)
diff --git a/app/src/main/kotlin/ac/mdiq/podcini/ui/fragment/AllEpisodesFragment.kt b/app/src/main/kotlin/ac/mdiq/podcini/ui/fragment/AllEpisodesFragment.kt
index 2e8613c8..ffb1b7b0 100644
--- a/app/src/main/kotlin/ac/mdiq/podcini/ui/fragment/AllEpisodesFragment.kt
+++ b/app/src/main/kotlin/ac/mdiq/podcini/ui/fragment/AllEpisodesFragment.kt
@@ -19,19 +19,17 @@ import android.view.LayoutInflater
import android.view.MenuItem
import android.view.View
import android.view.ViewGroup
-import androidx.annotation.OptIn
import androidx.lifecycle.lifecycleScope
-import androidx.media3.common.util.UnstableApi
import kotlinx.coroutines.Job
import kotlinx.coroutines.flow.collectLatest
import kotlinx.coroutines.launch
import org.apache.commons.lang3.StringUtils
-@UnstableApi
+
class AllEpisodesFragment : BaseEpisodesFragment() {
private var allEpisodes: List = listOf()
- @UnstableApi override fun onCreateView(inflater: LayoutInflater, container: ViewGroup?, savedInstanceState: Bundle?): View {
+ override fun onCreateView(inflater: LayoutInflater, container: ViewGroup?, savedInstanceState: Bundle?): View {
val root = super.onCreateView(inflater, container, savedInstanceState)
Logd(TAG, "fragment onCreateView")
@@ -85,7 +83,7 @@ class AllEpisodesFragment : BaseEpisodesFragment() {
return PREF_NAME
}
- @OptIn(UnstableApi::class) override fun onMenuItemClick(item: MenuItem): Boolean {
+ override fun onMenuItemClick(item: MenuItem): Boolean {
if (super.onOptionsItemSelected(item)) return true
when (item.itemId) {
diff --git a/app/src/main/kotlin/ac/mdiq/podcini/ui/fragment/AudioPlayerFragment.kt b/app/src/main/kotlin/ac/mdiq/podcini/ui/fragment/AudioPlayerFragment.kt
index bac26485..712a96cc 100644
--- a/app/src/main/kotlin/ac/mdiq/podcini/ui/fragment/AudioPlayerFragment.kt
+++ b/app/src/main/kotlin/ac/mdiq/podcini/ui/fragment/AudioPlayerFragment.kt
@@ -80,7 +80,7 @@ import androidx.core.content.ContextCompat
import androidx.core.text.HtmlCompat
import androidx.fragment.app.Fragment
import androidx.lifecycle.lifecycleScope
-import androidx.media3.common.util.UnstableApi
+
import androidx.media3.session.MediaController
import coil.compose.AsyncImage
import coil.request.CachePolicy
@@ -95,7 +95,7 @@ import java.text.DecimalFormat
import java.text.NumberFormat
import kotlin.math.max
-@UnstableApi
+
class AudioPlayerFragment : Fragment() {
private var isCollapsed by mutableStateOf(true)
@@ -556,8 +556,7 @@ class AudioPlayerFragment : Fragment() {
txtvPlaybackSpeed = speedStr
}
- @UnstableApi
- fun onPositionUpdate(event: FlowEvent.PlaybackPositionEvent) {
+ private fun onPositionUpdate(event: FlowEvent.PlaybackPositionEvent) {
Logd(TAG, "onPositionUpdate")
if (!playButInit && playButRes == R.drawable.ic_play_48dp && curMedia is EpisodeMedia) {
if (isCurrentlyPlaying(curMedia as? EpisodeMedia)) playButRes = R.drawable.ic_pause
@@ -588,8 +587,8 @@ class AudioPlayerFragment : Fragment() {
}
}
- @UnstableApi
- fun updateUi(media: Playable) {
+
+ private fun updateUi(media: Playable) {
Logd(TAG, "updateUi called $media")
titleText = media.getEpisodeTitle()
txtvPlaybackSpeed = DecimalFormat("0.00").format(curSpeedFB.toDouble())
@@ -726,7 +725,7 @@ class AudioPlayerFragment : Fragment() {
Logd(TAG, "displayCoverImage: imgLoc: $imgLoc")
}
- @UnstableApi private fun seekToPrevChapter() {
+ private fun seekToPrevChapter() {
val curr: Chapter? = currentChapter
if (curr == null || displayedChapterIndex == -1) return
when {
@@ -739,13 +738,13 @@ class AudioPlayerFragment : Fragment() {
}
}
- @UnstableApi private fun seekToNextChapter() {
+ private fun seekToNextChapter() {
if (currentMedia == null || currentMedia!!.getChapters().isEmpty() || displayedChapterIndex == -1 || displayedChapterIndex + 1 >= currentMedia!!.getChapters().size) return
refreshChapterData(displayedChapterIndex + 1)
seekTo(currentMedia!!.getChapters()[displayedChapterIndex].start.toInt())
}
- @UnstableApi private fun savePreference() {
+ private fun savePreference() {
Logd(TAG, "Saving preferences")
val editor = prefs?.edit() ?: return
if (curMedia != null) {
@@ -898,7 +897,7 @@ class AudioPlayerFragment : Fragment() {
cancelFlowEvents()
}
- @UnstableApi override fun onPause() {
+ override fun onPause() {
super.onPause()
savePreference()
}
diff --git a/app/src/main/kotlin/ac/mdiq/podcini/ui/fragment/BaseEpisodesFragment.kt b/app/src/main/kotlin/ac/mdiq/podcini/ui/fragment/BaseEpisodesFragment.kt
index fe2d05b6..70dd41d5 100644
--- a/app/src/main/kotlin/ac/mdiq/podcini/ui/fragment/BaseEpisodesFragment.kt
+++ b/app/src/main/kotlin/ac/mdiq/podcini/ui/fragment/BaseEpisodesFragment.kt
@@ -26,7 +26,7 @@ import androidx.compose.runtime.setValue
import androidx.core.util.Pair
import androidx.fragment.app.Fragment
import androidx.lifecycle.lifecycleScope
-import androidx.media3.common.util.UnstableApi
+
import com.google.android.material.appbar.MaterialToolbar
import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.Job
@@ -35,7 +35,7 @@ import kotlinx.coroutines.launch
import kotlinx.coroutines.withContext
-@UnstableApi
+
abstract class BaseEpisodesFragment : Fragment(), Toolbar.OnMenuItemClickListener {
val TAG = this::class.simpleName ?: "Anonymous"
@@ -57,7 +57,7 @@ abstract class BaseEpisodesFragment : Fragment(), Toolbar.OnMenuItemClickListene
private val vms = mutableStateListOf()
var showFilterDialog by mutableStateOf(false)
- @UnstableApi override fun onCreateView(inflater: LayoutInflater, container: ViewGroup?, savedInstanceState: Bundle?): View {
+ override fun onCreateView(inflater: LayoutInflater, container: ViewGroup?, savedInstanceState: Bundle?): View {
super.onCreateView(inflater, container, savedInstanceState)
_binding = ComposeFragmentBinding.inflate(inflater)
@@ -130,7 +130,7 @@ abstract class BaseEpisodesFragment : Fragment(), Toolbar.OnMenuItemClickListene
// }
@Deprecated("Deprecated in Java")
- @UnstableApi override fun onOptionsItemSelected(item: MenuItem): Boolean {
+ override fun onOptionsItemSelected(item: MenuItem): Boolean {
if (super.onOptionsItemSelected(item)) return true
val itemId = item.itemId
when (itemId) {
diff --git a/app/src/main/kotlin/ac/mdiq/podcini/ui/fragment/DownloadsFragment.kt b/app/src/main/kotlin/ac/mdiq/podcini/ui/fragment/DownloadsFragment.kt
index bfdbae10..cd76f73a 100644
--- a/app/src/main/kotlin/ac/mdiq/podcini/ui/fragment/DownloadsFragment.kt
+++ b/app/src/main/kotlin/ac/mdiq/podcini/ui/fragment/DownloadsFragment.kt
@@ -41,7 +41,7 @@ import androidx.compose.runtime.mutableStateOf
import androidx.compose.runtime.setValue
import androidx.fragment.app.Fragment
import androidx.lifecycle.lifecycleScope
-import androidx.media3.common.util.UnstableApi
+
import com.google.android.material.appbar.MaterialToolbar
import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.Job
@@ -55,7 +55,7 @@ import java.util.*
/**
* Displays all completed downloads and provides a button to delete them.
*/
-@UnstableApi class DownloadsFragment : Fragment(), Toolbar.OnMenuItemClickListener {
+ class DownloadsFragment : Fragment(), Toolbar.OnMenuItemClickListener {
private var _binding: ComposeFragmentBinding? = null
private val binding get() = _binding!!
@@ -74,7 +74,7 @@ import java.util.*
private var displayUpArrow = false
- @UnstableApi override fun onCreateView(inflater: LayoutInflater, container: ViewGroup?, savedInstanceState: Bundle?): View {
+ override fun onCreateView(inflater: LayoutInflater, container: ViewGroup?, savedInstanceState: Bundle?): View {
_binding = ComposeFragmentBinding.inflate(inflater)
Logd(TAG, "fragment onCreateView")
@@ -163,7 +163,7 @@ import java.util.*
super.onDestroyView()
}
- @UnstableApi override fun onMenuItemClick(item: MenuItem): Boolean {
+ override fun onMenuItemClick(item: MenuItem): Boolean {
when (item.itemId) {
R.id.filter_items -> {
showFilterDialog = true
diff --git a/app/src/main/kotlin/ac/mdiq/podcini/ui/fragment/EpisodeInfoFragment.kt b/app/src/main/kotlin/ac/mdiq/podcini/ui/fragment/EpisodeInfoFragment.kt
index 20a0eb37..865ba6ed 100644
--- a/app/src/main/kotlin/ac/mdiq/podcini/ui/fragment/EpisodeInfoFragment.kt
+++ b/app/src/main/kotlin/ac/mdiq/podcini/ui/fragment/EpisodeInfoFragment.kt
@@ -46,7 +46,6 @@ import android.webkit.WebViewClient
import android.widget.Button
import android.widget.TextView
import android.widget.Toast
-import androidx.annotation.OptIn
import androidx.appcompat.widget.Toolbar
import androidx.compose.foundation.background
import androidx.compose.foundation.clickable
@@ -74,7 +73,6 @@ import androidx.core.view.MenuProvider
import androidx.fragment.app.Fragment
import androidx.lifecycle.Lifecycle
import androidx.lifecycle.lifecycleScope
-import androidx.media3.common.util.UnstableApi
import coil.compose.AsyncImage
import com.google.android.material.appbar.MaterialToolbar
import com.google.android.material.snackbar.Snackbar
@@ -95,7 +93,6 @@ import java.util.*
/**
* Displays information about an Episode (FeedItem) and actions.
*/
-@UnstableApi
class EpisodeInfoFragment : Fragment(), Toolbar.OnMenuItemClickListener {
private var _binding: ComposeFragmentBinding? = null
private val binding get() = _binding!!
@@ -125,7 +122,7 @@ class EpisodeInfoFragment : Fragment(), Toolbar.OnMenuItemClickListener {
private var actionButton1 by mutableStateOf(null)
private var actionButton2 by mutableStateOf(null)
- @UnstableApi
+
override fun onCreateView(inflater: LayoutInflater, container: ViewGroup?, savedInstanceState: Bundle?): View {
super.onCreateView(inflater, container, savedInstanceState)
@@ -307,7 +304,7 @@ class EpisodeInfoFragment : Fragment(), Toolbar.OnMenuItemClickListener {
cancelFlowEvents()
}
- @OptIn(UnstableApi::class)
+
private fun showOnDemandConfigBalloon(offerStreaming: Boolean) {
val isLocaleRtl = (TextUtils.getLayoutDirectionFromLocale(Locale.getDefault()) == View.LAYOUT_DIRECTION_RTL)
val balloon: Balloon = Balloon.Builder(requireContext())
@@ -344,7 +341,7 @@ class EpisodeInfoFragment : Fragment(), Toolbar.OnMenuItemClickListener {
// balloon.showAlignBottom(butAction1, 0, (-12 * resources.displayMetrics.density).toInt())
}
- @UnstableApi
+
override fun onMenuItemClick(menuItem: MenuItem): Boolean {
when (menuItem.itemId) {
R.id.share_notes -> {
@@ -383,7 +380,7 @@ class EpisodeInfoFragment : Fragment(), Toolbar.OnMenuItemClickListener {
}
}
- @UnstableApi
+
override fun onResume() {
super.onResume()
if (itemLoaded) {
@@ -392,7 +389,7 @@ class EpisodeInfoFragment : Fragment(), Toolbar.OnMenuItemClickListener {
}
}
- @OptIn(UnstableApi::class) override fun onDestroyView() {
+ override fun onDestroyView() {
Logd(TAG, "onDestroyView")
episode = null
// webvDescription.clearHistory()
@@ -403,7 +400,7 @@ class EpisodeInfoFragment : Fragment(), Toolbar.OnMenuItemClickListener {
super.onDestroyView()
}
- @UnstableApi
+
private fun onFragmentLoaded() {
// if (!itemLoaded)
// webvDescription.loadDataWithBaseURL("https://127.0.0.1", webviewData, "text/html", "utf-8", "about:blank")
@@ -417,7 +414,7 @@ class EpisodeInfoFragment : Fragment(), Toolbar.OnMenuItemClickListener {
// else EpisodeMenuHandler.onPrepareMenu(toolbar.menu, episode, R.id.open_podcast, R.id.mark_read_item, R.id.visit_website_item)
// }
- @UnstableApi
+
private fun updateAppearance() {
if (episode == null) {
Logd(TAG, "updateAppearance item is null")
@@ -453,7 +450,7 @@ class EpisodeInfoFragment : Fragment(), Toolbar.OnMenuItemClickListener {
updateButtons()
}
- @UnstableApi
+
private fun updateButtons() {
// binding.circularProgressBar.visibility = View.GONE
val dls = DownloadServiceInterface.get()
@@ -503,7 +500,7 @@ class EpisodeInfoFragment : Fragment(), Toolbar.OnMenuItemClickListener {
// return webvDescription.onContextItemSelected(item)
// }
- @OptIn(UnstableApi::class) private fun openPodcast() {
+ private fun openPodcast() {
if (episode?.feedId == null) return
val fragment: Fragment = FeedEpisodesFragment.newInstance(episode!!.feedId!!)
@@ -585,7 +582,7 @@ class EpisodeInfoFragment : Fragment(), Toolbar.OnMenuItemClickListener {
}
private var loadItemsRunning = false
- @UnstableApi
+
private fun load() {
// if (!itemLoaded) binding.progbarLoading.visibility = View.VISIBLE
Logd(TAG, "load() called")
@@ -654,7 +651,7 @@ class EpisodeInfoFragment : Fragment(), Toolbar.OnMenuItemClickListener {
private var tts: TextToSpeech? = null
private var ttsReady = false
- @UnstableApi
+
override fun onCreateView(inflater: LayoutInflater, container: ViewGroup?, savedInstanceState: Bundle?): View {
super.onCreateView(inflater, container, savedInstanceState)
_binding = EpisodeHomeFragmentBinding.inflate(inflater, container, false)
@@ -681,13 +678,13 @@ class EpisodeInfoFragment : Fragment(), Toolbar.OnMenuItemClickListener {
return binding.root
}
- @OptIn(UnstableApi::class) private fun switchMode() {
+ private fun switchMode() {
readMode = !readMode
showContent()
updateAppearance()
}
- @OptIn(UnstableApi::class) private fun showReaderContent() {
+ private fun showReaderContent() {
runOnIOScope {
if (!episode?.link.isNullOrEmpty()) {
if (cleanedNotes == null) {
@@ -789,7 +786,7 @@ class EpisodeInfoFragment : Fragment(), Toolbar.OnMenuItemClickListener {
onPrepareMenu(menu)
}
- @OptIn(UnstableApi::class) override fun onMenuItemSelected(menuItem: MenuItem): Boolean {
+ override fun onMenuItemSelected(menuItem: MenuItem): Boolean {
when (menuItem.itemId) {
R.id.switch_home -> {
switchMode()
@@ -843,7 +840,7 @@ class EpisodeInfoFragment : Fragment(), Toolbar.OnMenuItemClickListener {
}
}
- @UnstableApi
+
override fun onResume() {
super.onResume()
updateAppearance()
@@ -857,7 +854,7 @@ class EpisodeInfoFragment : Fragment(), Toolbar.OnMenuItemClickListener {
webview.destroy()
}
- @OptIn(UnstableApi::class) override fun onDestroyView() {
+ override fun onDestroyView() {
Logd(TAG, "onDestroyView")
cleatWebview(binding.webView)
cleatWebview(binding.readerView)
@@ -868,7 +865,7 @@ class EpisodeInfoFragment : Fragment(), Toolbar.OnMenuItemClickListener {
super.onDestroyView()
}
- @UnstableApi
+
private fun updateAppearance() {
if (episode == null) {
Logd(TAG, "updateAppearance currentItem is null")
diff --git a/app/src/main/kotlin/ac/mdiq/podcini/ui/fragment/FeedEpisodesFragment.kt b/app/src/main/kotlin/ac/mdiq/podcini/ui/fragment/FeedEpisodesFragment.kt
index ddd65c73..abc27526 100644
--- a/app/src/main/kotlin/ac/mdiq/podcini/ui/fragment/FeedEpisodesFragment.kt
+++ b/app/src/main/kotlin/ac/mdiq/podcini/ui/fragment/FeedEpisodesFragment.kt
@@ -56,7 +56,7 @@ import androidx.constraintlayout.compose.ConstraintLayout
import androidx.constraintlayout.compose.Dimension
import androidx.fragment.app.Fragment
import androidx.lifecycle.lifecycleScope
-import androidx.media3.common.util.UnstableApi
+
import coil.compose.AsyncImage
import com.google.android.material.bottomsheet.BottomSheetBehavior
import kotlinx.coroutines.*
@@ -69,7 +69,7 @@ import java.util.concurrent.Semaphore
/**
* Displays a list of FeedItems.
*/
-@UnstableApi class FeedEpisodesFragment : Fragment(), Toolbar.OnMenuItemClickListener {
+ class FeedEpisodesFragment : Fragment(), Toolbar.OnMenuItemClickListener {
private var _binding: ComposeFragmentBinding? = null
private val binding get() = _binding!!
@@ -110,7 +110,7 @@ import java.util.concurrent.Semaphore
if (args != null) feedID = args.getLong(ARGUMENT_FEED_ID)
}
- @UnstableApi override fun onCreateView(inflater: LayoutInflater, container: ViewGroup?, savedInstanceState: Bundle?): View {
+ override fun onCreateView(inflater: LayoutInflater, container: ViewGroup?, savedInstanceState: Bundle?): View {
Logd(TAG, "fragment onCreateView")
_binding = ComposeFragmentBinding.inflate(inflater)
@@ -178,7 +178,10 @@ import java.util.concurrent.Semaphore
Logd(TAG, "persist Episode Filter(): feedId = [${feed?.id}], filterValues = [$filterValues]")
runOnIOScope {
val feed_ = realm.query(Feed::class, "id == ${feed!!.id}").first().find()
- if (feed_ != null) upsert(feed_) { it.preferences?.filterString = filterValues.joinToString() }
+ if (feed_ != null) {
+ upsert(feed_) { it.preferences?.filterString = filterValues.joinToString() }
+ loadFeed()
+ }
}
}
}
@@ -367,7 +370,7 @@ import java.util.concurrent.Semaphore
super.onDestroyView()
}
-// @UnstableApi
+//
// private fun refreshPosCallback(pos: Int, episode: Episode) {
// Logd(TAG, "FeedEpisode refreshPosCallback: $pos ${episode.title}")
//// if (pos >= 0 && pos < episodes.size) episodes[pos] = episode
@@ -396,7 +399,7 @@ import java.util.concurrent.Semaphore
//// horizontalSpacing, binding.header.headerContainer.paddingBottom)
// }
- @UnstableApi override fun onMenuItemClick(item: MenuItem): Boolean {
+ override fun onMenuItemClick(item: MenuItem): Boolean {
if (feed == null) {
(activity as MainActivity).showSnackbarAbovePlayer(R.string.please_wait_for_data, Toast.LENGTH_LONG)
return true
@@ -547,7 +550,7 @@ import java.util.concurrent.Semaphore
rightActionState.value = swipeActions.actions.right[0]
}
- @UnstableApi private fun refreshHeaderView() {
+ private fun refreshHeaderView() {
setupHeaderView()
if (feed == null) {
Log.e(TAG, "Unable to refresh header view")
@@ -577,7 +580,7 @@ import java.util.concurrent.Semaphore
infoBarText.value = "$infoTextFiltered $infoTextUpdate"
}
- @UnstableApi private fun setupHeaderView() {
+ private fun setupHeaderView() {
if (feed == null || headerCreated) return
// binding.imgvBackground.colorFilter = LightingColorFilter(-0x99999a, 0x000000)
@@ -602,7 +605,7 @@ import java.util.concurrent.Semaphore
// }
// }
-// @UnstableApi private fun showFeedInfo() {
+// private fun showFeedInfo() {
// if (feed != null) {
// val fragment = FeedInfoFragment.newInstance(feed!!)
// (activity as MainActivity).loadChildFragment(fragment, TransitionEffect.SLIDE)
@@ -627,18 +630,7 @@ import java.util.concurrent.Semaphore
}
return false
}
-
-// private fun redoFilter(list: List? = null) {
-// if (enableFilter && !feed?.preferences?.filterString.isNullOrEmpty()) {
-// val episodes_ = list ?: episodes.toList()
-// episodes.clear()
-// episodes.addAll(episodes_.filter { feed!!.episodeFilter.matches(it) })
-// ieMap = episodes.withIndex().associate { (index, episode) -> episode.id to index }
-// ueMap = episodes.mapIndexedNotNull { index, episode -> episode.media?.downloadUrl?.let { it to index } }.toMap()
-// }
-// }
-
- @UnstableApi
+
private fun loadFeed() {
if (!loadItemsRunning) {
loadItemsRunning = true
@@ -650,6 +642,7 @@ import java.util.concurrent.Semaphore
Logd(TAG, "loadItems feed_.episodes.size: ${feed_.episodes.size}")
val etmp = mutableListOf()
if (enableFilter && !feed_.preferences?.filterString.isNullOrEmpty()) {
+ Logd(TAG, "episodeFilter: ${feed_.episodeFilter.queryString()}")
val episodes_ = realm.query(Episode::class).query("feedId == ${feed_.id}").query(feed_.episodeFilter.queryString()).find()
// val episodes_ = feed_.episodes.filter { feed_.episodeFilter.matches(it) }
etmp.addAll(episodes_)
@@ -719,7 +712,7 @@ import java.util.concurrent.Semaphore
}
// class FeedEpisodeFilterDialog(val feed: Feed?) : EpisodeFilterDialog() {
-// @OptIn(UnstableApi::class) override fun onFilterChanged(newFilterValues: Set) {
+// override fun onFilterChanged(newFilterValues: Set) {
// if (feed != null) {
// Logd(TAG, "persist Episode Filter(): feedId = [$feed.id], filterValues = [$newFilterValues]")
// runOnIOScope {
@@ -747,7 +740,7 @@ import java.util.concurrent.Semaphore
super.onAddItem(title, ascending, descending, ascendingIsDefault)
}
}
- @UnstableApi override fun onSelectionChanged() {
+ override fun onSelectionChanged() {
super.onSelectionChanged()
if (feed != null) {
Logd(TAG, "persist Episode SortOrder")
diff --git a/app/src/main/kotlin/ac/mdiq/podcini/ui/fragment/FeedInfoFragment.kt b/app/src/main/kotlin/ac/mdiq/podcini/ui/fragment/FeedInfoFragment.kt
index e5d43c08..05105775 100644
--- a/app/src/main/kotlin/ac/mdiq/podcini/ui/fragment/FeedInfoFragment.kt
+++ b/app/src/main/kotlin/ac/mdiq/podcini/ui/fragment/FeedInfoFragment.kt
@@ -70,7 +70,7 @@ import androidx.documentfile.provider.DocumentFile
import androidx.fragment.app.Fragment
import androidx.fragment.compose.AndroidFragment
import androidx.lifecycle.lifecycleScope
-import androidx.media3.common.util.UnstableApi
+
import coil.compose.AsyncImage
import com.google.android.material.appbar.MaterialToolbar
import com.google.android.material.dialog.MaterialAlertDialogBuilder
@@ -82,7 +82,7 @@ import java.lang.ref.WeakReference
import java.util.*
import java.util.concurrent.ExecutionException
-@UnstableApi
+
class FeedInfoFragment : Fragment(), Toolbar.OnMenuItemClickListener {
private var _binding: ComposeFragmentBinding? = null
private val binding get() = _binding!!
@@ -382,7 +382,7 @@ class FeedInfoFragment : Fragment(), Toolbar.OnMenuItemClickListener {
return true
}
- @UnstableApi private fun addLocalFolderResult(uri: Uri?) {
+ private fun addLocalFolderResult(uri: Uri?) {
if (uri == null) return
// reconnectLocalFolder(uri)
lifecycleScope.launch {
@@ -403,7 +403,7 @@ class FeedInfoFragment : Fragment(), Toolbar.OnMenuItemClickListener {
}
}
-// @UnstableApi private fun reconnectLocalFolder(uri: Uri) {
+// private fun reconnectLocalFolder(uri: Uri) {
// lifecycleScope.launch {
// try {
// withContext(Dispatchers.IO) {
@@ -450,7 +450,7 @@ class FeedInfoFragment : Fragment(), Toolbar.OnMenuItemClickListener {
}
}
- @UnstableApi
+
abstract class EditUrlSettingsDialog(activity: Activity, private val feed: Feed) {
val TAG = this::class.simpleName ?: "Anonymous"
private val activityRef = WeakReference(activity)
@@ -466,7 +466,7 @@ class FeedInfoFragment : Fragment(), Toolbar.OnMenuItemClickListener {
.setNegativeButton(R.string.cancel_label, null)
.show()
}
- @UnstableApi private fun onConfirmed(original: String, updated: String) {
+ private fun onConfirmed(original: String, updated: String) {
try {
runBlocking { updateFeedDownloadURL(original, updated).join() }
feed.downloadUrl = updated
@@ -474,7 +474,7 @@ class FeedInfoFragment : Fragment(), Toolbar.OnMenuItemClickListener {
} catch (e: ExecutionException) { throw RuntimeException(e)
} catch (e: InterruptedException) { throw RuntimeException(e) }
}
- @UnstableApi private fun showConfirmAlertDialog(url: String) {
+ private fun showConfirmAlertDialog(url: String) {
val activity = activityRef.get()
val alertDialog = MaterialAlertDialogBuilder(activity!!)
.setTitle(R.string.edit_url_menu)
diff --git a/app/src/main/kotlin/ac/mdiq/podcini/ui/fragment/FeedSettingsFragment.kt b/app/src/main/kotlin/ac/mdiq/podcini/ui/fragment/FeedSettingsFragment.kt
index 531e2349..a5ff3374 100644
--- a/app/src/main/kotlin/ac/mdiq/podcini/ui/fragment/FeedSettingsFragment.kt
+++ b/app/src/main/kotlin/ac/mdiq/podcini/ui/fragment/FeedSettingsFragment.kt
@@ -54,7 +54,7 @@ import androidx.compose.ui.text.input.KeyboardType
import androidx.compose.ui.unit.dp
import androidx.compose.ui.window.Dialog
import androidx.fragment.app.Fragment
-import androidx.media3.common.util.UnstableApi
+
import androidx.recyclerview.widget.GridLayoutManager
import com.google.android.material.dialog.MaterialAlertDialogBuilder
import java.util.*
@@ -344,7 +344,7 @@ class FeedSettingsFragment : Fragment() {
object : AutoDownloadFilterPrefDialog(requireContext(),
feed?.preferences!!.autoDownloadFilter!!,
1) {
- @UnstableApi
+
override fun onConfirmed(filter: FeedAutoDownloadFilter) {
feed = upsertBlk(feed!!) {
it.preferences?.autoDownloadFilter = filter
@@ -364,7 +364,7 @@ class FeedSettingsFragment : Fragment() {
object : AutoDownloadFilterPrefDialog(requireContext(),
feed?.preferences!!.autoDownloadFilter!!,
-1) {
- @UnstableApi
+
override fun onConfirmed(filter: FeedAutoDownloadFilter) {
feed = upsertBlk(feed!!) {
it.preferences?.autoDownloadFilter = filter
diff --git a/app/src/main/kotlin/ac/mdiq/podcini/ui/fragment/HistoryFragment.kt b/app/src/main/kotlin/ac/mdiq/podcini/ui/fragment/HistoryFragment.kt
index ca01e382..920bf9d2 100644
--- a/app/src/main/kotlin/ac/mdiq/podcini/ui/fragment/HistoryFragment.kt
+++ b/app/src/main/kotlin/ac/mdiq/podcini/ui/fragment/HistoryFragment.kt
@@ -20,16 +20,14 @@ import android.view.LayoutInflater
import android.view.MenuItem
import android.view.View
import android.view.ViewGroup
-import androidx.annotation.OptIn
import androidx.lifecycle.lifecycleScope
-import androidx.media3.common.util.UnstableApi
import kotlinx.coroutines.Job
import kotlinx.coroutines.flow.collectLatest
import kotlinx.coroutines.launch
import java.util.*
import kotlin.math.min
-@UnstableApi class HistoryFragment : BaseEpisodesFragment() {
+class HistoryFragment : BaseEpisodesFragment() {
private var sortOrder : EpisodeSortOrder = EpisodeSortOrder.PLAYED_DATE_NEW_OLD
private var startDate : Long = 0L
@@ -40,7 +38,7 @@ import kotlin.math.min
return TAG
}
- @UnstableApi override fun onCreateView(inflater: LayoutInflater, container: ViewGroup?, savedInstanceState: Bundle?): View {
+ override fun onCreateView(inflater: LayoutInflater, container: ViewGroup?, savedInstanceState: Bundle?): View {
val root = super.onCreateView(inflater, container, savedInstanceState)
Logd(TAG, "fragment onCreateView")
toolbar.inflateMenu(R.menu.playback_history)
@@ -83,7 +81,7 @@ import kotlin.math.min
super.onDestroyView()
}
- @OptIn(UnstableApi::class) override fun onMenuItemClick(item: MenuItem): Boolean {
+ override fun onMenuItemClick(item: MenuItem): Boolean {
if (super.onOptionsItemSelected(item)) return true
when (item.itemId) {
R.id.episodes_sort -> HistorySortDialog().show(childFragmentManager.beginTransaction(), "SortDialog")
diff --git a/app/src/main/kotlin/ac/mdiq/podcini/ui/fragment/OnlineFeedFragment.kt b/app/src/main/kotlin/ac/mdiq/podcini/ui/fragment/OnlineFeedFragment.kt
index 82de7a54..234417a5 100644
--- a/app/src/main/kotlin/ac/mdiq/podcini/ui/fragment/OnlineFeedFragment.kt
+++ b/app/src/main/kotlin/ac/mdiq/podcini/ui/fragment/OnlineFeedFragment.kt
@@ -39,7 +39,6 @@ import android.view.LayoutInflater
import android.view.MenuItem
import android.view.View
import android.view.ViewGroup
-import androidx.annotation.OptIn
import androidx.annotation.UiThread
import androidx.collection.ArrayMap
import androidx.compose.foundation.*
@@ -59,7 +58,6 @@ import androidx.compose.ui.unit.dp
import androidx.constraintlayout.compose.ConstraintLayout
import androidx.fragment.app.Fragment
import androidx.lifecycle.lifecycleScope
-import androidx.media3.common.util.UnstableApi
import coil.compose.AsyncImage
import com.google.android.material.dialog.MaterialAlertDialogBuilder
import com.google.android.material.snackbar.Snackbar
@@ -79,7 +77,7 @@ import kotlin.concurrent.Volatile
* If the feed cannot be downloaded or parsed, an error dialog will be displayed
* and the activity will finish as soon as the error dialog is closed.
*/
-@OptIn(UnstableApi::class)
+
class OnlineFeedFragment : Fragment() {
private var _binding: ComposeFragmentBinding? = null
private val binding get() = _binding!!
@@ -122,7 +120,7 @@ class OnlineFeedFragment : Fragment() {
private var dialog: Dialog? = null
- @OptIn(UnstableApi::class) override fun onCreateView(inflater: LayoutInflater, container: ViewGroup?, savedInstanceState: Bundle?): View {
+ override fun onCreateView(inflater: LayoutInflater, container: ViewGroup?, savedInstanceState: Bundle?): View {
Logd(TAG, "fragment onCreateView")
_binding = ComposeFragmentBinding.inflate(layoutInflater)
displayUpArrow = parentFragmentManager.backStackEntryCount != 0
@@ -176,7 +174,7 @@ class OnlineFeedFragment : Fragment() {
super.onDestroy()
}
- @OptIn(UnstableApi::class) override fun onSaveInstanceState(outState: Bundle) {
+ override fun onSaveInstanceState(outState: Bundle) {
outState.putBoolean(KEY_UP_ARROW, displayUpArrow)
super.onSaveInstanceState(outState)
outState.putString("username", username)
@@ -267,7 +265,7 @@ class OnlineFeedFragment : Fragment() {
eventStickySink?.cancel()
eventStickySink = null
}
- @OptIn(UnstableApi::class) private fun procFlowEvents() {
+ private fun procFlowEvents() {
if (eventSink == null) eventSink = lifecycleScope.launch {
EventFlow.events.collectLatest { event ->
Logd(TAG, "Received event: ${event.TAG}")
@@ -307,7 +305,7 @@ class OnlineFeedFragment : Fragment() {
* Called when feed parsed successfully.
* This method is executed on the GUI thread.
*/
- @UnstableApi private fun showFeedInformation(feed: Feed, alternateFeedUrls: Map) {
+ private fun showFeedInformation(feed: Feed, alternateFeedUrls: Map) {
showProgress = false
// binding.feedDisplayContainer.visibility = View.VISIBLE
showFeedDisplay = true
@@ -480,7 +478,7 @@ class OnlineFeedFragment : Fragment() {
}
}
- @UnstableApi private fun showEpisodes(episodes: MutableList) {
+ private fun showEpisodes(episodes: MutableList) {
Logd(TAG, "showEpisodes ${episodes.size}")
if (episodes.isEmpty()) return
episodes.sortByDescending { it.pubDate }
@@ -494,7 +492,7 @@ class OnlineFeedFragment : Fragment() {
(activity as MainActivity).loadChildFragment(fragment)
}
- @UnstableApi private fun handleUpdatedFeedStatus() {
+ private fun handleUpdatedFeedStatus() {
val dli = DownloadServiceInterface.get()
if (dli == null || selectedDownloadUrl == null) return
@@ -708,11 +706,11 @@ class OnlineFeedFragment : Fragment() {
}
}
- @UnstableApi
+
class RemoteEpisodesFragment : BaseEpisodesFragment() {
private val episodeList: MutableList = mutableListOf()
- @UnstableApi override fun onCreateView(inflater: LayoutInflater, container: ViewGroup?, savedInstanceState: Bundle?): View {
+ override fun onCreateView(inflater: LayoutInflater, container: ViewGroup?, savedInstanceState: Bundle?): View {
val root = super.onCreateView(inflater, container, savedInstanceState)
Logd(TAG, "fragment onCreateView")
toolbar.inflateMenu(R.menu.episodes)
@@ -746,7 +744,7 @@ class OnlineFeedFragment : Fragment() {
binding.toolbar.menu.findItem(R.id.filter_items).setVisible(false)
infoBarText.value = "${episodes.size} episodes"
}
- @OptIn(UnstableApi::class) override fun onMenuItemClick(item: MenuItem): Boolean {
+ override fun onMenuItemClick(item: MenuItem): Boolean {
if (super.onOptionsItemSelected(item)) return true
when (item.itemId) {
else -> return false
diff --git a/app/src/main/kotlin/ac/mdiq/podcini/ui/fragment/OnlineSearchFragment.kt b/app/src/main/kotlin/ac/mdiq/podcini/ui/fragment/OnlineSearchFragment.kt
index 5a52dd8e..ce420eee 100644
--- a/app/src/main/kotlin/ac/mdiq/podcini/ui/fragment/OnlineSearchFragment.kt
+++ b/app/src/main/kotlin/ac/mdiq/podcini/ui/fragment/OnlineSearchFragment.kt
@@ -28,7 +28,7 @@ import androidx.activity.result.contract.ActivityResultContracts
import androidx.appcompat.app.AlertDialog
import androidx.documentfile.provider.DocumentFile
import androidx.fragment.app.Fragment
-import androidx.media3.common.util.UnstableApi
+
import com.google.android.material.dialog.MaterialAlertDialogBuilder
import com.google.android.material.snackbar.Snackbar
import kotlinx.coroutines.CoroutineScope
@@ -39,7 +39,7 @@ import kotlinx.coroutines.withContext
/**
* Provides actions for adding new podcast subscriptions.
*/
-@UnstableApi
+
class OnlineSearchFragment : Fragment() {
private var _binding: AddfeedBinding? = null
@@ -163,7 +163,7 @@ class OnlineSearchFragment : Fragment() {
startActivity(intent)
}
- @UnstableApi private fun addLocalFolderResult(uri: Uri?) {
+ private fun addLocalFolderResult(uri: Uri?) {
if (uri == null) return
val scope = CoroutineScope(Dispatchers.Main)
scope.launch {
@@ -182,7 +182,7 @@ class OnlineSearchFragment : Fragment() {
}
}
- @UnstableApi private fun addLocalFolder(uri: Uri): Feed? {
+ private fun addLocalFolder(uri: Uri): Feed? {
requireActivity().contentResolver.takePersistableUriPermission(uri, Intent.FLAG_GRANT_READ_URI_PERMISSION or Intent.FLAG_GRANT_WRITE_URI_PERMISSION)
val documentFile = DocumentFile.fromTreeUri(requireContext(), uri)
requireNotNull(documentFile) { "Unable to retrieve document tree" }
diff --git a/app/src/main/kotlin/ac/mdiq/podcini/ui/fragment/QueuesFragment.kt b/app/src/main/kotlin/ac/mdiq/podcini/ui/fragment/QueuesFragment.kt
index 2cbfeb29..4e1e57d4 100644
--- a/app/src/main/kotlin/ac/mdiq/podcini/ui/fragment/QueuesFragment.kt
+++ b/app/src/main/kotlin/ac/mdiq/podcini/ui/fragment/QueuesFragment.kt
@@ -67,7 +67,7 @@ import androidx.compose.ui.unit.dp
import androidx.compose.ui.window.Dialog
import androidx.fragment.app.Fragment
import androidx.lifecycle.lifecycleScope
-import androidx.media3.common.util.UnstableApi
+
import androidx.media3.session.MediaBrowser
import androidx.media3.session.SessionToken
import com.google.android.material.appbar.MaterialToolbar
@@ -83,7 +83,7 @@ import kotlinx.coroutines.runBlocking
import java.util.*
import kotlin.math.max
-@UnstableApi class QueuesFragment : Fragment(), Toolbar.OnMenuItemClickListener {
+ class QueuesFragment : Fragment(), Toolbar.OnMenuItemClickListener {
private var _binding: ComposeFragmentBinding? = null
private val binding get() = _binding!!
@@ -125,7 +125,7 @@ import kotlin.math.max
retainInstance = true
}
- @UnstableApi override fun onCreateView(inflater: LayoutInflater, container: ViewGroup?, savedInstanceState: Bundle?): View {
+ override fun onCreateView(inflater: LayoutInflater, container: ViewGroup?, savedInstanceState: Bundle?): View {
super.onCreateView(inflater, container, savedInstanceState)
_binding = ComposeFragmentBinding.inflate(inflater)
@@ -448,7 +448,7 @@ import kotlin.math.max
}
}
- @UnstableApi override fun onMenuItemClick(item: MenuItem): Boolean {
+ override fun onMenuItemClick(item: MenuItem): Boolean {
val itemId = item.itemId
when (itemId) {
R.id.show_bin -> {
@@ -478,7 +478,7 @@ import kotlin.math.max
R.id.clear_queue -> {
// make sure the user really wants to clear the queue
val conDialog: ConfirmationDialog = object : ConfirmationDialog(requireContext(), R.string.clear_queue_label, R.string.clear_queue_confirmation_msg) {
- @UnstableApi override fun onConfirmButtonPressed(dialog: DialogInterface) {
+ override fun onConfirmButtonPressed(dialog: DialogInterface) {
dialog.dismiss()
clearQueue()
}
@@ -609,7 +609,7 @@ import kotlin.math.max
}
}
- @UnstableApi private fun toggleQueueLock() {
+ private fun toggleQueueLock() {
val isLocked: Boolean = isQueueLocked
if (isLocked) setQueueLock(false)
else {
@@ -635,7 +635,7 @@ import kotlin.math.max
}
}
- @UnstableApi private fun setQueueLock(locked: Boolean) {
+ private fun setQueueLock(locked: Boolean) {
isQueueLocked = locked
appPrefs.edit().putBoolean(UserPreferences.Prefs.prefQueueLocked.name, locked).apply()
dragDropEnabled = !(isQueueKeepSorted || isQueueLocked)
@@ -711,7 +711,7 @@ import kotlin.math.max
if (ascending != EpisodeSortOrder.EPISODE_FILENAME_A_Z && ascending != EpisodeSortOrder.SIZE_SMALL_LARGE)
super.onAddItem(title, ascending, descending, ascendingIsDefault)
}
- @UnstableApi override fun onSelectionChanged() {
+ override fun onSelectionChanged() {
super.onSelectionChanged()
binding.keepSortedCheckbox.setEnabled(sortOrder != EpisodeSortOrder.RANDOM)
if (sortOrder == EpisodeSortOrder.RANDOM) binding.keepSortedCheckbox.setChecked(false)
diff --git a/app/src/main/kotlin/ac/mdiq/podcini/ui/fragment/QuickDiscoveryFragment.kt b/app/src/main/kotlin/ac/mdiq/podcini/ui/fragment/QuickDiscoveryFragment.kt
index de1d35a6..7730ea8b 100644
--- a/app/src/main/kotlin/ac/mdiq/podcini/ui/fragment/QuickDiscoveryFragment.kt
+++ b/app/src/main/kotlin/ac/mdiq/podcini/ui/fragment/QuickDiscoveryFragment.kt
@@ -25,7 +25,6 @@ import android.view.MenuItem
import android.view.View
import android.view.ViewGroup
import android.widget.*
-import androidx.annotation.OptIn
import androidx.appcompat.widget.Toolbar
import androidx.compose.foundation.layout.Arrangement
import androidx.compose.foundation.layout.fillMaxSize
@@ -44,7 +43,6 @@ import androidx.compose.ui.unit.dp
import androidx.constraintlayout.compose.ConstraintLayout
import androidx.fragment.app.Fragment
import androidx.lifecycle.lifecycleScope
-import androidx.media3.common.util.UnstableApi
import coil.load
import com.google.android.material.appbar.MaterialToolbar
import com.google.android.material.dialog.MaterialAlertDialogBuilder
@@ -68,7 +66,7 @@ class QuickDiscoveryFragment : Fragment(), AdapterView.OnItemClickListener {
private lateinit var errorView: LinearLayout
private lateinit var errorRetry: Button
- @OptIn(UnstableApi::class) override fun onCreateView(inflater: LayoutInflater, container: ViewGroup?, savedInstanceState: Bundle?): View {
+ override fun onCreateView(inflater: LayoutInflater, container: ViewGroup?, savedInstanceState: Bundle?): View {
super.onCreateView(inflater, container, savedInstanceState)
_binding = QuickFeedDiscoveryBinding.inflate(inflater)
@@ -195,7 +193,7 @@ class QuickDiscoveryFragment : Fragment(), AdapterView.OnItemClickListener {
}
}
- @OptIn(UnstableApi::class) override fun onItemClick(parent: AdapterView<*>?, view: View, position: Int, id: Long) {
+ override fun onItemClick(parent: AdapterView<*>?, view: View, position: Int, id: Long) {
val podcast: PodcastSearchResult? = adapter.getItem(position)
if (podcast?.feedUrl.isNullOrEmpty()) return
@@ -294,7 +292,7 @@ class QuickDiscoveryFragment : Fragment(), AdapterView.OnItemClickListener {
needsConfirm = prefs!!.getBoolean(ItunesTopListLoader.PREF_KEY_NEEDS_CONFIRM, true)
}
- @OptIn(UnstableApi::class) override fun onCreateView(inflater: LayoutInflater, container: ViewGroup?, savedInstanceState: Bundle?): View {
+ override fun onCreateView(inflater: LayoutInflater, container: ViewGroup?, savedInstanceState: Bundle?): View {
// Inflate the layout for this fragment
_binding = ComposeFragmentBinding.inflate(inflater)
Logd(TAG, "fragment onCreateView")
diff --git a/app/src/main/kotlin/ac/mdiq/podcini/ui/fragment/SearchFragment.kt b/app/src/main/kotlin/ac/mdiq/podcini/ui/fragment/SearchFragment.kt
index be975542..8ae38f81 100644
--- a/app/src/main/kotlin/ac/mdiq/podcini/ui/fragment/SearchFragment.kt
+++ b/app/src/main/kotlin/ac/mdiq/podcini/ui/fragment/SearchFragment.kt
@@ -49,7 +49,7 @@ import androidx.compose.ui.unit.dp
import androidx.constraintlayout.compose.ConstraintLayout
import androidx.fragment.app.Fragment
import androidx.lifecycle.lifecycleScope
-import androidx.media3.common.util.UnstableApi
+
import coil.compose.AsyncImage
import coil.request.CachePolicy
import coil.request.ImageRequest
@@ -65,7 +65,7 @@ import java.text.NumberFormat
/**
* Performs a search operation on all feeds or one specific feed and displays the search result.
*/
-@UnstableApi
+
class SearchFragment : Fragment() {
private var _binding: SearchFragmentBinding? = null
private val binding get() = _binding!!
@@ -87,7 +87,7 @@ class SearchFragment : Fragment() {
automaticSearchDebouncer = Handler(Looper.getMainLooper())
}
- @UnstableApi override fun onCreateView(inflater: LayoutInflater, container: ViewGroup?, savedInstanceState: Bundle?): View {
+ override fun onCreateView(inflater: LayoutInflater, container: ViewGroup?, savedInstanceState: Bundle?): View {
_binding = SearchFragmentBinding.inflate(inflater)
Logd(TAG, "fragment onCreateView")
setupToolbar(binding.toolbar)
@@ -148,12 +148,12 @@ class SearchFragment : Fragment() {
searchView.setQuery(requireArguments().getString(ARG_QUERY), true)
searchView.requestFocus()
searchView.setOnQueryTextListener(object : SearchView.OnQueryTextListener {
- @UnstableApi override fun onQueryTextSubmit(s: String): Boolean {
+ override fun onQueryTextSubmit(s: String): Boolean {
searchView.clearFocus()
search()
return true
}
- @UnstableApi override fun onQueryTextChange(s: String): Boolean {
+ override fun onQueryTextChange(s: String): Boolean {
automaticSearchDebouncer.removeCallbacksAndMessages(null)
if (s.isEmpty() || s.endsWith(" ") || (lastQueryChange != 0L && System.currentTimeMillis() > lastQueryChange + SEARCH_DEBOUNCE_INTERVAL))
search()
@@ -233,7 +233,7 @@ class SearchFragment : Fragment() {
}
@SuppressLint("StringFormatMatches")
- @UnstableApi private fun search() {
+ private fun search() {
// adapterFeeds.setEndButton(R.string.search_online) { this.searchOnline() }
chip.visibility = if ((requireArguments().getLong(ARG_FEED, 0) == 0L)) View.GONE else View.VISIBLE
@@ -344,7 +344,7 @@ class SearchFragment : Fragment() {
}
}
- @UnstableApi private fun performSearch(): Pair, List> {
+ private fun performSearch(): Pair, List> {
val query = searchView.query.toString()
if (query.isEmpty()) return Pair, List>(emptyList(), emptyList())
@@ -433,7 +433,7 @@ class SearchFragment : Fragment() {
imm.showSoftInput(view, 0)
}
- @UnstableApi private fun searchOnline() {
+ private fun searchOnline() {
searchView.clearFocus()
val inVal = requireActivity().getSystemService(Context.INPUT_METHOD_SERVICE) as InputMethodManager
inVal.hideSoftInputFromWindow(searchView.windowToken, 0)
diff --git a/app/src/main/kotlin/ac/mdiq/podcini/ui/fragment/SearchResultsFragment.kt b/app/src/main/kotlin/ac/mdiq/podcini/ui/fragment/SearchResultsFragment.kt
index 2b494745..896b5f76 100644
--- a/app/src/main/kotlin/ac/mdiq/podcini/ui/fragment/SearchResultsFragment.kt
+++ b/app/src/main/kotlin/ac/mdiq/podcini/ui/fragment/SearchResultsFragment.kt
@@ -40,7 +40,7 @@ import androidx.compose.ui.unit.dp
import androidx.constraintlayout.compose.ConstraintLayout
import androidx.fragment.app.Fragment
import androidx.lifecycle.lifecycleScope
-import androidx.media3.common.util.UnstableApi
+
import com.google.android.material.appbar.MaterialToolbar
import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.launch
@@ -73,7 +73,7 @@ class SearchResultsFragment : Fragment() {
if (searchProvider == null) Logd(TAG,"Podcast searcher not found")
}
- @UnstableApi override fun onCreateView(inflater: LayoutInflater, container: ViewGroup?, savedInstanceState: Bundle?): View {
+ override fun onCreateView(inflater: LayoutInflater, container: ViewGroup?, savedInstanceState: Bundle?): View {
_binding = ComposeFragmentBinding.inflate(inflater)
Logd(TAG, "fragment onCreateView")
binding.mainView.setContent {
diff --git a/app/src/main/kotlin/ac/mdiq/podcini/ui/fragment/SubscriptionsFragment.kt b/app/src/main/kotlin/ac/mdiq/podcini/ui/fragment/SubscriptionsFragment.kt
index 366bc59c..d0e40cd0 100644
--- a/app/src/main/kotlin/ac/mdiq/podcini/ui/fragment/SubscriptionsFragment.kt
+++ b/app/src/main/kotlin/ac/mdiq/podcini/ui/fragment/SubscriptionsFragment.kt
@@ -17,6 +17,7 @@ import ac.mdiq.podcini.storage.database.Feeds.getTags
import ac.mdiq.podcini.storage.database.RealmDB.realm
import ac.mdiq.podcini.storage.database.RealmDB.runOnIOScope
import ac.mdiq.podcini.storage.database.RealmDB.upsert
+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.FeedAutoDeleteOptions
@@ -49,7 +50,6 @@ import android.widget.ArrayAdapter
import android.widget.CompoundButton
import androidx.activity.result.ActivityResult
import androidx.activity.result.contract.ActivityResultContracts
-import androidx.annotation.OptIn
import androidx.appcompat.widget.Toolbar
import androidx.compose.foundation.*
import androidx.compose.foundation.layout.*
@@ -88,7 +88,6 @@ import androidx.constraintlayout.compose.ConstraintLayout
import androidx.core.util.Consumer
import androidx.fragment.app.Fragment
import androidx.lifecycle.lifecycleScope
-import androidx.media3.common.util.UnstableApi
import coil.compose.AsyncImage
import coil.request.CachePolicy
import coil.request.ImageRequest
@@ -145,7 +144,7 @@ class SubscriptionsFragment : Fragment(), Toolbar.OnMenuItemClickListener {
retainInstance = true
}
- @UnstableApi override fun onCreateView(inflater: LayoutInflater, container: ViewGroup?, savedInstanceState: Bundle?): View {
+ override fun onCreateView(inflater: LayoutInflater, container: ViewGroup?, savedInstanceState: Bundle?): View {
_binding = FragmentSubscriptionsBinding.inflate(inflater)
Logd(TAG, "fragment onCreateView")
@@ -306,7 +305,7 @@ class SubscriptionsFragment : Fragment(), Toolbar.OnMenuItemClickListener {
}
}
- @UnstableApi override fun onMenuItemClick(item: MenuItem): Boolean {
+ override fun onMenuItemClick(item: MenuItem): Boolean {
val itemId = item.itemId
when (itemId) {
R.id.subscriptions_filter -> {
@@ -334,7 +333,6 @@ class SubscriptionsFragment : Fragment(), Toolbar.OnMenuItemClickListener {
}
private var loadItemsRunning = false
- @OptIn(UnstableApi::class)
private fun loadSubscriptions() {
// emptyView.hide()
if (!loadItemsRunning) {
@@ -653,7 +651,10 @@ class SubscriptionsFragment : Fragment(), Toolbar.OnMenuItemClickListener {
Column(modifier = Modifier.padding(16.dp), verticalArrangement = Arrangement.spacedBy(16.dp)) {
for (rating in Rating.entries.reversed()) {
Row(verticalAlignment = Alignment.CenterVertically, modifier = Modifier.padding(4.dp).clickable {
- for (item in selected) Feeds.setRating(item, rating.code)
+ for (item in selected) {
+// Feeds.setRating(item, rating.code)
+ upsertBlk(item) { it.rating = rating.code }
+ }
onDismissRequest()
}) {
Icon(imageVector = ImageVector.vectorResource(id = rating.res), "")
@@ -711,7 +712,7 @@ class SubscriptionsFragment : Fragment(), Toolbar.OnMenuItemClickListener {
selectMode = false
Logd(TAG, "ic_download: ${selected.size}")
val preferenceSwitchDialog = PreferenceSwitchDialog(activity, activity.getString(R.string.auto_download_settings_label), activity.getString(R.string.auto_download_label))
- preferenceSwitchDialog.setOnPreferenceChangedListener(@UnstableApi object: PreferenceSwitchDialog.OnPreferenceChangedListener {
+ preferenceSwitchDialog.setOnPreferenceChangedListener( object: PreferenceSwitchDialog.OnPreferenceChangedListener {
override fun preferenceChanged(enabled: Boolean) {
saveFeedPreferences { it: FeedPreferences -> it.autoDownload = enabled }
}
diff --git a/app/src/main/kotlin/ac/mdiq/podcini/ui/statistics/StatisticsFragment.kt b/app/src/main/kotlin/ac/mdiq/podcini/ui/statistics/StatisticsFragment.kt
index b547b772..6f3b4f50 100644
--- a/app/src/main/kotlin/ac/mdiq/podcini/ui/statistics/StatisticsFragment.kt
+++ b/app/src/main/kotlin/ac/mdiq/podcini/ui/statistics/StatisticsFragment.kt
@@ -8,15 +8,15 @@ import ac.mdiq.podcini.storage.database.RealmDB.realm
import ac.mdiq.podcini.storage.database.RealmDB.runOnIOScope
import ac.mdiq.podcini.storage.database.RealmDB.update
import ac.mdiq.podcini.storage.model.*
+import ac.mdiq.podcini.storage.utils.DurationConverter.shortLocalizedDuration
import ac.mdiq.podcini.ui.activity.MainActivity
import ac.mdiq.podcini.ui.activity.starter.MainActivityStarter
import ac.mdiq.podcini.ui.dialog.ConfirmationDialog
import ac.mdiq.podcini.ui.dialog.DatesFilterDialog
import ac.mdiq.podcini.ui.statistics.PieChartView.PieChartData
-import ac.mdiq.podcini.storage.utils.DurationConverter.shortLocalizedDuration
-import ac.mdiq.podcini.util.Logd
import ac.mdiq.podcini.util.EventFlow
import ac.mdiq.podcini.util.FlowEvent
+import ac.mdiq.podcini.util.Logd
import android.annotation.SuppressLint
import android.app.Dialog
import android.content.Context
@@ -30,11 +30,9 @@ import android.view.*
import android.widget.ImageView
import android.widget.ProgressBar
import android.widget.TextView
-import androidx.annotation.OptIn
import androidx.fragment.app.DialogFragment
import androidx.fragment.app.Fragment
import androidx.lifecycle.lifecycleScope
-import androidx.media3.common.util.UnstableApi
import androidx.recyclerview.widget.LinearLayoutManager
import androidx.recyclerview.widget.RecyclerView
import androidx.viewpager2.adapter.FragmentStateAdapter
@@ -64,7 +62,7 @@ class StatisticsFragment : Fragment() {
private var _binding: PagerFragmentBinding? = null
private val binding get() = _binding!!
- @OptIn(UnstableApi::class) override fun onCreateView(inflater: LayoutInflater, container: ViewGroup?, savedInstanceState: Bundle?): View {
+ override fun onCreateView(inflater: LayoutInflater, container: ViewGroup?, savedInstanceState: Bundle?): View {
super.onCreateView(inflater, container, savedInstanceState)
setHasOptionsMenu(true)
_binding = PagerFragmentBinding.inflate(inflater)
@@ -98,7 +96,7 @@ class StatisticsFragment : Fragment() {
}
@Deprecated("Deprecated in Java")
- @UnstableApi override fun onOptionsItemSelected(item: MenuItem): Boolean {
+ override fun onOptionsItemSelected(item: MenuItem): Boolean {
if (item.itemId == R.id.statistics_reset) {
confirmResetStatistics()
return true
@@ -133,7 +131,7 @@ class StatisticsFragment : Fragment() {
})
}
- @UnstableApi private fun confirmResetStatistics() {
+ private fun confirmResetStatistics() {
val conDialog: ConfirmationDialog = object : ConfirmationDialog(requireContext(),
R.string.statistics_reset_data, R.string.statistics_reset_data_msg) {
override fun onConfirmButtonPressed(dialog: DialogInterface) {
@@ -144,7 +142,7 @@ class StatisticsFragment : Fragment() {
conDialog.createNewDialog().show()
}
- @UnstableApi private fun doResetStatistics() {
+ private fun doResetStatistics() {
prefs!!.edit()
.putBoolean(PREF_INCLUDE_MARKED_PLAYED, false)
.putLong(PREF_FILTER_FROM, 0)
diff --git a/app/src/main/kotlin/ac/mdiq/podcini/ui/view/ShownotesWebView.kt b/app/src/main/kotlin/ac/mdiq/podcini/ui/view/ShownotesWebView.kt
index c6095b13..c2d57de2 100644
--- a/app/src/main/kotlin/ac/mdiq/podcini/ui/view/ShownotesWebView.kt
+++ b/app/src/main/kotlin/ac/mdiq/podcini/ui/view/ShownotesWebView.kt
@@ -25,7 +25,7 @@ import android.webkit.WebView
import android.webkit.WebViewClient
import androidx.core.content.ContextCompat
import androidx.core.util.Consumer
-import androidx.media3.common.util.UnstableApi
+
import com.google.android.material.snackbar.Snackbar
import kotlin.math.max
@@ -75,7 +75,7 @@ class ShownotesWebView : WebView, View.OnLongClickListener {
})
}
- @UnstableApi override fun onLongClick(v: View): Boolean {
+ override fun onLongClick(v: View): Boolean {
val r: HitTestResult = getHitTestResult()
when (r.type) {
HitTestResult.SRC_ANCHOR_TYPE -> {
diff --git a/app/src/main/kotlin/ac/mdiq/podcini/util/config/ClientConfigurator.kt b/app/src/main/kotlin/ac/mdiq/podcini/util/config/ClientConfigurator.kt
index 4b011c5a..b9c2c5b2 100644
--- a/app/src/main/kotlin/ac/mdiq/podcini/util/config/ClientConfigurator.kt
+++ b/app/src/main/kotlin/ac/mdiq/podcini/util/config/ClientConfigurator.kt
@@ -14,10 +14,10 @@ import ac.mdiq.podcini.preferences.UserPreferences
import ac.mdiq.podcini.preferences.UserPreferences.proxyConfig
import ac.mdiq.podcini.ui.utils.NotificationUtils
import android.content.Context
-import androidx.media3.common.util.UnstableApi
+
import java.io.File
-@UnstableApi
+
object ClientConfigurator {
private var initialized = false
diff --git a/app/src/main/res/drawable/baseline_comment_24.xml b/app/src/main/res/drawable/baseline_comment_24.xml
new file mode 100644
index 00000000..5972c48a
--- /dev/null
+++ b/app/src/main/res/drawable/baseline_comment_24.xml
@@ -0,0 +1,5 @@
+
+
+
+
+
diff --git a/app/src/main/res/values/strings.xml b/app/src/main/res/values/strings.xml
index 918dd22a..fd86cc38 100644
--- a/app/src/main/res/values/strings.xml
+++ b/app/src/main/res/values/strings.xml
@@ -273,6 +273,7 @@
JavaScript
No action
My opinion
+ Add opinion
Cancelled on
Set played state
diff --git a/changelog.md b/changelog.md
index ed25973e..afc9c50f 100644
--- a/changelog.md
+++ b/changelog.md
@@ -1,3 +1,13 @@
+# 6.13.3
+
+* on playing the next episode in queue, if its state is lower than InProgress, the state is set as such
+* added "add commment" in swipe actions
+* in FeedEpisodes, fixed incorrect ordering of episodes after filtering
+* when removing episode media, if remove-from-queue is set, the episode is removed from all queues rather than only the active queue
+* removed the @UnstableAPI annotations previously required for Media3
+* updated Contributing.md
+* various dependencies update
+
# 6.13.2
* replaced the setting of prefSmartMarkAsPlayedSecs by an adaptive internal val smartMarkAsPlayedPercent = 95
diff --git a/fastlane/metadata/android/en-US/changelogs/3020289.txt b/fastlane/metadata/android/en-US/changelogs/3020289.txt
index e7bd4062..fb1120d6 100644
--- a/fastlane/metadata/android/en-US/changelogs/3020289.txt
+++ b/fastlane/metadata/android/en-US/changelogs/3020289.txt
@@ -1,4 +1,4 @@
- Version 6.13.1
+ Version 6.13.2
* replaced the setting of prefSmartMarkAsPlayedSecs by an adaptive internal val smartMarkAsPlayedPercent = 95
* if the episode is played to over 95% of its duration, it's considered played
diff --git a/fastlane/metadata/android/en-US/changelogs/3020290.txt b/fastlane/metadata/android/en-US/changelogs/3020290.txt
new file mode 100644
index 00000000..7efe30b1
--- /dev/null
+++ b/fastlane/metadata/android/en-US/changelogs/3020290.txt
@@ -0,0 +1,9 @@
+ Version 6.13.3
+
+* on playing the next episode in queue, if its state is lower than InProgress, the state is set as such
+* added "add commment" in swipe actions
+* in FeedEpisodes, fixed incorrect ordering of episodes after filtering
+* when removing episode media, if remove-from-queue is set, the episode is removed from all queues rather than only the active queue
+* removed the @UnstableAPI annotations previously required for Media3
+* updated Contributing.md
+* various dependencies update
diff --git a/gradle/libs.versions.toml b/gradle/libs.versions.toml
index e590a954..b82895d2 100644
--- a/gradle/libs.versions.toml
+++ b/gradle/libs.versions.toml
@@ -1,18 +1,18 @@
[versions]
activityCompose = "1.9.3"
-annotation = "1.9.0"
+annotation = "1.9.1"
appcompat = "1.7.0"
#awaitility = "4.2.1"
balloon = "1.6.6"
coil = "2.7.0"
commonsLang3 = "3.15.0"
commonsIo = "2.16.1"
-composeBom = "2024.10.00"
+composeBom = "2024.10.01"
conscryptAndroid = "2.5.2"
-constraintlayoutCompose = "1.0.1"
+constraintlayoutCompose = "1.1.0"
coordinatorlayout = "1.2.0"
-coreKtx = "1.13.1"
+coreKtx = "1.15.0"
coreKtxVersion = "1.8.1"
coreSplashscreen = "1.0.1"
desugar_jdk_libs_nio = "2.1.2"
@@ -34,9 +34,9 @@ jsoup = "1.18.1"
kotlin = "2.0.20"
kotlinxCoroutinesAndroid = "1.8.1"
libraryBase = "2.1.0"
-lifecycleRuntimeKtx = "2.8.6"
+lifecycleRuntimeKtx = "2.8.7"
#material = "1.7.2"
-material3 = "1.3.0"
+material3 = "1.3.1"
#material3Android = "1.3.0"
#materialIconsExtended = "1.7.3"
materialVersion = "1.12.0"
@@ -66,16 +66,16 @@ rxjavaVersion = "3.1.8"
#speedDial = "3.3.0"
searchpreference = "v2.5.0"
stream = "1.2.2"
-uiToolingPreview = "1.7.4"
-uiTooling = "1.7.4"
+uiToolingPreview = "1.7.5"
+uiTooling = "1.7.5"
viewpager2 = "1.1.0"
vistaguide = "lv0.24.2.6"
wearable = "2.9.0"
webkit = "1.12.1"
window = "1.3.0"
-workRuntime = "2.9.1"
+workRuntime = "2.10.0"
#uiViewbinding = "1.7.2"
-fragmentCompose = "1.8.4"
+fragmentCompose = "1.8.5"
#fragment-ktx = "1.8.4"
[libraries]
androidx-activity-compose = { module = "androidx.activity:activity-compose", version.ref = "activityCompose" }
@@ -158,7 +158,7 @@ desugar_jdk_libs_nio = { module = "com.android.tools:desugar_jdk_libs_nio", vers
wearable = { module = "com.google.android.wearable:wearable", version.ref = "wearable" }
#androidx-ui-viewbinding = { group = "androidx.compose.ui", name = "ui-viewbinding", version.ref = "uiViewbinding" }
androidx-fragment-compose = { group = "androidx.fragment", name = "fragment-compose", version.ref = "fragmentCompose" }
-androidx-fragment-fragment-ktx = { module = "androidx.fragment:fragment-ktx", version = "1.8.4" }
+androidx-fragment-fragment-ktx = { module = "androidx.fragment:fragment-ktx", version = "1.8.5" }
[plugins]
org-jetbrains-kotlin-android = { id = "org.jetbrains.kotlin.android", version.ref = "kotlin" }