6.6.1 commit
This commit is contained in:
parent
7a1f2feac2
commit
efd51ed6e1
|
@ -31,8 +31,8 @@ android {
|
||||||
testApplicationId "ac.mdiq.podcini.tests"
|
testApplicationId "ac.mdiq.podcini.tests"
|
||||||
testInstrumentationRunner "androidx.test.runner.AndroidJUnitRunner"
|
testInstrumentationRunner "androidx.test.runner.AndroidJUnitRunner"
|
||||||
|
|
||||||
versionCode 3020245
|
versionCode 3020246
|
||||||
versionName "6.6.0"
|
versionName "6.6.1"
|
||||||
|
|
||||||
applicationId "ac.mdiq.podcini.R"
|
applicationId "ac.mdiq.podcini.R"
|
||||||
def commit = ""
|
def commit = ""
|
||||||
|
|
|
@ -32,6 +32,7 @@ import ac.mdiq.podcini.preferences.UserPreferences
|
||||||
import ac.mdiq.podcini.preferences.UserPreferences.appPrefs
|
import ac.mdiq.podcini.preferences.UserPreferences.appPrefs
|
||||||
import ac.mdiq.podcini.preferences.UserPreferences.fastForwardSecs
|
import ac.mdiq.podcini.preferences.UserPreferences.fastForwardSecs
|
||||||
import ac.mdiq.podcini.preferences.UserPreferences.isSkipSilence
|
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.preferences.UserPreferences.rewindSecs
|
||||||
import ac.mdiq.podcini.receiver.MediaButtonReceiver
|
import ac.mdiq.podcini.receiver.MediaButtonReceiver
|
||||||
import ac.mdiq.podcini.storage.database.Episodes.addToHistory
|
import ac.mdiq.podcini.storage.database.Episodes.addToHistory
|
||||||
|
@ -1432,7 +1433,7 @@ class PlaybackService : MediaLibraryService() {
|
||||||
val streamInfo = StreamInfo.getInfo(vService, url)
|
val streamInfo = StreamInfo.getInfo(vService, url)
|
||||||
val audioStreamsList = getFilteredAudioStreams(streamInfo.audioStreams)
|
val audioStreamsList = getFilteredAudioStreams(streamInfo.audioStreams)
|
||||||
Logd(TAG, "setDataSource1 audioStreamsList ${audioStreamsList.size}")
|
Logd(TAG, "setDataSource1 audioStreamsList ${audioStreamsList.size}")
|
||||||
val audioIndex = if (isNetworkRestricted) 0 else audioStreamsList.size - 1
|
val audioIndex = if (isNetworkRestricted && prefLowQualityMedia) 0 else audioStreamsList.size - 1
|
||||||
val audioStream = audioStreamsList[audioIndex]
|
val audioStream = audioStreamsList[audioIndex]
|
||||||
Logd(TAG, "setDataSource1 use audio quality: ${audioStream.bitrate}")
|
Logd(TAG, "setDataSource1 use audio quality: ${audioStream.bitrate}")
|
||||||
val aSource = DefaultMediaSourceFactory(context).createMediaSource(
|
val aSource = DefaultMediaSourceFactory(context).createMediaSource(
|
||||||
|
|
|
@ -197,6 +197,12 @@ object UserPreferences {
|
||||||
appPrefs.edit().putBoolean(Prefs.prefStreamOverDownload.name, stream).apply()
|
appPrefs.edit().putBoolean(Prefs.prefStreamOverDownload.name, stream).apply()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
var prefLowQualityMedia: Boolean
|
||||||
|
get() = appPrefs.getBoolean(Prefs.prefLowQualityOnMobile.name, false)
|
||||||
|
set(stream) {
|
||||||
|
appPrefs.edit().putBoolean(Prefs.prefLowQualityOnMobile.name, stream).apply()
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Sets up the UserPreferences class.
|
* Sets up the UserPreferences class.
|
||||||
* @throws IllegalArgumentException if context is null
|
* @throws IllegalArgumentException if context is null
|
||||||
|
@ -324,6 +330,7 @@ object UserPreferences {
|
||||||
prefPauseForFocusLoss,
|
prefPauseForFocusLoss,
|
||||||
prefPlaybackTimeRespectsSpeed,
|
prefPlaybackTimeRespectsSpeed,
|
||||||
prefStreamOverDownload,
|
prefStreamOverDownload,
|
||||||
|
prefLowQualityOnMobile,
|
||||||
prefSpeedforwardSpeed,
|
prefSpeedforwardSpeed,
|
||||||
|
|
||||||
// Network
|
// Network
|
||||||
|
|
|
@ -1,6 +1,5 @@
|
||||||
package ac.mdiq.podcini.storage.database
|
package ac.mdiq.podcini.storage.database
|
||||||
|
|
||||||
import ac.mdiq.podcini.BuildConfig
|
|
||||||
import ac.mdiq.podcini.net.download.DownloadError
|
import ac.mdiq.podcini.net.download.DownloadError
|
||||||
import ac.mdiq.podcini.net.sync.model.EpisodeAction
|
import ac.mdiq.podcini.net.sync.model.EpisodeAction
|
||||||
import ac.mdiq.podcini.net.sync.queue.SynchronizationQueueSink
|
import ac.mdiq.podcini.net.sync.queue.SynchronizationQueueSink
|
||||||
|
@ -20,18 +19,20 @@ import ac.mdiq.podcini.storage.database.RealmDB.upsertBlk
|
||||||
import ac.mdiq.podcini.storage.model.*
|
import ac.mdiq.podcini.storage.model.*
|
||||||
import ac.mdiq.podcini.storage.model.FeedPreferences.AutoDeleteAction
|
import ac.mdiq.podcini.storage.model.FeedPreferences.AutoDeleteAction
|
||||||
import ac.mdiq.podcini.storage.model.FeedPreferences.Companion.TAG_ROOT
|
import ac.mdiq.podcini.storage.model.FeedPreferences.Companion.TAG_ROOT
|
||||||
import ac.mdiq.podcini.storage.model.VolumeAdaptionSetting
|
|
||||||
import ac.mdiq.podcini.storage.utils.FilesUtils.feedfilePath
|
import ac.mdiq.podcini.storage.utils.FilesUtils.feedfilePath
|
||||||
import ac.mdiq.podcini.storage.utils.FilesUtils.getFeedfileName
|
import ac.mdiq.podcini.storage.utils.FilesUtils.getFeedfileName
|
||||||
import ac.mdiq.podcini.util.Logd
|
|
||||||
import ac.mdiq.podcini.util.EventFlow
|
import ac.mdiq.podcini.util.EventFlow
|
||||||
import ac.mdiq.podcini.util.FlowEvent
|
import ac.mdiq.podcini.util.FlowEvent
|
||||||
|
import ac.mdiq.podcini.util.Logd
|
||||||
import android.app.backup.BackupManager
|
import android.app.backup.BackupManager
|
||||||
import android.content.Context
|
import android.content.Context
|
||||||
import android.net.Uri
|
import android.net.Uri
|
||||||
import androidx.documentfile.provider.DocumentFile
|
import androidx.documentfile.provider.DocumentFile
|
||||||
import io.realm.kotlin.ext.asFlow
|
import io.realm.kotlin.ext.asFlow
|
||||||
import io.realm.kotlin.notifications.*
|
import io.realm.kotlin.notifications.ResultsChange
|
||||||
|
import io.realm.kotlin.notifications.SingleQueryChange
|
||||||
|
import io.realm.kotlin.notifications.UpdatedObject
|
||||||
|
import io.realm.kotlin.notifications.UpdatedResults
|
||||||
import kotlinx.coroutines.*
|
import kotlinx.coroutines.*
|
||||||
import java.io.File
|
import java.io.File
|
||||||
import java.text.DateFormat
|
import java.text.DateFormat
|
||||||
|
@ -241,7 +242,7 @@ object Feeds {
|
||||||
""".trimIndent()))
|
""".trimIndent()))
|
||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
var oldItem = EpisodeAssistant.searchEpisodeByIdentifyingValue(savedFeed.episodes, episode)
|
var oldItem = searchEpisodeByIdentifyingValue(savedFeed.episodes, episode)
|
||||||
if (!newFeed.isLocalFeed && oldItem == null) {
|
if (!newFeed.isLocalFeed && oldItem == null) {
|
||||||
oldItem = EpisodeAssistant.searchEpisodeGuessDuplicate(savedFeed.episodes, episode)
|
oldItem = EpisodeAssistant.searchEpisodeGuessDuplicate(savedFeed.episodes, episode)
|
||||||
if (oldItem != null) {
|
if (oldItem != null) {
|
||||||
|
@ -299,7 +300,7 @@ object Feeds {
|
||||||
val it = savedFeed.episodes.toMutableList().iterator()
|
val it = savedFeed.episodes.toMutableList().iterator()
|
||||||
while (it.hasNext()) {
|
while (it.hasNext()) {
|
||||||
val feedItem = it.next()
|
val feedItem = it.next()
|
||||||
if (EpisodeAssistant.searchEpisodeByIdentifyingValue(newFeed.episodes, feedItem) == null) {
|
if (searchEpisodeByIdentifyingValue(newFeed.episodes, feedItem) == null) {
|
||||||
unlistedItems.add(feedItem)
|
unlistedItems.add(feedItem)
|
||||||
it.remove()
|
it.remove()
|
||||||
}
|
}
|
||||||
|
@ -442,15 +443,13 @@ object Feeds {
|
||||||
if (searchEpisodeByIdentifyingValue(feed.episodes, episode) != null) return
|
if (searchEpisodeByIdentifyingValue(feed.episodes, episode) != null) return
|
||||||
|
|
||||||
Logd(TAG, "addToYoutubeSyndicate adding new episode: ${episode.title}")
|
Logd(TAG, "addToYoutubeSyndicate adding new episode: ${episode.title}")
|
||||||
runOnIOScope {
|
episode.feed = feed
|
||||||
episode.feed = feed
|
episode.id = Feed.newId()
|
||||||
episode.id = Feed.newId()
|
episode.feedId = feed.id
|
||||||
episode.feedId = feed.id
|
episode.media?.id = episode.id
|
||||||
episode.media?.id = episode.id
|
upsertBlk(episode) {}
|
||||||
upsert(episode) {}
|
feed.episodes.add(episode)
|
||||||
feed.episodes.add(episode)
|
upsertBlk(feed) {}
|
||||||
upsert(feed) {}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|
|
@ -3,7 +3,6 @@ package ac.mdiq.podcini.ui.activity
|
||||||
import ac.mdiq.podcini.R
|
import ac.mdiq.podcini.R
|
||||||
import ac.mdiq.podcini.storage.database.Episodes.episodeFromStreamInfo
|
import ac.mdiq.podcini.storage.database.Episodes.episodeFromStreamInfo
|
||||||
import ac.mdiq.podcini.storage.database.Feeds.addToYoutubeSyndicate
|
import ac.mdiq.podcini.storage.database.Feeds.addToYoutubeSyndicate
|
||||||
import ac.mdiq.podcini.storage.model.Episode
|
|
||||||
import ac.mdiq.podcini.ui.compose.CustomTheme
|
import ac.mdiq.podcini.ui.compose.CustomTheme
|
||||||
import ac.mdiq.podcini.util.Logd
|
import ac.mdiq.podcini.util.Logd
|
||||||
import ac.mdiq.vista.extractor.Vista
|
import ac.mdiq.vista.extractor.Vista
|
||||||
|
@ -13,7 +12,6 @@ import android.content.Intent
|
||||||
import android.net.Uri
|
import android.net.Uri
|
||||||
import android.os.Bundle
|
import android.os.Bundle
|
||||||
import android.util.Log
|
import android.util.Log
|
||||||
import android.view.ViewGroup
|
|
||||||
import androidx.activity.compose.setContent
|
import androidx.activity.compose.setContent
|
||||||
import androidx.annotation.OptIn
|
import androidx.annotation.OptIn
|
||||||
import androidx.appcompat.app.AppCompatActivity
|
import androidx.appcompat.app.AppCompatActivity
|
||||||
|
@ -23,7 +21,6 @@ import androidx.compose.material.*
|
||||||
import androidx.compose.runtime.*
|
import androidx.compose.runtime.*
|
||||||
import androidx.compose.ui.Alignment
|
import androidx.compose.ui.Alignment
|
||||||
import androidx.compose.ui.Modifier
|
import androidx.compose.ui.Modifier
|
||||||
import androidx.compose.ui.platform.ComposeView
|
|
||||||
import androidx.compose.ui.res.stringResource
|
import androidx.compose.ui.res.stringResource
|
||||||
import androidx.compose.ui.unit.dp
|
import androidx.compose.ui.unit.dp
|
||||||
import androidx.compose.ui.window.Dialog
|
import androidx.compose.ui.window.Dialog
|
||||||
|
@ -32,14 +29,14 @@ import com.google.android.material.dialog.MaterialAlertDialogBuilder
|
||||||
import kotlinx.coroutines.CoroutineScope
|
import kotlinx.coroutines.CoroutineScope
|
||||||
import kotlinx.coroutines.Dispatchers
|
import kotlinx.coroutines.Dispatchers
|
||||||
import kotlinx.coroutines.launch
|
import kotlinx.coroutines.launch
|
||||||
import kotlinx.coroutines.withContext
|
|
||||||
import java.net.URLDecoder
|
import java.net.URLDecoder
|
||||||
|
|
||||||
class ShareReceiverActivity : AppCompatActivity() {
|
class ShareReceiverActivity : AppCompatActivity() {
|
||||||
|
var feedUrl: String? = null
|
||||||
|
|
||||||
@OptIn(UnstableApi::class) override fun onCreate(savedInstanceState: Bundle?) {
|
@OptIn(UnstableApi::class) override fun onCreate(savedInstanceState: Bundle?) {
|
||||||
super.onCreate(savedInstanceState)
|
super.onCreate(savedInstanceState)
|
||||||
|
|
||||||
var feedUrl: String? = null
|
|
||||||
when {
|
when {
|
||||||
intent.hasExtra(ARG_FEEDURL) -> feedUrl = intent.getStringExtra(ARG_FEEDURL)
|
intent.hasExtra(ARG_FEEDURL) -> feedUrl = intent.getStringExtra(ARG_FEEDURL)
|
||||||
intent.action == Intent.ACTION_SEND -> feedUrl = intent.getStringExtra(Intent.EXTRA_TEXT)
|
intent.action == Intent.ACTION_SEND -> feedUrl = intent.getStringExtra(Intent.EXTRA_TEXT)
|
||||||
|
@ -50,7 +47,7 @@ class ShareReceiverActivity : AppCompatActivity() {
|
||||||
showNoPodcastFoundError()
|
showNoPodcastFoundError()
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
if (!feedUrl.startsWith("http")) {
|
if (!feedUrl!!.startsWith("http")) {
|
||||||
val uri = Uri.parse(feedUrl)
|
val uri = Uri.parse(feedUrl)
|
||||||
val urlString = uri?.getQueryParameter("url")
|
val urlString = uri?.getQueryParameter("url")
|
||||||
if (urlString != null) feedUrl = URLDecoder.decode(urlString, "UTF-8")
|
if (urlString != null) feedUrl = URLDecoder.decode(urlString, "UTF-8")
|
||||||
|
@ -59,32 +56,26 @@ class ShareReceiverActivity : AppCompatActivity() {
|
||||||
when {
|
when {
|
||||||
// plain text
|
// plain text
|
||||||
feedUrl!!.matches(Regex("^[^\\s<>/]+\$")) -> {
|
feedUrl!!.matches(Regex("^[^\\s<>/]+\$")) -> {
|
||||||
val intent = MainActivity.showOnlineSearch(this, feedUrl)
|
val intent = MainActivity.showOnlineSearch(this, feedUrl!!)
|
||||||
startActivity(intent)
|
startActivity(intent)
|
||||||
finish()
|
finish()
|
||||||
}
|
}
|
||||||
// Youtube media
|
// Youtube media
|
||||||
feedUrl.startsWith("https://youtube.com/watch?") -> {
|
feedUrl!!.startsWith("https://youtube.com/watch?") -> {
|
||||||
Logd(TAG, "got youtube media")
|
Logd(TAG, "got youtube media")
|
||||||
CoroutineScope(Dispatchers.IO).launch {
|
setContent {
|
||||||
val info = StreamInfo.getInfo(Vista.getService(0), feedUrl)
|
val showDialog = remember { mutableStateOf(true) }
|
||||||
Logd(TAG, "info: $info")
|
CustomTheme(this@ShareReceiverActivity) {
|
||||||
val episode = episodeFromStreamInfo(info)
|
confirmAddEpisode(showDialog.value, onDismissRequest = {
|
||||||
Logd(TAG, "episode: $episode")
|
showDialog.value = false
|
||||||
withContext(Dispatchers.Main) {
|
finish()
|
||||||
setContent {
|
})
|
||||||
val showDialog = remember { mutableStateOf(true) }
|
|
||||||
CustomTheme(this@ShareReceiverActivity) {
|
|
||||||
confirmAddEpisode(showDialog.value, episode, onDismissRequest = { showDialog.value = false })
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
else -> {
|
else -> {
|
||||||
Logd(TAG, "Activity was started with url $feedUrl")
|
Logd(TAG, "Activity was started with url $feedUrl")
|
||||||
val intent = MainActivity.showOnlineFeed(this, feedUrl)
|
val intent = MainActivity.showOnlineFeed(this, feedUrl!!)
|
||||||
// intent.putExtra(MainActivity.Extras.started_from_share.name, getIntent().getBooleanExtra(MainActivity.Extras.started_from_share.name, false))
|
// intent.putExtra(MainActivity.Extras.started_from_share.name, getIntent().getBooleanExtra(MainActivity.Extras.started_from_share.name, false))
|
||||||
startActivity(intent)
|
startActivity(intent)
|
||||||
finish()
|
finish()
|
||||||
|
@ -93,7 +84,7 @@ class ShareReceiverActivity : AppCompatActivity() {
|
||||||
}
|
}
|
||||||
|
|
||||||
@Composable
|
@Composable
|
||||||
fun confirmAddEpisode(showDialog: Boolean, episode: Episode, onDismissRequest: () -> Unit) {
|
fun confirmAddEpisode(showDialog: Boolean, onDismissRequest: () -> Unit) {
|
||||||
if (showDialog) {
|
if (showDialog) {
|
||||||
Dialog(onDismissRequest = { onDismissRequest() }) {
|
Dialog(onDismissRequest = { onDismissRequest() }) {
|
||||||
Card(
|
Card(
|
||||||
|
@ -106,11 +97,11 @@ class ShareReceiverActivity : AppCompatActivity() {
|
||||||
modifier = Modifier.padding(16.dp),
|
modifier = Modifier.padding(16.dp),
|
||||||
verticalArrangement = Arrangement.Center
|
verticalArrangement = Arrangement.Center
|
||||||
) {
|
) {
|
||||||
var checked by remember { mutableStateOf(false) }
|
var audioOnly by remember { mutableStateOf(false) }
|
||||||
Row(Modifier.fillMaxWidth()) {
|
Row(Modifier.fillMaxWidth()) {
|
||||||
Checkbox(checked = checked,
|
Checkbox(checked = audioOnly,
|
||||||
onCheckedChange = {
|
onCheckedChange = {
|
||||||
checked = it
|
audioOnly = it
|
||||||
}
|
}
|
||||||
)
|
)
|
||||||
Text(
|
Text(
|
||||||
|
@ -119,8 +110,14 @@ class ShareReceiverActivity : AppCompatActivity() {
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
Button(onClick = {
|
Button(onClick = {
|
||||||
addToYoutubeSyndicate(episode, !checked)
|
CoroutineScope(Dispatchers.IO).launch {
|
||||||
finish()
|
val info = StreamInfo.getInfo(Vista.getService(0), feedUrl!!)
|
||||||
|
Logd(TAG, "info: $info")
|
||||||
|
val episode = episodeFromStreamInfo(info)
|
||||||
|
Logd(TAG, "episode: $episode")
|
||||||
|
addToYoutubeSyndicate(episode, !audioOnly)
|
||||||
|
}
|
||||||
|
onDismissRequest()
|
||||||
}) {
|
}) {
|
||||||
Text("Confirm")
|
Text("Confirm")
|
||||||
}
|
}
|
||||||
|
|
|
@ -71,6 +71,8 @@ import java.util.concurrent.Semaphore
|
||||||
private lateinit var swipeActions: SwipeActions
|
private lateinit var swipeActions: SwipeActions
|
||||||
private lateinit var nextPageLoader: MoreContentListFooterUtil
|
private lateinit var nextPageLoader: MoreContentListFooterUtil
|
||||||
|
|
||||||
|
private var infoTextFiltered = ""
|
||||||
|
private var infoTextUpdate = ""
|
||||||
private var displayUpArrow = false
|
private var displayUpArrow = false
|
||||||
private var headerCreated = false
|
private var headerCreated = false
|
||||||
private var feedID: Long = 0
|
private var feedID: Long = 0
|
||||||
|
@ -155,6 +157,7 @@ import java.util.concurrent.Semaphore
|
||||||
})
|
})
|
||||||
|
|
||||||
binding.swipeRefresh.setDistanceToTriggerSync(resources.getInteger(R.integer.swipe_refresh_distance))
|
binding.swipeRefresh.setDistanceToTriggerSync(resources.getInteger(R.integer.swipe_refresh_distance))
|
||||||
|
binding.swipeRefresh.setProgressViewEndTarget(false, 0)
|
||||||
binding.swipeRefresh.setOnRefreshListener {
|
binding.swipeRefresh.setOnRefreshListener {
|
||||||
FeedUpdateManager.runOnceOrAsk(requireContext(), feed)
|
FeedUpdateManager.runOnceOrAsk(requireContext(), feed)
|
||||||
}
|
}
|
||||||
|
@ -429,6 +432,8 @@ import java.util.concurrent.Semaphore
|
||||||
private fun onFeedUpdateRunningEvent(event: FlowEvent.FeedUpdatingEvent) {
|
private fun onFeedUpdateRunningEvent(event: FlowEvent.FeedUpdatingEvent) {
|
||||||
nextPageLoader.setLoadingState(event.isRunning)
|
nextPageLoader.setLoadingState(event.isRunning)
|
||||||
if (!event.isRunning) nextPageLoader.root.visibility = View.GONE
|
if (!event.isRunning) nextPageLoader.root.visibility = View.GONE
|
||||||
|
infoTextUpdate = if (event.isRunning) getString(R.string.refreshing_label) else ""
|
||||||
|
binding.header.txtvInformation.text = ("{gmo-info} $infoTextFiltered $infoTextUpdate")
|
||||||
binding.swipeRefresh.isRefreshing = event.isRunning
|
binding.swipeRefresh.isRefreshing = event.isRunning
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -454,18 +459,20 @@ import java.util.concurrent.Semaphore
|
||||||
|
|
||||||
binding.header.txtvTitle.text = feed!!.title
|
binding.header.txtvTitle.text = feed!!.title
|
||||||
binding.header.txtvAuthor.text = feed!!.author
|
binding.header.txtvAuthor.text = feed!!.author
|
||||||
|
binding.header.txtvInformation.setOnClickListener {}
|
||||||
|
infoTextFiltered = ""
|
||||||
if (!feed?.preferences?.filterString.isNullOrEmpty()) {
|
if (!feed?.preferences?.filterString.isNullOrEmpty()) {
|
||||||
val filter: EpisodeFilter = feed!!.episodeFilter
|
val filter: EpisodeFilter = feed!!.episodeFilter
|
||||||
if (filter.values.isNotEmpty()) {
|
if (filter.values.isNotEmpty()) {
|
||||||
binding.header.txtvInformation.text = ("{gmo-info} " + this.getString(R.string.filtered_label))
|
infoTextFiltered = this.getString(R.string.filtered_label)
|
||||||
binding.header.txtvInformation.setOnClickListener {
|
binding.header.txtvInformation.setOnClickListener {
|
||||||
val dialog = FeedEpisodeFilterDialog(feed)
|
val dialog = FeedEpisodeFilterDialog(feed)
|
||||||
dialog.filter = feed!!.episodeFilter
|
dialog.filter = feed!!.episodeFilter
|
||||||
dialog.show(childFragmentManager, null)
|
dialog.show(childFragmentManager, null)
|
||||||
}
|
}
|
||||||
binding.header.txtvInformation.visibility = View.VISIBLE
|
}
|
||||||
} else binding.header.txtvInformation.visibility = View.GONE
|
}
|
||||||
} else binding.header.txtvInformation.visibility = View.GONE
|
binding.header.txtvInformation.text = ("{gmo-info} $infoTextFiltered $infoTextUpdate")
|
||||||
}
|
}
|
||||||
|
|
||||||
@UnstableApi private fun setupHeaderView() {
|
@UnstableApi private fun setupHeaderView() {
|
||||||
|
|
|
@ -110,6 +110,8 @@ class SubscriptionsFragment : Fragment(), Toolbar.OnMenuItemClickListener, Selec
|
||||||
|
|
||||||
private lateinit var catAdapter: ArrayAdapter<String>
|
private lateinit var catAdapter: ArrayAdapter<String>
|
||||||
|
|
||||||
|
private var infoTextFiltered = ""
|
||||||
|
private var infoTextUpdate = ""
|
||||||
private var tagFilterIndex = 1
|
private var tagFilterIndex = 1
|
||||||
// TODO: currently not used
|
// TODO: currently not used
|
||||||
private var displayedFolder: String = ""
|
private var displayedFolder: String = ""
|
||||||
|
@ -187,7 +189,8 @@ class SubscriptionsFragment : Fragment(), Toolbar.OnMenuItemClickListener, Selec
|
||||||
} else false
|
} else false
|
||||||
}
|
}
|
||||||
|
|
||||||
binding.progressBar.visibility = View.VISIBLE
|
// binding.progressBar.visibility = View.VISIBLE
|
||||||
|
binding.progressBar.visibility = View.GONE
|
||||||
|
|
||||||
val subscriptionAddButton: FloatingActionButton = binding.subscriptionsAdd
|
val subscriptionAddButton: FloatingActionButton = binding.subscriptionsAdd
|
||||||
subscriptionAddButton.setOnClickListener {
|
subscriptionAddButton.setOnClickListener {
|
||||||
|
@ -218,8 +221,10 @@ class SubscriptionsFragment : Fragment(), Toolbar.OnMenuItemClickListener, Selec
|
||||||
private fun setSwipeRefresh() {
|
private fun setSwipeRefresh() {
|
||||||
if (swipeToRefresh) {
|
if (swipeToRefresh) {
|
||||||
binding.swipeRefresh.isEnabled = true
|
binding.swipeRefresh.isEnabled = true
|
||||||
|
binding.swipeRefresh.setProgressViewEndTarget(false, 0)
|
||||||
binding.swipeRefresh.setDistanceToTriggerSync(resources.getInteger(R.integer.swipe_refresh_distance))
|
binding.swipeRefresh.setDistanceToTriggerSync(resources.getInteger(R.integer.swipe_refresh_distance))
|
||||||
binding.swipeRefresh.setOnRefreshListener {
|
binding.swipeRefresh.setOnRefreshListener {
|
||||||
|
Logd(TAG, "running FeedUpdateManager")
|
||||||
FeedUpdateManager.runOnceOrAsk(requireContext())
|
FeedUpdateManager.runOnceOrAsk(requireContext())
|
||||||
}
|
}
|
||||||
} else binding.swipeRefresh.isEnabled = false
|
} else binding.swipeRefresh.isEnabled = false
|
||||||
|
@ -327,7 +332,9 @@ class SubscriptionsFragment : Fragment(), Toolbar.OnMenuItemClickListener, Selec
|
||||||
when (event) {
|
when (event) {
|
||||||
is FlowEvent.FeedUpdatingEvent -> {
|
is FlowEvent.FeedUpdatingEvent -> {
|
||||||
Logd(TAG, "FeedUpdateRunningEvent: ${event.isRunning}")
|
Logd(TAG, "FeedUpdateRunningEvent: ${event.isRunning}")
|
||||||
binding.swipeRefresh.isRefreshing = event.isRunning
|
infoTextUpdate = if (event.isRunning) " " + this@SubscriptionsFragment.getString(R.string.refreshing_label) else ""
|
||||||
|
binding.txtvInformation.text = (infoTextFiltered + infoTextUpdate)
|
||||||
|
if (swipeToRefresh) binding.swipeRefresh.isRefreshing = event.isRunning
|
||||||
if (!event.isRunning && event.id != prevFeedUpdatingEvent?.id) loadSubscriptions()
|
if (!event.isRunning && event.id != prevFeedUpdatingEvent?.id) loadSubscriptions()
|
||||||
prevFeedUpdatingEvent = event
|
prevFeedUpdatingEvent = event
|
||||||
}
|
}
|
||||||
|
@ -377,18 +384,20 @@ class SubscriptionsFragment : Fragment(), Toolbar.OnMenuItemClickListener, Selec
|
||||||
// We have fewer items. This can result in items being selected that are no longer visible.
|
// We have fewer items. This can result in items being selected that are no longer visible.
|
||||||
if (feedListFiltered.size > feedList.size) adapter.endSelectMode()
|
if (feedListFiltered.size > feedList.size) adapter.endSelectMode()
|
||||||
filterOnTag()
|
filterOnTag()
|
||||||
binding.progressBar.visibility = View.GONE
|
// binding.progressBar.visibility = View.GONE
|
||||||
adapter.setItems(feedListFiltered)
|
adapter.setItems(feedListFiltered)
|
||||||
binding.count.text = feedListFiltered.size.toString() + " / " + feedList.size.toString()
|
binding.count.text = feedListFiltered.size.toString() + " / " + feedList.size.toString()
|
||||||
|
infoTextFiltered = " "
|
||||||
|
binding.txtvInformation.setOnClickListener {}
|
||||||
if (feedsFilter.isNotEmpty()) {
|
if (feedsFilter.isNotEmpty()) {
|
||||||
val filter = FeedFilter(feedsFilter)
|
val filter = FeedFilter(feedsFilter)
|
||||||
binding.txtvInformation.text = ("{gmo-info} " + getString(R.string.filtered_label))
|
infoTextFiltered = getString(R.string.filtered_label)
|
||||||
binding.txtvInformation.setOnClickListener {
|
binding.txtvInformation.setOnClickListener {
|
||||||
val dialog = FeedFilterDialog.newInstance(filter)
|
val dialog = FeedFilterDialog.newInstance(filter)
|
||||||
dialog.show(childFragmentManager, null)
|
dialog.show(childFragmentManager, null)
|
||||||
}
|
}
|
||||||
binding.txtvInformation.visibility = View.VISIBLE
|
}
|
||||||
} else binding.txtvInformation.visibility = View.GONE
|
binding.txtvInformation.text = (infoTextFiltered + infoTextUpdate)
|
||||||
emptyView.updateVisibility()
|
emptyView.updateVisibility()
|
||||||
}
|
}
|
||||||
} catch (e: Throwable) { Log.e(TAG, Log.getStackTraceString(e))
|
} catch (e: Throwable) { Log.e(TAG, Log.getStackTraceString(e))
|
||||||
|
@ -1187,7 +1196,7 @@ class SubscriptionsFragment : Fragment(), Toolbar.OnMenuItemClickListener, Selec
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fun onFilterChanged(newFilterValues: Set<String>) {
|
private fun onFilterChanged(newFilterValues: Set<String>) {
|
||||||
feedsFilter = StringUtils.join(newFilterValues, ",")
|
feedsFilter = StringUtils.join(newFilterValues, ",")
|
||||||
Logd(TAG, "onFilterChanged: $feedsFilter")
|
Logd(TAG, "onFilterChanged: $feedsFilter")
|
||||||
EventFlow.postEvent(FlowEvent.FeedsFilterEvent(newFilterValues))
|
EventFlow.postEvent(FlowEvent.FeedsFilterEvent(newFilterValues))
|
||||||
|
|
|
@ -187,7 +187,6 @@
|
||||||
android:padding="2dp"
|
android:padding="2dp"
|
||||||
android:background="?android:attr/colorBackground"
|
android:background="?android:attr/colorBackground"
|
||||||
android:foreground="?android:attr/selectableItemBackground"
|
android:foreground="?android:attr/selectableItemBackground"
|
||||||
android:visibility="gone"
|
|
||||||
android:gravity="center"
|
android:gravity="center"
|
||||||
android:textColor="?attr/colorAccent"
|
android:textColor="?attr/colorAccent"
|
||||||
tools:visibility="visible"
|
tools:visibility="visible"
|
||||||
|
|
|
@ -50,7 +50,6 @@
|
||||||
android:padding="2dp"
|
android:padding="2dp"
|
||||||
android:background="?android:attr/colorBackground"
|
android:background="?android:attr/colorBackground"
|
||||||
android:foreground="?android:attr/selectableItemBackground"
|
android:foreground="?android:attr/selectableItemBackground"
|
||||||
android:visibility="gone"
|
|
||||||
android:gravity="center"
|
android:gravity="center"
|
||||||
android:textColor="?attr/colorAccent"
|
android:textColor="?attr/colorAccent"
|
||||||
tools:visibility="visible"
|
tools:visibility="visible"
|
||||||
|
|
|
@ -119,6 +119,7 @@
|
||||||
<string name="error_label">Error</string>
|
<string name="error_label">Error</string>
|
||||||
<string name="error_msg_prefix">An error occurred:</string>
|
<string name="error_msg_prefix">An error occurred:</string>
|
||||||
<string name="refresh_label">Refresh</string>
|
<string name="refresh_label">Refresh</string>
|
||||||
|
<string name="refreshing_label">Refreshing</string>
|
||||||
<string name="reconsile_label">Reconsile</string>
|
<string name="reconsile_label">Reconsile</string>
|
||||||
<string name="chapters_label">Chapters</string>
|
<string name="chapters_label">Chapters</string>
|
||||||
<string name="no_chapters_label">No chapters</string>
|
<string name="no_chapters_label">No chapters</string>
|
||||||
|
@ -478,6 +479,8 @@
|
||||||
<string name="pref_audio_only_sum">Only play audio of a video media</string>
|
<string name="pref_audio_only_sum">Only play audio of a video media</string>
|
||||||
<string name="pref_stream_over_download_title">Prefer streaming</string>
|
<string name="pref_stream_over_download_title">Prefer streaming</string>
|
||||||
<string name="pref_stream_over_download_sum">Display stream button instead of download button in lists</string>
|
<string name="pref_stream_over_download_sum">Display stream button instead of download button in lists</string>
|
||||||
|
<string name="pref_low_quality_on_mobile_title">Prefer low quality on mobile</string>
|
||||||
|
<string name="pref_low_quality_on_mobile_sum">On metered network, only low quality media (if available) is fetched</string>
|
||||||
<string name="pref_mobileUpdate_title">Mobile updates</string>
|
<string name="pref_mobileUpdate_title">Mobile updates</string>
|
||||||
<string name="pref_mobileUpdate_sum">Select what should be allowed over the mobile data connection</string>
|
<string name="pref_mobileUpdate_sum">Select what should be allowed over the mobile data connection</string>
|
||||||
<string name="pref_mobileUpdate_refresh">Podcast refresh</string>
|
<string name="pref_mobileUpdate_refresh">Podcast refresh</string>
|
||||||
|
|
|
@ -57,10 +57,15 @@
|
||||||
android:summary="@string/pref_speed_forward_sum"
|
android:summary="@string/pref_speed_forward_sum"
|
||||||
android:title="@string/pref_speed_forward"/>
|
android:title="@string/pref_speed_forward"/>
|
||||||
<SwitchPreferenceCompat
|
<SwitchPreferenceCompat
|
||||||
android:defaultValue="false"
|
android:defaultValue="false"
|
||||||
android:key="prefStreamOverDownload"
|
android:key="prefStreamOverDownload"
|
||||||
android:summary="@string/pref_stream_over_download_sum"
|
android:summary="@string/pref_stream_over_download_sum"
|
||||||
android:title="@string/pref_stream_over_download_title"/>
|
android:title="@string/pref_stream_over_download_title"/>
|
||||||
|
<SwitchPreferenceCompat
|
||||||
|
android:defaultValue="false"
|
||||||
|
android:key="prefLowQualityOnMobile"
|
||||||
|
android:summary="@string/pref_low_quality_on_mobile_sum"
|
||||||
|
android:title="@string/pref_low_quality_on_mobile_title"/>
|
||||||
<Preference
|
<Preference
|
||||||
android:title="@string/pref_playback_video_mode"
|
android:title="@string/pref_playback_video_mode"
|
||||||
android:key="prefPlaybackVideoModeLauncher"
|
android:key="prefPlaybackVideoModeLauncher"
|
||||||
|
|
|
@ -1,3 +1,11 @@
|
||||||
|
# 6.6.1
|
||||||
|
|
||||||
|
* the confirm dialog is more responsive when receiving a youtube media share
|
||||||
|
* receiving a youtube media share can be dismissed by not pressing the confirm button
|
||||||
|
* in Subscriptions and FeedEpisodes views, swipe down to refresh no longer blocks UI, only shows "Refreshing" status on the info bar
|
||||||
|
* added preference "Prefer low quality on mobile" under Settings -> Playback -> Playback control, and default it to false,
|
||||||
|
* if set true, Youtube media will use low quality audio on mobile network (which has been the default way of handling)
|
||||||
|
|
||||||
# 6.6.0
|
# 6.6.0
|
||||||
|
|
||||||
* added ability to receive shared Youtube media,
|
* added ability to receive shared Youtube media,
|
||||||
|
|
|
@ -1,4 +1,4 @@
|
||||||
Version 6.5.10:
|
Version 6.6.0:
|
||||||
|
|
||||||
* added ability to receive shared Youtube media,
|
* added ability to receive shared Youtube media,
|
||||||
* once received, the user can choose to set it as "audio only" before confirm
|
* once received, the user can choose to set it as "audio only" before confirm
|
||||||
|
|
|
@ -0,0 +1,7 @@
|
||||||
|
Version 6.6.1:
|
||||||
|
|
||||||
|
* the confirm dialog is more responsive when receiving a youtube media share
|
||||||
|
* receiving a youtube media share can be dismissed by not pressing the confirm button
|
||||||
|
* in Subscriptions and FeedEpisodes views, swipe down to refresh no longer blocks UI, only shows "Refreshing" status on the info bar
|
||||||
|
* added preference "Prefer low quality on mobile" under Settings -> Playback -> Playback control, and default it to false,
|
||||||
|
* if set true, Youtube media will use low quality audio on mobile network (which has been the default way of handling)
|
Loading…
Reference in New Issue