Skip to content

Commit

Permalink
6.1.0 commit
Browse files Browse the repository at this point in the history
  • Loading branch information
XilinJia committed Jul 18, 2024
1 parent f913362 commit 86cc7cf
Show file tree
Hide file tree
Showing 152 changed files with 1,949 additions and 1,516 deletions.
20 changes: 16 additions & 4 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -73,15 +73,15 @@ While podcast subscriptions' OPML files (from AntennaPod or any other sources) c
* operations are only on the selected (single or multiple)
* List info is shown in Queue and Downloads views
* Left and right swipe actions on lists now have telltales and can be configured on the spot
* Played episodes have clearer markings
* Played or new episodes have clearer markings
* Sort dialog no longer dims the main view
* download date can be used to sort both feeds and episodes
* Subscriptions sorting is now bi-directional based on various explicit measures
* in episode list view, if episode has no media, TTS button is shown for fetching transcript (if not exist) and then generating audio file from the transcript. TTS audio files are playable in the same way as local media (with speed setting, pause and rewind/forward)
* Long-press filter button in FeedEpisode view enables/disables filters without changing filter settings
* Subscriptions view has various explicit measures for sorting
* subscriptions sorting is now bi-directional
* in Subscriptions view, click on cover image of a feed opens the FeedInfo view (not FeedEpisodes view)
* History view shows time of last play, and allows filters and sorts
* 5 queues are provided by default: Default queue, and Queues 1-4
* Multiple queues can be used: 5 queues are provided by default: Default queue, and Queues 1-4
* all queue operations are on the curQueue, which can be set in all episodes list views
* on app startup, the most recently updated queue is set to curQueue
* queue is circular: if the final item in queue finished, the first item in queue (if exists) will get played
Expand Down Expand Up @@ -115,6 +115,18 @@ While podcast subscriptions' OPML files (from AntennaPod or any other sources) c
* It syncs the play states (position and played) of episodes that exist in both devices (ensure to refresh first) and that have been played (completed or not)
* So far, every sync is a full sync, no sync for subscriptions and media files

### Automation

* auto download algorithm is changed to individual feed based.
* When auto download is enabled in the Settings, feeds to be auto-downloaded need to be separately enabled in the feed settings.
* Each feed also has its own download policy (only new episodes, newest episodes, and oldest episodes. "newest episodes" meaning most recent episodes, new or old)
* Each feed has its own limit (Episode cache) for number of episodes downloaded, this limit rules in combination of the overall limit for the app.
* After auto download run, episodes with New status is changed to Unplayed.
* auto download feed setting dialog is also changed:
* there are now separate dialogs for inclusive and exclusive filters where filter tokens can be specified independently
* on exclusive dialog, there are optional check boxes "Exclude episodes shorter than" and "Mark excluded episodes played"


### Security and reliability

* Disabled `usesCleartextTraffic`, so that all content transmission is more private and secure
Expand Down
6 changes: 3 additions & 3 deletions app/build.gradle
Original file line number Diff line number Diff line change
Expand Up @@ -115,7 +115,7 @@ android {
checkOnly += ['NewApi', 'InlinedApi', 'Performance', 'DuplicateIds']

disable += ['TypographyDashes', 'TypographyQuotes', 'ObsoleteLintCustomCheck', 'CheckResult', 'UnusedAttribute', 'BatteryLife', 'InflateParams',
'RestrictedApi', 'TrustAllX509TrustManager', 'ExportedReceiver', 'AllowBackup', 'VectorDrawableCompat',
'RestrictedApi', 'TrustAllX509TrustManager', 'ExportedReceiver', 'VectorDrawableCompat',
'StaticFieldLeak', 'UseCompoundDrawables', 'NestedWeights', 'Overdraw', 'UselessParent', 'TextFields',
'AlwaysShowAction', 'Autofill', 'ClickableViewAccessibility', 'ContentDescription',
'KeyboardInaccessibleWidget', 'LabelFor', 'SetTextI18n', 'HardcodedText', 'RelativeOverlap',
Expand All @@ -126,8 +126,8 @@ android {
buildConfig true
}
defaultConfig {
versionCode 3020213
versionName "6.0.13"
versionCode 3020214
versionName "6.1.0"

applicationId "ac.mdiq.podcini.R"
def commit = ""
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -140,12 +140,12 @@ object EspressoTestUtils {
InstrumentationRegistry.getInstrumentation().targetContext
.getSharedPreferences(MainActivity.PREF_NAME, Context.MODE_PRIVATE)
.edit()
.putBoolean(MainActivity.PREF_IS_FIRST_LAUNCH, false)
.putBoolean(MainActivity.Extras.prefMainActivityIsFirstLaunch.name, false)
.commit()

PreferenceManager.getDefaultSharedPreferences(InstrumentationRegistry.getInstrumentation().targetContext)
.edit()
.putString(UserPreferences.PREF_UPDATE_INTERVAL, "0")
.putString(UserPreferences.Prefs.prefAutoUpdateIntervall.name, "0")
.commit()

RatingDialog.init(InstrumentationRegistry.getInstrumentation().targetContext)
Expand All @@ -160,7 +160,7 @@ object EspressoTestUtils {
.commit()
PreferenceManager.getDefaultSharedPreferences(InstrumentationRegistry.getInstrumentation().targetContext)
.edit()
.putString(UserPreferences.PREF_DEFAULT_PAGE, UserPreferences.DEFAULT_PAGE_REMEMBER)
.putString(UserPreferences.Prefs.prefDefaultPage.name, UserPreferences.DEFAULT_PAGE_REMEMBER)
.commit()
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -194,17 +194,17 @@ class PlaybackTest {

protected fun setContinuousPlaybackPreference(value: Boolean) {
val prefs = PreferenceManager.getDefaultSharedPreferences(context)
prefs.edit().putBoolean(UserPreferences.PREF_FOLLOW_QUEUE, value).commit()
prefs.edit().putBoolean(UserPreferences.Prefs.prefFollowQueue.name, value).commit()
}

protected fun setSkipKeepsEpisodePreference(value: Boolean) {
val prefs = PreferenceManager.getDefaultSharedPreferences(context)
prefs.edit().putBoolean(UserPreferences.PREF_SKIP_KEEPS_EPISODE, value).commit()
prefs.edit().putBoolean(UserPreferences.Prefs.prefSkipKeepsEpisode.name, value).commit()
}

protected fun setSmartMarkAsPlayedPreference(smartMarkAsPlayedSecs: Int) {
val prefs = PreferenceManager.getDefaultSharedPreferences(context)
prefs.edit().putString(UserPreferences.PREF_SMART_MARK_AS_PLAYED_SECS,
prefs.edit().putString(UserPreferences.Prefs.prefSmartMarkAsPlayedSecs.name,
smartMarkAsPlayedSecs.toString(10))
.commit()
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -39,22 +39,19 @@ class AutoDownloadTest {
// Setup: enable automatic download
// it is not needed, as the actual automatic download is stubbed.
stubDownloadAlgorithm = StubDownloadAlgorithm()
// setDownloadAlgorithm(stubDownloadAlgorithm!!)
downloadAlgorithm = stubDownloadAlgorithm!!
}

@After
@Throws(Exception::class)
fun tearDown() {
// setDownloadAlgorithm(Episodes.AutomaticDownloadAlgorithm())
downloadAlgorithm = AutoDownloads.AutoDownloadAlgorithm()
EspressoTestUtils.tryKillPlaybackService()
stubFeedsServer!!.tearDown()
}

/**
* A cross-functional test, ensuring playback's behavior works with Auto Download in boundary condition.
*
* Scenario:
* - For setting enqueue location AFTER_CURRENTLY_PLAYING
* - when playback of an episode is complete and the app advances to the next episode (continuous playback on)
Expand Down Expand Up @@ -107,7 +104,7 @@ class AutoDownloadTest {
var currentlyPlayingAtDownload: Long = -1
private set

override fun autoDownloadEpisodeMedia(context: Context): Runnable {
override fun autoDownloadEpisodeMediaNew(context: Context): Runnable {
return Runnable {
if (currentlyPlayingAtDownload == -1L) {
// currentlyPlayingAtDownload = currentlyPlayingFeedMediaId
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -39,7 +39,7 @@ class FeedSettingsTest {
uiTestUtils!!.addLocalFeedData(false)
feed = uiTestUtils!!.hostedFeeds[0]
val intent = Intent(InstrumentationRegistry.getInstrumentation().targetContext, MainActivity::class.java)
intent.putExtra(MainActivity.EXTRA_FEED_ID, feed!!.id)
intent.putExtra(MainActivity.Extras.fragment_feed_id.name, feed!!.id)
activityRule.launchActivity(intent)
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -32,11 +32,11 @@ import ac.mdiq.podcini.preferences.UserPreferences.isAutoDeleteLocal
import ac.mdiq.podcini.preferences.UserPreferences.isEnableAutodownload
import ac.mdiq.podcini.preferences.UserPreferences.isEnableAutodownloadOnBattery
import ac.mdiq.podcini.preferences.UserPreferences.rewindSecs
import ac.mdiq.podcini.preferences.UserPreferences.shouldDeleteRemoveFromQueue
import ac.mdiq.podcini.preferences.UserPreferences.shouldPauseForFocusLoss
import ac.mdiq.podcini.preferences.UserPreferences.showNextChapterOnFullNotification
import ac.mdiq.podcini.preferences.UserPreferences.showPlaybackSpeedOnFullNotification
import ac.mdiq.podcini.preferences.UserPreferences.showSkipOnFullNotification
import ac.mdiq.podcini.storage.database.Episodes.shouldDeleteRemoveFromQueue
import ac.mdiq.podcini.storage.database.Queues
import ac.mdiq.podcini.storage.database.Queues.enqueueLocation
import de.test.podcini.EspressoTestUtils
Expand Down Expand Up @@ -65,7 +65,7 @@ class PreferencesTest {
EspressoTestUtils.clearPreferences()
activityTestRule.launchActivity(Intent())
val prefs = PreferenceManager.getDefaultSharedPreferences(activityTestRule.activity)
prefs.edit().putBoolean(UserPreferences.PREF_ENABLE_AUTODL, true).commit()
prefs.edit().putBoolean(UserPreferences.Prefs.prefEnableAutoDl.name, true).commit()

res = activityTestRule.activity.resources
init(activityTestRule.activity)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,6 @@ import ac.mdiq.podcini.net.sync.model.EpisodeAction
import ac.mdiq.podcini.net.sync.queue.SynchronizationQueueSink
import ac.mdiq.podcini.net.utils.NetworkUtils.isAllowMobileEpisodeDownload
import ac.mdiq.podcini.preferences.UserPreferences
import ac.mdiq.podcini.preferences.UserPreferences.PREF_ENQUEUE_DOWNLOADED
import ac.mdiq.podcini.preferences.UserPreferences.appPrefs
import ac.mdiq.podcini.storage.database.Episodes
import ac.mdiq.podcini.storage.database.LogsAndStats
Expand Down Expand Up @@ -126,7 +125,7 @@ class DownloadServiceInterfaceImpl : DownloadServiceInterface() {
return workRequest
}
private fun enqueueDownloadedEpisodes(): Boolean {
return appPrefs.getBoolean(PREF_ENQUEUE_DOWNLOADED, true)
return appPrefs.getBoolean(UserPreferences.Prefs.prefEnqueueDownloaded.name, true)
}
}

Expand Down Expand Up @@ -291,7 +290,7 @@ class DownloadServiceInterfaceImpl : DownloadServiceInterface() {
// sendMessage(title, false)
// return
// }
val builder = NotificationCompat.Builder(applicationContext, NotificationUtils.CHANNEL_ID_DOWNLOAD_ERROR)
val builder = NotificationCompat.Builder(applicationContext, NotificationUtils.CHANNEL_ID.error.name)
builder.setTicker(applicationContext.getString(R.string.download_report_title))
.setContentTitle(applicationContext.getString(R.string.download_report_title))
.setContentText(applicationContext.getString(R.string.download_error_tap_for_details))
Expand All @@ -314,7 +313,7 @@ class DownloadServiceInterfaceImpl : DownloadServiceInterface() {
val bigText = bigTextB.toString().trim { it <= ' ' }
val contentText = if (progressCopy.size == 1) bigText
else applicationContext.resources.getQuantityString(R.plurals.downloads_left, progressCopy.size, progressCopy.size)
val builder = NotificationCompat.Builder(applicationContext, NotificationUtils.CHANNEL_ID_DOWNLOADING)
val builder = NotificationCompat.Builder(applicationContext, NotificationUtils.CHANNEL_ID.downloading.name)
builder.setTicker(applicationContext.getString(R.string.download_notification_title_episodes))
.setContentTitle(applicationContext.getString(R.string.download_notification_title_episodes))
.setContentText(contentText)
Expand Down
28 changes: 14 additions & 14 deletions app/src/main/kotlin/ac/mdiq/podcini/net/feed/FeedUpdateManager.kt
Original file line number Diff line number Diff line change
Expand Up @@ -8,14 +8,13 @@ import ac.mdiq.podcini.net.download.serviceinterface.DownloadRequest
import ac.mdiq.podcini.net.feed.parser.FeedHandler
import ac.mdiq.podcini.net.feed.parser.FeedHandlerResult
import ac.mdiq.podcini.net.utils.NetworkUtils.isAllowMobileFeedRefresh
import ac.mdiq.podcini.preferences.UserPreferences
import ac.mdiq.podcini.storage.model.Feed
import ac.mdiq.podcini.util.Logd
import ac.mdiq.podcini.net.utils.NetworkUtils.isFeedRefreshAllowed
import ac.mdiq.podcini.net.utils.NetworkUtils.isNetworkRestricted
import ac.mdiq.podcini.net.utils.NetworkUtils.isVpnOverWifi
import ac.mdiq.podcini.net.utils.NetworkUtils.networkAvailable
import ac.mdiq.podcini.preferences.UserPreferences.PREF_UPDATE_INTERVAL
import ac.mdiq.podcini.preferences.UserPreferences
import ac.mdiq.podcini.preferences.UserPreferences.appPrefs
import ac.mdiq.podcini.storage.algorithms.AutoDownloads.autodownloadEpisodeMedia
import ac.mdiq.podcini.storage.database.Feeds
Expand Down Expand Up @@ -66,7 +65,7 @@ object FeedUpdateManager {
const val EXTRA_EVEN_ON_MOBILE: String = "even_on_mobile"

val updateInterval: Long
get() = appPrefs.getString(PREF_UPDATE_INTERVAL, "12")!!.toInt().toLong()
get() = appPrefs.getString(UserPreferences.Prefs.prefAutoUpdateIntervall.name, "12")!!.toInt().toLong()

val isAutoUpdateDisabled: Boolean
get() = updateInterval == 0L
Expand All @@ -77,9 +76,8 @@ object FeedUpdateManager {
*/
@JvmStatic
fun restartUpdateAlarm(context: Context, replace: Boolean) {
if (isAutoUpdateDisabled) {
WorkManager.getInstance(context).cancelUniqueWork(WORK_ID_FEED_UPDATE)
} else {
if (isAutoUpdateDisabled) WorkManager.getInstance(context).cancelUniqueWork(WORK_ID_FEED_UPDATE)
else {
val workRequest: PeriodicWorkRequest = PeriodicWorkRequest.Builder(FeedUpdateWorker::class.java, updateInterval, TimeUnit.HOURS)
.setConstraints(Builder()
.setRequiredNetworkType(if (isAllowMobileFeedRefresh) NetworkType.CONNECTED else NetworkType.UNMETERED)
Expand Down Expand Up @@ -172,7 +170,8 @@ object FeedUpdateManager {
}
refreshFeeds(toUpdate, force)
notificationManager.cancel(R.id.notification_updating_feeds)
autodownloadEpisodeMedia(applicationContext)
autodownloadEpisodeMedia(applicationContext, toUpdate.toList())
toUpdate.clear()
return Result.success()
}
private fun createNotification(toUpdate: List<Feed?>?): Notification {
Expand All @@ -184,7 +183,7 @@ object FeedUpdateManager {
toUpdate.size, toUpdate.size)
bigText = Stream.of(toUpdate).map { feed: Feed? -> "" + feed!!.title }.collect(Collectors.joining("\n"))
}
return NotificationCompat.Builder(context, NotificationUtils.CHANNEL_ID_DOWNLOADING)
return NotificationCompat.Builder(context, NotificationUtils.CHANNEL_ID.downloading.name)
.setContentTitle(context.getString(R.string.download_notification_title_feeds))
.setContentText(contentText)
.setStyle(NotificationCompat.BigTextStyle().bigText(bigText))
Expand Down Expand Up @@ -212,10 +211,11 @@ object FeedUpdateManager {
// Toast.makeText(applicationContext, R.string.notification_permission_text, Toast.LENGTH_LONG).show()
return
}
while (toUpdate.isNotEmpty()) {
var i = 0
while (i < toUpdate.size) {
if (isStopped) return
notificationManager.notify(R.id.notification_updating_feeds, createNotification(toUpdate))
val feed = unmanaged(toUpdate[0])
val feed = unmanaged(toUpdate[i++])
try {
Logd(TAG, "updating local feed? ${feed.isLocalFeed} ${feed.title}")
if (feed.isLocalFeed) LocalFeedUpdater.updateFeed(feed, applicationContext, null)
Expand All @@ -226,7 +226,7 @@ object FeedUpdateManager {
val status = DownloadResult(feed.id, feed.title?:"", DownloadError.ERROR_IO_ERROR, false, e.message?:"")
LogsAndStats.addDownloadStatus(status)
}
toUpdate.removeAt(0)
// toUpdate.removeAt(0)
}
}
@UnstableApi
Expand Down Expand Up @@ -363,8 +363,8 @@ object FeedUpdateManager {
}

class FeedSyncTask(private val context: Context, request: DownloadRequest) {
var savedFeed: Feed? = null
private set
// var savedFeed: Feed? = null
// private set
private val task = FeedParserTask(request)
private var feedHandlerResult: FeedHandlerResult? = null
val downloadStatus: DownloadResult
Expand All @@ -375,7 +375,7 @@ object FeedUpdateManager {
fun run(): Boolean {
feedHandlerResult = task.call()
if (!task.isSuccessful) return false
savedFeed = Feeds.updateFeed(context, feedHandlerResult!!.feed, false)
Feeds.updateFeed(context, feedHandlerResult!!.feed, false)
return true
}
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@ import kotlinx.coroutines.supervisorScope

class CombinedSearcher : PodcastSearcher {

override suspend fun search1(query: String): List<PodcastSearchResult?> {
override suspend fun search(query: String): List<PodcastSearchResult?> {
val searchProviders = PodcastSearcherRegistry.searchProviders
val searchResults = MutableList<List<PodcastSearchResult?>?>(searchProviders.size) { null }

Expand All @@ -19,7 +19,7 @@ class CombinedSearcher : PodcastSearcher {
if (searchProviderInfo.weight > 0.00001f && searcher.javaClass != CombinedSearcher::class.java) {
async(Dispatchers.IO) {
try {
val results = searcher.search1(query)
val results = searcher.search(query)
searchResults[index] = results
} catch (e: Throwable) {
Log.d(TAG, Log.getStackTraceString(e))
Expand Down Expand Up @@ -70,7 +70,7 @@ class CombinedSearcher : PodcastSearcher {
// return PodcastSearcherRegistry.lookupUrl(url)
// }

override suspend fun lookupUrl1(resultUrl: String): String {
override suspend fun lookupUrl(resultUrl: String): String {
return PodcastSearcherRegistry.lookupUrl1(resultUrl)
}

Expand Down

This file was deleted.

Loading

0 comments on commit 86cc7cf

Please sign in to comment.