6.9.3 commit
This commit is contained in:
parent
3ba9134c6f
commit
ac6d2bd105
|
@ -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 3020267
|
versionCode 3020268
|
||||||
versionName "6.9.2"
|
versionName "6.9.3"
|
||||||
|
|
||||||
applicationId "ac.mdiq.podcini.R"
|
applicationId "ac.mdiq.podcini.R"
|
||||||
def commit = ""
|
def commit = ""
|
||||||
|
|
|
@ -75,8 +75,8 @@ object EpisodeMenuHandler {
|
||||||
setItemTitle(menu, R.id.mark_unread_item, R.string.mark_unread_label_no_media)
|
setItemTitle(menu, R.id.mark_unread_item, R.string.mark_unread_label_no_media)
|
||||||
}
|
}
|
||||||
|
|
||||||
setItemVisibility(menu, R.id.add_to_favorites_item, !isFavorite)
|
// setItemVisibility(menu, R.id.add_to_favorites_item, !isFavorite)
|
||||||
setItemVisibility(menu, R.id.remove_from_favorites_item, isFavorite)
|
// setItemVisibility(menu, R.id.remove_from_favorites_item, isFavorite)
|
||||||
|
|
||||||
CoroutineScope(Dispatchers.Main).launch {
|
CoroutineScope(Dispatchers.Main).launch {
|
||||||
val fileDownloaded = withContext(Dispatchers.IO) { hasMedia && selectedItem.media?.fileExists() ?: false }
|
val fileDownloaded = withContext(Dispatchers.IO) { hasMedia && selectedItem.media?.fileExists() ?: false }
|
||||||
|
@ -167,8 +167,8 @@ object EpisodeMenuHandler {
|
||||||
}
|
}
|
||||||
R.id.add_to_queue_item -> addToQueue(true, selectedItem)
|
R.id.add_to_queue_item -> addToQueue(true, selectedItem)
|
||||||
R.id.remove_from_queue_item -> removeFromQueue(selectedItem)
|
R.id.remove_from_queue_item -> removeFromQueue(selectedItem)
|
||||||
R.id.add_to_favorites_item -> setFavorite(selectedItem, true)
|
// R.id.add_to_favorites_item -> setFavorite(selectedItem, true)
|
||||||
R.id.remove_from_favorites_item -> setFavorite(selectedItem, false)
|
// R.id.remove_from_favorites_item -> setFavorite(selectedItem, false)
|
||||||
R.id.reset_position -> {
|
R.id.reset_position -> {
|
||||||
selectedItem.media?.setPosition(0)
|
selectedItem.media?.setPosition(0)
|
||||||
if (curState.curMediaId == (selectedItem.media?.id ?: "")) {
|
if (curState.curMediaId == (selectedItem.media?.id ?: "")) {
|
||||||
|
|
|
@ -1,166 +0,0 @@
|
||||||
package ac.mdiq.podcini.ui.actions
|
|
||||||
|
|
||||||
import ac.mdiq.podcini.R
|
|
||||||
import ac.mdiq.podcini.databinding.SelectQueueDialogBinding
|
|
||||||
import ac.mdiq.podcini.net.download.service.DownloadServiceInterface
|
|
||||||
import ac.mdiq.podcini.playback.base.InTheatre.curQueue
|
|
||||||
import ac.mdiq.podcini.storage.database.Episodes
|
|
||||||
import ac.mdiq.podcini.storage.database.Episodes.setPlayState
|
|
||||||
import ac.mdiq.podcini.storage.database.Queues
|
|
||||||
import ac.mdiq.podcini.storage.database.Queues.addToQueueSync
|
|
||||||
import ac.mdiq.podcini.storage.database.Queues.removeFromAllQueuesQuiet
|
|
||||||
import ac.mdiq.podcini.storage.database.Queues.removeFromQueue
|
|
||||||
import ac.mdiq.podcini.storage.database.RealmDB.realm
|
|
||||||
import ac.mdiq.podcini.storage.model.Episode
|
|
||||||
import ac.mdiq.podcini.storage.model.PlayQueue
|
|
||||||
import ac.mdiq.podcini.ui.activity.MainActivity
|
|
||||||
import ac.mdiq.podcini.ui.utils.LocalDeleteModal
|
|
||||||
import ac.mdiq.podcini.util.EventFlow
|
|
||||||
import ac.mdiq.podcini.util.FlowEvent
|
|
||||||
import android.app.Activity
|
|
||||||
import android.content.DialogInterface
|
|
||||||
import android.util.Log
|
|
||||||
import android.view.LayoutInflater
|
|
||||||
import android.view.View
|
|
||||||
import android.widget.RadioButton
|
|
||||||
import androidx.annotation.PluralsRes
|
|
||||||
import androidx.media3.common.util.UnstableApi
|
|
||||||
import com.google.android.material.dialog.MaterialAlertDialogBuilder
|
|
||||||
import com.google.android.material.snackbar.Snackbar
|
|
||||||
import kotlinx.coroutines.runBlocking
|
|
||||||
import java.lang.ref.WeakReference
|
|
||||||
|
|
||||||
|
|
||||||
@UnstableApi
|
|
||||||
class EpisodeMultiSelectHandler(private val activity: MainActivity, private val actionId: Int) {
|
|
||||||
private var totalNumItems = 0
|
|
||||||
private var snackbar: Snackbar? = null
|
|
||||||
|
|
||||||
fun handleAction(items: List<Episode>) {
|
|
||||||
when (actionId) {
|
|
||||||
R.id.toggle_favorite_batch -> toggleFavorite(items)
|
|
||||||
R.id.add_to_queue_batch -> queueChecked(items)
|
|
||||||
R.id.put_in_queue_batch -> PutToQueueDialog(activity, items).show()
|
|
||||||
R.id.remove_from_queue_batch -> removeFromQueueChecked(items)
|
|
||||||
R.id.toggle_played_batch -> {
|
|
||||||
setPlayState(Episode.PlayState.UNSPECIFIED.code, false, *items.toTypedArray())
|
|
||||||
// showMessage(R.plurals.marked_read_batch_label, items.size)
|
|
||||||
}
|
|
||||||
R.id.download_batch -> downloadChecked(items)
|
|
||||||
R.id.delete_batch -> deleteChecked(items)
|
|
||||||
else -> Log.e(TAG, "Unrecognized speed dial action item. Do nothing. id=$actionId")
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private fun queueChecked(items: List<Episode>) {
|
|
||||||
// Check if an episode actually contains any media files before adding it to queue
|
|
||||||
// val toQueue = mutableListOf<Long>()
|
|
||||||
// for (episode in items) {
|
|
||||||
// if (episode.media != null) toQueue.add(episode.id)
|
|
||||||
// }
|
|
||||||
Queues.addToQueue(true, *items.toTypedArray())
|
|
||||||
showMessage(R.plurals.added_to_queue_batch_label, items.size)
|
|
||||||
}
|
|
||||||
|
|
||||||
private fun removeFromQueueChecked(items: List<Episode>) {
|
|
||||||
// val checkedIds = getSelectedIds(items)
|
|
||||||
removeFromQueue(*items.toTypedArray())
|
|
||||||
showMessage(R.plurals.removed_from_queue_batch_label, items.size)
|
|
||||||
}
|
|
||||||
|
|
||||||
private fun toggleFavorite(items: List<Episode>) {
|
|
||||||
for (item in items) {
|
|
||||||
Episodes.setFavorite(item, null)
|
|
||||||
}
|
|
||||||
showMessage(R.plurals.marked_favorite_batch_label, items.size)
|
|
||||||
}
|
|
||||||
|
|
||||||
private fun downloadChecked(items: List<Episode>) {
|
|
||||||
// download the check episodes in the same order as they are currently displayed
|
|
||||||
for (episode in items) {
|
|
||||||
if (episode.media != null && episode.feed != null && !episode.feed!!.isLocalFeed) DownloadServiceInterface.get()?.download(activity, episode)
|
|
||||||
}
|
|
||||||
showMessage(R.plurals.downloading_batch_label, items.size)
|
|
||||||
}
|
|
||||||
|
|
||||||
private fun deleteChecked(items: List<Episode>) {
|
|
||||||
LocalDeleteModal.deleteEpisodesWarnLocal(activity, items)
|
|
||||||
showMessage(R.plurals.deleted_multi_episode_batch_label, items.size)
|
|
||||||
}
|
|
||||||
|
|
||||||
private fun showMessage(@PluralsRes msgId: Int, numItems: Int) {
|
|
||||||
totalNumItems += numItems
|
|
||||||
activity.runOnUiThread {
|
|
||||||
val text: String = activity.resources.getQuantityString(msgId, totalNumItems, totalNumItems)
|
|
||||||
if (snackbar != null) {
|
|
||||||
snackbar?.setText(text)
|
|
||||||
snackbar?.show() // Resets the timeout
|
|
||||||
} else snackbar = activity.showSnackbarAbovePlayer(text, Snackbar.LENGTH_LONG)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// private fun getSelectedIds(items: List<Episode>): List<Long> {
|
|
||||||
// val checkedIds = mutableListOf<Long>()
|
|
||||||
// for (i in items.indices) {
|
|
||||||
// checkedIds.add(items[i].id)
|
|
||||||
// }
|
|
||||||
// return checkedIds
|
|
||||||
// }
|
|
||||||
|
|
||||||
class PutToQueueDialog(activity: Activity, val items: List<Episode>) {
|
|
||||||
private val activityRef: WeakReference<Activity> = WeakReference(activity)
|
|
||||||
|
|
||||||
fun show() {
|
|
||||||
val activity = activityRef.get() ?: return
|
|
||||||
val binding = SelectQueueDialogBinding.inflate(LayoutInflater.from(activity))
|
|
||||||
binding.removeCheckbox.visibility = View.VISIBLE
|
|
||||||
|
|
||||||
val queues = realm.query(PlayQueue::class).find()
|
|
||||||
for (i in queues.indices) {
|
|
||||||
val radioButton = RadioButton(activity)
|
|
||||||
radioButton.text = queues[i].name
|
|
||||||
radioButton.textSize = 20f
|
|
||||||
radioButton.tag = i
|
|
||||||
binding.radioGroup.addView(radioButton)
|
|
||||||
}
|
|
||||||
var toQueue: PlayQueue = curQueue
|
|
||||||
binding.radioGroup.setOnCheckedChangeListener { group, checkedId ->
|
|
||||||
val radioButton = group.findViewById<RadioButton>(checkedId)
|
|
||||||
val selectedIndex = radioButton.tag as Int
|
|
||||||
toQueue = queues[selectedIndex]
|
|
||||||
}
|
|
||||||
val dialog = MaterialAlertDialogBuilder(activity)
|
|
||||||
.setView(binding.root)
|
|
||||||
.setTitle(R.string.put_in_queue_label)
|
|
||||||
.setPositiveButton(android.R.string.ok) { _: DialogInterface?, _: Int ->
|
|
||||||
// val queues = realm.query(PlayQueue::class).find()
|
|
||||||
if (binding.removeCheckbox.isChecked) {
|
|
||||||
val toRemove = mutableSetOf<Long>()
|
|
||||||
val toRemoveCur = mutableListOf<Episode>()
|
|
||||||
items.forEach { e ->
|
|
||||||
if (curQueue.contains(e)) toRemoveCur.add(e)
|
|
||||||
}
|
|
||||||
items.forEach { e ->
|
|
||||||
for (q in queues) {
|
|
||||||
if (q.contains(e)) {
|
|
||||||
toRemove.add(e.id)
|
|
||||||
break
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if (toRemove.isNotEmpty()) runBlocking { removeFromAllQueuesQuiet(toRemove.toList()) }
|
|
||||||
if (toRemoveCur.isNotEmpty()) EventFlow.postEvent(FlowEvent.QueueEvent.removed(toRemoveCur))
|
|
||||||
}
|
|
||||||
items.forEach { e ->
|
|
||||||
runBlocking { addToQueueSync(false, e, toQueue) }
|
|
||||||
}
|
|
||||||
}
|
|
||||||
.setNegativeButton(R.string.cancel_label, null)
|
|
||||||
dialog.show()
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
companion object {
|
|
||||||
private val TAG: String = EpisodeMultiSelectHandler::class.simpleName ?: "Anonymous"
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -399,7 +399,7 @@ class MainActivity : CastEnabledActivity() {
|
||||||
navigationBarInsets.bottom + (if (visible) externalPlayerHeight else 0))
|
navigationBarInsets.bottom + (if (visible) externalPlayerHeight else 0))
|
||||||
mainView.layoutParams = params
|
mainView.layoutParams = params
|
||||||
// val playerView = findViewById<FragmentContainerView>(R.id.playerFragment1)
|
// val playerView = findViewById<FragmentContainerView>(R.id.playerFragment1)
|
||||||
val playerView = findViewById<ComposeView>(R.id.composeView1)
|
val playerView = findViewById<ComposeView>(R.id.player1)
|
||||||
val playerParams = playerView?.layoutParams as? MarginLayoutParams
|
val playerParams = playerView?.layoutParams as? MarginLayoutParams
|
||||||
playerParams?.setMargins(navigationBarInsets.left, 0, navigationBarInsets.right, 0)
|
playerParams?.setMargins(navigationBarInsets.left, 0, navigationBarInsets.right, 0)
|
||||||
playerView?.layoutParams = playerParams
|
playerView?.layoutParams = playerParams
|
||||||
|
|
|
@ -9,6 +9,8 @@ import ac.mdiq.podcini.ui.compose.confirmAddYoutubeEpisode
|
||||||
import ac.mdiq.podcini.util.Logd
|
import ac.mdiq.podcini.util.Logd
|
||||||
import ac.mdiq.vista.extractor.services.youtube.YoutubeParsingHelper.isYoutubeServiceURL
|
import ac.mdiq.vista.extractor.services.youtube.YoutubeParsingHelper.isYoutubeServiceURL
|
||||||
import ac.mdiq.vista.extractor.services.youtube.YoutubeParsingHelper.isYoutubeURL
|
import ac.mdiq.vista.extractor.services.youtube.YoutubeParsingHelper.isYoutubeURL
|
||||||
|
import android.app.Service.START_STICKY
|
||||||
|
import android.content.Context
|
||||||
import android.content.DialogInterface
|
import android.content.DialogInterface
|
||||||
import android.content.Intent
|
import android.content.Intent
|
||||||
import android.net.Uri
|
import android.net.Uri
|
||||||
|
@ -20,6 +22,7 @@ import androidx.appcompat.app.AppCompatActivity
|
||||||
import androidx.compose.runtime.mutableStateOf
|
import androidx.compose.runtime.mutableStateOf
|
||||||
import androidx.compose.runtime.remember
|
import androidx.compose.runtime.remember
|
||||||
import androidx.media3.common.util.UnstableApi
|
import androidx.media3.common.util.UnstableApi
|
||||||
|
import androidx.work.WorkerParameters
|
||||||
import com.google.android.material.dialog.MaterialAlertDialogBuilder
|
import com.google.android.material.dialog.MaterialAlertDialogBuilder
|
||||||
import java.net.URL
|
import java.net.URL
|
||||||
import java.net.URLDecoder
|
import java.net.URLDecoder
|
||||||
|
@ -49,42 +52,18 @@ class ShareReceiverActivity : AppCompatActivity() {
|
||||||
Logd(TAG, "feedUrl: $sharedUrl")
|
Logd(TAG, "feedUrl: $sharedUrl")
|
||||||
val log = ShareLog(sharedUrl!!)
|
val log = ShareLog(sharedUrl!!)
|
||||||
upsertBlk(log) {}
|
upsertBlk(log) {}
|
||||||
receiveShared(sharedUrl!!,this, true)
|
|
||||||
|
|
||||||
// val url = URL(sharedUrl)
|
receiveShared(sharedUrl!!,this, true) {
|
||||||
// when {
|
setContent {
|
||||||
//// plain text
|
val showDialog = remember { mutableStateOf(true) }
|
||||||
// sharedUrl!!.matches(Regex("^[^\\s<>/]+\$")) -> {
|
CustomTheme(this) {
|
||||||
// log = upsertBlk(log) {it.type = "text" }
|
confirmAddYoutubeEpisode(listOf(sharedUrl!!), showDialog.value, onDismissRequest = {
|
||||||
// val intent = MainActivity.showOnlineSearch(this, sharedUrl!!)
|
showDialog.value = false
|
||||||
// startActivity(intent)
|
|
||||||
// finish()
|
// finish()
|
||||||
// }
|
})
|
||||||
//// Youtube media
|
}
|
||||||
//// sharedUrl!!.startsWith("https://youtube.com/watch?") || sharedUrl!!.startsWith("https://www.youtube.com/watch?") || sharedUrl!!.startsWith("https://music.youtube.com/watch?") -> {
|
}
|
||||||
// (isYoutubeURL(url) && url.path.startsWith("/watch")) || isYoutubeServiceURL(url) -> {
|
}
|
||||||
// log = upsertBlk(log) {it.type = "youtube media" }
|
|
||||||
// Logd(TAG, "got youtube media")
|
|
||||||
// setContent {
|
|
||||||
// val showDialog = remember { mutableStateOf(true) }
|
|
||||||
// CustomTheme(this@ShareReceiverActivity) {
|
|
||||||
// confirmAddYoutubeEpisode(listOf(sharedUrl!!), showDialog.value, onDismissRequest = {
|
|
||||||
// showDialog.value = false
|
|
||||||
// finish()
|
|
||||||
// })
|
|
||||||
// }
|
|
||||||
// }
|
|
||||||
// }
|
|
||||||
//// podcast or Youtube channel, Youtube playlist, or other?
|
|
||||||
// else -> {
|
|
||||||
// log = upsertBlk(log) {it.type = "podcast" }
|
|
||||||
// Logd(TAG, "Activity was started with url $sharedUrl")
|
|
||||||
// val intent = MainActivity.showOnlineFeed(this, sharedUrl!!)
|
|
||||||
//// intent.putExtra(MainActivity.Extras.started_from_share.name, getIntent().getBooleanExtra(MainActivity.Extras.started_from_share.name, false))
|
|
||||||
// startActivity(intent)
|
|
||||||
// finish()
|
|
||||||
// }
|
|
||||||
// }
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun showNoPodcastFoundError() {
|
private fun showNoPodcastFoundError() {
|
||||||
|
@ -105,13 +84,31 @@ class ShareReceiverActivity : AppCompatActivity() {
|
||||||
overridePendingTransition(android.R.anim.fade_in, android.R.anim.fade_out)
|
overridePendingTransition(android.R.anim.fade_in, android.R.anim.fade_out)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// class UrlFetchWorker(appContext: Context, workerParams: WorkerParameters) : Worker(appContext, workerParams) {
|
||||||
|
// override fun doWork(): Result {
|
||||||
|
// val url = inputData.getString("shared_url") ?: return Result.failure()
|
||||||
|
//
|
||||||
|
// // Fetch the content from URL using OkHttp or another HTTP client
|
||||||
|
// // Ensure you're on a background thread
|
||||||
|
//
|
||||||
|
// return Result.success()
|
||||||
|
// }
|
||||||
|
// }
|
||||||
|
|
||||||
|
// // Schedule the worker
|
||||||
|
// val workRequest = OneTimeWorkRequestBuilder<UrlFetchWorker>()
|
||||||
|
// .setInputData(workDataOf("shared_url" to sharedUrl))
|
||||||
|
// .build()
|
||||||
|
//
|
||||||
|
// WorkManager.getInstance(context).enqueue(workRequest)
|
||||||
|
|
||||||
companion object {
|
companion object {
|
||||||
private val TAG: String = ShareReceiverActivity::class.simpleName ?: "Anonymous"
|
private val TAG: String = ShareReceiverActivity::class.simpleName ?: "Anonymous"
|
||||||
|
|
||||||
const val ARG_FEEDURL: String = "arg.feedurl"
|
const val ARG_FEEDURL: String = "arg.feedurl"
|
||||||
private const val RESULT_ERROR = 2
|
private const val RESULT_ERROR = 2
|
||||||
|
|
||||||
fun receiveShared(sharedUrl: String, activity: AppCompatActivity, finish: Boolean) {
|
fun receiveShared(sharedUrl: String, activity: AppCompatActivity, finish: Boolean, mediaCB: ()->Unit) {
|
||||||
val url = URL(sharedUrl)
|
val url = URL(sharedUrl)
|
||||||
val log = realm.query(ShareLog::class).query("url == $0", sharedUrl).first().find()
|
val log = realm.query(ShareLog::class).query("url == $0", sharedUrl).first().find()
|
||||||
when {
|
when {
|
||||||
|
@ -126,15 +123,7 @@ class ShareReceiverActivity : AppCompatActivity() {
|
||||||
(isYoutubeURL(url) && url.path.startsWith("/watch")) || isYoutubeServiceURL(url) -> {
|
(isYoutubeURL(url) && url.path.startsWith("/watch")) || isYoutubeServiceURL(url) -> {
|
||||||
if (log != null) upsertBlk(log) {it.type = "youtube media" }
|
if (log != null) upsertBlk(log) {it.type = "youtube media" }
|
||||||
Logd(TAG, "got youtube media")
|
Logd(TAG, "got youtube media")
|
||||||
activity.setContent {
|
mediaCB()
|
||||||
val showDialog = remember { mutableStateOf(true) }
|
|
||||||
CustomTheme(activity) {
|
|
||||||
confirmAddYoutubeEpisode(listOf(sharedUrl), showDialog.value, onDismissRequest = {
|
|
||||||
showDialog.value = false
|
|
||||||
if (finish) activity.finish()
|
|
||||||
})
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
// podcast or Youtube channel, Youtube playlist, or other?
|
// podcast or Youtube channel, Youtube playlist, or other?
|
||||||
else -> {
|
else -> {
|
||||||
|
|
|
@ -255,12 +255,12 @@ class VideoplayerActivity : CastEnabledActivity() {
|
||||||
val isItemHasDownloadLink = isEpisodeMedia && (media as EpisodeMedia?)?.downloadUrl != null
|
val isItemHasDownloadLink = isEpisodeMedia && (media as EpisodeMedia?)?.downloadUrl != null
|
||||||
menu.findItem(R.id.share_item).setVisible(hasWebsiteLink || isItemAndHasLink || isItemHasDownloadLink)
|
menu.findItem(R.id.share_item).setVisible(hasWebsiteLink || isItemAndHasLink || isItemHasDownloadLink)
|
||||||
|
|
||||||
menu.findItem(R.id.add_to_favorites_item).setVisible(false)
|
// menu.findItem(R.id.add_to_favorites_item).setVisible(false)
|
||||||
menu.findItem(R.id.remove_from_favorites_item).setVisible(false)
|
// menu.findItem(R.id.remove_from_favorites_item).setVisible(false)
|
||||||
if (isEpisodeMedia) {
|
// if (isEpisodeMedia) {
|
||||||
menu.findItem(R.id.add_to_favorites_item).setVisible(!videoEpisodeFragment.isFavorite)
|
// menu.findItem(R.id.add_to_favorites_item).setVisible(!videoEpisodeFragment.isFavorite)
|
||||||
menu.findItem(R.id.remove_from_favorites_item).setVisible(videoEpisodeFragment.isFavorite)
|
// menu.findItem(R.id.remove_from_favorites_item).setVisible(videoEpisodeFragment.isFavorite)
|
||||||
}
|
// }
|
||||||
|
|
||||||
menu.findItem(R.id.set_sleeptimer_item).setVisible(!isSleepTimerActive())
|
menu.findItem(R.id.set_sleeptimer_item).setVisible(!isSleepTimerActive())
|
||||||
menu.findItem(R.id.disable_sleeptimer_item).setVisible(isSleepTimerActive())
|
menu.findItem(R.id.disable_sleeptimer_item).setVisible(isSleepTimerActive())
|
||||||
|
@ -271,8 +271,8 @@ class VideoplayerActivity : CastEnabledActivity() {
|
||||||
menu.findItem(R.id.player_show_chapters).setVisible(true)
|
menu.findItem(R.id.player_show_chapters).setVisible(true)
|
||||||
|
|
||||||
if (videoMode == VideoMode.WINDOW_VIEW) {
|
if (videoMode == VideoMode.WINDOW_VIEW) {
|
||||||
menu.findItem(R.id.add_to_favorites_item).setShowAsAction(SHOW_AS_ACTION_NEVER)
|
// menu.findItem(R.id.add_to_favorites_item).setShowAsAction(SHOW_AS_ACTION_NEVER)
|
||||||
menu.findItem(R.id.remove_from_favorites_item).setShowAsAction(SHOW_AS_ACTION_NEVER)
|
// menu.findItem(R.id.remove_from_favorites_item).setShowAsAction(SHOW_AS_ACTION_NEVER)
|
||||||
menu.findItem(R.id.set_sleeptimer_item).setShowAsAction(SHOW_AS_ACTION_NEVER)
|
menu.findItem(R.id.set_sleeptimer_item).setShowAsAction(SHOW_AS_ACTION_NEVER)
|
||||||
menu.findItem(R.id.disable_sleeptimer_item).setShowAsAction(SHOW_AS_ACTION_NEVER)
|
menu.findItem(R.id.disable_sleeptimer_item).setShowAsAction(SHOW_AS_ACTION_NEVER)
|
||||||
menu.findItem(R.id.player_switch_to_audio_only).setShowAsAction(SHOW_AS_ACTION_NEVER)
|
menu.findItem(R.id.player_switch_to_audio_only).setShowAsAction(SHOW_AS_ACTION_NEVER)
|
||||||
|
@ -305,16 +305,16 @@ class VideoplayerActivity : CastEnabledActivity() {
|
||||||
val media = curMedia ?: return false
|
val media = curMedia ?: return false
|
||||||
val feedItem = (media as? EpisodeMedia)?.episodeOrFetch()
|
val feedItem = (media as? EpisodeMedia)?.episodeOrFetch()
|
||||||
when {
|
when {
|
||||||
item.itemId == R.id.add_to_favorites_item && feedItem != null -> {
|
// item.itemId == R.id.add_to_favorites_item && feedItem != null -> {
|
||||||
setFavorite(feedItem, true)
|
// setFavorite(feedItem, true)
|
||||||
videoEpisodeFragment.isFavorite = true
|
// videoEpisodeFragment.isFavorite = true
|
||||||
invalidateOptionsMenu()
|
// invalidateOptionsMenu()
|
||||||
}
|
// }
|
||||||
item.itemId == R.id.remove_from_favorites_item && feedItem != null -> {
|
// item.itemId == R.id.remove_from_favorites_item && feedItem != null -> {
|
||||||
setFavorite(feedItem, false)
|
// setFavorite(feedItem, false)
|
||||||
videoEpisodeFragment.isFavorite = false
|
// videoEpisodeFragment.isFavorite = false
|
||||||
invalidateOptionsMenu()
|
// invalidateOptionsMenu()
|
||||||
}
|
// }
|
||||||
item.itemId == R.id.disable_sleeptimer_item || item.itemId == R.id.set_sleeptimer_item ->
|
item.itemId == R.id.disable_sleeptimer_item || item.itemId == R.id.set_sleeptimer_item ->
|
||||||
SleepTimerDialog().show(supportFragmentManager, "SleepTimerDialog")
|
SleepTimerDialog().show(supportFragmentManager, "SleepTimerDialog")
|
||||||
item.itemId == R.id.audio_controls -> {
|
item.itemId == R.id.audio_controls -> {
|
||||||
|
|
|
@ -13,38 +13,19 @@ 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.graphics.Color
|
import androidx.compose.ui.graphics.Color
|
||||||
import androidx.compose.ui.platform.LocalContext
|
|
||||||
import androidx.compose.ui.unit.dp
|
import androidx.compose.ui.unit.dp
|
||||||
import kotlinx.coroutines.delay
|
import kotlinx.coroutines.delay
|
||||||
|
|
||||||
@OptIn(ExperimentalMaterial3Api::class)
|
@OptIn(ExperimentalMaterial3Api::class)
|
||||||
@Composable
|
@Composable
|
||||||
fun Spinner(
|
fun Spinner(items: List<String>, selectedItem: String, onItemSelected: (String) -> Unit) {
|
||||||
items: List<String>,
|
|
||||||
selectedItem: String,
|
|
||||||
onItemSelected: (String) -> Unit
|
|
||||||
) {
|
|
||||||
var expanded by remember { mutableStateOf(false) }
|
var expanded by remember { mutableStateOf(false) }
|
||||||
val context = LocalContext.current
|
|
||||||
|
|
||||||
ExposedDropdownMenuBox(
|
ExposedDropdownMenuBox(expanded = expanded, onExpandedChange = { expanded = it }) {
|
||||||
expanded = expanded,
|
TextField(readOnly = true, value = selectedItem, onValueChange = {}, label = { Text("Select an item") },
|
||||||
onExpandedChange = { expanded = !expanded }
|
modifier = Modifier.menuAnchor(MenuAnchorType.PrimaryNotEditable, true), // Material3 requirement
|
||||||
) {
|
trailingIcon = { ExposedDropdownMenuDefaults.TrailingIcon(expanded = expanded) }, colors = ExposedDropdownMenuDefaults.textFieldColors())
|
||||||
TextField(
|
ExposedDropdownMenu(expanded = expanded, onDismissRequest = { expanded = false }) {
|
||||||
readOnly = true,
|
|
||||||
value = selectedItem,
|
|
||||||
onValueChange = {},
|
|
||||||
label = { Text("Select an item") },
|
|
||||||
trailingIcon = {
|
|
||||||
ExposedDropdownMenuDefaults.TrailingIcon(expanded = expanded)
|
|
||||||
},
|
|
||||||
colors = ExposedDropdownMenuDefaults.textFieldColors()
|
|
||||||
)
|
|
||||||
ExposedDropdownMenu(
|
|
||||||
expanded = expanded,
|
|
||||||
onDismissRequest = { expanded = false }
|
|
||||||
) {
|
|
||||||
items.forEach { item ->
|
items.forEach { item ->
|
||||||
DropdownMenuItem(text = { Text(item) },
|
DropdownMenuItem(text = { Text(item) },
|
||||||
onClick = {
|
onClick = {
|
||||||
|
|
|
@ -12,21 +12,25 @@ import ac.mdiq.podcini.storage.database.Episodes.setPlayState
|
||||||
import ac.mdiq.podcini.storage.database.Feeds.addToMiscSyndicate
|
import ac.mdiq.podcini.storage.database.Feeds.addToMiscSyndicate
|
||||||
import ac.mdiq.podcini.storage.database.Feeds.addToYoutubeSyndicate
|
import ac.mdiq.podcini.storage.database.Feeds.addToYoutubeSyndicate
|
||||||
import ac.mdiq.podcini.storage.database.Queues
|
import ac.mdiq.podcini.storage.database.Queues
|
||||||
|
import ac.mdiq.podcini.storage.database.Queues.addToQueueSync
|
||||||
|
import ac.mdiq.podcini.storage.database.Queues.removeFromAllQueuesQuiet
|
||||||
import ac.mdiq.podcini.storage.database.Queues.removeFromQueue
|
import ac.mdiq.podcini.storage.database.Queues.removeFromQueue
|
||||||
import ac.mdiq.podcini.storage.database.RealmDB.realm
|
import ac.mdiq.podcini.storage.database.RealmDB.realm
|
||||||
import ac.mdiq.podcini.storage.database.RealmDB.upsert
|
import ac.mdiq.podcini.storage.database.RealmDB.upsert
|
||||||
import ac.mdiq.podcini.storage.model.Episode
|
import ac.mdiq.podcini.storage.model.Episode
|
||||||
import ac.mdiq.podcini.storage.model.MediaType
|
import ac.mdiq.podcini.storage.model.MediaType
|
||||||
|
import ac.mdiq.podcini.storage.model.PlayQueue
|
||||||
import ac.mdiq.podcini.storage.model.ShareLog
|
import ac.mdiq.podcini.storage.model.ShareLog
|
||||||
import ac.mdiq.podcini.storage.utils.DurationConverter
|
import ac.mdiq.podcini.storage.utils.DurationConverter
|
||||||
import ac.mdiq.podcini.storage.utils.ImageResourceUtils
|
import ac.mdiq.podcini.storage.utils.ImageResourceUtils
|
||||||
import ac.mdiq.podcini.ui.actions.EpisodeActionButton
|
import ac.mdiq.podcini.ui.actions.EpisodeActionButton
|
||||||
import ac.mdiq.podcini.ui.actions.EpisodeMultiSelectHandler.PutToQueueDialog
|
|
||||||
import ac.mdiq.podcini.ui.actions.SwipeAction
|
import ac.mdiq.podcini.ui.actions.SwipeAction
|
||||||
import ac.mdiq.podcini.ui.activity.MainActivity
|
import ac.mdiq.podcini.ui.activity.MainActivity
|
||||||
import ac.mdiq.podcini.ui.fragment.EpisodeInfoFragment
|
import ac.mdiq.podcini.ui.fragment.EpisodeInfoFragment
|
||||||
import ac.mdiq.podcini.ui.fragment.FeedInfoFragment
|
import ac.mdiq.podcini.ui.fragment.FeedInfoFragment
|
||||||
import ac.mdiq.podcini.ui.utils.LocalDeleteModal
|
import ac.mdiq.podcini.ui.utils.LocalDeleteModal
|
||||||
|
import ac.mdiq.podcini.util.EventFlow
|
||||||
|
import ac.mdiq.podcini.util.FlowEvent
|
||||||
import ac.mdiq.podcini.util.Logd
|
import ac.mdiq.podcini.util.Logd
|
||||||
import ac.mdiq.podcini.util.MiscFormatter.formatAbbrev
|
import ac.mdiq.podcini.util.MiscFormatter.formatAbbrev
|
||||||
import ac.mdiq.vista.extractor.Vista
|
import ac.mdiq.vista.extractor.Vista
|
||||||
|
@ -173,6 +177,77 @@ class EpisodeVM(var episode: Episode) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Composable
|
||||||
|
fun ChooseRatingDialog(selected: List<Episode>, onDismissRequest: () -> Unit) {
|
||||||
|
Dialog(onDismissRequest = onDismissRequest) {
|
||||||
|
Surface(shape = RoundedCornerShape(16.dp)) {
|
||||||
|
Column(modifier = Modifier.padding(16.dp), verticalArrangement = Arrangement.spacedBy(16.dp)) {
|
||||||
|
for (rating in Episode.Rating.entries) {
|
||||||
|
Row(verticalAlignment = Alignment.CenterVertically, modifier = Modifier.padding(4.dp).clickable {
|
||||||
|
for (item in selected) Episodes.setRating(item, rating.code)
|
||||||
|
onDismissRequest()
|
||||||
|
}) {
|
||||||
|
Icon(imageVector = ImageVector.vectorResource(id = rating.res), "")
|
||||||
|
Text(rating.name, Modifier.padding(start = 4.dp))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Composable
|
||||||
|
fun PutToQueueDialog(selected: List<Episode>, onDismissRequest: () -> Unit) {
|
||||||
|
val queues = realm.query(PlayQueue::class).find()
|
||||||
|
Dialog(onDismissRequest = onDismissRequest) {
|
||||||
|
Surface(shape = RoundedCornerShape(16.dp)) {
|
||||||
|
val scrollState = rememberScrollState()
|
||||||
|
Column(modifier = Modifier.verticalScroll(scrollState).padding(16.dp), verticalArrangement = Arrangement.spacedBy(1.dp)) {
|
||||||
|
var removeChecked by remember { mutableStateOf(false) }
|
||||||
|
var toQueue by remember { mutableStateOf(curQueue) }
|
||||||
|
for (q in queues) {
|
||||||
|
Row(verticalAlignment = Alignment.CenterVertically) {
|
||||||
|
RadioButton(selected = toQueue == q, onClick = { toQueue = q })
|
||||||
|
Text(q.name,)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
Row(verticalAlignment = Alignment.CenterVertically) {
|
||||||
|
Checkbox(checked = removeChecked, onCheckedChange = { removeChecked = it })
|
||||||
|
Text(text = stringResource(R.string.remove_from_other_queues), style = MaterialTheme.typography.bodyLarge.merge(), modifier = Modifier.padding(start = 10.dp))
|
||||||
|
}
|
||||||
|
Row {
|
||||||
|
Spacer(Modifier.weight(1f))
|
||||||
|
Button(onClick = {
|
||||||
|
if (removeChecked) {
|
||||||
|
val toRemove = mutableSetOf<Long>()
|
||||||
|
val toRemoveCur = mutableListOf<Episode>()
|
||||||
|
selected.forEach { e ->
|
||||||
|
if (curQueue.contains(e)) toRemoveCur.add(e)
|
||||||
|
}
|
||||||
|
selected.forEach { e ->
|
||||||
|
for (q in queues) {
|
||||||
|
if (q.contains(e)) {
|
||||||
|
toRemove.add(e.id)
|
||||||
|
break
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (toRemove.isNotEmpty()) runBlocking { removeFromAllQueuesQuiet(toRemove.toList()) }
|
||||||
|
if (toRemoveCur.isNotEmpty()) EventFlow.postEvent(FlowEvent.QueueEvent.removed(toRemoveCur))
|
||||||
|
}
|
||||||
|
selected.forEach { e ->
|
||||||
|
runBlocking { addToQueueSync(false, e, toQueue) }
|
||||||
|
}
|
||||||
|
onDismissRequest()
|
||||||
|
}) {
|
||||||
|
Text("Confirm")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
@OptIn(ExperimentalFoundationApi::class, ExperimentalMaterial3Api::class)
|
@OptIn(ExperimentalFoundationApi::class, ExperimentalMaterial3Api::class)
|
||||||
@Composable
|
@Composable
|
||||||
fun EpisodeLazyColumn(activity: MainActivity, vms: SnapshotStateList<EpisodeVM>, refreshCB: (()->Unit)? = null,
|
fun EpisodeLazyColumn(activity: MainActivity, vms: SnapshotStateList<EpisodeVM>, refreshCB: (()->Unit)? = null,
|
||||||
|
@ -192,26 +267,11 @@ fun EpisodeLazyColumn(activity: MainActivity, vms: SnapshotStateList<EpisodeVM>,
|
||||||
showConfirmYoutubeDialog.value = false
|
showConfirmYoutubeDialog.value = false
|
||||||
})
|
})
|
||||||
|
|
||||||
@Composable
|
|
||||||
fun ChooseRatingDialog(onDismissRequest: () -> Unit) {
|
|
||||||
Dialog(onDismissRequest = onDismissRequest) {
|
|
||||||
Surface(shape = RoundedCornerShape(16.dp)) {
|
|
||||||
Column(modifier = Modifier.padding(16.dp), verticalArrangement = Arrangement.spacedBy(16.dp)) {
|
|
||||||
for (rating in Episode.Rating.entries) {
|
|
||||||
Row(verticalAlignment = Alignment.CenterVertically, modifier = Modifier.padding(4.dp).clickable {
|
|
||||||
for (item in selected) Episodes.setRating(item, rating.code)
|
|
||||||
onDismissRequest()
|
|
||||||
}) {
|
|
||||||
Icon(imageVector = ImageVector.vectorResource(id = rating.res), "")
|
|
||||||
Text(rating.name, Modifier.padding(start = 4.dp))
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
var showChooseRatingDialog by remember { mutableStateOf(false) }
|
var showChooseRatingDialog by remember { mutableStateOf(false) }
|
||||||
if (showChooseRatingDialog) ChooseRatingDialog { showChooseRatingDialog = false }
|
if (showChooseRatingDialog) ChooseRatingDialog(selected) { showChooseRatingDialog = false }
|
||||||
|
|
||||||
|
var showPutToQueueDialog by remember { mutableStateOf(false) }
|
||||||
|
if (showPutToQueueDialog) PutToQueueDialog(selected) { showPutToQueueDialog = false }
|
||||||
|
|
||||||
@Composable
|
@Composable
|
||||||
fun EpisodeSpeedDial(modifier: Modifier = Modifier) {
|
fun EpisodeSpeedDial(modifier: Modifier = Modifier) {
|
||||||
|
@ -270,7 +330,8 @@ fun EpisodeLazyColumn(activity: MainActivity, vms: SnapshotStateList<EpisodeVM>,
|
||||||
isExpanded = false
|
isExpanded = false
|
||||||
selectMode = false
|
selectMode = false
|
||||||
Logd(TAG, "ic_playlist_play: ${selected.size}")
|
Logd(TAG, "ic_playlist_play: ${selected.size}")
|
||||||
PutToQueueDialog(activity, selected).show()
|
showPutToQueueDialog = true
|
||||||
|
// PutToQueueDialog(activity, selected).show()
|
||||||
}, verticalAlignment = Alignment.CenterVertically) {
|
}, verticalAlignment = Alignment.CenterVertically) {
|
||||||
Icon(imageVector = ImageVector.vectorResource(id = R.drawable.ic_playlist_play), "")
|
Icon(imageVector = ImageVector.vectorResource(id = R.drawable.ic_playlist_play), "")
|
||||||
Text(stringResource(id = R.string.put_in_queue_label)) } },
|
Text(stringResource(id = R.string.put_in_queue_label)) } },
|
||||||
|
@ -325,7 +386,6 @@ fun EpisodeLazyColumn(activity: MainActivity, vms: SnapshotStateList<EpisodeVM>,
|
||||||
}
|
}
|
||||||
|
|
||||||
var refreshing by remember { mutableStateOf(false)}
|
var refreshing by remember { mutableStateOf(false)}
|
||||||
|
|
||||||
PullToRefreshBox(modifier = Modifier.fillMaxWidth(), isRefreshing = refreshing, indicator = {}, onRefresh = {
|
PullToRefreshBox(modifier = Modifier.fillMaxWidth(), isRefreshing = refreshing, indicator = {}, onRefresh = {
|
||||||
refreshing = true
|
refreshing = true
|
||||||
refreshCB?.invoke()
|
refreshCB?.invoke()
|
||||||
|
|
|
@ -36,6 +36,7 @@ import ac.mdiq.podcini.ui.actions.EpisodeMenuHandler
|
||||||
import ac.mdiq.podcini.ui.activity.MainActivity
|
import ac.mdiq.podcini.ui.activity.MainActivity
|
||||||
import ac.mdiq.podcini.ui.activity.VideoplayerActivity.Companion.videoMode
|
import ac.mdiq.podcini.ui.activity.VideoplayerActivity.Companion.videoMode
|
||||||
import ac.mdiq.podcini.ui.activity.starter.VideoPlayerActivityStarter
|
import ac.mdiq.podcini.ui.activity.starter.VideoPlayerActivityStarter
|
||||||
|
import ac.mdiq.podcini.ui.compose.ChooseRatingDialog
|
||||||
import ac.mdiq.podcini.ui.compose.CustomTheme
|
import ac.mdiq.podcini.ui.compose.CustomTheme
|
||||||
import ac.mdiq.podcini.ui.dialog.MediaPlayerErrorDialog
|
import ac.mdiq.podcini.ui.dialog.MediaPlayerErrorDialog
|
||||||
import ac.mdiq.podcini.ui.dialog.SkipPreferenceDialog
|
import ac.mdiq.podcini.ui.dialog.SkipPreferenceDialog
|
||||||
|
@ -136,7 +137,7 @@ class AudioPlayerFragment : Fragment(), Toolbar.OnMenuItemClickListener {
|
||||||
private var episodeDate by mutableStateOf("")
|
private var episodeDate by mutableStateOf("")
|
||||||
private var chapterControlVisible by mutableStateOf(false)
|
private var chapterControlVisible by mutableStateOf(false)
|
||||||
private var hasNextChapter by mutableStateOf(true)
|
private var hasNextChapter by mutableStateOf(true)
|
||||||
// var imgLoc by mutableStateOf<String?>("")
|
var rating by mutableStateOf(currentItem?.rating ?: 0)
|
||||||
private val currentChapter: Chapter?
|
private val currentChapter: Chapter?
|
||||||
get() {
|
get() {
|
||||||
if (currentMedia == null || currentMedia!!.getChapters().isEmpty() || displayedChapterIndex == -1) return null
|
if (currentMedia == null || currentMedia!!.getChapters().isEmpty() || displayedChapterIndex == -1) return null
|
||||||
|
@ -160,7 +161,7 @@ class AudioPlayerFragment : Fragment(), Toolbar.OnMenuItemClickListener {
|
||||||
controller!!.init()
|
controller!!.init()
|
||||||
onCollaped()
|
onCollaped()
|
||||||
|
|
||||||
binding.composeView1.setContent {
|
binding.player1.setContent {
|
||||||
CustomTheme(requireContext()) {
|
CustomTheme(requireContext()) {
|
||||||
if (showPlayer1) PlayerUI()
|
if (showPlayer1) PlayerUI()
|
||||||
else Spacer(modifier = Modifier.size(0.dp))
|
else Spacer(modifier = Modifier.size(0.dp))
|
||||||
|
@ -173,7 +174,7 @@ class AudioPlayerFragment : Fragment(), Toolbar.OnMenuItemClickListener {
|
||||||
// else Spacer(modifier = Modifier.size(0.dp))
|
// else Spacer(modifier = Modifier.size(0.dp))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
binding.composeView2.setContent {
|
binding.player2.setContent {
|
||||||
CustomTheme(requireContext()) {
|
CustomTheme(requireContext()) {
|
||||||
if (!showPlayer1) PlayerUI()
|
if (!showPlayer1) PlayerUI()
|
||||||
else Spacer(modifier = Modifier.size(0.dp))
|
else Spacer(modifier = Modifier.size(0.dp))
|
||||||
|
@ -334,6 +335,11 @@ class AudioPlayerFragment : Fragment(), Toolbar.OnMenuItemClickListener {
|
||||||
@OptIn(ExperimentalFoundationApi::class)
|
@OptIn(ExperimentalFoundationApi::class)
|
||||||
@Composable
|
@Composable
|
||||||
fun DetailUI() {
|
fun DetailUI() {
|
||||||
|
var showChooseRatingDialog by remember { mutableStateOf(false) }
|
||||||
|
if (showChooseRatingDialog) ChooseRatingDialog(listOf(currentItem!!)) {
|
||||||
|
showChooseRatingDialog = false
|
||||||
|
}
|
||||||
|
|
||||||
val scrollState = rememberScrollState()
|
val scrollState = rememberScrollState()
|
||||||
Column(modifier = Modifier.fillMaxWidth().verticalScroll(scrollState)) {
|
Column(modifier = Modifier.fillMaxWidth().verticalScroll(scrollState)) {
|
||||||
val textColor = MaterialTheme.colorScheme.onSurface
|
val textColor = MaterialTheme.colorScheme.onSurface
|
||||||
|
@ -354,7 +360,16 @@ class AudioPlayerFragment : Fragment(), Toolbar.OnMenuItemClickListener {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}, onLongClick = { copyText(currentMedia?.getFeedTitle()?:"") }))
|
}, onLongClick = { copyText(currentMedia?.getFeedTitle()?:"") }))
|
||||||
Text(episodeDate, textAlign = TextAlign.Center, modifier = Modifier.fillMaxWidth().padding(top = 2.dp, bottom = 2.dp), color = textColor, style = MaterialTheme.typography.bodyMedium)
|
Row(modifier = Modifier.fillMaxWidth().padding(top = 2.dp, bottom = 2.dp), ) {
|
||||||
|
Spacer(modifier = Modifier.weight(0.2f))
|
||||||
|
var ratingIconRes = Episode.Rating.fromCode(rating).res
|
||||||
|
Icon(painter = painterResource(ratingIconRes), tint = MaterialTheme.colorScheme.tertiary, contentDescription = "rating", modifier = Modifier.width(15.dp).height(15.dp).clickable(onClick = {
|
||||||
|
showChooseRatingDialog = true
|
||||||
|
}))
|
||||||
|
Spacer(modifier = Modifier.weight(0.4f))
|
||||||
|
Text(episodeDate, textAlign = TextAlign.Center, color = textColor, style = MaterialTheme.typography.bodyMedium)
|
||||||
|
Spacer(modifier = Modifier.weight(0.6f))
|
||||||
|
}
|
||||||
Text(titleText, textAlign = TextAlign.Center, color = textColor, style = MaterialTheme.typography.titleLarge, modifier = Modifier.fillMaxWidth().padding(top = 2.dp, bottom = 5.dp)
|
Text(titleText, textAlign = TextAlign.Center, color = textColor, style = MaterialTheme.typography.titleLarge, modifier = Modifier.fillMaxWidth().padding(top = 2.dp, bottom = 5.dp)
|
||||||
.combinedClickable(onClick = {}, onLongClick = { copyText(currentItem?.title?:"") }))
|
.combinedClickable(onClick = {}, onLongClick = { copyText(currentItem?.title?:"") }))
|
||||||
fun restoreFromPreference(): Boolean {
|
fun restoreFromPreference(): Boolean {
|
||||||
|
@ -899,7 +914,7 @@ class AudioPlayerFragment : Fragment(), Toolbar.OnMenuItemClickListener {
|
||||||
onPlaybackServiceChanged(event)
|
onPlaybackServiceChanged(event)
|
||||||
}
|
}
|
||||||
is FlowEvent.PlayEvent -> onPlayEvent(event)
|
is FlowEvent.PlayEvent -> onPlayEvent(event)
|
||||||
is FlowEvent.RatingEvent -> onFavoriteEvent(event)
|
is FlowEvent.RatingEvent -> onRatingEvent(event)
|
||||||
is FlowEvent.PlayerErrorEvent -> MediaPlayerErrorDialog.show(activity as Activity, event)
|
is FlowEvent.PlayerErrorEvent -> MediaPlayerErrorDialog.show(activity as Activity, event)
|
||||||
// is FlowEvent.SleepTimerUpdatedEvent -> if (event.isCancelled || event.wasJustEnabled()) loadMediaInfo(false)
|
// is FlowEvent.SleepTimerUpdatedEvent -> if (event.isCancelled || event.wasJustEnabled()) loadMediaInfo(false)
|
||||||
is FlowEvent.SleepTimerUpdatedEvent -> if (event.isCancelled || event.wasJustEnabled()) setupOptionsMenu()
|
is FlowEvent.SleepTimerUpdatedEvent -> if (event.isCancelled || event.wasJustEnabled()) setupOptionsMenu()
|
||||||
|
@ -911,8 +926,11 @@ class AudioPlayerFragment : Fragment(), Toolbar.OnMenuItemClickListener {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun onFavoriteEvent(event: FlowEvent.RatingEvent) {
|
private fun onRatingEvent(event: FlowEvent.RatingEvent) {
|
||||||
if (curEpisode?.id == event.episode.id) EpisodeMenuHandler.onPrepareMenu(toolbar.menu, event.episode)
|
if (curEpisode?.id == event.episode.id) {
|
||||||
|
rating = event.rating
|
||||||
|
EpisodeMenuHandler.onPrepareMenu(toolbar.menu, event.episode)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun setupOptionsMenu() {
|
private fun setupOptionsMenu() {
|
||||||
|
@ -982,7 +1000,7 @@ class AudioPlayerFragment : Fragment(), Toolbar.OnMenuItemClickListener {
|
||||||
|
|
||||||
fun fadePlayerToToolbar(slideOffset: Float) {
|
fun fadePlayerToToolbar(slideOffset: Float) {
|
||||||
val playerFadeProgress = (max(0.0, min(0.2, (slideOffset - 0.2f).toDouble())) / 0.2f).toFloat()
|
val playerFadeProgress = (max(0.0, min(0.2, (slideOffset - 0.2f).toDouble())) / 0.2f).toFloat()
|
||||||
val player = binding.composeView1
|
val player = binding.player1
|
||||||
player.alpha = 1 - playerFadeProgress
|
player.alpha = 1 - playerFadeProgress
|
||||||
player.visibility = if (playerFadeProgress > 0.99f) View.GONE else View.VISIBLE
|
player.visibility = if (playerFadeProgress > 0.99f) View.GONE else View.VISIBLE
|
||||||
val toolbarFadeProgress = (max(0.0, min(0.2, (slideOffset - 0.6f).toDouble())) / 0.2f).toFloat()
|
val toolbarFadeProgress = (max(0.0, min(0.2, (slideOffset - 0.6f).toDouble())) / 0.2f).toFloat()
|
||||||
|
|
|
@ -11,6 +11,7 @@ import ac.mdiq.podcini.playback.base.InTheatre
|
||||||
import ac.mdiq.podcini.playback.service.PlaybackService.Companion.seekTo
|
import ac.mdiq.podcini.playback.service.PlaybackService.Companion.seekTo
|
||||||
import ac.mdiq.podcini.preferences.UsageStatistics
|
import ac.mdiq.podcini.preferences.UsageStatistics
|
||||||
import ac.mdiq.podcini.preferences.UserPreferences
|
import ac.mdiq.podcini.preferences.UserPreferences
|
||||||
|
import ac.mdiq.podcini.storage.database.RealmDB.realm
|
||||||
import ac.mdiq.podcini.storage.database.RealmDB.runOnIOScope
|
import ac.mdiq.podcini.storage.database.RealmDB.runOnIOScope
|
||||||
import ac.mdiq.podcini.storage.database.RealmDB.unmanaged
|
import ac.mdiq.podcini.storage.database.RealmDB.unmanaged
|
||||||
import ac.mdiq.podcini.storage.database.RealmDB.upsert
|
import ac.mdiq.podcini.storage.database.RealmDB.upsert
|
||||||
|
@ -22,6 +23,7 @@ import ac.mdiq.podcini.storage.utils.DurationConverter
|
||||||
import ac.mdiq.podcini.storage.utils.ImageResourceUtils
|
import ac.mdiq.podcini.storage.utils.ImageResourceUtils
|
||||||
import ac.mdiq.podcini.ui.actions.*
|
import ac.mdiq.podcini.ui.actions.*
|
||||||
import ac.mdiq.podcini.ui.activity.MainActivity
|
import ac.mdiq.podcini.ui.activity.MainActivity
|
||||||
|
import ac.mdiq.podcini.ui.compose.ChooseRatingDialog
|
||||||
import ac.mdiq.podcini.ui.compose.CustomTheme
|
import ac.mdiq.podcini.ui.compose.CustomTheme
|
||||||
import ac.mdiq.podcini.ui.utils.ShownotesCleaner
|
import ac.mdiq.podcini.ui.utils.ShownotesCleaner
|
||||||
import ac.mdiq.podcini.ui.utils.ThemeUtils
|
import ac.mdiq.podcini.ui.utils.ThemeUtils
|
||||||
|
@ -100,6 +102,15 @@ class EpisodeInfoFragment : Fragment(), Toolbar.OnMenuItemClickListener {
|
||||||
private var itemLoaded = false
|
private var itemLoaded = false
|
||||||
private var episode: Episode? = null // managed
|
private var episode: Episode? = null // managed
|
||||||
|
|
||||||
|
private var txtvPodcast by mutableStateOf("")
|
||||||
|
private var txtvTitle by mutableStateOf("")
|
||||||
|
private var txtvPublished by mutableStateOf("")
|
||||||
|
private var txtvSize by mutableStateOf("")
|
||||||
|
private var txtvDuration by mutableStateOf("")
|
||||||
|
private var itemLink by mutableStateOf("")
|
||||||
|
var hasMedia by mutableStateOf(true)
|
||||||
|
var rating by mutableStateOf(episode?.rating ?: 0)
|
||||||
|
|
||||||
private var webviewData by mutableStateOf("")
|
private var webviewData by mutableStateOf("")
|
||||||
|
|
||||||
private lateinit var shownotesCleaner: ShownotesCleaner
|
private lateinit var shownotesCleaner: ShownotesCleaner
|
||||||
|
@ -188,6 +199,11 @@ class EpisodeInfoFragment : Fragment(), Toolbar.OnMenuItemClickListener {
|
||||||
runOnIOScope { if (episode != null) episode = upsert(episode!!) { it.comment = commentTextState.text } }
|
runOnIOScope { if (episode != null) episode = upsert(episode!!) { it.comment = commentTextState.text } }
|
||||||
})
|
})
|
||||||
|
|
||||||
|
var showChooseRatingDialog by remember { mutableStateOf(false) }
|
||||||
|
if (showChooseRatingDialog) ChooseRatingDialog(listOf(episode!!)) {
|
||||||
|
showChooseRatingDialog = false
|
||||||
|
}
|
||||||
|
|
||||||
Column {
|
Column {
|
||||||
Row(modifier = Modifier.padding(start = 16.dp, end = 16.dp), verticalAlignment = Alignment.CenterVertically) {
|
Row(modifier = Modifier.padding(start = 16.dp, end = 16.dp), verticalAlignment = Alignment.CenterVertically) {
|
||||||
val imgLoc = if (episode != null) ImageResourceUtils.getEpisodeListImageLocation(episode!!) else null
|
val imgLoc = if (episode != null) ImageResourceUtils.getEpisodeListImageLocation(episode!!) else null
|
||||||
|
@ -199,7 +215,12 @@ class EpisodeInfoFragment : Fragment(), Toolbar.OnMenuItemClickListener {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
Row(verticalAlignment = Alignment.CenterVertically) {
|
Row(verticalAlignment = Alignment.CenterVertically) {
|
||||||
Spacer(modifier = Modifier.weight(1f))
|
Spacer(modifier = Modifier.weight(0.4f))
|
||||||
|
var ratingIconRes = Episode.Rating.fromCode(rating).res
|
||||||
|
Icon(painter = painterResource(ratingIconRes), tint = MaterialTheme.colorScheme.tertiary, contentDescription = "rating", modifier = Modifier.width(15.dp).height(15.dp).clickable(onClick = {
|
||||||
|
showChooseRatingDialog = true
|
||||||
|
}))
|
||||||
|
Spacer(modifier = Modifier.weight(0.2f))
|
||||||
if (hasMedia) Icon(painter = painterResource(actionButton1?.getDrawable()?: R.drawable.ic_questionmark), tint = textColor, contentDescription = "butAction1",
|
if (hasMedia) Icon(painter = painterResource(actionButton1?.getDrawable()?: R.drawable.ic_questionmark), tint = textColor, contentDescription = "butAction1",
|
||||||
modifier = Modifier.width(24.dp).height(24.dp).clickable(onClick = {
|
modifier = Modifier.width(24.dp).height(24.dp).clickable(onClick = {
|
||||||
when {
|
when {
|
||||||
|
@ -235,7 +256,7 @@ class EpisodeInfoFragment : Fragment(), Toolbar.OnMenuItemClickListener {
|
||||||
})
|
})
|
||||||
// if (cond) CircularProgressIndicator(progress = 0.01f * dlPercent, strokeWidth = 4.dp, color = textColor)
|
// if (cond) CircularProgressIndicator(progress = 0.01f * dlPercent, strokeWidth = 4.dp, color = textColor)
|
||||||
}
|
}
|
||||||
Spacer(modifier = Modifier.weight(1f))
|
Spacer(modifier = Modifier.weight(0.4f))
|
||||||
}
|
}
|
||||||
if (!hasMedia) Text("noMediaLabel", color = textColor, style = MaterialTheme.typography.bodyMedium)
|
if (!hasMedia) Text("noMediaLabel", color = textColor, style = MaterialTheme.typography.bodyMedium)
|
||||||
val scrollState = rememberScrollState()
|
val scrollState = rememberScrollState()
|
||||||
|
@ -367,12 +388,6 @@ 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)
|
else EpisodeMenuHandler.onPrepareMenu(toolbar.menu, episode, R.id.open_podcast, R.id.mark_read_item, R.id.visit_website_item)
|
||||||
}
|
}
|
||||||
|
|
||||||
private var txtvPodcast by mutableStateOf("")
|
|
||||||
private var txtvTitle by mutableStateOf("")
|
|
||||||
private var txtvPublished by mutableStateOf("")
|
|
||||||
private var txtvSize by mutableStateOf("")
|
|
||||||
private var txtvDuration by mutableStateOf("")
|
|
||||||
private var itemLink by mutableStateOf("")
|
|
||||||
@UnstableApi
|
@UnstableApi
|
||||||
private fun updateAppearance() {
|
private fun updateAppearance() {
|
||||||
if (episode == null) {
|
if (episode == null) {
|
||||||
|
@ -429,7 +444,6 @@ class EpisodeInfoFragment : Fragment(), Toolbar.OnMenuItemClickListener {
|
||||||
updateButtons()
|
updateButtons()
|
||||||
}
|
}
|
||||||
|
|
||||||
var hasMedia by mutableStateOf(true)
|
|
||||||
@UnstableApi
|
@UnstableApi
|
||||||
private fun updateButtons() {
|
private fun updateButtons() {
|
||||||
// binding.circularProgressBar.visibility = View.GONE
|
// binding.circularProgressBar.visibility = View.GONE
|
||||||
|
@ -501,7 +515,7 @@ class EpisodeInfoFragment : Fragment(), Toolbar.OnMenuItemClickListener {
|
||||||
Logd(TAG, "Received event: ${event.TAG}")
|
Logd(TAG, "Received event: ${event.TAG}")
|
||||||
when (event) {
|
when (event) {
|
||||||
is FlowEvent.QueueEvent -> onQueueEvent(event)
|
is FlowEvent.QueueEvent -> onQueueEvent(event)
|
||||||
is FlowEvent.RatingEvent -> onFavoriteEvent(event)
|
is FlowEvent.RatingEvent -> onRatingEvent(event)
|
||||||
is FlowEvent.EpisodeEvent -> onEpisodeEvent(event)
|
is FlowEvent.EpisodeEvent -> onEpisodeEvent(event)
|
||||||
is FlowEvent.PlayerSettingsEvent -> updateButtons()
|
is FlowEvent.PlayerSettingsEvent -> updateButtons()
|
||||||
is FlowEvent.EpisodePlayedEvent -> load()
|
is FlowEvent.EpisodePlayedEvent -> load()
|
||||||
|
@ -520,10 +534,11 @@ class EpisodeInfoFragment : Fragment(), Toolbar.OnMenuItemClickListener {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun onFavoriteEvent(event: FlowEvent.RatingEvent) {
|
private fun onRatingEvent(event: FlowEvent.RatingEvent) {
|
||||||
if (episode?.id == event.episode.id) {
|
if (episode?.id == event.episode.id) {
|
||||||
episode = unmanaged(episode!!)
|
episode = unmanaged(episode!!)
|
||||||
episode!!.rating = if (event.episode.isFavorite) Episode.Rating.FAVORITE.code else Episode.Rating.NEUTRAL.code
|
episode!!.rating = event.rating
|
||||||
|
rating = episode!!.rating
|
||||||
// episode = event.episode
|
// episode = event.episode
|
||||||
prepareMenu()
|
prepareMenu()
|
||||||
}
|
}
|
||||||
|
@ -587,6 +602,7 @@ class EpisodeInfoFragment : Fragment(), Toolbar.OnMenuItemClickListener {
|
||||||
}
|
}
|
||||||
withContext(Dispatchers.Main) {
|
withContext(Dispatchers.Main) {
|
||||||
// binding.progbarLoading.visibility = View.GONE
|
// binding.progbarLoading.visibility = View.GONE
|
||||||
|
rating = episode!!.rating
|
||||||
onFragmentLoaded()
|
onFragmentLoaded()
|
||||||
itemLoaded = true
|
itemLoaded = true
|
||||||
}
|
}
|
||||||
|
@ -597,7 +613,7 @@ class EpisodeInfoFragment : Fragment(), Toolbar.OnMenuItemClickListener {
|
||||||
}
|
}
|
||||||
|
|
||||||
fun setItem(item_: Episode) {
|
fun setItem(item_: Episode) {
|
||||||
episode = item_
|
episode = realm.query(Episode::class).query("id == ${item_.id}").first().find()
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|
|
@ -104,16 +104,19 @@ class FeedInfoFragment : Fragment(), Toolbar.OnMenuItemClickListener {
|
||||||
txtvAuthor = feed.author ?: ""
|
txtvAuthor = feed.author ?: ""
|
||||||
txtvUrl = feed.downloadUrl
|
txtvUrl = feed.downloadUrl
|
||||||
|
|
||||||
binding.header.setContent {
|
// binding.header.setContent {
|
||||||
CustomTheme(requireContext()) {
|
// CustomTheme(requireContext()) {
|
||||||
HeaderUI()
|
// HeaderUI()
|
||||||
}
|
// }
|
||||||
}
|
// }
|
||||||
binding.detailUI.setContent {
|
binding.detailUI.setContent {
|
||||||
CustomTheme(requireContext()) {
|
CustomTheme(requireContext()) {
|
||||||
|
Column {
|
||||||
|
HeaderUI()
|
||||||
DetailUI()
|
DetailUI()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// imgvBackground = binding.imgvBackground
|
// imgvBackground = binding.imgvBackground
|
||||||
// https://github.com/bumptech/glide/issues/529
|
// https://github.com/bumptech/glide/issues/529
|
||||||
|
|
|
@ -36,8 +36,10 @@ import androidx.activity.result.contract.ActivityResultContracts
|
||||||
import androidx.appcompat.app.AlertDialog
|
import androidx.appcompat.app.AlertDialog
|
||||||
import androidx.compose.foundation.clickable
|
import androidx.compose.foundation.clickable
|
||||||
import androidx.compose.foundation.layout.*
|
import androidx.compose.foundation.layout.*
|
||||||
|
import androidx.compose.foundation.rememberScrollState
|
||||||
import androidx.compose.foundation.shape.RoundedCornerShape
|
import androidx.compose.foundation.shape.RoundedCornerShape
|
||||||
import androidx.compose.foundation.text.KeyboardOptions
|
import androidx.compose.foundation.text.KeyboardOptions
|
||||||
|
import androidx.compose.foundation.verticalScroll
|
||||||
import androidx.compose.material3.*
|
import androidx.compose.material3.*
|
||||||
import androidx.compose.runtime.*
|
import androidx.compose.runtime.*
|
||||||
import androidx.compose.ui.Alignment
|
import androidx.compose.ui.Alignment
|
||||||
|
@ -93,26 +95,17 @@ class FeedSettingsFragment : Fragment() {
|
||||||
binding.composeView.setContent {
|
binding.composeView.setContent {
|
||||||
CustomTheme(requireContext()) {
|
CustomTheme(requireContext()) {
|
||||||
val textColor = MaterialTheme.colorScheme.onSurface
|
val textColor = MaterialTheme.colorScheme.onSurface
|
||||||
Column(
|
Column(modifier = Modifier.padding(start = 20.dp, end = 16.dp, top = 10.dp, bottom = 10.dp), verticalArrangement = Arrangement.spacedBy(8.dp)) {
|
||||||
modifier = Modifier.padding(start = 20.dp, end = 16.dp, top = 10.dp, bottom = 10.dp),
|
|
||||||
verticalArrangement = Arrangement.spacedBy(8.dp)
|
|
||||||
) {
|
|
||||||
if ((feed?.id ?: 0) > 10) {
|
if ((feed?.id ?: 0) > 10) {
|
||||||
// refresh
|
// refresh
|
||||||
Column {
|
Column {
|
||||||
Row(Modifier.fillMaxWidth()) {
|
Row(Modifier.fillMaxWidth()) {
|
||||||
Icon(ImageVector.vectorResource(id = R.drawable.ic_refresh), "", tint = textColor)
|
Icon(ImageVector.vectorResource(id = R.drawable.ic_refresh), "", tint = textColor)
|
||||||
Spacer(modifier = Modifier.width(20.dp))
|
Spacer(modifier = Modifier.width(20.dp))
|
||||||
Text(
|
Text(text = stringResource(R.string.keep_updated), style = MaterialTheme.typography.titleLarge, color = textColor)
|
||||||
text = stringResource(R.string.keep_updated),
|
|
||||||
style = MaterialTheme.typography.titleLarge,
|
|
||||||
color = textColor
|
|
||||||
)
|
|
||||||
Spacer(modifier = Modifier.weight(1f))
|
Spacer(modifier = Modifier.weight(1f))
|
||||||
var checked by remember { mutableStateOf(feed?.preferences?.keepUpdated ?: true) }
|
var checked by remember { mutableStateOf(feed?.preferences?.keepUpdated ?: true) }
|
||||||
Switch(
|
Switch(checked = checked, modifier = Modifier.height(24.dp),
|
||||||
checked = checked,
|
|
||||||
modifier = Modifier.height(24.dp),
|
|
||||||
onCheckedChange = {
|
onCheckedChange = {
|
||||||
checked = it
|
checked = it
|
||||||
feed = upsertBlk(feed!!) { f ->
|
feed = upsertBlk(feed!!) { f ->
|
||||||
|
@ -121,41 +114,22 @@ class FeedSettingsFragment : Fragment() {
|
||||||
}
|
}
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
Text(
|
Text(text = stringResource(R.string.keep_updated_summary), style = MaterialTheme.typography.bodyMedium, color = textColor)
|
||||||
text = stringResource(R.string.keep_updated_summary),
|
|
||||||
style = MaterialTheme.typography.bodyMedium,
|
|
||||||
color = textColor
|
|
||||||
)
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if ((feed?.id?:0) > 10 && feed?.hasVideoMedia == true) {
|
if ((feed?.id?:0) > 10 && feed?.hasVideoMedia == true) {
|
||||||
// video mode
|
// video mode
|
||||||
Column {
|
Column {
|
||||||
Row(Modifier.fillMaxWidth()) {
|
Row(Modifier.fillMaxWidth()) {
|
||||||
|
val showDialog = remember { mutableStateOf(false) }
|
||||||
|
if (showDialog.value) VideoModeDialog(showDialog.value, onDismissRequest = { showDialog.value = false })
|
||||||
Icon(ImageVector.vectorResource(id = R.drawable.ic_delete), "", tint = textColor)
|
Icon(ImageVector.vectorResource(id = R.drawable.ic_delete), "", tint = textColor)
|
||||||
Spacer(modifier = Modifier.width(20.dp))
|
Spacer(modifier = Modifier.width(20.dp))
|
||||||
Text(
|
Text(text = stringResource(R.string.feed_video_mode_label), style = MaterialTheme.typography.titleLarge, color = textColor,
|
||||||
text = stringResource(R.string.feed_video_mode_label),
|
modifier = Modifier.clickable(onClick = { showDialog.value = true })
|
||||||
style = MaterialTheme.typography.titleLarge,
|
|
||||||
color = textColor,
|
|
||||||
modifier = Modifier.clickable(onClick = {
|
|
||||||
val composeView = ComposeView(requireContext()).apply {
|
|
||||||
setContent {
|
|
||||||
val showDialog = remember { mutableStateOf(true) }
|
|
||||||
CustomTheme(requireContext()) {
|
|
||||||
VideoModeDialog(showDialog.value, onDismissRequest = { showDialog.value = false })
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
(view as? ViewGroup)?.addView(composeView)
|
|
||||||
})
|
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
Text(
|
Text(text = stringResource(videoModeSummaryResId), style = MaterialTheme.typography.bodyMedium, color = textColor)
|
||||||
text = stringResource(videoModeSummaryResId),
|
|
||||||
style = MaterialTheme.typography.bodyMedium,
|
|
||||||
color = textColor
|
|
||||||
)
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (feed?.type != Feed.FeedType.YOUTUBE.name) {
|
if (feed?.type != Feed.FeedType.YOUTUBE.name) {
|
||||||
|
@ -164,18 +138,12 @@ class FeedSettingsFragment : Fragment() {
|
||||||
Row(Modifier.fillMaxWidth()) {
|
Row(Modifier.fillMaxWidth()) {
|
||||||
Icon(ImageVector.vectorResource(id = R.drawable.ic_stream), "", tint = textColor)
|
Icon(ImageVector.vectorResource(id = R.drawable.ic_stream), "", tint = textColor)
|
||||||
Spacer(modifier = Modifier.width(20.dp))
|
Spacer(modifier = Modifier.width(20.dp))
|
||||||
Text(
|
Text(text = stringResource(R.string.pref_stream_over_download_title), style = MaterialTheme.typography.titleLarge, color = textColor)
|
||||||
text = stringResource(R.string.pref_stream_over_download_title),
|
|
||||||
style = MaterialTheme.typography.titleLarge,
|
|
||||||
color = textColor
|
|
||||||
)
|
|
||||||
Spacer(modifier = Modifier.weight(1f))
|
Spacer(modifier = Modifier.weight(1f))
|
||||||
var checked by remember {
|
var checked by remember {
|
||||||
mutableStateOf(feed?.preferences?.prefStreamOverDownload ?: false)
|
mutableStateOf(feed?.preferences?.prefStreamOverDownload ?: false)
|
||||||
}
|
}
|
||||||
Switch(
|
Switch(checked = checked, modifier = Modifier.height(24.dp),
|
||||||
checked = checked,
|
|
||||||
modifier = Modifier.height(24.dp),
|
|
||||||
onCheckedChange = {
|
onCheckedChange = {
|
||||||
checked = it
|
checked = it
|
||||||
feed = upsertBlk(feed!!) { f ->
|
feed = upsertBlk(feed!!) { f ->
|
||||||
|
@ -184,61 +152,37 @@ class FeedSettingsFragment : Fragment() {
|
||||||
}
|
}
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
Text(
|
Text(text = stringResource(R.string.pref_stream_over_download_sum), style = MaterialTheme.typography.bodyMedium, color = textColor)
|
||||||
text = stringResource(R.string.pref_stream_over_download_sum),
|
|
||||||
style = MaterialTheme.typography.bodyMedium,
|
|
||||||
color = textColor
|
|
||||||
)
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
// associated queue
|
// associated queue
|
||||||
Column {
|
Column {
|
||||||
curPrefQueue = feed?.preferences?.queueTextExt ?: "Default"
|
curPrefQueue = feed?.preferences?.queueTextExt ?: "Default"
|
||||||
|
var showDialog by remember { mutableStateOf(false) }
|
||||||
|
var selectedOption by remember { mutableStateOf(feed?.preferences?.queueText ?: "Default") }
|
||||||
|
if (showDialog) SetAssociatedQueue(showDialog, selectedOption = selectedOption, onDismissRequest = { showDialog = false })
|
||||||
Row(Modifier.fillMaxWidth()) {
|
Row(Modifier.fillMaxWidth()) {
|
||||||
Icon(ImageVector.vectorResource(id = R.drawable.ic_playlist_play), "", tint = textColor)
|
Icon(ImageVector.vectorResource(id = R.drawable.ic_playlist_play), "", tint = textColor)
|
||||||
Spacer(modifier = Modifier.width(20.dp))
|
Spacer(modifier = Modifier.width(20.dp))
|
||||||
Text(
|
Text(text = stringResource(R.string.pref_feed_associated_queue), style = MaterialTheme.typography.titleLarge, color = textColor,
|
||||||
text = stringResource(R.string.pref_feed_associated_queue),
|
|
||||||
style = MaterialTheme.typography.titleLarge,
|
|
||||||
color = textColor,
|
|
||||||
modifier = Modifier.clickable(onClick = {
|
modifier = Modifier.clickable(onClick = {
|
||||||
val selectedOption = feed?.preferences?.queueText ?: "Default"
|
selectedOption = feed?.preferences?.queueText ?: "Default"
|
||||||
val composeView = ComposeView(requireContext()).apply {
|
showDialog = true
|
||||||
setContent {
|
|
||||||
val showDialog = remember { mutableStateOf(true) }
|
|
||||||
CustomTheme(requireContext()) {
|
|
||||||
SetAssociatedQueue(showDialog.value, selectedOption = selectedOption, onDismissRequest = { showDialog.value = false })
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
(view as? ViewGroup)?.addView(composeView)
|
|
||||||
})
|
})
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
Text(
|
Text(text = curPrefQueue + " : " + stringResource(R.string.pref_feed_associated_queue_sum), style = MaterialTheme.typography.bodyMedium, color = textColor)
|
||||||
text = curPrefQueue + " : " + stringResource(R.string.pref_feed_associated_queue_sum),
|
|
||||||
style = MaterialTheme.typography.bodyMedium,
|
|
||||||
color = textColor
|
|
||||||
)
|
|
||||||
}
|
}
|
||||||
// auto add new to queue
|
// auto add new to queue
|
||||||
if (curPrefQueue != "None") {
|
if (curPrefQueue != "None") {
|
||||||
Column {
|
Column {
|
||||||
Row(Modifier.fillMaxWidth()) {
|
Row(Modifier.fillMaxWidth()) {
|
||||||
Icon(ImageVector.vectorResource(id = androidx.media3.session.R.drawable.media3_icon_queue_add),
|
Icon(ImageVector.vectorResource(id = androidx.media3.session.R.drawable.media3_icon_queue_add), "", tint = textColor)
|
||||||
"",
|
|
||||||
tint = textColor)
|
|
||||||
Spacer(modifier = Modifier.width(20.dp))
|
Spacer(modifier = Modifier.width(20.dp))
|
||||||
Text(
|
Text(text = stringResource(R.string.audo_add_new_queue), style = MaterialTheme.typography.titleLarge, color = textColor)
|
||||||
text = stringResource(R.string.audo_add_new_queue),
|
|
||||||
style = MaterialTheme.typography.titleLarge,
|
|
||||||
color = textColor
|
|
||||||
)
|
|
||||||
Spacer(modifier = Modifier.weight(1f))
|
Spacer(modifier = Modifier.weight(1f))
|
||||||
var checked by remember { mutableStateOf(feed?.preferences?.autoAddNewToQueue ?: true) }
|
var checked by remember { mutableStateOf(feed?.preferences?.autoAddNewToQueue ?: true) }
|
||||||
Switch(
|
Switch(checked = checked, modifier = Modifier.height(24.dp),
|
||||||
checked = checked,
|
|
||||||
modifier = Modifier.height(24.dp),
|
|
||||||
onCheckedChange = {
|
onCheckedChange = {
|
||||||
checked = it
|
checked = it
|
||||||
feed = upsertBlk(feed!!) { f ->
|
feed = upsertBlk(feed!!) { f ->
|
||||||
|
@ -247,41 +191,21 @@ class FeedSettingsFragment : Fragment() {
|
||||||
}
|
}
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
Text(
|
Text(text = stringResource(R.string.audo_add_new_queue_summary), style = MaterialTheme.typography.bodyMedium, color = textColor)
|
||||||
text = stringResource(R.string.audo_add_new_queue_summary),
|
|
||||||
style = MaterialTheme.typography.bodyMedium,
|
|
||||||
color = textColor
|
|
||||||
)
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (feed?.type != Feed.FeedType.YOUTUBE.name) {
|
if (feed?.type != Feed.FeedType.YOUTUBE.name) {
|
||||||
// auto delete
|
// auto delete
|
||||||
Column {
|
Column {
|
||||||
Row(Modifier.fillMaxWidth()) {
|
Row(Modifier.fillMaxWidth()) {
|
||||||
|
val showDialog = remember { mutableStateOf(false) }
|
||||||
|
if (showDialog.value) AutoDeleteDialog(showDialog.value, onDismissRequest = { showDialog.value = false })
|
||||||
Icon(ImageVector.vectorResource(id = R.drawable.ic_delete), "", tint = textColor)
|
Icon(ImageVector.vectorResource(id = R.drawable.ic_delete), "", tint = textColor)
|
||||||
Spacer(modifier = Modifier.width(20.dp))
|
Spacer(modifier = Modifier.width(20.dp))
|
||||||
Text(
|
Text(text = stringResource(R.string.auto_delete_label), style = MaterialTheme.typography.titleLarge, color = textColor,
|
||||||
text = stringResource(R.string.auto_delete_label),
|
modifier = Modifier.clickable(onClick = { showDialog.value = true }))
|
||||||
style = MaterialTheme.typography.titleLarge,
|
|
||||||
color = textColor,
|
|
||||||
modifier = Modifier.clickable(onClick = {
|
|
||||||
val composeView = ComposeView(requireContext()).apply {
|
|
||||||
setContent {
|
|
||||||
val showDialog = remember { mutableStateOf(true) }
|
|
||||||
CustomTheme(requireContext()) {
|
|
||||||
AutoDeleteDialog(showDialog.value, onDismissRequest = { showDialog.value = false })
|
|
||||||
}
|
}
|
||||||
}
|
Text(text = stringResource(autoDeleteSummaryResId), style = MaterialTheme.typography.bodyMedium, color = textColor)
|
||||||
}
|
|
||||||
(view as? ViewGroup)?.addView(composeView)
|
|
||||||
})
|
|
||||||
)
|
|
||||||
}
|
|
||||||
Text(
|
|
||||||
text = stringResource(autoDeleteSummaryResId),
|
|
||||||
style = MaterialTheme.typography.bodyMedium,
|
|
||||||
color = textColor
|
|
||||||
)
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
// tags
|
// tags
|
||||||
|
@ -289,127 +213,64 @@ class FeedSettingsFragment : Fragment() {
|
||||||
Row(Modifier.fillMaxWidth()) {
|
Row(Modifier.fillMaxWidth()) {
|
||||||
Icon(ImageVector.vectorResource(id = R.drawable.ic_tag), "", tint = textColor)
|
Icon(ImageVector.vectorResource(id = R.drawable.ic_tag), "", tint = textColor)
|
||||||
Spacer(modifier = Modifier.width(20.dp))
|
Spacer(modifier = Modifier.width(20.dp))
|
||||||
Text(
|
Text(text = stringResource(R.string.feed_tags_label), style = MaterialTheme.typography.titleLarge, color = textColor,
|
||||||
text = stringResource(R.string.feed_tags_label),
|
|
||||||
style = MaterialTheme.typography.titleLarge,
|
|
||||||
color = textColor,
|
|
||||||
modifier = Modifier.clickable(onClick = {
|
modifier = Modifier.clickable(onClick = {
|
||||||
val dialog = TagSettingsDialog.newInstance(listOf(feed!!))
|
val dialog = TagSettingsDialog.newInstance(listOf(feed!!))
|
||||||
dialog.show(parentFragmentManager, TagSettingsDialog.TAG)
|
dialog.show(parentFragmentManager, TagSettingsDialog.TAG)
|
||||||
})
|
})
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
Text(
|
Text(text = stringResource(R.string.feed_tags_summary), style = MaterialTheme.typography.bodyMedium, color = textColor)
|
||||||
text = stringResource(R.string.feed_tags_summary),
|
|
||||||
style = MaterialTheme.typography.bodyMedium,
|
|
||||||
color = textColor
|
|
||||||
)
|
|
||||||
}
|
}
|
||||||
// playback speed
|
// playback speed
|
||||||
Column {
|
Column {
|
||||||
Row(Modifier.fillMaxWidth()) {
|
Row(Modifier.fillMaxWidth()) {
|
||||||
Icon(ImageVector.vectorResource(id = R.drawable.ic_playback_speed), "", tint = textColor)
|
Icon(ImageVector.vectorResource(id = R.drawable.ic_playback_speed), "", tint = textColor)
|
||||||
Spacer(modifier = Modifier.width(20.dp))
|
Spacer(modifier = Modifier.width(20.dp))
|
||||||
Text(
|
Text(text = stringResource(R.string.playback_speed), style = MaterialTheme.typography.titleLarge, color = textColor,
|
||||||
text = stringResource(R.string.playback_speed),
|
|
||||||
style = MaterialTheme.typography.titleLarge,
|
|
||||||
color = textColor,
|
|
||||||
modifier = Modifier.clickable(onClick = {
|
modifier = Modifier.clickable(onClick = {
|
||||||
PlaybackSpeedDialog().show()
|
PlaybackSpeedDialog().show()
|
||||||
})
|
})
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
Text(
|
Text(text = stringResource(R.string.pref_feed_playback_speed_sum), style = MaterialTheme.typography.bodyMedium, color = textColor)
|
||||||
text = stringResource(R.string.pref_feed_playback_speed_sum),
|
|
||||||
style = MaterialTheme.typography.bodyMedium,
|
|
||||||
color = textColor
|
|
||||||
)
|
|
||||||
}
|
}
|
||||||
// auto skip
|
// auto skip
|
||||||
Column {
|
Column {
|
||||||
Row(Modifier.fillMaxWidth()) {
|
Row(Modifier.fillMaxWidth()) {
|
||||||
|
val showDialog = remember { mutableStateOf(false) }
|
||||||
|
if (showDialog.value) AutoSkipDialog(showDialog.value, onDismiss = { showDialog.value = false })
|
||||||
Icon(ImageVector.vectorResource(id = R.drawable.ic_skip_24dp), "", tint = textColor)
|
Icon(ImageVector.vectorResource(id = R.drawable.ic_skip_24dp), "", tint = textColor)
|
||||||
Spacer(modifier = Modifier.width(20.dp))
|
Spacer(modifier = Modifier.width(20.dp))
|
||||||
Text(
|
Text(text = stringResource(R.string.pref_feed_skip), style = MaterialTheme.typography.titleLarge, color = textColor,
|
||||||
text = stringResource(R.string.pref_feed_skip),
|
modifier = Modifier.clickable(onClick = { showDialog.value = true }))
|
||||||
style = MaterialTheme.typography.titleLarge,
|
|
||||||
color = textColor,
|
|
||||||
modifier = Modifier.clickable(onClick = {
|
|
||||||
val composeView = ComposeView(requireContext()).apply {
|
|
||||||
setContent {
|
|
||||||
val showDialog = remember { mutableStateOf(true) }
|
|
||||||
CustomTheme(requireContext()) {
|
|
||||||
AutoSkipDialog(showDialog.value, onDismiss = { showDialog.value = false })
|
|
||||||
}
|
}
|
||||||
}
|
Text(text = stringResource(R.string.pref_feed_skip_sum), style = MaterialTheme.typography.bodyMedium, color = textColor)
|
||||||
}
|
|
||||||
(view as? ViewGroup)?.addView(composeView)
|
|
||||||
})
|
|
||||||
)
|
|
||||||
}
|
|
||||||
Text(
|
|
||||||
text = stringResource(R.string.pref_feed_skip_sum),
|
|
||||||
style = MaterialTheme.typography.bodyMedium,
|
|
||||||
color = textColor
|
|
||||||
)
|
|
||||||
}
|
}
|
||||||
// volume adaption
|
// volume adaption
|
||||||
Column {
|
Column {
|
||||||
Row(Modifier.fillMaxWidth()) {
|
Row(Modifier.fillMaxWidth()) {
|
||||||
|
val showDialog = remember { mutableStateOf(false) }
|
||||||
|
if (showDialog.value) VolumeAdaptionDialog(showDialog.value, onDismissRequest = { showDialog.value = false })
|
||||||
Icon(ImageVector.vectorResource(id = R.drawable.ic_volume_adaption), "", tint = textColor)
|
Icon(ImageVector.vectorResource(id = R.drawable.ic_volume_adaption), "", tint = textColor)
|
||||||
Spacer(modifier = Modifier.width(20.dp))
|
Spacer(modifier = Modifier.width(20.dp))
|
||||||
Text(
|
Text(text = stringResource(R.string.feed_volume_adapdation), style = MaterialTheme.typography.titleLarge, color = textColor,
|
||||||
text = stringResource(R.string.feed_volume_adapdation),
|
modifier = Modifier.clickable(onClick = { showDialog.value = true }))
|
||||||
style = MaterialTheme.typography.titleLarge,
|
|
||||||
color = textColor,
|
|
||||||
modifier = Modifier.clickable(onClick = {
|
|
||||||
val composeView = ComposeView(requireContext()).apply {
|
|
||||||
setContent {
|
|
||||||
val showDialog = remember { mutableStateOf(true) }
|
|
||||||
CustomTheme(requireContext()) {
|
|
||||||
VolumeAdaptionDialog(showDialog.value, onDismissRequest = { showDialog.value = false })
|
|
||||||
}
|
}
|
||||||
}
|
Text(text = stringResource(R.string.feed_volume_adaptation_summary), style = MaterialTheme.typography.bodyMedium, color = textColor)
|
||||||
}
|
|
||||||
(view as? ViewGroup)?.addView(composeView)
|
|
||||||
})
|
|
||||||
)
|
|
||||||
}
|
|
||||||
Text(
|
|
||||||
text = stringResource(R.string.feed_volume_adaptation_summary),
|
|
||||||
style = MaterialTheme.typography.bodyMedium,
|
|
||||||
color = textColor
|
|
||||||
)
|
|
||||||
}
|
}
|
||||||
// authentication
|
// authentication
|
||||||
if ((feed?.id?:0) > 0 && feed?.isLocalFeed != true) {
|
if ((feed?.id?:0) > 0 && feed?.isLocalFeed != true) {
|
||||||
Column {
|
Column {
|
||||||
Row(Modifier.fillMaxWidth()) {
|
Row(Modifier.fillMaxWidth()) {
|
||||||
|
val showDialog = remember { mutableStateOf(false) }
|
||||||
|
if (showDialog.value) AuthenticationDialog(showDialog.value, onDismiss = { showDialog.value = false })
|
||||||
Icon(ImageVector.vectorResource(id = R.drawable.ic_key), "", tint = textColor)
|
Icon(ImageVector.vectorResource(id = R.drawable.ic_key), "", tint = textColor)
|
||||||
Spacer(modifier = Modifier.width(20.dp))
|
Spacer(modifier = Modifier.width(20.dp))
|
||||||
Text(
|
Text(text = stringResource(R.string.authentication_label), style = MaterialTheme.typography.titleLarge, color = textColor,
|
||||||
text = stringResource(R.string.authentication_label),
|
modifier = Modifier.clickable(onClick = { showDialog.value = true }))
|
||||||
style = MaterialTheme.typography.titleLarge,
|
|
||||||
color = textColor,
|
|
||||||
modifier = Modifier.clickable(onClick = {
|
|
||||||
val composeView = ComposeView(requireContext()).apply {
|
|
||||||
setContent {
|
|
||||||
val showDialog = remember { mutableStateOf(true) }
|
|
||||||
CustomTheme(requireContext()) {
|
|
||||||
AuthenticationDialog(showDialog.value,
|
|
||||||
onDismiss = { showDialog.value = false })
|
|
||||||
}
|
}
|
||||||
}
|
Text(text = stringResource(R.string.authentication_descr), style = MaterialTheme.typography.bodyMedium, color = textColor)
|
||||||
}
|
|
||||||
(view as? ViewGroup)?.addView(composeView)
|
|
||||||
})
|
|
||||||
)
|
|
||||||
}
|
|
||||||
Text(
|
|
||||||
text = stringResource(R.string.authentication_descr),
|
|
||||||
style = MaterialTheme.typography.bodyMedium,
|
|
||||||
color = textColor
|
|
||||||
)
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (isEnableAutodownload && feed?.type != Feed.FeedType.YOUTUBE.name) {
|
if (isEnableAutodownload && feed?.type != Feed.FeedType.YOUTUBE.name) {
|
||||||
|
@ -417,15 +278,9 @@ class FeedSettingsFragment : Fragment() {
|
||||||
var audoDownloadChecked by remember { mutableStateOf(feed?.preferences?.autoDownload ?: false) }
|
var audoDownloadChecked by remember { mutableStateOf(feed?.preferences?.autoDownload ?: false) }
|
||||||
Column {
|
Column {
|
||||||
Row(Modifier.fillMaxWidth()) {
|
Row(Modifier.fillMaxWidth()) {
|
||||||
Text(
|
Text(text = stringResource(R.string.auto_download_label), style = MaterialTheme.typography.titleLarge, color = textColor)
|
||||||
text = stringResource(R.string.auto_download_label),
|
|
||||||
style = MaterialTheme.typography.titleLarge,
|
|
||||||
color = textColor
|
|
||||||
)
|
|
||||||
Spacer(modifier = Modifier.weight(1f))
|
Spacer(modifier = Modifier.weight(1f))
|
||||||
Switch(
|
Switch(checked = audoDownloadChecked, modifier = Modifier.height(24.dp),
|
||||||
checked = audoDownloadChecked,
|
|
||||||
modifier = Modifier.height(24.dp),
|
|
||||||
onCheckedChange = {
|
onCheckedChange = {
|
||||||
audoDownloadChecked = it
|
audoDownloadChecked = it
|
||||||
feed = upsertBlk(feed!!) { f -> f.preferences?.autoDownload = audoDownloadChecked }
|
feed = upsertBlk(feed!!) { f -> f.preferences?.autoDownload = audoDownloadChecked }
|
||||||
|
@ -433,32 +288,18 @@ class FeedSettingsFragment : Fragment() {
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
if (!isEnableAutodownload) {
|
if (!isEnableAutodownload) {
|
||||||
Text(
|
Text(text = stringResource(R.string.auto_download_disabled_globally), style = MaterialTheme.typography.bodyMedium, color = textColor)
|
||||||
text = stringResource(R.string.auto_download_disabled_globally),
|
|
||||||
style = MaterialTheme.typography.bodyMedium,
|
|
||||||
color = textColor
|
|
||||||
)
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (audoDownloadChecked) {
|
if (audoDownloadChecked) {
|
||||||
// auto download policy
|
// auto download policy
|
||||||
Column (modifier = Modifier.padding(start = 20.dp)){
|
Column (modifier = Modifier.padding(start = 20.dp)){
|
||||||
Row(Modifier.fillMaxWidth()) {
|
Row(Modifier.fillMaxWidth()) {
|
||||||
Text(
|
val showDialog = remember { mutableStateOf(false) }
|
||||||
text = stringResource(R.string.feed_auto_download_policy),
|
if (showDialog.value) AutoDownloadPolicyDialog(showDialog.value, onDismissRequest = { showDialog.value = false })
|
||||||
style = MaterialTheme.typography.titleLarge,
|
Text(text = stringResource(R.string.feed_auto_download_policy), style = MaterialTheme.typography.titleLarge, color = textColor,
|
||||||
color = textColor,
|
|
||||||
modifier = Modifier.clickable(onClick = {
|
modifier = Modifier.clickable(onClick = {
|
||||||
val composeView = ComposeView(requireContext()).apply {
|
showDialog.value = true
|
||||||
setContent {
|
|
||||||
val showDialog = remember { mutableStateOf(true) }
|
|
||||||
CustomTheme(requireContext()) {
|
|
||||||
AutoDownloadPolicyDialog(showDialog.value,
|
|
||||||
onDismissRequest = { showDialog.value = false })
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
(view as? ViewGroup)?.addView(composeView)
|
|
||||||
})
|
})
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
@ -466,45 +307,23 @@ class FeedSettingsFragment : Fragment() {
|
||||||
// episode cache
|
// episode cache
|
||||||
Column (modifier = Modifier.padding(start = 20.dp)) {
|
Column (modifier = Modifier.padding(start = 20.dp)) {
|
||||||
Row(Modifier.fillMaxWidth()) {
|
Row(Modifier.fillMaxWidth()) {
|
||||||
Text(
|
val showDialog = remember { mutableStateOf(false) }
|
||||||
text = stringResource(R.string.pref_episode_cache_title),
|
if (showDialog.value) SetEpisodesCacheDialog(showDialog.value, onDismiss = { showDialog.value = false })
|
||||||
style = MaterialTheme.typography.titleLarge,
|
Text(text = stringResource(R.string.pref_episode_cache_title), style = MaterialTheme.typography.titleLarge, color = textColor,
|
||||||
color = textColor,
|
modifier = Modifier.clickable(onClick = { showDialog.value = true })
|
||||||
modifier = Modifier.clickable(onClick = {
|
|
||||||
val composeView = ComposeView(requireContext()).apply {
|
|
||||||
setContent {
|
|
||||||
val showDialog = remember { mutableStateOf(true) }
|
|
||||||
CustomTheme(requireContext()) {
|
|
||||||
SetEpisodesCacheDialog(showDialog.value,
|
|
||||||
onDismiss = { showDialog.value = false })
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
(view as? ViewGroup)?.addView(composeView)
|
|
||||||
})
|
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
Text(
|
Text(text = stringResource(R.string.pref_episode_cache_summary), style = MaterialTheme.typography.bodyMedium, color = textColor)
|
||||||
text = stringResource(R.string.pref_episode_cache_summary),
|
|
||||||
style = MaterialTheme.typography.bodyMedium,
|
|
||||||
color = textColor
|
|
||||||
)
|
|
||||||
}
|
}
|
||||||
// counting played
|
// counting played
|
||||||
Column (modifier = Modifier.padding(start = 20.dp)) {
|
Column (modifier = Modifier.padding(start = 20.dp)) {
|
||||||
Row(Modifier.fillMaxWidth()) {
|
Row(Modifier.fillMaxWidth()) {
|
||||||
Text(
|
Text(text = stringResource(R.string.pref_auto_download_counting_played_title), style = MaterialTheme.typography.titleLarge, color = textColor)
|
||||||
text = stringResource(R.string.pref_auto_download_counting_played_title),
|
|
||||||
style = MaterialTheme.typography.titleLarge,
|
|
||||||
color = textColor
|
|
||||||
)
|
|
||||||
Spacer(modifier = Modifier.weight(1f))
|
Spacer(modifier = Modifier.weight(1f))
|
||||||
var checked by remember {
|
var checked by remember {
|
||||||
mutableStateOf(feed?.preferences?.countingPlayed ?: true)
|
mutableStateOf(feed?.preferences?.countingPlayed ?: true)
|
||||||
}
|
}
|
||||||
Switch(
|
Switch(checked = checked, modifier = Modifier.height(24.dp),
|
||||||
checked = checked,
|
|
||||||
modifier = Modifier.height(24.dp),
|
|
||||||
onCheckedChange = {
|
onCheckedChange = {
|
||||||
checked = it
|
checked = it
|
||||||
feed = upsertBlk(feed!!) { f ->
|
feed = upsertBlk(feed!!) { f ->
|
||||||
|
@ -513,19 +332,12 @@ class FeedSettingsFragment : Fragment() {
|
||||||
}
|
}
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
Text(
|
Text(text = stringResource(R.string.pref_auto_download_counting_played_summary), style = MaterialTheme.typography.bodyMedium, color = textColor)
|
||||||
text = stringResource(R.string.pref_auto_download_counting_played_summary),
|
|
||||||
style = MaterialTheme.typography.bodyMedium,
|
|
||||||
color = textColor
|
|
||||||
)
|
|
||||||
}
|
}
|
||||||
// inclusive filter
|
// inclusive filter
|
||||||
Column (modifier = Modifier.padding(start = 20.dp)) {
|
Column (modifier = Modifier.padding(start = 20.dp)) {
|
||||||
Row(Modifier.fillMaxWidth()) {
|
Row(Modifier.fillMaxWidth()) {
|
||||||
Text(
|
Text(text = stringResource(R.string.episode_inclusive_filters_label), style = MaterialTheme.typography.titleLarge, color = textColor,
|
||||||
text = stringResource(R.string.episode_inclusive_filters_label),
|
|
||||||
style = MaterialTheme.typography.titleLarge,
|
|
||||||
color = textColor,
|
|
||||||
modifier = Modifier.clickable(onClick = {
|
modifier = Modifier.clickable(onClick = {
|
||||||
object : AutoDownloadFilterPrefDialog(requireContext(),
|
object : AutoDownloadFilterPrefDialog(requireContext(),
|
||||||
feed?.preferences!!.autoDownloadFilter!!,
|
feed?.preferences!!.autoDownloadFilter!!,
|
||||||
|
@ -540,19 +352,12 @@ class FeedSettingsFragment : Fragment() {
|
||||||
})
|
})
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
Text(
|
Text(text = stringResource(R.string.episode_filters_description), style = MaterialTheme.typography.bodyMedium, color = textColor)
|
||||||
text = stringResource(R.string.episode_filters_description),
|
|
||||||
style = MaterialTheme.typography.bodyMedium,
|
|
||||||
color = textColor
|
|
||||||
)
|
|
||||||
}
|
}
|
||||||
// exclusive filter
|
// exclusive filter
|
||||||
Column (modifier = Modifier.padding(start = 20.dp)) {
|
Column (modifier = Modifier.padding(start = 20.dp)) {
|
||||||
Row(Modifier.fillMaxWidth()) {
|
Row(Modifier.fillMaxWidth()) {
|
||||||
Text(
|
Text(text = stringResource(R.string.episode_exclusive_filters_label), style = MaterialTheme.typography.titleLarge, color = textColor,
|
||||||
text = stringResource(R.string.episode_exclusive_filters_label),
|
|
||||||
style = MaterialTheme.typography.titleLarge,
|
|
||||||
color = textColor,
|
|
||||||
modifier = Modifier.clickable(onClick = {
|
modifier = Modifier.clickable(onClick = {
|
||||||
object : AutoDownloadFilterPrefDialog(requireContext(),
|
object : AutoDownloadFilterPrefDialog(requireContext(),
|
||||||
feed?.preferences!!.autoDownloadFilter!!,
|
feed?.preferences!!.autoDownloadFilter!!,
|
||||||
|
@ -567,20 +372,14 @@ class FeedSettingsFragment : Fragment() {
|
||||||
})
|
})
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
Text(
|
Text(text = stringResource(R.string.episode_filters_description), style = MaterialTheme.typography.bodyMedium, color = textColor)
|
||||||
text = stringResource(R.string.episode_filters_description),
|
|
||||||
style = MaterialTheme.typography.bodyMedium,
|
|
||||||
color = textColor
|
|
||||||
)
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (feed != null) {
|
if (feed != null) toolbar.subtitle = feed!!.title
|
||||||
toolbar.subtitle = feed!!.title
|
|
||||||
}
|
|
||||||
return binding.root
|
return binding.root
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -617,23 +416,11 @@ class FeedSettingsFragment : Fragment() {
|
||||||
if (showDialog) {
|
if (showDialog) {
|
||||||
val (selectedOption, onOptionSelected) = remember { mutableStateOf(videoMode) }
|
val (selectedOption, onOptionSelected) = remember { mutableStateOf(videoMode) }
|
||||||
Dialog(onDismissRequest = { onDismissRequest() }) {
|
Dialog(onDismissRequest = { onDismissRequest() }) {
|
||||||
Card(
|
Card(modifier = Modifier.wrapContentSize(align = Alignment.Center).padding(16.dp), shape = RoundedCornerShape(16.dp)) {
|
||||||
modifier = Modifier
|
Column(modifier = Modifier.padding(16.dp), verticalArrangement = Arrangement.spacedBy(8.dp)) {
|
||||||
.wrapContentSize(align = Alignment.Center)
|
|
||||||
.padding(16.dp),
|
|
||||||
shape = RoundedCornerShape(16.dp),
|
|
||||||
) {
|
|
||||||
Column(
|
|
||||||
modifier = Modifier.padding(16.dp),
|
|
||||||
verticalArrangement = Arrangement.spacedBy(8.dp)
|
|
||||||
) {
|
|
||||||
Column {
|
Column {
|
||||||
videoModeTags.forEach { text ->
|
videoModeTags.forEach { text ->
|
||||||
Row(Modifier
|
Row(Modifier.fillMaxWidth().padding(horizontal = 16.dp), verticalAlignment = Alignment.CenterVertically) {
|
||||||
.fillMaxWidth()
|
|
||||||
.padding(horizontal = 16.dp),
|
|
||||||
verticalAlignment = Alignment.CenterVertically
|
|
||||||
) {
|
|
||||||
Checkbox(checked = (text == selectedOption),
|
Checkbox(checked = (text == selectedOption),
|
||||||
onCheckedChange = {
|
onCheckedChange = {
|
||||||
Logd(TAG, "row clicked: $text $selectedOption")
|
Logd(TAG, "row clicked: $text $selectedOption")
|
||||||
|
@ -652,12 +439,7 @@ class FeedSettingsFragment : Fragment() {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
)
|
)
|
||||||
Text(
|
Text(text = text, style = MaterialTheme.typography.bodyLarge.merge(), modifier = Modifier.padding(start = 16.dp))
|
||||||
text = text,
|
|
||||||
style = MaterialTheme.typography.bodyLarge.merge(),
|
|
||||||
// color = textColor,
|
|
||||||
modifier = Modifier.padding(start = 16.dp)
|
|
||||||
)
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -688,23 +470,11 @@ class FeedSettingsFragment : Fragment() {
|
||||||
if (showDialog) {
|
if (showDialog) {
|
||||||
val (selectedOption, onOptionSelected) = remember { mutableStateOf(autoDeletePolicy) }
|
val (selectedOption, onOptionSelected) = remember { mutableStateOf(autoDeletePolicy) }
|
||||||
Dialog(onDismissRequest = { onDismissRequest() }) {
|
Dialog(onDismissRequest = { onDismissRequest() }) {
|
||||||
Card(
|
Card(modifier = Modifier.wrapContentSize(align = Alignment.Center).padding(16.dp), shape = RoundedCornerShape(16.dp)) {
|
||||||
modifier = Modifier
|
Column(modifier = Modifier.padding(16.dp), verticalArrangement = Arrangement.spacedBy(8.dp)) {
|
||||||
.wrapContentSize(align = Alignment.Center)
|
|
||||||
.padding(16.dp),
|
|
||||||
shape = RoundedCornerShape(16.dp),
|
|
||||||
) {
|
|
||||||
Column(
|
|
||||||
modifier = Modifier.padding(16.dp),
|
|
||||||
verticalArrangement = Arrangement.spacedBy(8.dp)
|
|
||||||
) {
|
|
||||||
Column {
|
Column {
|
||||||
FeedAutoDeleteOptions.forEach { text ->
|
FeedAutoDeleteOptions.forEach { text ->
|
||||||
Row(Modifier
|
Row(Modifier.fillMaxWidth().padding(horizontal = 16.dp), verticalAlignment = Alignment.CenterVertically) {
|
||||||
.fillMaxWidth()
|
|
||||||
.padding(horizontal = 16.dp),
|
|
||||||
verticalAlignment = Alignment.CenterVertically
|
|
||||||
) {
|
|
||||||
Checkbox(checked = (text == selectedOption),
|
Checkbox(checked = (text == selectedOption),
|
||||||
onCheckedChange = {
|
onCheckedChange = {
|
||||||
Logd(TAG, "row clicked: $text $selectedOption")
|
Logd(TAG, "row clicked: $text $selectedOption")
|
||||||
|
@ -722,12 +492,7 @@ class FeedSettingsFragment : Fragment() {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
)
|
)
|
||||||
Text(
|
Text(text = text, style = MaterialTheme.typography.bodyLarge.merge(), modifier = Modifier.padding(start = 16.dp))
|
||||||
text = text,
|
|
||||||
style = MaterialTheme.typography.bodyLarge.merge(),
|
|
||||||
// color = textColor,
|
|
||||||
modifier = Modifier.padding(start = 16.dp)
|
|
||||||
)
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -742,23 +507,11 @@ class FeedSettingsFragment : Fragment() {
|
||||||
if (showDialog) {
|
if (showDialog) {
|
||||||
val (selectedOption, onOptionSelected) = remember { mutableStateOf(feed?.preferences?.volumeAdaptionSetting ?: VolumeAdaptionSetting.OFF) }
|
val (selectedOption, onOptionSelected) = remember { mutableStateOf(feed?.preferences?.volumeAdaptionSetting ?: VolumeAdaptionSetting.OFF) }
|
||||||
Dialog(onDismissRequest = { onDismissRequest() }) {
|
Dialog(onDismissRequest = { onDismissRequest() }) {
|
||||||
Card(
|
Card(modifier = Modifier.wrapContentSize(align = Alignment.Center).padding(16.dp), shape = RoundedCornerShape(16.dp)) {
|
||||||
modifier = Modifier
|
Column(modifier = Modifier.padding(16.dp), verticalArrangement = Arrangement.spacedBy(8.dp)) {
|
||||||
.wrapContentSize(align = Alignment.Center)
|
|
||||||
.padding(16.dp),
|
|
||||||
shape = RoundedCornerShape(16.dp),
|
|
||||||
) {
|
|
||||||
Column(
|
|
||||||
modifier = Modifier.padding(16.dp),
|
|
||||||
verticalArrangement = Arrangement.spacedBy(8.dp)
|
|
||||||
) {
|
|
||||||
Column {
|
Column {
|
||||||
VolumeAdaptionSetting.entries.forEach { item ->
|
VolumeAdaptionSetting.entries.forEach { item ->
|
||||||
Row(Modifier
|
Row(Modifier.fillMaxWidth().padding(horizontal = 16.dp), verticalAlignment = Alignment.CenterVertically) {
|
||||||
.fillMaxWidth()
|
|
||||||
.padding(horizontal = 16.dp),
|
|
||||||
verticalAlignment = Alignment.CenterVertically
|
|
||||||
) {
|
|
||||||
Checkbox(checked = (item == selectedOption),
|
Checkbox(checked = (item == selectedOption),
|
||||||
onCheckedChange = { _ ->
|
onCheckedChange = { _ ->
|
||||||
Logd(TAG, "row clicked: $item $selectedOption")
|
Logd(TAG, "row clicked: $item $selectedOption")
|
||||||
|
@ -769,12 +522,7 @@ class FeedSettingsFragment : Fragment() {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
)
|
)
|
||||||
Text(
|
Text(text = stringResource(item.resId), style = MaterialTheme.typography.bodyLarge.merge(), modifier = Modifier.padding(start = 16.dp))
|
||||||
text = stringResource(item.resId),
|
|
||||||
style = MaterialTheme.typography.bodyLarge.merge(),
|
|
||||||
// color = textColor,
|
|
||||||
modifier = Modifier.padding(start = 16.dp)
|
|
||||||
)
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -789,16 +537,8 @@ class FeedSettingsFragment : Fragment() {
|
||||||
if (showDialog) {
|
if (showDialog) {
|
||||||
val (selectedOption, onOptionSelected) = remember { mutableStateOf(feed?.preferences?.autoDLPolicy ?: AutoDownloadPolicy.ONLY_NEW) }
|
val (selectedOption, onOptionSelected) = remember { mutableStateOf(feed?.preferences?.autoDLPolicy ?: AutoDownloadPolicy.ONLY_NEW) }
|
||||||
Dialog(onDismissRequest = { onDismissRequest() }) {
|
Dialog(onDismissRequest = { onDismissRequest() }) {
|
||||||
Card(
|
Card(modifier = Modifier.wrapContentSize(align = Alignment.Center).padding(16.dp), shape = RoundedCornerShape(16.dp)) {
|
||||||
modifier = Modifier
|
Column(modifier = Modifier.padding(16.dp), verticalArrangement = Arrangement.spacedBy(8.dp)) {
|
||||||
.wrapContentSize(align = Alignment.Center)
|
|
||||||
.padding(16.dp),
|
|
||||||
shape = RoundedCornerShape(16.dp),
|
|
||||||
) {
|
|
||||||
Column(
|
|
||||||
modifier = Modifier.padding(16.dp),
|
|
||||||
verticalArrangement = Arrangement.spacedBy(8.dp)
|
|
||||||
) {
|
|
||||||
Column {
|
Column {
|
||||||
AutoDownloadPolicy.entries.forEach { item ->
|
AutoDownloadPolicy.entries.forEach { item ->
|
||||||
Row(Modifier
|
Row(Modifier
|
||||||
|
@ -817,12 +557,7 @@ class FeedSettingsFragment : Fragment() {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
)
|
)
|
||||||
Text(
|
Text(text = stringResource(item.resId), style = MaterialTheme.typography.bodyLarge.merge(), modifier = Modifier.padding(start = 16.dp))
|
||||||
text = stringResource(item.resId),
|
|
||||||
style = MaterialTheme.typography.bodyLarge.merge(),
|
|
||||||
// color = textColor,
|
|
||||||
modifier = Modifier.padding(start = 16.dp)
|
|
||||||
)
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -836,17 +571,10 @@ class FeedSettingsFragment : Fragment() {
|
||||||
fun SetEpisodesCacheDialog(showDialog: Boolean, onDismiss: () -> Unit) {
|
fun SetEpisodesCacheDialog(showDialog: Boolean, onDismiss: () -> Unit) {
|
||||||
if (showDialog) {
|
if (showDialog) {
|
||||||
Dialog(onDismissRequest = onDismiss) {
|
Dialog(onDismissRequest = onDismiss) {
|
||||||
Card(modifier = Modifier
|
Card(modifier = Modifier.wrapContentSize(align = Alignment.Center).padding(16.dp), shape = RoundedCornerShape(16.dp)) {
|
||||||
.wrapContentSize(align = Alignment.Center)
|
Column(modifier = Modifier.padding(16.dp), verticalArrangement = Arrangement.spacedBy(8.dp)) {
|
||||||
.padding(16.dp),
|
|
||||||
shape = RoundedCornerShape(16.dp),
|
|
||||||
) {
|
|
||||||
Column(modifier = Modifier.padding(16.dp),
|
|
||||||
verticalArrangement = Arrangement.spacedBy(8.dp)
|
|
||||||
) {
|
|
||||||
var newCache by remember { mutableStateOf((feed?.preferences?.autoDLMaxEpisodes ?: 1).toString()) }
|
var newCache by remember { mutableStateOf((feed?.preferences?.autoDLMaxEpisodes ?: 1).toString()) }
|
||||||
TextField(value = newCache,
|
TextField(value = newCache, onValueChange = { if (it.isEmpty() || it.toIntOrNull() != null) newCache = it },
|
||||||
onValueChange = { if (it.isEmpty() || it.toIntOrNull() != null) newCache = it },
|
|
||||||
keyboardOptions = KeyboardOptions(keyboardType = KeyboardType.Number),
|
keyboardOptions = KeyboardOptions(keyboardType = KeyboardType.Number),
|
||||||
// visualTransformation = PositiveIntegerTransform(),
|
// visualTransformation = PositiveIntegerTransform(),
|
||||||
label = { Text("Max episodes allowed") }
|
label = { Text("Max episodes allowed") }
|
||||||
|
@ -870,18 +598,10 @@ class FeedSettingsFragment : Fragment() {
|
||||||
var selected by remember {mutableStateOf(selectedOption)}
|
var selected by remember {mutableStateOf(selectedOption)}
|
||||||
if (showDialog) {
|
if (showDialog) {
|
||||||
Dialog(onDismissRequest = { onDismissRequest() }) {
|
Dialog(onDismissRequest = { onDismissRequest() }) {
|
||||||
Card(modifier = Modifier
|
Card(modifier = Modifier.wrapContentSize(align = Alignment.Center).padding(16.dp), shape = RoundedCornerShape(16.dp)) {
|
||||||
.wrapContentSize(align = Alignment.Center)
|
Column(modifier = Modifier.padding(16.dp), verticalArrangement = Arrangement.spacedBy(8.dp)) {
|
||||||
.padding(16.dp),
|
|
||||||
shape = RoundedCornerShape(16.dp),
|
|
||||||
) {
|
|
||||||
Column(modifier = Modifier.padding(16.dp),
|
|
||||||
verticalArrangement = Arrangement.spacedBy(8.dp)
|
|
||||||
) {
|
|
||||||
queueSettingOptions.forEach { option ->
|
queueSettingOptions.forEach { option ->
|
||||||
Row(modifier = Modifier.fillMaxWidth(),
|
Row(modifier = Modifier.fillMaxWidth(), verticalAlignment = Alignment.CenterVertically) {
|
||||||
verticalAlignment = Alignment.CenterVertically
|
|
||||||
) {
|
|
||||||
Checkbox(checked = option == selected,
|
Checkbox(checked = option == selected,
|
||||||
onCheckedChange = { isChecked ->
|
onCheckedChange = { isChecked ->
|
||||||
selected = option
|
selected = option
|
||||||
|
@ -911,6 +631,7 @@ class FeedSettingsFragment : Fragment() {
|
||||||
}
|
}
|
||||||
if (selected == "Custom") {
|
if (selected == "Custom") {
|
||||||
if (queues == null) queues = realm.query(PlayQueue::class).find()
|
if (queues == null) queues = realm.query(PlayQueue::class).find()
|
||||||
|
Logd(TAG, "queues: ${queues?.size}")
|
||||||
Spinner(items = queues!!.map { it.name }, selectedItem = feed?.preferences?.queue?.name ?: "Default") { name ->
|
Spinner(items = queues!!.map { it.name }, selectedItem = feed?.preferences?.queue?.name ?: "Default") { name ->
|
||||||
Logd(TAG, "Queue selected: $name")
|
Logd(TAG, "Queue selected: $name")
|
||||||
val q = queues?.firstOrNull { it.name == name }
|
val q = queues?.firstOrNull { it.name == name }
|
||||||
|
@ -929,26 +650,14 @@ class FeedSettingsFragment : Fragment() {
|
||||||
fun AuthenticationDialog(showDialog: Boolean, onDismiss: () -> Unit) {
|
fun AuthenticationDialog(showDialog: Boolean, onDismiss: () -> Unit) {
|
||||||
if (showDialog) {
|
if (showDialog) {
|
||||||
Dialog(onDismissRequest = onDismiss) {
|
Dialog(onDismissRequest = onDismiss) {
|
||||||
Card(modifier = Modifier
|
Card(modifier = Modifier.wrapContentSize(align = Alignment.Center).padding(16.dp), shape = RoundedCornerShape(16.dp)) {
|
||||||
.wrapContentSize(align = Alignment.Center)
|
Column(modifier = Modifier.padding(16.dp), verticalArrangement = Arrangement.spacedBy(8.dp)) {
|
||||||
.padding(16.dp),
|
|
||||||
shape = RoundedCornerShape(16.dp),
|
|
||||||
) {
|
|
||||||
Column(modifier = Modifier.padding(16.dp),
|
|
||||||
verticalArrangement = Arrangement.spacedBy(8.dp)
|
|
||||||
) {
|
|
||||||
val oldName = feed?.preferences?.username?:""
|
val oldName = feed?.preferences?.username?:""
|
||||||
var newName by remember { mutableStateOf(oldName) }
|
var newName by remember { mutableStateOf(oldName) }
|
||||||
TextField(value = newName,
|
TextField(value = newName, onValueChange = { newName = it }, label = { Text("Username") })
|
||||||
onValueChange = { newName = it },
|
|
||||||
label = { Text("Username") }
|
|
||||||
)
|
|
||||||
val oldPW = feed?.preferences?.password?:""
|
val oldPW = feed?.preferences?.password?:""
|
||||||
var newPW by remember { mutableStateOf(oldPW) }
|
var newPW by remember { mutableStateOf(oldPW) }
|
||||||
TextField(value = newPW,
|
TextField(value = newPW, onValueChange = { newPW = it }, label = { Text("Password") })
|
||||||
onValueChange = { newPW = it },
|
|
||||||
label = { Text("Password") }
|
|
||||||
)
|
|
||||||
Button(onClick = {
|
Button(onClick = {
|
||||||
if (newName.isNotEmpty() && oldName != newName) {
|
if (newName.isNotEmpty() && oldName != newName) {
|
||||||
feed = upsertBlk(feed!!) {
|
feed = upsertBlk(feed!!) {
|
||||||
|
@ -971,14 +680,8 @@ class FeedSettingsFragment : Fragment() {
|
||||||
fun AutoSkipDialog(showDialog: Boolean, onDismiss: () -> Unit) {
|
fun AutoSkipDialog(showDialog: Boolean, onDismiss: () -> Unit) {
|
||||||
if (showDialog) {
|
if (showDialog) {
|
||||||
Dialog(onDismissRequest = onDismiss) {
|
Dialog(onDismissRequest = onDismiss) {
|
||||||
Card(modifier = Modifier
|
Card(modifier = Modifier.wrapContentSize(align = Alignment.Center).padding(16.dp), shape = RoundedCornerShape(16.dp)) {
|
||||||
.wrapContentSize(align = Alignment.Center)
|
Column(modifier = Modifier.padding(16.dp), verticalArrangement = Arrangement.spacedBy(8.dp)) {
|
||||||
.padding(16.dp),
|
|
||||||
shape = RoundedCornerShape(16.dp),
|
|
||||||
) {
|
|
||||||
Column(modifier = Modifier.padding(16.dp),
|
|
||||||
verticalArrangement = Arrangement.spacedBy(8.dp)
|
|
||||||
) {
|
|
||||||
var intro by remember { mutableStateOf((feed?.preferences?.introSkip ?: 0).toString()) }
|
var intro by remember { mutableStateOf((feed?.preferences?.introSkip ?: 0).toString()) }
|
||||||
TextField(value = intro,
|
TextField(value = intro,
|
||||||
onValueChange = { if (it.isEmpty() || it.toIntOrNull() != null) intro = it },
|
onValueChange = { if (it.isEmpty() || it.toIntOrNull() != null) intro = it },
|
||||||
|
|
|
@ -7,6 +7,7 @@ import ac.mdiq.podcini.storage.database.RealmDB.runOnIOScope
|
||||||
import ac.mdiq.podcini.storage.model.ShareLog
|
import ac.mdiq.podcini.storage.model.ShareLog
|
||||||
import ac.mdiq.podcini.ui.activity.ShareReceiverActivity.Companion.receiveShared
|
import ac.mdiq.podcini.ui.activity.ShareReceiverActivity.Companion.receiveShared
|
||||||
import ac.mdiq.podcini.ui.compose.CustomTheme
|
import ac.mdiq.podcini.ui.compose.CustomTheme
|
||||||
|
import ac.mdiq.podcini.ui.compose.confirmAddYoutubeEpisode
|
||||||
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 ac.mdiq.podcini.util.Logd
|
||||||
|
@ -43,6 +44,7 @@ import androidx.compose.ui.unit.dp
|
||||||
import androidx.compose.ui.window.Dialog
|
import androidx.compose.ui.window.Dialog
|
||||||
import androidx.fragment.app.Fragment
|
import androidx.fragment.app.Fragment
|
||||||
import androidx.lifecycle.lifecycleScope
|
import androidx.lifecycle.lifecycleScope
|
||||||
|
import io.realm.kotlin.query.Sort
|
||||||
import kotlinx.coroutines.Dispatchers
|
import kotlinx.coroutines.Dispatchers
|
||||||
import kotlinx.coroutines.launch
|
import kotlinx.coroutines.launch
|
||||||
import kotlinx.coroutines.withContext
|
import kotlinx.coroutines.withContext
|
||||||
|
@ -82,12 +84,13 @@ class SharedLogFragment : Fragment(), Toolbar.OnMenuItemClickListener {
|
||||||
val showDialog = remember { mutableStateOf(false) }
|
val showDialog = remember { mutableStateOf(false) }
|
||||||
val dialogParam = remember { mutableStateOf(ShareLog()) }
|
val dialogParam = remember { mutableStateOf(ShareLog()) }
|
||||||
if (showDialog.value) {
|
if (showDialog.value) {
|
||||||
DetailDialog(
|
DetailDialog(status = dialogParam.value, showDialog = showDialog.value, onDismissRequest = { showDialog.value = false })
|
||||||
status = dialogParam.value,
|
|
||||||
showDialog = showDialog.value,
|
|
||||||
onDismissRequest = { showDialog.value = false },
|
|
||||||
)
|
|
||||||
}
|
}
|
||||||
|
var showYTMediaConfirmDialog by remember { mutableStateOf(false) }
|
||||||
|
var sharedUrl by remember { mutableStateOf("") }
|
||||||
|
if (showYTMediaConfirmDialog)
|
||||||
|
confirmAddYoutubeEpisode(listOf(sharedUrl), showYTMediaConfirmDialog, onDismissRequest = { showYTMediaConfirmDialog = false })
|
||||||
|
|
||||||
LazyColumn(state = lazyListState, modifier = Modifier.padding(start = 10.dp, end = 6.dp, top = 5.dp, bottom = 5.dp),
|
LazyColumn(state = lazyListState, modifier = Modifier.padding(start = 10.dp, end = 6.dp, top = 5.dp, bottom = 5.dp),
|
||||||
verticalArrangement = Arrangement.spacedBy(8.dp)) {
|
verticalArrangement = Arrangement.spacedBy(8.dp)) {
|
||||||
itemsIndexed(logs) { position, log ->
|
itemsIndexed(logs) { position, log ->
|
||||||
|
@ -96,7 +99,12 @@ class SharedLogFragment : Fragment(), Toolbar.OnMenuItemClickListener {
|
||||||
if (log.status == 1) {
|
if (log.status == 1) {
|
||||||
showDialog.value = true
|
showDialog.value = true
|
||||||
dialogParam.value = log
|
dialogParam.value = log
|
||||||
} else receiveShared(log.url!!, activity as AppCompatActivity, false)
|
} else {
|
||||||
|
receiveShared(log.url!!, activity as AppCompatActivity, false) {
|
||||||
|
sharedUrl = log.url!!
|
||||||
|
showYTMediaConfirmDialog = true
|
||||||
|
}
|
||||||
|
}
|
||||||
}) {
|
}) {
|
||||||
Column {
|
Column {
|
||||||
Row {
|
Row {
|
||||||
|
@ -104,6 +112,13 @@ class SharedLogFragment : Fragment(), Toolbar.OnMenuItemClickListener {
|
||||||
val iconColor = remember { if (log.status == 1) Color.Green else Color.Yellow }
|
val iconColor = remember { if (log.status == 1) Color.Green else Color.Yellow }
|
||||||
Icon(icon, "Info", tint = iconColor, modifier = Modifier.padding(end = 2.dp))
|
Icon(icon, "Info", tint = iconColor, modifier = Modifier.padding(end = 2.dp))
|
||||||
Text(formatDateTimeFlex(Date(log.id)), color = textColor)
|
Text(formatDateTimeFlex(Date(log.id)), color = textColor)
|
||||||
|
Spacer(Modifier.weight(1f))
|
||||||
|
var showAction by remember { mutableStateOf(log.status != 1) }
|
||||||
|
if (true || showAction) {
|
||||||
|
Icon(painter = painterResource(R.drawable.ic_delete), tint = textColor, contentDescription = null,
|
||||||
|
modifier = Modifier.width(25.dp).height(25.dp).clickable {
|
||||||
|
})
|
||||||
|
}
|
||||||
}
|
}
|
||||||
Text(log.url?:"unknown", color = textColor)
|
Text(log.url?:"unknown", color = textColor)
|
||||||
val statusText = remember {"" }
|
val statusText = remember {"" }
|
||||||
|
@ -113,15 +128,6 @@ class SharedLogFragment : Fragment(), Toolbar.OnMenuItemClickListener {
|
||||||
Text(stringResource(R.string.download_error_tap_for_details), color = textColor)
|
Text(stringResource(R.string.download_error_tap_for_details), color = textColor)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
var showAction by remember { mutableStateOf(log.status != 1) }
|
|
||||||
if (showAction) {
|
|
||||||
Icon(painter = painterResource(R.drawable.ic_refresh),
|
|
||||||
tint = textColor,
|
|
||||||
contentDescription = null,
|
|
||||||
modifier = Modifier.width(28.dp).height(32.dp).clickable {
|
|
||||||
|
|
||||||
})
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -154,7 +160,7 @@ class SharedLogFragment : Fragment(), Toolbar.OnMenuItemClickListener {
|
||||||
try {
|
try {
|
||||||
val result = withContext(Dispatchers.IO) {
|
val result = withContext(Dispatchers.IO) {
|
||||||
Logd(TAG, "getDownloadLog() called")
|
Logd(TAG, "getDownloadLog() called")
|
||||||
val dlog = realm.query(ShareLog::class).find().toMutableList()
|
val dlog = realm.query(ShareLog::class).sort("id", Sort.DESCENDING).find().toMutableList()
|
||||||
realm.copyFromRealm(dlog)
|
realm.copyFromRealm(dlog)
|
||||||
}
|
}
|
||||||
withContext(Dispatchers.Main) {
|
withContext(Dispatchers.Main) {
|
||||||
|
|
|
@ -529,9 +529,8 @@ class SubscriptionsFragment : Fragment(), Toolbar.OnMenuItemClickListener {
|
||||||
Column(modifier = Modifier.padding(16.dp), verticalArrangement = Arrangement.spacedBy(8.dp)) {
|
Column(modifier = Modifier.padding(16.dp), verticalArrangement = Arrangement.spacedBy(8.dp)) {
|
||||||
Column {
|
Column {
|
||||||
FeedAutoDeleteOptions.forEach { text ->
|
FeedAutoDeleteOptions.forEach { text ->
|
||||||
Row(
|
Row(Modifier.fillMaxWidth().padding(horizontal = 16.dp)
|
||||||
Modifier.fillMaxWidth().padding(horizontal = 16.dp).selectable(
|
.selectable(selected = (text == selectedOption),
|
||||||
selected = (text == selectedOption),
|
|
||||||
onClick = {
|
onClick = {
|
||||||
if (text != selectedOption) {
|
if (text != selectedOption) {
|
||||||
val autoDeleteAction: AutoDeleteAction = AutoDeleteAction.fromTag(text)
|
val autoDeleteAction: AutoDeleteAction = AutoDeleteAction.fromTag(text)
|
||||||
|
@ -545,11 +544,7 @@ class SubscriptionsFragment : Fragment(), Toolbar.OnMenuItemClickListener {
|
||||||
verticalAlignment = Alignment.CenterVertically
|
verticalAlignment = Alignment.CenterVertically
|
||||||
) {
|
) {
|
||||||
RadioButton(selected = (text == selectedOption), onClick = { })
|
RadioButton(selected = (text == selectedOption), onClick = { })
|
||||||
Text(
|
Text(text = text, style = MaterialTheme.typography.bodyLarge.merge(), modifier = Modifier.padding(start = 16.dp))
|
||||||
text = text,
|
|
||||||
style = MaterialTheme.typography.bodyLarge.merge(),
|
|
||||||
modifier = Modifier.padding(start = 16.dp)
|
|
||||||
)
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -641,27 +636,15 @@ class SubscriptionsFragment : Fragment(), Toolbar.OnMenuItemClickListener {
|
||||||
CustomTheme(activity) {
|
CustomTheme(activity) {
|
||||||
if (showDialog.value) {
|
if (showDialog.value) {
|
||||||
Dialog(onDismissRequest = { showDialog.value = false }) {
|
Dialog(onDismissRequest = { showDialog.value = false }) {
|
||||||
Card(
|
Card(modifier = Modifier.wrapContentSize(align = Alignment.Center).padding(16.dp), shape = RoundedCornerShape(16.dp)) {
|
||||||
modifier = Modifier
|
Column(modifier = Modifier.padding(16.dp), verticalArrangement = Arrangement.Center) {
|
||||||
.wrapContentSize(align = Alignment.Center)
|
|
||||||
.padding(16.dp),
|
|
||||||
shape = RoundedCornerShape(16.dp),
|
|
||||||
) {
|
|
||||||
Column(
|
|
||||||
modifier = Modifier.padding(16.dp),
|
|
||||||
verticalArrangement = Arrangement.Center
|
|
||||||
) {
|
|
||||||
Row(Modifier.fillMaxWidth()) {
|
Row(Modifier.fillMaxWidth()) {
|
||||||
Icon(ImageVector.vectorResource(id = R.drawable.ic_refresh), "")
|
Icon(ImageVector.vectorResource(id = R.drawable.ic_refresh), "")
|
||||||
Spacer(modifier = Modifier.width(20.dp))
|
Spacer(modifier = Modifier.width(20.dp))
|
||||||
Text(
|
Text(text = stringResource(R.string.keep_updated), style = MaterialTheme.typography.titleLarge)
|
||||||
text = stringResource(R.string.keep_updated),
|
|
||||||
style = MaterialTheme.typography.titleLarge
|
|
||||||
)
|
|
||||||
Spacer(modifier = Modifier.weight(1f))
|
Spacer(modifier = Modifier.weight(1f))
|
||||||
var checked by remember { mutableStateOf(false) }
|
var checked by remember { mutableStateOf(false) }
|
||||||
Switch(
|
Switch(checked = checked,
|
||||||
checked = checked,
|
|
||||||
onCheckedChange = {
|
onCheckedChange = {
|
||||||
checked = it
|
checked = it
|
||||||
saveFeedPreferences { pref: FeedPreferences ->
|
saveFeedPreferences { pref: FeedPreferences ->
|
||||||
|
@ -670,10 +653,7 @@ class SubscriptionsFragment : Fragment(), Toolbar.OnMenuItemClickListener {
|
||||||
}
|
}
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
Text(
|
Text(text = stringResource(R.string.keep_updated_summary), style = MaterialTheme.typography.bodyMedium)
|
||||||
text = stringResource(R.string.keep_updated_summary),
|
|
||||||
style = MaterialTheme.typography.bodyMedium
|
|
||||||
)
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -799,9 +779,7 @@ class SubscriptionsFragment : Fragment(), Toolbar.OnMenuItemClickListener {
|
||||||
val scrollState = rememberScrollState()
|
val scrollState = rememberScrollState()
|
||||||
Column(modifier = modifier.verticalScroll(scrollState), verticalArrangement = Arrangement.Bottom) {
|
Column(modifier = modifier.verticalScroll(scrollState), verticalArrangement = Arrangement.Bottom) {
|
||||||
if (isExpanded) options.forEachIndexed { _, button ->
|
if (isExpanded) options.forEachIndexed { _, button ->
|
||||||
FloatingActionButton(modifier = Modifier.padding(start = 4.dp, bottom = 6.dp).height(40.dp),
|
FloatingActionButton(modifier = Modifier.padding(start = 4.dp, bottom = 6.dp).height(40.dp), containerColor = Color.LightGray, onClick = {}) { button() }
|
||||||
containerColor = Color.LightGray,
|
|
||||||
onClick = {}) { button() }
|
|
||||||
}
|
}
|
||||||
FloatingActionButton(containerColor = MaterialTheme.colorScheme.secondaryContainer,
|
FloatingActionButton(containerColor = MaterialTheme.colorScheme.secondaryContainer,
|
||||||
contentColor = MaterialTheme.colorScheme.secondary,
|
contentColor = MaterialTheme.colorScheme.secondary,
|
||||||
|
@ -826,10 +804,8 @@ class SubscriptionsFragment : Fragment(), Toolbar.OnMenuItemClickListener {
|
||||||
}) {
|
}) {
|
||||||
if (if (useGrid == null) useGridLayout else useGrid!!) {
|
if (if (useGrid == null) useGridLayout else useGrid!!) {
|
||||||
val lazyGridState = rememberLazyGridState()
|
val lazyGridState = rememberLazyGridState()
|
||||||
LazyVerticalGrid(state = lazyGridState,
|
LazyVerticalGrid(state = lazyGridState, columns = GridCells.Fixed(3),
|
||||||
columns = GridCells.Fixed(3),
|
verticalArrangement = Arrangement.spacedBy(16.dp), horizontalArrangement = Arrangement.spacedBy(16.dp),
|
||||||
verticalArrangement = Arrangement.spacedBy(16.dp),
|
|
||||||
horizontalArrangement = Arrangement.spacedBy(16.dp),
|
|
||||||
contentPadding = PaddingValues(start = 12.dp, top = 16.dp, end = 12.dp, bottom = 16.dp)
|
contentPadding = PaddingValues(start = 12.dp, top = 16.dp, end = 12.dp, bottom = 16.dp)
|
||||||
) {
|
) {
|
||||||
items(feedListFiltered.size, key = {index -> feedListFiltered[index].id}) { index ->
|
items(feedListFiltered.size, key = {index -> feedListFiltered[index].id}) { index ->
|
||||||
|
@ -867,8 +843,7 @@ class SubscriptionsFragment : Fragment(), Toolbar.OnMenuItemClickListener {
|
||||||
val textColor = MaterialTheme.colorScheme.onSurface
|
val textColor = MaterialTheme.colorScheme.onSurface
|
||||||
ConstraintLayout {
|
ConstraintLayout {
|
||||||
val (coverImage, episodeCount, error) = createRefs()
|
val (coverImage, episodeCount, error) = createRefs()
|
||||||
AsyncImage(model = feed.imageUrl, contentDescription = "coverImage",
|
AsyncImage(model = feed.imageUrl, contentDescription = "coverImage", placeholder = painterResource(R.mipmap.ic_launcher),
|
||||||
placeholder = painterResource(R.mipmap.ic_launcher),
|
|
||||||
modifier = Modifier
|
modifier = Modifier
|
||||||
.constrainAs(coverImage) {
|
.constrainAs(coverImage) {
|
||||||
top.linkTo(parent.top)
|
top.linkTo(parent.top)
|
||||||
|
@ -881,24 +856,19 @@ class SubscriptionsFragment : Fragment(), Toolbar.OnMenuItemClickListener {
|
||||||
top.linkTo(coverImage.top)
|
top.linkTo(coverImage.top)
|
||||||
})
|
})
|
||||||
// TODO: need to use state
|
// TODO: need to use state
|
||||||
if (feed.lastUpdateFailed) Icon(painter = painterResource(R.drawable.ic_error), tint = Color.Red,
|
if (feed.lastUpdateFailed) Icon(painter = painterResource(R.drawable.ic_error), tint = Color.Red, contentDescription = "error",
|
||||||
contentDescription = "error",
|
|
||||||
modifier = Modifier.constrainAs(error) {
|
modifier = Modifier.constrainAs(error) {
|
||||||
end.linkTo(parent.end)
|
end.linkTo(parent.end)
|
||||||
bottom.linkTo(coverImage.bottom)
|
bottom.linkTo(coverImage.bottom)
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
Text(feed.title ?: "No title",
|
Text(feed.title ?: "No title", color = textColor, maxLines = 2, overflow = TextOverflow.Ellipsis)
|
||||||
color = textColor,
|
|
||||||
maxLines = 2,
|
|
||||||
overflow = TextOverflow.Ellipsis)
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
val lazyListState = rememberLazyListState()
|
val lazyListState = rememberLazyListState()
|
||||||
LazyColumn(state = lazyListState,
|
LazyColumn(state = lazyListState, modifier = Modifier.padding(start = 10.dp, end = 10.dp, top = 10.dp, bottom = 10.dp),
|
||||||
modifier = Modifier.padding(start = 10.dp, end = 10.dp, top = 10.dp, bottom = 10.dp),
|
|
||||||
verticalArrangement = Arrangement.spacedBy(8.dp)) {
|
verticalArrangement = Arrangement.spacedBy(8.dp)) {
|
||||||
itemsIndexed(feedListFiltered, key = {index, feed -> feed.id}) { index, feed ->
|
itemsIndexed(feedListFiltered, key = {index, feed -> feed.id}) { index, feed ->
|
||||||
var isSelected by remember { mutableStateOf(false) }
|
var isSelected by remember { mutableStateOf(false) }
|
||||||
|
@ -912,8 +882,7 @@ class SubscriptionsFragment : Fragment(), Toolbar.OnMenuItemClickListener {
|
||||||
Logd(TAG, "toggleSelected: selected: ${selected.size}")
|
Logd(TAG, "toggleSelected: selected: ${selected.size}")
|
||||||
}
|
}
|
||||||
Row(Modifier.background(if (isSelected) MaterialTheme.colorScheme.secondaryContainer else MaterialTheme.colorScheme.surface)) {
|
Row(Modifier.background(if (isSelected) MaterialTheme.colorScheme.secondaryContainer else MaterialTheme.colorScheme.surface)) {
|
||||||
AsyncImage(model = feed.imageUrl, contentDescription = "imgvCover",
|
AsyncImage(model = feed.imageUrl, contentDescription = "imgvCover", placeholder = painterResource(R.mipmap.ic_launcher),
|
||||||
placeholder = painterResource(R.mipmap.ic_launcher),
|
|
||||||
modifier = Modifier.width(80.dp).height(80.dp)
|
modifier = Modifier.width(80.dp).height(80.dp)
|
||||||
.clickable(onClick = {
|
.clickable(onClick = {
|
||||||
Logd(TAG, "icon clicked!")
|
Logd(TAG, "icon clicked!")
|
||||||
|
@ -964,13 +933,9 @@ class SubscriptionsFragment : Fragment(), Toolbar.OnMenuItemClickListener {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (selectMode) {
|
if (selectMode) {
|
||||||
Row(modifier = Modifier.align(Alignment.TopEnd).width(150.dp).height(45.dp)
|
Row(modifier = Modifier.align(Alignment.TopEnd).width(150.dp).height(45.dp).background(Color.LightGray),
|
||||||
.background(Color.LightGray),
|
horizontalArrangement = Arrangement.Center, verticalAlignment = Alignment.CenterVertically) {
|
||||||
horizontalArrangement = Arrangement.Center,
|
Icon(painter = painterResource(R.drawable.baseline_arrow_upward_24), tint = Color.Black, contentDescription = null,
|
||||||
verticalAlignment = Alignment.CenterVertically) {
|
|
||||||
Icon(painter = painterResource(R.drawable.baseline_arrow_upward_24),
|
|
||||||
tint = Color.Black,
|
|
||||||
contentDescription = null,
|
|
||||||
modifier = Modifier.width(35.dp).height(35.dp).padding(end = 10.dp)
|
modifier = Modifier.width(35.dp).height(35.dp).padding(end = 10.dp)
|
||||||
.clickable(onClick = {
|
.clickable(onClick = {
|
||||||
selected.clear()
|
selected.clear()
|
||||||
|
@ -980,9 +945,7 @@ class SubscriptionsFragment : Fragment(), Toolbar.OnMenuItemClickListener {
|
||||||
selectedSize = selected.size
|
selectedSize = selected.size
|
||||||
Logd(TAG, "selectedIds: ${selected.size}")
|
Logd(TAG, "selectedIds: ${selected.size}")
|
||||||
}))
|
}))
|
||||||
Icon(painter = painterResource(R.drawable.baseline_arrow_downward_24),
|
Icon(painter = painterResource(R.drawable.baseline_arrow_downward_24), tint = Color.Black, contentDescription = null,
|
||||||
tint = Color.Black,
|
|
||||||
contentDescription = null,
|
|
||||||
modifier = Modifier.width(35.dp).height(35.dp).padding(end = 10.dp)
|
modifier = Modifier.width(35.dp).height(35.dp).padding(end = 10.dp)
|
||||||
.clickable(onClick = {
|
.clickable(onClick = {
|
||||||
selected.clear()
|
selected.clear()
|
||||||
|
@ -993,9 +956,7 @@ class SubscriptionsFragment : Fragment(), Toolbar.OnMenuItemClickListener {
|
||||||
Logd(TAG, "selectedIds: ${selected.size}")
|
Logd(TAG, "selectedIds: ${selected.size}")
|
||||||
}))
|
}))
|
||||||
var selectAllRes by remember { mutableIntStateOf(R.drawable.ic_select_all) }
|
var selectAllRes by remember { mutableIntStateOf(R.drawable.ic_select_all) }
|
||||||
Icon(painter = painterResource(selectAllRes),
|
Icon(painter = painterResource(selectAllRes), tint = Color.Black, contentDescription = null,
|
||||||
tint = Color.Black,
|
|
||||||
contentDescription = null,
|
|
||||||
modifier = Modifier.width(35.dp).height(35.dp)
|
modifier = Modifier.width(35.dp).height(35.dp)
|
||||||
.clickable(onClick = {
|
.clickable(onClick = {
|
||||||
if (selectedSize != feedListFiltered.size) {
|
if (selectedSize != feedListFiltered.size) {
|
||||||
|
|
|
@ -9,7 +9,7 @@
|
||||||
android:orientation="vertical">
|
android:orientation="vertical">
|
||||||
|
|
||||||
<androidx.compose.ui.platform.ComposeView
|
<androidx.compose.ui.platform.ComposeView
|
||||||
android:id="@+id/composeView1"
|
android:id="@+id/player1"
|
||||||
android:layout_width="match_parent"
|
android:layout_width="match_parent"
|
||||||
android:layout_height="@dimen/external_player_height"
|
android:layout_height="@dimen/external_player_height"
|
||||||
android:elevation="8dp"
|
android:elevation="8dp"
|
||||||
|
@ -38,7 +38,7 @@
|
||||||
android:layout_marginBottom="12dp"/>
|
android:layout_marginBottom="12dp"/>
|
||||||
|
|
||||||
<androidx.compose.ui.platform.ComposeView
|
<androidx.compose.ui.platform.ComposeView
|
||||||
android:id="@+id/composeView2"
|
android:id="@+id/player2"
|
||||||
android:layout_width="match_parent"
|
android:layout_width="match_parent"
|
||||||
android:layout_height="@dimen/external_player_height"/>
|
android:layout_height="@dimen/external_player_height"/>
|
||||||
|
|
||||||
|
|
|
@ -25,10 +25,10 @@
|
||||||
app:navigationContentDescription="@string/toolbar_back_button_content_description"
|
app:navigationContentDescription="@string/toolbar_back_button_content_description"
|
||||||
app:navigationIcon="?homeAsUpIndicator" />
|
app:navigationIcon="?homeAsUpIndicator" />
|
||||||
|
|
||||||
<androidx.compose.ui.platform.ComposeView
|
<!-- <androidx.compose.ui.platform.ComposeView-->
|
||||||
android:id="@+id/header"
|
<!-- android:id="@+id/header"-->
|
||||||
android:layout_width="match_parent"
|
<!-- android:layout_width="match_parent"-->
|
||||||
android:layout_height="wrap_content"/>
|
<!-- android:layout_height="wrap_content"/>-->
|
||||||
</com.google.android.material.appbar.AppBarLayout>
|
</com.google.android.material.appbar.AppBarLayout>
|
||||||
|
|
||||||
<androidx.compose.ui.platform.ComposeView
|
<androidx.compose.ui.platform.ComposeView
|
||||||
|
|
|
@ -34,17 +34,17 @@
|
||||||
android:title="@string/remove_from_queue_label">
|
android:title="@string/remove_from_queue_label">
|
||||||
</item>
|
</item>
|
||||||
|
|
||||||
<item
|
<!-- <item-->
|
||||||
android:id="@+id/add_to_favorites_item"
|
<!-- android:id="@+id/add_to_favorites_item"-->
|
||||||
android:icon="@drawable/ic_star_border"
|
<!-- android:icon="@drawable/ic_star_border"-->
|
||||||
custom:showAsAction="always"
|
<!-- custom:showAsAction="always"-->
|
||||||
android:title="@string/add_to_favorite_label" />
|
<!-- android:title="@string/add_to_favorite_label" />-->
|
||||||
|
|
||||||
<item
|
<!-- <item-->
|
||||||
android:id="@+id/remove_from_favorites_item"
|
<!-- android:id="@+id/remove_from_favorites_item"-->
|
||||||
android:icon="@drawable/ic_star"
|
<!-- android:icon="@drawable/ic_star"-->
|
||||||
custom:showAsAction="always"
|
<!-- custom:showAsAction="always"-->
|
||||||
android:title="@string/remove_from_favorite_label" />
|
<!-- android:title="@string/remove_from_favorite_label" />-->
|
||||||
|
|
||||||
<item
|
<item
|
||||||
android:id="@+id/reset_position"
|
android:id="@+id/reset_position"
|
||||||
|
|
|
@ -30,15 +30,15 @@
|
||||||
android:menuCategory="container"
|
android:menuCategory="container"
|
||||||
android:title="@string/delete_label" />
|
android:title="@string/delete_label" />
|
||||||
|
|
||||||
<item
|
<!-- <item-->
|
||||||
android:id="@+id/add_to_favorites_item"
|
<!-- android:id="@+id/add_to_favorites_item"-->
|
||||||
android:menuCategory="container"
|
<!-- android:menuCategory="container"-->
|
||||||
android:title="@string/add_to_favorite_label" />
|
<!-- android:title="@string/add_to_favorite_label" />-->
|
||||||
|
|
||||||
<item
|
<!-- <item-->
|
||||||
android:id="@+id/remove_from_favorites_item"
|
<!-- android:id="@+id/remove_from_favorites_item"-->
|
||||||
android:menuCategory="container"
|
<!-- android:menuCategory="container"-->
|
||||||
android:title="@string/remove_from_favorite_label" />
|
<!-- android:title="@string/remove_from_favorite_label" />-->
|
||||||
|
|
||||||
<item
|
<item
|
||||||
android:id="@+id/reset_position"
|
android:id="@+id/reset_position"
|
||||||
|
|
|
@ -18,18 +18,18 @@
|
||||||
custom:showAsAction="always">
|
custom:showAsAction="always">
|
||||||
</item>
|
</item>
|
||||||
|
|
||||||
<item
|
<!-- <item-->
|
||||||
android:id="@+id/add_to_favorites_item"
|
<!-- android:id="@+id/add_to_favorites_item"-->
|
||||||
android:icon="@drawable/ic_star_border"
|
<!-- android:icon="@drawable/ic_star_border"-->
|
||||||
android:title="@string/add_to_favorite_label"
|
<!-- android:title="@string/add_to_favorite_label"-->
|
||||||
custom:showAsAction="always">
|
<!-- custom:showAsAction="always">-->
|
||||||
</item>
|
<!-- </item>-->
|
||||||
<item
|
<!-- <item-->
|
||||||
android:id="@+id/remove_from_favorites_item"
|
<!-- android:id="@+id/remove_from_favorites_item"-->
|
||||||
android:icon="@drawable/ic_star"
|
<!-- android:icon="@drawable/ic_star"-->
|
||||||
android:title="@string/remove_from_favorite_label"
|
<!-- android:title="@string/remove_from_favorite_label"-->
|
||||||
custom:showAsAction="always">
|
<!-- custom:showAsAction="always">-->
|
||||||
</item>
|
<!-- </item>-->
|
||||||
|
|
||||||
<item
|
<item
|
||||||
android:id="@+id/disable_sleeptimer_item"
|
android:id="@+id/disable_sleeptimer_item"
|
||||||
|
|
|
@ -1,3 +1,11 @@
|
||||||
|
# 6.9.3
|
||||||
|
|
||||||
|
* fixed app quit issue when repairing a shared item
|
||||||
|
* fixed custom queue spinner not showing up (issue introduced in 6.8.3 when migrating to Material3)
|
||||||
|
* updated dialog popup mechanism in FeedSettings
|
||||||
|
* updated UI to reflect the new rating system
|
||||||
|
* a couple dialog converted to Compose and removed EpisodeMultiSelectHandler
|
||||||
|
|
||||||
# 6.9.2
|
# 6.9.2
|
||||||
|
|
||||||
* fixed getting 0 episodes with Youtube playlist etc
|
* fixed getting 0 episodes with Youtube playlist etc
|
||||||
|
|
|
@ -0,0 +1,7 @@
|
||||||
|
Version 6.9.3
|
||||||
|
|
||||||
|
* fixed app quit issue when repairing a shared item
|
||||||
|
* fixed custom queue spinner not showing up (issue introduced in 6.8.3 when migrating to Material3)
|
||||||
|
* updated dialog popup mechanism in FeedSettings
|
||||||
|
* updated UI to reflect the new rating system
|
||||||
|
* a couple dialog converted to Compose and removed EpisodeMultiSelectHandler
|
Loading…
Reference in New Issue