6.12.6 commit
This commit is contained in:
parent
974bea78cf
commit
6b29cc3f5d
|
@ -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 3020283
|
versionCode 3020284
|
||||||
versionName "6.12.5"
|
versionName "6.12.6"
|
||||||
|
|
||||||
applicationId "ac.mdiq.podcini.R"
|
applicationId "ac.mdiq.podcini.R"
|
||||||
def commit = ""
|
def commit = ""
|
||||||
|
|
|
@ -247,7 +247,7 @@ import kotlin.math.min
|
||||||
// only push downloaded items
|
// only push downloaded items
|
||||||
val pausedItems = getEpisodes(0, Int.MAX_VALUE, EpisodeFilter(EpisodeFilter.States.paused.name), EpisodeSortOrder.DATE_NEW_OLD)
|
val pausedItems = getEpisodes(0, Int.MAX_VALUE, EpisodeFilter(EpisodeFilter.States.paused.name), EpisodeSortOrder.DATE_NEW_OLD)
|
||||||
val readItems = getEpisodes(0, Int.MAX_VALUE, EpisodeFilter(EpisodeFilter.States.played.name), EpisodeSortOrder.DATE_NEW_OLD)
|
val readItems = getEpisodes(0, Int.MAX_VALUE, EpisodeFilter(EpisodeFilter.States.played.name), EpisodeSortOrder.DATE_NEW_OLD)
|
||||||
val favoriteItems = getEpisodes(0, Int.MAX_VALUE, EpisodeFilter(EpisodeFilter.States.is_favorite.name), EpisodeSortOrder.DATE_NEW_OLD)
|
val favoriteItems = getEpisodes(0, Int.MAX_VALUE, EpisodeFilter(EpisodeFilter.States.favorite.name), EpisodeSortOrder.DATE_NEW_OLD)
|
||||||
val comItems = mutableSetOf<Episode>()
|
val comItems = mutableSetOf<Episode>()
|
||||||
comItems.addAll(pausedItems)
|
comItems.addAll(pausedItems)
|
||||||
comItems.addAll(readItems)
|
comItems.addAll(readItems)
|
||||||
|
|
|
@ -959,7 +959,7 @@ class ImportExportPreferencesFragment : PreferenceFragmentCompat() {
|
||||||
val queuedEpisodeActions: MutableList<EpisodeAction> = mutableListOf()
|
val queuedEpisodeActions: MutableList<EpisodeAction> = mutableListOf()
|
||||||
val pausedItems = getEpisodes(0, Int.MAX_VALUE, EpisodeFilter(EpisodeFilter.States.paused.name), EpisodeSortOrder.DATE_NEW_OLD)
|
val pausedItems = getEpisodes(0, Int.MAX_VALUE, EpisodeFilter(EpisodeFilter.States.paused.name), EpisodeSortOrder.DATE_NEW_OLD)
|
||||||
val readItems = getEpisodes(0, Int.MAX_VALUE, EpisodeFilter(EpisodeFilter.States.played.name), EpisodeSortOrder.DATE_NEW_OLD)
|
val readItems = getEpisodes(0, Int.MAX_VALUE, EpisodeFilter(EpisodeFilter.States.played.name), EpisodeSortOrder.DATE_NEW_OLD)
|
||||||
val favoriteItems = getEpisodes(0, Int.MAX_VALUE, EpisodeFilter(EpisodeFilter.States.is_favorite.name), EpisodeSortOrder.DATE_NEW_OLD)
|
val favoriteItems = getEpisodes(0, Int.MAX_VALUE, EpisodeFilter(EpisodeFilter.States.favorite.name), EpisodeSortOrder.DATE_NEW_OLD)
|
||||||
val comItems = mutableSetOf<Episode>()
|
val comItems = mutableSetOf<Episode>()
|
||||||
comItems.addAll(pausedItems)
|
comItems.addAll(pausedItems)
|
||||||
comItems.addAll(readItems)
|
comItems.addAll(readItems)
|
||||||
|
@ -1018,7 +1018,7 @@ class ImportExportPreferencesFragment : PreferenceFragmentCompat() {
|
||||||
val favTemplate = IOUtils.toString(favTemplateStream, UTF_8)
|
val favTemplate = IOUtils.toString(favTemplateStream, UTF_8)
|
||||||
val feedTemplateStream = context.assets.open(FEED_TEMPLATE)
|
val feedTemplateStream = context.assets.open(FEED_TEMPLATE)
|
||||||
val feedTemplate = IOUtils.toString(feedTemplateStream, UTF_8)
|
val feedTemplate = IOUtils.toString(feedTemplateStream, UTF_8)
|
||||||
val allFavorites = getEpisodes(0, Int.MAX_VALUE, EpisodeFilter(EpisodeFilter.States.is_favorite.name), EpisodeSortOrder.DATE_NEW_OLD)
|
val allFavorites = getEpisodes(0, Int.MAX_VALUE, EpisodeFilter(EpisodeFilter.States.favorite.name), EpisodeSortOrder.DATE_NEW_OLD)
|
||||||
val favoritesByFeed = buildFeedMap(allFavorites)
|
val favoritesByFeed = buildFeedMap(allFavorites)
|
||||||
writer!!.append(templateParts[0])
|
writer!!.append(templateParts[0])
|
||||||
for (feedId in favoritesByFeed.keys) {
|
for (feedId in favoritesByFeed.keys) {
|
||||||
|
|
|
@ -19,6 +19,9 @@ import ac.mdiq.podcini.util.EventFlow
|
||||||
import ac.mdiq.podcini.util.FlowEvent
|
import ac.mdiq.podcini.util.FlowEvent
|
||||||
import android.util.Log
|
import android.util.Log
|
||||||
import androidx.annotation.OptIn
|
import androidx.annotation.OptIn
|
||||||
|
import androidx.compose.runtime.getValue
|
||||||
|
import androidx.compose.runtime.mutableStateOf
|
||||||
|
import androidx.compose.runtime.setValue
|
||||||
import androidx.media3.common.util.UnstableApi
|
import androidx.media3.common.util.UnstableApi
|
||||||
import kotlinx.coroutines.Job
|
import kotlinx.coroutines.Job
|
||||||
import java.util.*
|
import java.util.*
|
||||||
|
@ -30,12 +33,6 @@ object Queues {
|
||||||
BACK, FRONT, AFTER_CURRENTLY_PLAYING, RANDOM
|
BACK, FRONT, AFTER_CURRENTLY_PLAYING, RANDOM
|
||||||
}
|
}
|
||||||
|
|
||||||
var isQueueLocked: Boolean
|
|
||||||
get() = appPrefs.getBoolean(UserPreferences.Prefs.prefQueueLocked.name, false)
|
|
||||||
set(locked) {
|
|
||||||
appPrefs.edit().putBoolean(UserPreferences.Prefs.prefQueueLocked.name, locked).apply()
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Returns if the queue is in keep sorted mode.
|
* Returns if the queue is in keep sorted mode.
|
||||||
* Enables/disables the keep sorted mode of the queue.
|
* Enables/disables the keep sorted mode of the queue.
|
||||||
|
@ -66,8 +63,7 @@ object Queues {
|
||||||
var enqueueLocation: EnqueueLocation
|
var enqueueLocation: EnqueueLocation
|
||||||
get() {
|
get() {
|
||||||
val valStr = appPrefs.getString(UserPreferences.Prefs.prefEnqueueLocation.name, EnqueueLocation.BACK.name)
|
val valStr = appPrefs.getString(UserPreferences.Prefs.prefEnqueueLocation.name, EnqueueLocation.BACK.name)
|
||||||
try {
|
try { return EnqueueLocation.valueOf(valStr!!)
|
||||||
return EnqueueLocation.valueOf(valStr!!)
|
|
||||||
} catch (t: Throwable) {
|
} catch (t: Throwable) {
|
||||||
// should never happen but just in case
|
// should never happen but just in case
|
||||||
Log.e(TAG, "getEnqueueLocation: invalid value '$valStr' Use default.", t)
|
Log.e(TAG, "getEnqueueLocation: invalid value '$valStr' Use default.", t)
|
||||||
|
|
|
@ -2,20 +2,21 @@ package ac.mdiq.podcini.storage.model
|
||||||
|
|
||||||
import ac.mdiq.podcini.R
|
import ac.mdiq.podcini.R
|
||||||
import ac.mdiq.podcini.storage.database.Queues.inAnyQueue
|
import ac.mdiq.podcini.storage.database.Queues.inAnyQueue
|
||||||
|
import ac.mdiq.podcini.util.Logd
|
||||||
import java.io.Serializable
|
import java.io.Serializable
|
||||||
|
|
||||||
class EpisodeFilter(vararg properties_: String) : Serializable {
|
class EpisodeFilter(vararg properties_: String) : Serializable {
|
||||||
val properties: HashSet<String> = setOf(*properties_).filter { it.isNotEmpty() }.map {it.trim()}.toHashSet()
|
val properties: HashSet<String> = setOf(*properties_).filter { it.isNotEmpty() }.map {it.trim()}.toHashSet()
|
||||||
|
|
||||||
val showPlayed: Boolean = properties.contains(States.played.name)
|
// val showPlayed: Boolean = properties.contains(States.played.name)
|
||||||
val showUnplayed: Boolean = properties.contains(States.unplayed.name)
|
// val showUnplayed: Boolean = properties.contains(States.unplayed.name)
|
||||||
val showNew: Boolean = properties.contains(States.new.name)
|
// val showNew: Boolean = properties.contains(States.new.name)
|
||||||
val showQueued: Boolean = properties.contains(States.queued.name)
|
val showQueued: Boolean = properties.contains(States.queued.name)
|
||||||
val showNotQueued: Boolean = properties.contains(States.not_queued.name)
|
val showNotQueued: Boolean = properties.contains(States.not_queued.name)
|
||||||
val showDownloaded: Boolean = properties.contains(States.downloaded.name)
|
val showDownloaded: Boolean = properties.contains(States.downloaded.name)
|
||||||
val showNotDownloaded: Boolean = properties.contains(States.not_downloaded.name)
|
val showNotDownloaded: Boolean = properties.contains(States.not_downloaded.name)
|
||||||
val showIsFavorite: Boolean = properties.contains(States.is_favorite.name)
|
// val showIsFavorite: Boolean = properties.contains(States.is_favorite.name)
|
||||||
val showNotFavorite: Boolean = properties.contains(States.not_favorite.name)
|
// val showNotFavorite: Boolean = properties.contains(States.not_favorite.name)
|
||||||
|
|
||||||
constructor(properties: String) : this(*(properties.split(",").toTypedArray()))
|
constructor(properties: String) : this(*(properties.split(",").toTypedArray()))
|
||||||
|
|
||||||
|
@ -30,11 +31,11 @@ class EpisodeFilter(vararg properties_: String) : Serializable {
|
||||||
|
|
||||||
fun queryString(): String {
|
fun queryString(): String {
|
||||||
val statements: MutableList<String> = mutableListOf()
|
val statements: MutableList<String> = mutableListOf()
|
||||||
when {
|
// when {
|
||||||
showPlayed -> statements.add("playState >= ${PlayState.PLAYED.code}")
|
//// showPlayed -> statements.add("playState >= ${PlayState.PLAYED.code}")
|
||||||
showUnplayed -> statements.add(" playState < ${PlayState.PLAYED.code} ") // Match "New" items (read = -1) as well
|
//// showUnplayed -> statements.add(" playState < ${PlayState.PLAYED.code} ") // Match "New" items (read = -1) as well
|
||||||
showNew -> statements.add("playState == -1 ")
|
//// showNew -> statements.add("playState == -1 ")
|
||||||
}
|
// }
|
||||||
|
|
||||||
val mediaTypeQuerys = mutableListOf<String>()
|
val mediaTypeQuerys = mutableListOf<String>()
|
||||||
if (properties.contains(States.unknown.name)) mediaTypeQuerys.add(" media == nil OR media.mimeType == nil OR media.mimeType == '' ")
|
if (properties.contains(States.unknown.name)) mediaTypeQuerys.add(" media == nil OR media.mimeType == nil OR media.mimeType == '' ")
|
||||||
|
@ -118,10 +119,10 @@ class EpisodeFilter(vararg properties_: String) : Serializable {
|
||||||
properties.contains(States.has_comments.name) -> statements.add(" comment != '' ")
|
properties.contains(States.has_comments.name) -> statements.add(" comment != '' ")
|
||||||
properties.contains(States.no_comments.name) -> statements.add(" comment == '' ")
|
properties.contains(States.no_comments.name) -> statements.add(" comment == '' ")
|
||||||
}
|
}
|
||||||
when {
|
// when {
|
||||||
showIsFavorite -> statements.add("rating == ${Rating.FAVORITE.code} ")
|
// showIsFavorite -> statements.add("rating == ${Rating.FAVORITE.code} ")
|
||||||
showNotFavorite -> statements.add("rating != ${Rating.FAVORITE.code} ")
|
// showNotFavorite -> statements.add("rating != ${Rating.FAVORITE.code} ")
|
||||||
}
|
// }
|
||||||
|
|
||||||
if (statements.isEmpty()) return "id > 0"
|
if (statements.isEmpty()) return "id > 0"
|
||||||
val query = StringBuilder(" (" + statements[0])
|
val query = StringBuilder(" (" + statements[0])
|
||||||
|
@ -130,6 +131,7 @@ class EpisodeFilter(vararg properties_: String) : Serializable {
|
||||||
query.append(r)
|
query.append(r)
|
||||||
}
|
}
|
||||||
query.append(") ")
|
query.append(") ")
|
||||||
|
Logd("EpisodeFilter", "queryString: $query")
|
||||||
return query.toString()
|
return query.toString()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -154,8 +156,8 @@ class EpisodeFilter(vararg properties_: String) : Serializable {
|
||||||
audio_app,
|
audio_app,
|
||||||
paused,
|
paused,
|
||||||
not_paused,
|
not_paused,
|
||||||
is_favorite,
|
// is_favorite,
|
||||||
not_favorite,
|
// not_favorite,
|
||||||
has_media,
|
has_media,
|
||||||
no_media,
|
no_media,
|
||||||
has_comments,
|
has_comments,
|
||||||
|
|
|
@ -28,6 +28,7 @@ import ac.mdiq.podcini.ui.fragment.*
|
||||||
import ac.mdiq.podcini.ui.utils.LocalDeleteModal.deleteEpisodesWarnLocal
|
import ac.mdiq.podcini.ui.utils.LocalDeleteModal.deleteEpisodesWarnLocal
|
||||||
import ac.mdiq.podcini.util.EventFlow
|
import ac.mdiq.podcini.util.EventFlow
|
||||||
import ac.mdiq.podcini.util.FlowEvent
|
import ac.mdiq.podcini.util.FlowEvent
|
||||||
|
import ac.mdiq.podcini.util.Logd
|
||||||
import android.content.Context
|
import android.content.Context
|
||||||
import android.content.SharedPreferences
|
import android.content.SharedPreferences
|
||||||
import android.util.TypedValue
|
import android.util.TypedValue
|
||||||
|
@ -92,6 +93,7 @@ open class SwipeActions(private val fragment: Fragment, private val tag: String)
|
||||||
// EventFlow.postEvent(FlowEvent.SwipeActionsChangedEvent())
|
// EventFlow.postEvent(FlowEvent.SwipeActionsChangedEvent())
|
||||||
// }
|
// }
|
||||||
// })
|
// })
|
||||||
|
Logd("SwipeActions", "showDialog()")
|
||||||
val composeView = ComposeView(fragment.requireContext()).apply {
|
val composeView = ComposeView(fragment.requireContext()).apply {
|
||||||
setContent {
|
setContent {
|
||||||
val showDialog = remember { mutableStateOf(true) }
|
val showDialog = remember { mutableStateOf(true) }
|
||||||
|
@ -101,6 +103,7 @@ open class SwipeActions(private val fragment: Fragment, private val tag: String)
|
||||||
(fragment.view as? ViewGroup)?.removeView(this@apply)
|
(fragment.view as? ViewGroup)?.removeView(this@apply)
|
||||||
}) {
|
}) {
|
||||||
actions = getPrefs(this@SwipeActions.tag)
|
actions = getPrefs(this@SwipeActions.tag)
|
||||||
|
// TODO: remove the need of event
|
||||||
EventFlow.postEvent(FlowEvent.SwipeActionsChangedEvent())
|
EventFlow.postEvent(FlowEvent.SwipeActionsChangedEvent())
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -149,7 +152,8 @@ open class SwipeActions(private val fragment: Fragment, private val tag: String)
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun willRemove(filter: EpisodeFilter, item: Episode): Boolean {
|
override fun willRemove(filter: EpisodeFilter, item: Episode): Boolean {
|
||||||
return filter.showQueued || filter.showNew
|
return false
|
||||||
|
// return filter.showQueued || filter.showNew
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -208,7 +212,8 @@ open class SwipeActions(private val fragment: Fragment, private val tag: String)
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun willRemove(filter: EpisodeFilter, item: Episode): Boolean {
|
override fun willRemove(filter: EpisodeFilter, item: Episode): Boolean {
|
||||||
return filter.showQueued || filter.showNew
|
return false
|
||||||
|
// return filter.showQueued || filter.showNew
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -274,7 +279,8 @@ open class SwipeActions(private val fragment: Fragment, private val tag: String)
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun willRemove(filter: EpisodeFilter, item: Episode): Boolean {
|
override fun willRemove(filter: EpisodeFilter, item: Episode): Boolean {
|
||||||
return filter.showIsFavorite || filter.showNotFavorite
|
return false
|
||||||
|
// return filter.showIsFavorite || filter.showNotFavorite
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -479,8 +485,9 @@ open class SwipeActions(private val fragment: Fragment, private val tag: String)
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun willRemove(filter: EpisodeFilter, item: Episode): Boolean {
|
override fun willRemove(filter: EpisodeFilter, item: Episode): Boolean {
|
||||||
return if (item.playState == PlayState.NEW.code) filter.showPlayed || filter.showNew
|
return false
|
||||||
else filter.showUnplayed || filter.showPlayed || filter.showNew
|
// return if (item.playState == PlayState.NEW.code) filter.showPlayed || filter.showNew
|
||||||
|
// else filter.showUnplayed || filter.showPlayed || filter.showNew
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -55,8 +55,7 @@ import android.view.Gravity
|
||||||
import androidx.compose.animation.core.Animatable
|
import androidx.compose.animation.core.Animatable
|
||||||
import androidx.compose.animation.core.tween
|
import androidx.compose.animation.core.tween
|
||||||
import androidx.compose.foundation.*
|
import androidx.compose.foundation.*
|
||||||
import androidx.compose.foundation.gestures.detectHorizontalDragGestures
|
import androidx.compose.foundation.gestures.*
|
||||||
import androidx.compose.foundation.gestures.detectTapGestures
|
|
||||||
import androidx.compose.foundation.layout.*
|
import androidx.compose.foundation.layout.*
|
||||||
import androidx.compose.foundation.lazy.LazyColumn
|
import androidx.compose.foundation.lazy.LazyColumn
|
||||||
import androidx.compose.foundation.lazy.itemsIndexed
|
import androidx.compose.foundation.lazy.itemsIndexed
|
||||||
|
@ -77,6 +76,7 @@ import androidx.compose.ui.graphics.vector.ImageVector
|
||||||
import androidx.compose.ui.input.pointer.pointerInput
|
import androidx.compose.ui.input.pointer.pointerInput
|
||||||
import androidx.compose.ui.input.pointer.util.VelocityTracker
|
import androidx.compose.ui.input.pointer.util.VelocityTracker
|
||||||
import androidx.compose.ui.platform.LocalContext
|
import androidx.compose.ui.platform.LocalContext
|
||||||
|
import androidx.compose.ui.platform.LocalDensity
|
||||||
import androidx.compose.ui.platform.LocalView
|
import androidx.compose.ui.platform.LocalView
|
||||||
import androidx.compose.ui.res.stringResource
|
import androidx.compose.ui.res.stringResource
|
||||||
import androidx.compose.ui.res.vectorResource
|
import androidx.compose.ui.res.vectorResource
|
||||||
|
@ -410,10 +410,10 @@ fun ShelveDialog(selected: List<Episode>, onDismissRequest: () -> Unit) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@OptIn(ExperimentalFoundationApi::class, ExperimentalMaterial3Api::class)
|
@OptIn(ExperimentalFoundationApi::class, ExperimentalMaterial3Api::class)
|
||||||
@Composable
|
@Composable
|
||||||
fun EpisodeLazyColumn(activity: MainActivity, vms: List<EpisodeVM>, feed: Feed? = null,
|
fun EpisodeLazyColumn(activity: MainActivity, vms: MutableList<EpisodeVM>, feed: Feed? = null,
|
||||||
|
isDraggable: Boolean = false, dragCB: ((Int, Int)->Unit)? = null,
|
||||||
refreshCB: (()->Unit)? = null, leftSwipeCB: ((Episode) -> Unit)? = null, rightSwipeCB: ((Episode) -> Unit)? = null,
|
refreshCB: (()->Unit)? = null, leftSwipeCB: ((Episode) -> Unit)? = null, rightSwipeCB: ((Episode) -> Unit)? = null,
|
||||||
actionButton_: ((Episode)-> EpisodeActionButton)? = null) {
|
actionButton_: ((Episode)-> EpisodeActionButton)? = null) {
|
||||||
val TAG = "EpisodeLazyColumn"
|
val TAG = "EpisodeLazyColumn"
|
||||||
|
@ -457,10 +457,7 @@ fun EpisodeLazyColumn(activity: MainActivity, vms: List<EpisodeVM>, feed: Feed?
|
||||||
Text(stringResource(R.string.feed_delete_reason_msg))
|
Text(stringResource(R.string.feed_delete_reason_msg))
|
||||||
BasicTextField(value = textState, onValueChange = { textState = it },
|
BasicTextField(value = textState, onValueChange = { textState = it },
|
||||||
textStyle = TextStyle(fontSize = 16.sp, color = textColor),
|
textStyle = TextStyle(fontSize = 16.sp, color = textColor),
|
||||||
modifier = Modifier
|
modifier = Modifier.fillMaxWidth().height(100.dp).padding(start = 10.dp, end = 10.dp, bottom = 10.dp)
|
||||||
.fillMaxWidth()
|
|
||||||
.height(100.dp)
|
|
||||||
.padding(start = 10.dp, end = 10.dp, bottom = 10.dp)
|
|
||||||
.border(1.dp, MaterialTheme.colorScheme.primary, MaterialTheme.shapes.small)
|
.border(1.dp, MaterialTheme.colorScheme.primary, MaterialTheme.shapes.small)
|
||||||
)
|
)
|
||||||
Button(onClick = {
|
Button(onClick = {
|
||||||
|
@ -649,19 +646,26 @@ fun EpisodeLazyColumn(activity: MainActivity, vms: List<EpisodeVM>, feed: Feed?
|
||||||
}
|
}
|
||||||
|
|
||||||
@Composable
|
@Composable
|
||||||
fun MainRow(vm: EpisodeVM, index: Int) {
|
fun MainRow(vm: EpisodeVM, index: Int, isBeingDragged: Boolean, yOffset: Float, onDragStart: () -> Unit, onDrag: (Float) -> Unit, onDragEnd: () -> Unit) {
|
||||||
val textColor = MaterialTheme.colorScheme.onSurface
|
val textColor = MaterialTheme.colorScheme.onSurface
|
||||||
fun toggleSelected() {
|
fun toggleSelected() {
|
||||||
vm.isSelected = !vm.isSelected
|
vm.isSelected = !vm.isSelected
|
||||||
if (vm.isSelected) selected.add(vms[index].episode)
|
if (vm.isSelected) selected.add(vms[index].episode)
|
||||||
else selected.remove(vms[index].episode)
|
else selected.remove(vms[index].episode)
|
||||||
}
|
}
|
||||||
Row(Modifier.background(if (vm.isSelected) MaterialTheme.colorScheme.secondaryContainer else MaterialTheme.colorScheme.surface)) {
|
val density = LocalDensity.current
|
||||||
if (false) {
|
Row(Modifier.background(if (vm.isSelected) MaterialTheme.colorScheme.secondaryContainer else MaterialTheme.colorScheme.surface)
|
||||||
|
.offset(y = with(density) { yOffset.toDp() })) {
|
||||||
|
if (isDraggable) {
|
||||||
val typedValue = TypedValue()
|
val typedValue = TypedValue()
|
||||||
LocalContext.current.theme.resolveAttribute(R.attr.dragview_background, typedValue, true)
|
context.theme.resolveAttribute(R.attr.dragview_background, typedValue, true)
|
||||||
Icon(imageVector = ImageVector.vectorResource(typedValue.resourceId), tint = textColor, contentDescription = "drag handle",
|
Icon(imageVector = ImageVector.vectorResource(typedValue.resourceId), tint = textColor, contentDescription = "drag handle",
|
||||||
modifier = Modifier.width(16.dp).align(Alignment.CenterVertically))
|
modifier = Modifier.width(50.dp).align(Alignment.CenterVertically).padding(start = 10.dp, end = 15.dp)
|
||||||
|
.draggable(orientation = Orientation.Vertical,
|
||||||
|
state = rememberDraggableState { delta -> onDrag(delta) },
|
||||||
|
onDragStarted = { onDragStart() },
|
||||||
|
onDragStopped = { onDragEnd() }
|
||||||
|
))
|
||||||
}
|
}
|
||||||
ConstraintLayout(modifier = Modifier.width(56.dp).height(56.dp)) {
|
ConstraintLayout(modifier = Modifier.width(56.dp).height(56.dp)) {
|
||||||
val (imgvCover, checkMark) = createRefs()
|
val (imgvCover, checkMark) = createRefs()
|
||||||
|
@ -727,7 +731,7 @@ fun EpisodeLazyColumn(activity: MainActivity, vms: List<EpisodeVM>, feed: Feed?
|
||||||
val durText = remember { DurationConverter.getDurationStringLong(dur) }
|
val durText = remember { DurationConverter.getDurationStringLong(dur) }
|
||||||
val dateSizeText = " · " + formatAbbrev(curContext, vm.episode.getPubDate()) + " · " + durText + " · " +
|
val dateSizeText = " · " + formatAbbrev(curContext, vm.episode.getPubDate()) + " · " + durText + " · " +
|
||||||
if ((vm.episode.media?.size ?: 0) > 0) Formatter.formatShortFileSize(curContext, vm.episode.media?.size ?: 0) else ""
|
if ((vm.episode.media?.size ?: 0) > 0) Formatter.formatShortFileSize(curContext, vm.episode.media?.size ?: 0) else ""
|
||||||
Text(dateSizeText, color = textColor, style = MaterialTheme.typography.bodyMedium)
|
Text(dateSizeText, color = textColor, style = MaterialTheme.typography.bodyMedium, maxLines = 1, overflow = TextOverflow.Ellipsis)
|
||||||
}
|
}
|
||||||
Text(vm.episode.title ?: "", color = textColor, maxLines = 2, overflow = TextOverflow.Ellipsis)
|
Text(vm.episode.title ?: "", color = textColor, maxLines = 2, overflow = TextOverflow.Ellipsis)
|
||||||
}
|
}
|
||||||
|
@ -774,7 +778,7 @@ fun EpisodeLazyColumn(activity: MainActivity, vms: List<EpisodeVM>, feed: Feed?
|
||||||
val dur = remember { vm.episode.media?.getDuration() ?: 0 }
|
val dur = remember { vm.episode.media?.getDuration() ?: 0 }
|
||||||
val durText = remember { DurationConverter.getDurationStringLong(dur) }
|
val durText = remember { DurationConverter.getDurationStringLong(dur) }
|
||||||
vm.prog = if (dur > 0 && pos >= 0 && dur >= pos) 1.0f * pos / dur else 0f
|
vm.prog = if (dur > 0 && pos >= 0 && dur >= pos) 1.0f * pos / dur else 0f
|
||||||
Logd(TAG, "$index vm.prog: ${vm.prog}")
|
// Logd(TAG, "$index vm.prog: ${vm.prog}")
|
||||||
Row {
|
Row {
|
||||||
Text(DurationConverter.getDurationStringLong(vm.positionState), color = textColor, style = MaterialTheme.typography.bodySmall)
|
Text(DurationConverter.getDurationStringLong(vm.positionState), color = textColor, style = MaterialTheme.typography.bodySmall)
|
||||||
LinearProgressIndicator(progress = { vm.prog }, modifier = Modifier.weight(1f).height(4.dp).align(Alignment.CenterVertically))
|
LinearProgressIndicator(progress = { vm.prog }, modifier = Modifier.weight(1f).height(4.dp).align(Alignment.CenterVertically))
|
||||||
|
@ -789,6 +793,13 @@ fun EpisodeLazyColumn(activity: MainActivity, vms: List<EpisodeVM>, feed: Feed?
|
||||||
refreshCB?.invoke()
|
refreshCB?.invoke()
|
||||||
refreshing = false
|
refreshing = false
|
||||||
}) {
|
}) {
|
||||||
|
fun <T> MutableList<T>.move(fromIndex: Int, toIndex: Int) {
|
||||||
|
if (fromIndex != toIndex && fromIndex in indices && toIndex in indices) {
|
||||||
|
val item = removeAt(fromIndex)
|
||||||
|
add(toIndex, item)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
val rowHeightPx = with(LocalDensity.current) { 56.dp.toPx() }
|
||||||
LazyColumn(state = lazyListState, modifier = Modifier.padding(start = 10.dp, end = 10.dp, top = 10.dp, bottom = 10.dp), verticalArrangement = Arrangement.spacedBy(8.dp)) {
|
LazyColumn(state = lazyListState, modifier = Modifier.padding(start = 10.dp, end = 10.dp, top = 10.dp, bottom = 10.dp), verticalArrangement = Arrangement.spacedBy(8.dp)) {
|
||||||
itemsIndexed(vms, key = { _, vm -> vm.episode.id}) { index, vm ->
|
itemsIndexed(vms, key = { _, vm -> vm.episode.id}) { index, vm ->
|
||||||
vm.startMonitoring()
|
vm.startMonitoring()
|
||||||
|
@ -801,7 +812,6 @@ fun EpisodeLazyColumn(activity: MainActivity, vms: List<EpisodeVM>, feed: Feed?
|
||||||
val velocityTracker = remember { VelocityTracker() }
|
val velocityTracker = remember { VelocityTracker() }
|
||||||
val offsetX = remember { Animatable(0f) }
|
val offsetX = remember { Animatable(0f) }
|
||||||
Box(modifier = Modifier.fillMaxWidth().pointerInput(Unit) {
|
Box(modifier = Modifier.fillMaxWidth().pointerInput(Unit) {
|
||||||
Logd(TAG, "top box")
|
|
||||||
detectHorizontalDragGestures(onDragStart = { velocityTracker.resetTracking() },
|
detectHorizontalDragGestures(onDragStart = { velocityTracker.resetTracking() },
|
||||||
onHorizontalDrag = { change, dragAmount ->
|
onHorizontalDrag = { change, dragAmount ->
|
||||||
Logd(TAG, "onHorizontalDrag $dragAmount")
|
Logd(TAG, "onHorizontalDrag $dragAmount")
|
||||||
|
@ -829,7 +839,25 @@ fun EpisodeLazyColumn(activity: MainActivity, vms: List<EpisodeVM>, feed: Feed?
|
||||||
Logd(TAG, "LaunchedEffect $index ${vm.isSelected} ${selected.size}")
|
Logd(TAG, "LaunchedEffect $index ${vm.isSelected} ${selected.size}")
|
||||||
}
|
}
|
||||||
Column {
|
Column {
|
||||||
MainRow(vm, index)
|
var yOffset by remember { mutableStateOf(0f) }
|
||||||
|
var draggedIndex by remember { mutableStateOf<Int?>(null) }
|
||||||
|
MainRow(vm, index, isBeingDragged = draggedIndex == index,
|
||||||
|
yOffset = if (draggedIndex == index) yOffset else 0f,
|
||||||
|
onDragStart = { draggedIndex = index },
|
||||||
|
onDrag = { delta -> yOffset += delta },
|
||||||
|
onDragEnd = {
|
||||||
|
draggedIndex?.let { startIndex ->
|
||||||
|
val newIndex = (startIndex + (yOffset / rowHeightPx).toInt()).coerceIn(0, vms.lastIndex)
|
||||||
|
Logd(TAG, "onDragEnd draggedIndex: $draggedIndex newIndex: $newIndex")
|
||||||
|
if (newIndex != startIndex) {
|
||||||
|
dragCB?.invoke(startIndex, newIndex)
|
||||||
|
val item = vms.removeAt(startIndex)
|
||||||
|
vms.add(newIndex, item)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
draggedIndex = null
|
||||||
|
yOffset = 0f
|
||||||
|
})
|
||||||
ProgressRow(vm, index)
|
ProgressRow(vm, index)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -842,9 +870,7 @@ fun EpisodeLazyColumn(activity: MainActivity, vms: List<EpisodeVM>, feed: Feed?
|
||||||
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()
|
||||||
for (i in 0..longPressIndex) {
|
for (i in 0..longPressIndex) selected.add(vms[i].episode)
|
||||||
selected.add(vms[i].episode)
|
|
||||||
}
|
|
||||||
selectedSize = selected.size
|
selectedSize = selected.size
|
||||||
Logd(TAG, "selectedIds: ${selected.size}")
|
Logd(TAG, "selectedIds: ${selected.size}")
|
||||||
}))
|
}))
|
||||||
|
@ -852,9 +878,7 @@ fun EpisodeLazyColumn(activity: MainActivity, vms: List<EpisodeVM>, feed: Feed?
|
||||||
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()
|
||||||
for (i in longPressIndex..<vms.size) {
|
for (i in longPressIndex..<vms.size) selected.add(vms[i].episode)
|
||||||
selected.add(vms[i].episode)
|
|
||||||
}
|
|
||||||
selectedSize = selected.size
|
selectedSize = selected.size
|
||||||
Logd(TAG, "selectedIds: ${selected.size}")
|
Logd(TAG, "selectedIds: ${selected.size}")
|
||||||
}))
|
}))
|
||||||
|
@ -863,9 +887,7 @@ fun EpisodeLazyColumn(activity: MainActivity, vms: List<EpisodeVM>, feed: Feed?
|
||||||
.clickable(onClick = {
|
.clickable(onClick = {
|
||||||
if (selectedSize != vms.size) {
|
if (selectedSize != vms.size) {
|
||||||
selected.clear()
|
selected.clear()
|
||||||
for (vm in vms) {
|
for (vm in vms) selected.add(vm.episode)
|
||||||
selected.add(vm.episode)
|
|
||||||
}
|
|
||||||
selectAllRes = R.drawable.ic_select_none
|
selectAllRes = R.drawable.ic_select_none
|
||||||
} else {
|
} else {
|
||||||
selected.clear()
|
selected.clear()
|
||||||
|
@ -924,8 +946,7 @@ fun ConfirmAddYoutubeEpisode(sharedUrls: List<String>, showDialog: Boolean, onDi
|
||||||
}) {
|
}) {
|
||||||
Text("Confirm")
|
Text("Confirm")
|
||||||
}
|
}
|
||||||
} else CircularProgressIndicator(progress = { 0.6f }, strokeWidth = 4.dp,
|
} else CircularProgressIndicator(progress = { 0.6f }, strokeWidth = 4.dp, modifier = Modifier.padding(start = 20.dp, end = 20.dp).width(30.dp).height(30.dp))
|
||||||
modifier = Modifier.padding(start = 20.dp, end = 20.dp).width(30.dp).height(30.dp))
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -936,7 +957,6 @@ fun ConfirmAddYoutubeEpisode(sharedUrls: List<String>, showDialog: Boolean, onDi
|
||||||
fun EpisodesFilterDialog(filter: EpisodeFilter? = null, filtersDisabled: MutableSet<EpisodeFilter.EpisodesFilterGroup> = mutableSetOf(),
|
fun EpisodesFilterDialog(filter: EpisodeFilter? = null, filtersDisabled: MutableSet<EpisodeFilter.EpisodesFilterGroup> = mutableSetOf(),
|
||||||
onDismissRequest: () -> Unit, onFilterChanged: (Set<String>) -> Unit) {
|
onDismissRequest: () -> Unit, onFilterChanged: (Set<String>) -> Unit) {
|
||||||
val filterValues: MutableSet<String> = mutableSetOf()
|
val filterValues: MutableSet<String> = mutableSetOf()
|
||||||
|
|
||||||
Dialog(properties = DialogProperties(usePlatformDefaultWidth = false), onDismissRequest = { onDismissRequest() }) {
|
Dialog(properties = DialogProperties(usePlatformDefaultWidth = false), onDismissRequest = { onDismissRequest() }) {
|
||||||
val dialogWindowProvider = LocalView.current.parent as? DialogWindowProvider
|
val dialogWindowProvider = LocalView.current.parent as? DialogWindowProvider
|
||||||
dialogWindowProvider?.window?.let { window ->
|
dialogWindowProvider?.window?.let { window ->
|
||||||
|
@ -1001,21 +1021,74 @@ fun EpisodesFilterDialog(filter: EpisodeFilter? = null, filtersDisabled: Mutable
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
Column(modifier = Modifier.padding(start = 5.dp, bottom = 2.dp).fillMaxWidth()) {
|
Column(modifier = Modifier.padding(start = 5.dp, bottom = 2.dp).fillMaxWidth()) {
|
||||||
Text(stringResource(item.nameRes) + " :", fontWeight = FontWeight.Bold, style = MaterialTheme.typography.headlineSmall, color = textColor)
|
val selectedList = remember { MutableList(item.values.size) { mutableStateOf(false)} }
|
||||||
NonlazyGrid(columns = 3, itemCount = item.values.size) { index ->
|
var expandRow by remember { mutableStateOf(false) }
|
||||||
var selected by remember { mutableStateOf(false) }
|
Row {
|
||||||
if (selectNone) selected = false
|
Text(stringResource(item.nameRes) + ".. :", fontWeight = FontWeight.Bold, style = MaterialTheme.typography.headlineSmall, color = textColor, modifier = Modifier.clickable {
|
||||||
|
expandRow = !expandRow
|
||||||
|
})
|
||||||
|
var lowerSelected by remember { mutableStateOf(false) }
|
||||||
|
var higherSelected by remember { mutableStateOf(false) }
|
||||||
|
Spacer(Modifier.weight(1f))
|
||||||
|
if (expandRow) Text("<<<", color = if (lowerSelected) Color.Green else textColor, style = MaterialTheme.typography.headlineSmall, modifier = Modifier.clickable {
|
||||||
|
val hIndex = selectedList.indexOfLast { it.value }
|
||||||
|
if (hIndex < 0) return@clickable
|
||||||
|
if (!lowerSelected) {
|
||||||
|
for (i in 0..hIndex) selectedList[i].value = true
|
||||||
|
} else {
|
||||||
|
for (i in 0..hIndex) selectedList[i].value = false
|
||||||
|
selectedList[hIndex].value = true
|
||||||
|
}
|
||||||
|
lowerSelected = !lowerSelected
|
||||||
|
for (i in item.values.indices) {
|
||||||
|
if (selectedList[i].value) filterValues.add(item.values[i].filterId)
|
||||||
|
else filterValues.remove(item.values[i].filterId)
|
||||||
|
}
|
||||||
|
onFilterChanged(filterValues)
|
||||||
|
})
|
||||||
|
Spacer(Modifier.weight(1f))
|
||||||
|
if (expandRow) Text("X", color = textColor, style = MaterialTheme.typography.headlineSmall, modifier = Modifier.clickable {
|
||||||
|
lowerSelected = false
|
||||||
|
higherSelected = false
|
||||||
|
for (i in item.values.indices) {
|
||||||
|
selectedList[i].value = false
|
||||||
|
filterValues.remove(item.values[i].filterId)
|
||||||
|
}
|
||||||
|
onFilterChanged(filterValues)
|
||||||
|
})
|
||||||
|
Spacer(Modifier.weight(1f))
|
||||||
|
if (expandRow) Text(">>>", color = if (higherSelected) Color.Green else textColor, style = MaterialTheme.typography.headlineSmall, modifier = Modifier.clickable {
|
||||||
|
val lIndex = selectedList.indexOfFirst { it.value }
|
||||||
|
if (lIndex < 0) return@clickable
|
||||||
|
if (!higherSelected) {
|
||||||
|
for (i in lIndex..item.values.size - 1) selectedList[i].value = true
|
||||||
|
} else {
|
||||||
|
for (i in lIndex..item.values.size - 1) selectedList[i].value = false
|
||||||
|
selectedList[lIndex].value = true
|
||||||
|
}
|
||||||
|
higherSelected = !higherSelected
|
||||||
|
for (i in item.values.indices) {
|
||||||
|
if (selectedList[i].value) filterValues.add(item.values[i].filterId)
|
||||||
|
else filterValues.remove(item.values[i].filterId)
|
||||||
|
}
|
||||||
|
onFilterChanged(filterValues)
|
||||||
|
})
|
||||||
|
Spacer(Modifier.weight(1f))
|
||||||
|
}
|
||||||
|
if (expandRow) NonlazyGrid(columns = 3, itemCount = item.values.size) { index ->
|
||||||
|
if (selectNone) selectedList[index].value = false
|
||||||
LaunchedEffect(Unit) {
|
LaunchedEffect(Unit) {
|
||||||
if (filter != null) {
|
if (filter != null) {
|
||||||
if (item.values[index].filterId in filter.properties) selected = true
|
if (item.values[index].filterId in filter.properties) selectedList[index].value = true
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
OutlinedButton(modifier = Modifier.padding(0.dp).heightIn(min = 20.dp).widthIn(min = 20.dp).wrapContentWidth(),
|
OutlinedButton(
|
||||||
border = BorderStroke(2.dp, if (selected) Color.Green else textColor),
|
modifier = Modifier.padding(0.dp).heightIn(min = 20.dp).widthIn(min = 20.dp).wrapContentWidth(),
|
||||||
|
border = BorderStroke(2.dp, if (selectedList[index].value) Color.Green else textColor),
|
||||||
onClick = {
|
onClick = {
|
||||||
selectNone = false
|
selectNone = false
|
||||||
selected = !selected
|
selectedList[index].value = !selectedList[index].value
|
||||||
if (selected) filterValues.add(item.values[index].filterId)
|
if (selectedList[index].value) filterValues.add(item.values[index].filterId)
|
||||||
else filterValues.remove(item.values[index].filterId)
|
else filterValues.remove(item.values[index].filterId)
|
||||||
onFilterChanged(filterValues)
|
onFilterChanged(filterValues)
|
||||||
},
|
},
|
||||||
|
|
|
@ -92,11 +92,11 @@ abstract class BaseEpisodesFragment : Fragment(), Toolbar.OnMenuItemClickListene
|
||||||
EpisodeLazyColumn(
|
EpisodeLazyColumn(
|
||||||
activity as MainActivity, vms = vms,
|
activity as MainActivity, vms = vms,
|
||||||
leftSwipeCB = {
|
leftSwipeCB = {
|
||||||
if (leftActionState.value == NoActionSwipeAction()) swipeActions.showDialog()
|
if (leftActionState.value is NoActionSwipeAction) swipeActions.showDialog()
|
||||||
else leftActionState.value.performAction(it, this@BaseEpisodesFragment, swipeActions.filter ?: EpisodeFilter())
|
else leftActionState.value.performAction(it, this@BaseEpisodesFragment, swipeActions.filter ?: EpisodeFilter())
|
||||||
},
|
},
|
||||||
rightSwipeCB = {
|
rightSwipeCB = {
|
||||||
if (rightActionState.value == NoActionSwipeAction()) swipeActions.showDialog()
|
if (rightActionState.value is NoActionSwipeAction) swipeActions.showDialog()
|
||||||
else rightActionState.value.performAction(it, this@BaseEpisodesFragment, swipeActions.filter ?: EpisodeFilter())
|
else rightActionState.value.performAction(it, this@BaseEpisodesFragment, swipeActions.filter ?: EpisodeFilter())
|
||||||
},
|
},
|
||||||
)
|
)
|
||||||
|
|
|
@ -111,11 +111,11 @@ import java.util.*
|
||||||
InforBar(infoBarText, leftAction = leftActionState, rightAction = rightActionState, actionConfig = {swipeActions.showDialog()})
|
InforBar(infoBarText, leftAction = leftActionState, rightAction = rightActionState, actionConfig = {swipeActions.showDialog()})
|
||||||
EpisodeLazyColumn(activity as MainActivity, vms = vms,
|
EpisodeLazyColumn(activity as MainActivity, vms = vms,
|
||||||
leftSwipeCB = {
|
leftSwipeCB = {
|
||||||
if (leftActionState.value == NoActionSwipeAction()) swipeActions.showDialog()
|
if (leftActionState.value is NoActionSwipeAction) swipeActions.showDialog()
|
||||||
else leftActionState.value.performAction(it, this@DownloadsFragment, swipeActions.filter ?: EpisodeFilter())
|
else leftActionState.value.performAction(it, this@DownloadsFragment, swipeActions.filter ?: EpisodeFilter())
|
||||||
},
|
},
|
||||||
rightSwipeCB = {
|
rightSwipeCB = {
|
||||||
if (rightActionState.value == NoActionSwipeAction()) swipeActions.showDialog()
|
if (rightActionState.value is NoActionSwipeAction) swipeActions.showDialog()
|
||||||
else rightActionState.value.performAction(it, this@DownloadsFragment, swipeActions.filter ?: EpisodeFilter())
|
else rightActionState.value.performAction(it, this@DownloadsFragment, swipeActions.filter ?: EpisodeFilter())
|
||||||
},
|
},
|
||||||
actionButton_ = { DeleteActionButton(it) })
|
actionButton_ = { DeleteActionButton(it) })
|
||||||
|
|
|
@ -190,11 +190,12 @@ import java.util.concurrent.Semaphore
|
||||||
EpisodeLazyColumn(activity as MainActivity, vms = vms, feed = feed,
|
EpisodeLazyColumn(activity as MainActivity, vms = vms, feed = feed,
|
||||||
refreshCB = { FeedUpdateManager.runOnceOrAsk(requireContext(), feed) },
|
refreshCB = { FeedUpdateManager.runOnceOrAsk(requireContext(), feed) },
|
||||||
leftSwipeCB = {
|
leftSwipeCB = {
|
||||||
if (leftActionState.value == NoActionSwipeAction()) swipeActions.showDialog()
|
if (leftActionState.value is NoActionSwipeAction) swipeActions.showDialog()
|
||||||
else leftActionState.value.performAction(it, this@FeedEpisodesFragment, swipeActions.filter ?: EpisodeFilter())
|
else leftActionState.value.performAction(it, this@FeedEpisodesFragment, swipeActions.filter ?: EpisodeFilter())
|
||||||
},
|
},
|
||||||
rightSwipeCB = {
|
rightSwipeCB = {
|
||||||
if (rightActionState.value == NoActionSwipeAction()) swipeActions.showDialog()
|
Logd(TAG, "rightActionState: ${rightActionState.value.getId()}")
|
||||||
|
if (rightActionState.value is NoActionSwipeAction) swipeActions.showDialog()
|
||||||
else rightActionState.value.performAction(it, this@FeedEpisodesFragment, swipeActions.filter ?: EpisodeFilter())
|
else rightActionState.value.performAction(it, this@FeedEpisodesFragment, swipeActions.filter ?: EpisodeFilter())
|
||||||
},
|
},
|
||||||
)
|
)
|
||||||
|
@ -402,7 +403,7 @@ import java.util.concurrent.Semaphore
|
||||||
}
|
}
|
||||||
when (item.itemId) {
|
when (item.itemId) {
|
||||||
R.id.visit_website_item -> if (feed!!.link != null) IntentUtils.openInBrowser(requireContext(), feed!!.link!!)
|
R.id.visit_website_item -> if (feed!!.link != null) IntentUtils.openInBrowser(requireContext(), feed!!.link!!)
|
||||||
R.id.share_feed -> ShareUtils.shareFeedLink(requireContext(), feed!!)
|
R.id.share_feed -> ShareUtils.shareFeedLinkNew(requireContext(), feed!!)
|
||||||
R.id.refresh_feed -> FeedUpdateManager.runOnceOrAsk(requireContext(), feed)
|
R.id.refresh_feed -> FeedUpdateManager.runOnceOrAsk(requireContext(), feed)
|
||||||
R.id.refresh_complete_item -> {
|
R.id.refresh_complete_item -> {
|
||||||
Thread {
|
Thread {
|
||||||
|
|
|
@ -347,7 +347,7 @@ class FeedInfoFragment : Fragment(), Toolbar.OnMenuItemClickListener {
|
||||||
override fun onMenuItemClick(item: MenuItem): Boolean {
|
override fun onMenuItemClick(item: MenuItem): Boolean {
|
||||||
when (item.itemId) {
|
when (item.itemId) {
|
||||||
R.id.visit_website_item -> if (feed.link != null) IntentUtils.openInBrowser(requireContext(), feed.link!!)
|
R.id.visit_website_item -> if (feed.link != null) IntentUtils.openInBrowser(requireContext(), feed.link!!)
|
||||||
R.id.share_item -> ShareUtils.shareFeedLink(requireContext(), feed)
|
R.id.share_item -> ShareUtils.shareFeedLinkNew(requireContext(), feed)
|
||||||
R.id.reconnect_local_folder -> {
|
R.id.reconnect_local_folder -> {
|
||||||
val alert = MaterialAlertDialogBuilder(requireContext())
|
val alert = MaterialAlertDialogBuilder(requireContext())
|
||||||
alert.setMessage(R.string.reconnect_local_folder_warning)
|
alert.setMessage(R.string.reconnect_local_folder_warning)
|
||||||
|
|
|
@ -11,9 +11,10 @@ import ac.mdiq.podcini.playback.service.PlaybackService
|
||||||
import ac.mdiq.podcini.playback.service.PlaybackService.Companion.mediaBrowser
|
import ac.mdiq.podcini.playback.service.PlaybackService.Companion.mediaBrowser
|
||||||
import ac.mdiq.podcini.playback.service.PlaybackService.Companion.playbackService
|
import ac.mdiq.podcini.playback.service.PlaybackService.Companion.playbackService
|
||||||
import ac.mdiq.podcini.preferences.UserPreferences
|
import ac.mdiq.podcini.preferences.UserPreferences
|
||||||
|
import ac.mdiq.podcini.preferences.UserPreferences.appPrefs
|
||||||
import ac.mdiq.podcini.storage.database.Queues.clearQueue
|
import ac.mdiq.podcini.storage.database.Queues.clearQueue
|
||||||
import ac.mdiq.podcini.storage.database.Queues.isQueueKeepSorted
|
import ac.mdiq.podcini.storage.database.Queues.isQueueKeepSorted
|
||||||
import ac.mdiq.podcini.storage.database.Queues.isQueueLocked
|
import ac.mdiq.podcini.storage.database.Queues.moveInQueue
|
||||||
import ac.mdiq.podcini.storage.database.Queues.queueKeepSortedOrder
|
import ac.mdiq.podcini.storage.database.Queues.queueKeepSortedOrder
|
||||||
import ac.mdiq.podcini.storage.database.RealmDB.realm
|
import ac.mdiq.podcini.storage.database.RealmDB.realm
|
||||||
import ac.mdiq.podcini.storage.database.RealmDB.runOnIOScope
|
import ac.mdiq.podcini.storage.database.RealmDB.runOnIOScope
|
||||||
|
@ -33,7 +34,6 @@ import ac.mdiq.podcini.ui.activity.MainActivity
|
||||||
import ac.mdiq.podcini.ui.compose.*
|
import ac.mdiq.podcini.ui.compose.*
|
||||||
import ac.mdiq.podcini.ui.dialog.ConfirmationDialog
|
import ac.mdiq.podcini.ui.dialog.ConfirmationDialog
|
||||||
import ac.mdiq.podcini.ui.dialog.EpisodeSortDialog
|
import ac.mdiq.podcini.ui.dialog.EpisodeSortDialog
|
||||||
import ac.mdiq.podcini.ui.utils.EmptyViewHandler
|
|
||||||
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
|
||||||
|
@ -88,7 +88,7 @@ import kotlin.math.max
|
||||||
private var _binding: ComposeFragmentBinding? = null
|
private var _binding: ComposeFragmentBinding? = null
|
||||||
private val binding get() = _binding!!
|
private val binding get() = _binding!!
|
||||||
|
|
||||||
private lateinit var emptyViewHandler: EmptyViewHandler
|
// private lateinit var emptyViewHandler: EmptyViewHandler
|
||||||
private lateinit var toolbar: MaterialToolbar
|
private lateinit var toolbar: MaterialToolbar
|
||||||
private lateinit var swipeActions: SwipeActions
|
private lateinit var swipeActions: SwipeActions
|
||||||
private lateinit var swipeActionsBin: SwipeActions
|
private lateinit var swipeActionsBin: SwipeActions
|
||||||
|
@ -102,6 +102,8 @@ import kotlin.math.max
|
||||||
private var leftActionStateBin = mutableStateOf<SwipeAction>(NoActionSwipeAction())
|
private var leftActionStateBin = mutableStateOf<SwipeAction>(NoActionSwipeAction())
|
||||||
private var rightActionStateBin = mutableStateOf<SwipeAction>(NoActionSwipeAction())
|
private var rightActionStateBin = mutableStateOf<SwipeAction>(NoActionSwipeAction())
|
||||||
|
|
||||||
|
var isQueueLocked = appPrefs.getBoolean(UserPreferences.Prefs.prefQueueLocked.name, true)
|
||||||
|
|
||||||
private lateinit var spinnerLayout: View
|
private lateinit var spinnerLayout: View
|
||||||
private lateinit var queueNames: Array<String>
|
private lateinit var queueNames: Array<String>
|
||||||
private lateinit var spinnerTexts: MutableList<String>
|
private lateinit var spinnerTexts: MutableList<String>
|
||||||
|
@ -115,7 +117,7 @@ import kotlin.math.max
|
||||||
|
|
||||||
private var showBin by mutableStateOf(false)
|
private var showBin by mutableStateOf(false)
|
||||||
|
|
||||||
// private var dragDropEnabled: Boolean = !(isQueueKeepSorted || isQueueLocked)
|
private var dragDropEnabled by mutableStateOf(!(isQueueKeepSorted || isQueueLocked))
|
||||||
|
|
||||||
private lateinit var browserFuture: ListenableFuture<MediaBrowser>
|
private lateinit var browserFuture: ListenableFuture<MediaBrowser>
|
||||||
|
|
||||||
|
@ -190,11 +192,11 @@ import kotlin.math.max
|
||||||
Column {
|
Column {
|
||||||
InforBar(infoBarText, leftAction = leftActionStateBin, rightAction = rightActionStateBin, actionConfig = { swipeActionsBin.showDialog() })
|
InforBar(infoBarText, leftAction = leftActionStateBin, rightAction = rightActionStateBin, actionConfig = { swipeActionsBin.showDialog() })
|
||||||
val leftCB = { episode: Episode ->
|
val leftCB = { episode: Episode ->
|
||||||
if (leftActionStateBin.value == NoActionSwipeAction()) swipeActionsBin.showDialog()
|
if (leftActionStateBin.value is NoActionSwipeAction) swipeActionsBin.showDialog()
|
||||||
else leftActionStateBin.value.performAction(episode, this@QueuesFragment, swipeActionsBin.filter ?: EpisodeFilter())
|
else leftActionStateBin.value.performAction(episode, this@QueuesFragment, swipeActionsBin.filter ?: EpisodeFilter())
|
||||||
}
|
}
|
||||||
val rightCB = { episode: Episode ->
|
val rightCB = { episode: Episode ->
|
||||||
if (rightActionStateBin.value == NoActionSwipeAction()) swipeActionsBin.showDialog()
|
if (rightActionStateBin.value is NoActionSwipeAction) swipeActionsBin.showDialog()
|
||||||
else rightActionStateBin.value.performAction(episode, this@QueuesFragment, swipeActionsBin.filter ?: EpisodeFilter())
|
else rightActionStateBin.value.performAction(episode, this@QueuesFragment, swipeActionsBin.filter ?: EpisodeFilter())
|
||||||
}
|
}
|
||||||
EpisodeLazyColumn(activity as MainActivity, vms = vms, leftSwipeCB = { leftCB(it) }, rightSwipeCB = { rightCB(it) })
|
EpisodeLazyColumn(activity as MainActivity, vms = vms, leftSwipeCB = { leftCB(it) }, rightSwipeCB = { rightCB(it) })
|
||||||
|
@ -203,14 +205,16 @@ import kotlin.math.max
|
||||||
Column {
|
Column {
|
||||||
InforBar(infoBarText, leftAction = leftActionState, rightAction = rightActionState, actionConfig = { swipeActions.showDialog() })
|
InforBar(infoBarText, leftAction = leftActionState, rightAction = rightActionState, actionConfig = { swipeActions.showDialog() })
|
||||||
val leftCB = { episode: Episode ->
|
val leftCB = { episode: Episode ->
|
||||||
if (leftActionState.value == NoActionSwipeAction()) swipeActions.showDialog()
|
if (leftActionState.value is NoActionSwipeAction) swipeActions.showDialog()
|
||||||
else leftActionState.value.performAction(episode, this@QueuesFragment, swipeActions.filter ?: EpisodeFilter())
|
else leftActionState.value.performAction(episode, this@QueuesFragment, swipeActions.filter ?: EpisodeFilter())
|
||||||
}
|
}
|
||||||
val rightCB = { episode: Episode ->
|
val rightCB = { episode: Episode ->
|
||||||
if (rightActionState.value == NoActionSwipeAction()) swipeActions.showDialog()
|
if (rightActionState.value is NoActionSwipeAction) swipeActions.showDialog()
|
||||||
else rightActionState.value.performAction(episode, this@QueuesFragment, swipeActions.filter ?: EpisodeFilter())
|
else rightActionState.value.performAction(episode, this@QueuesFragment, swipeActions.filter ?: EpisodeFilter())
|
||||||
}
|
}
|
||||||
EpisodeLazyColumn(activity as MainActivity, vms = vms, leftSwipeCB = { leftCB(it) }, rightSwipeCB = { rightCB(it) })
|
EpisodeLazyColumn(activity as MainActivity, vms = vms,
|
||||||
|
isDraggable = dragDropEnabled, dragCB = { iFrom, iTo -> moveInQueue(iFrom, iTo, true) },
|
||||||
|
leftSwipeCB = { leftCB(it) }, rightSwipeCB = { rightCB(it) })
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -219,13 +223,6 @@ import kotlin.math.max
|
||||||
lifecycle.addObserver(swipeActions)
|
lifecycle.addObserver(swipeActions)
|
||||||
refreshSwipeTelltale()
|
refreshSwipeTelltale()
|
||||||
|
|
||||||
emptyViewHandler = EmptyViewHandler(requireContext())
|
|
||||||
// emptyViewHandler.attachToRecyclerView(recyclerView)
|
|
||||||
emptyViewHandler.setIcon(R.drawable.ic_playlist_play)
|
|
||||||
emptyViewHandler.setTitle(R.string.no_items_header_label)
|
|
||||||
emptyViewHandler.setMessage(R.string.no_items_label)
|
|
||||||
// emptyViewHandler.updateAdapter(adapter)
|
|
||||||
|
|
||||||
return binding.root
|
return binding.root
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -612,10 +609,10 @@ import kotlin.math.max
|
||||||
|
|
||||||
@UnstableApi private fun toggleQueueLock() {
|
@UnstableApi private fun toggleQueueLock() {
|
||||||
val isLocked: Boolean = isQueueLocked
|
val isLocked: Boolean = isQueueLocked
|
||||||
if (isLocked) setQueueLocked(false)
|
if (isLocked) setQueueLock(false)
|
||||||
else {
|
else {
|
||||||
val shouldShowLockWarning: Boolean = prefs!!.getBoolean(PREF_SHOW_LOCK_WARNING, true)
|
val shouldShowLockWarning: Boolean = prefs!!.getBoolean(PREF_SHOW_LOCK_WARNING, true)
|
||||||
if (!shouldShowLockWarning) setQueueLocked(true)
|
if (!shouldShowLockWarning) setQueueLock(true)
|
||||||
else {
|
else {
|
||||||
val builder = MaterialAlertDialogBuilder(requireContext())
|
val builder = MaterialAlertDialogBuilder(requireContext())
|
||||||
builder.setTitle(R.string.lock_queue)
|
builder.setTitle(R.string.lock_queue)
|
||||||
|
@ -628,7 +625,7 @@ import kotlin.math.max
|
||||||
|
|
||||||
builder.setPositiveButton(R.string.lock_queue) { _: DialogInterface?, _: Int ->
|
builder.setPositiveButton(R.string.lock_queue) { _: DialogInterface?, _: Int ->
|
||||||
prefs!!.edit().putBoolean(PREF_SHOW_LOCK_WARNING, !checkDoNotShowAgain.isChecked).apply()
|
prefs!!.edit().putBoolean(PREF_SHOW_LOCK_WARNING, !checkDoNotShowAgain.isChecked).apply()
|
||||||
setQueueLocked(true)
|
setQueueLock(true)
|
||||||
}
|
}
|
||||||
builder.setNegativeButton(R.string.cancel_label, null)
|
builder.setNegativeButton(R.string.cancel_label, null)
|
||||||
builder.show()
|
builder.show()
|
||||||
|
@ -636,8 +633,10 @@ import kotlin.math.max
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@UnstableApi private fun setQueueLocked(locked: Boolean) {
|
@UnstableApi private fun setQueueLock(locked: Boolean) {
|
||||||
isQueueLocked = locked
|
isQueueLocked = locked
|
||||||
|
appPrefs.edit().putBoolean(UserPreferences.Prefs.prefQueueLocked.name, locked).apply()
|
||||||
|
dragDropEnabled = !(isQueueKeepSorted || isQueueLocked)
|
||||||
refreshMenuItems()
|
refreshMenuItems()
|
||||||
// adapter?.updateDragDropEnabled()
|
// adapter?.updateDragDropEnabled()
|
||||||
|
|
||||||
|
@ -677,7 +676,7 @@ import kotlin.math.max
|
||||||
loadItemsRunning = true
|
loadItemsRunning = true
|
||||||
Logd(TAG, "loadCurQueue() called ${curQueue.name}")
|
Logd(TAG, "loadCurQueue() called ${curQueue.name}")
|
||||||
while (curQueue.name.isEmpty()) runBlocking { delay(100) }
|
while (curQueue.name.isEmpty()) runBlocking { delay(100) }
|
||||||
if (queueItems.isNotEmpty()) emptyViewHandler.hide()
|
// if (queueItems.isNotEmpty()) emptyViewHandler.hide()
|
||||||
queueItems.clear()
|
queueItems.clear()
|
||||||
vms.clear()
|
vms.clear()
|
||||||
if (showBin) queueItems.addAll(realm.query(Episode::class, "id IN $0", curQueue.idsBinList)
|
if (showBin) queueItems.addAll(realm.query(Episode::class, "id IN $0", curQueue.idsBinList)
|
||||||
|
@ -748,7 +747,6 @@ import kotlin.math.max
|
||||||
val TAG = QueuesFragment::class.simpleName ?: "Anonymous"
|
val TAG = QueuesFragment::class.simpleName ?: "Anonymous"
|
||||||
|
|
||||||
private const val KEY_UP_ARROW = "up_arrow"
|
private const val KEY_UP_ARROW = "up_arrow"
|
||||||
|
|
||||||
private const val PREFS = "QueueFragment"
|
private const val PREFS = "QueueFragment"
|
||||||
private const val PREF_SHOW_LOCK_WARNING = "show_lock_warning"
|
private const val PREF_SHOW_LOCK_WARNING = "show_lock_warning"
|
||||||
|
|
||||||
|
|
|
@ -36,10 +36,7 @@ import androidx.compose.foundation.combinedClickable
|
||||||
import androidx.compose.foundation.layout.*
|
import androidx.compose.foundation.layout.*
|
||||||
import androidx.compose.foundation.lazy.LazyRow
|
import androidx.compose.foundation.lazy.LazyRow
|
||||||
import androidx.compose.foundation.lazy.rememberLazyListState
|
import androidx.compose.foundation.lazy.rememberLazyListState
|
||||||
import androidx.compose.material3.Checkbox
|
import androidx.compose.material3.*
|
||||||
import androidx.compose.material3.Icon
|
|
||||||
import androidx.compose.material3.MaterialTheme
|
|
||||||
import androidx.compose.material3.Text
|
|
||||||
import androidx.compose.runtime.*
|
import androidx.compose.runtime.*
|
||||||
import androidx.compose.ui.Alignment
|
import androidx.compose.ui.Alignment
|
||||||
import androidx.compose.ui.Modifier
|
import androidx.compose.ui.Modifier
|
||||||
|
@ -272,19 +269,30 @@ class SearchFragment : Fragment() {
|
||||||
@Composable
|
@Composable
|
||||||
fun CriteriaList() {
|
fun CriteriaList() {
|
||||||
val textColor = MaterialTheme.colorScheme.onSurface
|
val textColor = MaterialTheme.colorScheme.onSurface
|
||||||
NonlazyGrid(columns = 2, itemCount = SearchBy.entries.size) { index ->
|
var showGrid by remember { mutableStateOf(false) }
|
||||||
val c = SearchBy.entries[index]
|
Column {
|
||||||
Row(verticalAlignment = Alignment.CenterVertically, modifier = Modifier.padding(start = 10.dp, end = 10.dp)) {
|
Row {
|
||||||
var isChecked by remember { mutableStateOf(true) }
|
Button(onClick = {showGrid = !showGrid}) {
|
||||||
Checkbox(
|
Text(stringResource(R.string.show_criteria))
|
||||||
checked = isChecked,
|
}
|
||||||
onCheckedChange = { newValue ->
|
Button(onClick = { searchOnline() }) {
|
||||||
c.selected = newValue
|
Text(stringResource(R.string.search_online))
|
||||||
isChecked = newValue
|
}
|
||||||
}
|
}
|
||||||
)
|
if (showGrid) NonlazyGrid(columns = 2, itemCount = SearchBy.entries.size) { index ->
|
||||||
Spacer(modifier = Modifier.width(2.dp))
|
val c = SearchBy.entries[index]
|
||||||
Text(stringResource(c.nameRes), color = textColor)
|
Row(verticalAlignment = Alignment.CenterVertically, modifier = Modifier.padding(start = 10.dp, end = 10.dp)) {
|
||||||
|
var isChecked by remember { mutableStateOf(true) }
|
||||||
|
Checkbox(
|
||||||
|
checked = isChecked,
|
||||||
|
onCheckedChange = { newValue ->
|
||||||
|
c.selected = newValue
|
||||||
|
isChecked = newValue
|
||||||
|
}
|
||||||
|
)
|
||||||
|
Spacer(modifier = Modifier.width(2.dp))
|
||||||
|
Text(stringResource(c.nameRes), color = textColor)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -1155,21 +1155,73 @@ class SubscriptionsFragment : Fragment(), Toolbar.OnMenuItemClickListener {
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
Column(modifier = Modifier.padding(start = 5.dp, bottom = 2.dp).fillMaxWidth()) {
|
Column(modifier = Modifier.padding(start = 5.dp, bottom = 2.dp).fillMaxWidth()) {
|
||||||
Text(stringResource(item.nameRes) + " :", fontWeight = FontWeight.Bold, style = MaterialTheme.typography.headlineSmall, color = textColor)
|
val selectedList = remember { MutableList(item.values.size) { mutableStateOf(false)} }
|
||||||
NonlazyGrid(columns = 3, itemCount = item.values.size) { index ->
|
var expandRow by remember { mutableStateOf(false) }
|
||||||
var selected by remember { mutableStateOf(false) }
|
Row {
|
||||||
if (selectNone) selected = false
|
Text(stringResource(item.nameRes) + ".. :", fontWeight = FontWeight.Bold, style = MaterialTheme.typography.headlineSmall, color = textColor, modifier = Modifier.clickable {
|
||||||
|
expandRow = !expandRow
|
||||||
|
})
|
||||||
|
var lowerSelected by remember { mutableStateOf(false) }
|
||||||
|
var higherSelected by remember { mutableStateOf(false) }
|
||||||
|
Spacer(Modifier.weight(1f))
|
||||||
|
if (expandRow) Text("<<<", color = if (lowerSelected) Color.Green else textColor, style = MaterialTheme.typography.headlineSmall, modifier = Modifier.clickable {
|
||||||
|
val hIndex = selectedList.indexOfLast { it.value }
|
||||||
|
if (hIndex < 0) return@clickable
|
||||||
|
if (!lowerSelected) {
|
||||||
|
for (i in 0..hIndex) selectedList[i].value = true
|
||||||
|
} else {
|
||||||
|
for (i in 0..hIndex) selectedList[i].value = false
|
||||||
|
selectedList[hIndex].value = true
|
||||||
|
}
|
||||||
|
lowerSelected = !lowerSelected
|
||||||
|
for (i in item.values.indices) {
|
||||||
|
if (selectedList[i].value) filterValues.add(item.values[i].filterId)
|
||||||
|
else filterValues.remove(item.values[i].filterId)
|
||||||
|
}
|
||||||
|
onFilterChanged(filterValues)
|
||||||
|
})
|
||||||
|
Spacer(Modifier.weight(1f))
|
||||||
|
if (expandRow) Text("X", color = textColor, style = MaterialTheme.typography.headlineSmall, modifier = Modifier.clickable {
|
||||||
|
lowerSelected = false
|
||||||
|
higherSelected = false
|
||||||
|
for (i in item.values.indices) {
|
||||||
|
selectedList[i].value = false
|
||||||
|
filterValues.remove(item.values[i].filterId)
|
||||||
|
}
|
||||||
|
onFilterChanged(filterValues)
|
||||||
|
})
|
||||||
|
Spacer(Modifier.weight(1f))
|
||||||
|
if (expandRow) Text(">>>", color = if (higherSelected) Color.Green else textColor, style = MaterialTheme.typography.headlineSmall, modifier = Modifier.clickable {
|
||||||
|
val lIndex = selectedList.indexOfFirst { it.value }
|
||||||
|
if (lIndex < 0) return@clickable
|
||||||
|
if (!higherSelected) {
|
||||||
|
for (i in lIndex..item.values.size - 1) selectedList[i].value = true
|
||||||
|
} else {
|
||||||
|
for (i in lIndex..item.values.size - 1) selectedList[i].value = false
|
||||||
|
selectedList[lIndex].value = true
|
||||||
|
}
|
||||||
|
higherSelected = !higherSelected
|
||||||
|
for (i in item.values.indices) {
|
||||||
|
if (selectedList[i].value) filterValues.add(item.values[i].filterId)
|
||||||
|
else filterValues.remove(item.values[i].filterId)
|
||||||
|
}
|
||||||
|
onFilterChanged(filterValues)
|
||||||
|
})
|
||||||
|
Spacer(Modifier.weight(1f))
|
||||||
|
}
|
||||||
|
if (expandRow) NonlazyGrid(columns = 3, itemCount = item.values.size) { index ->
|
||||||
|
if (selectNone) selectedList[index].value = false
|
||||||
LaunchedEffect(Unit) {
|
LaunchedEffect(Unit) {
|
||||||
if (filter != null) {
|
if (filter != null) {
|
||||||
if (item.values[index].filterId in filter.properties) selected = true
|
if (item.values[index].filterId in filter.properties) selectedList[index].value = true
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
OutlinedButton(modifier = Modifier.padding(0.dp).heightIn(min = 20.dp).widthIn(min = 20.dp).wrapContentWidth(),
|
OutlinedButton(modifier = Modifier.padding(0.dp).heightIn(min = 20.dp).widthIn(min = 20.dp).wrapContentWidth(),
|
||||||
border = BorderStroke(2.dp, if (selected) Color.Green else textColor),
|
border = BorderStroke(2.dp, if (selectedList[index].value) Color.Green else textColor),
|
||||||
onClick = {
|
onClick = {
|
||||||
selectNone = false
|
selectNone = false
|
||||||
selected = !selected
|
selectedList[index].value = !selectedList[index].value
|
||||||
if (selected) filterValues.add(item.values[index].filterId)
|
if (selectedList[index].value) filterValues.add(item.values[index].filterId)
|
||||||
else filterValues.remove(item.values[index].filterId)
|
else filterValues.remove(item.values[index].filterId)
|
||||||
onFilterChanged(filterValues)
|
onFilterChanged(filterValues)
|
||||||
},
|
},
|
||||||
|
|
|
@ -47,6 +47,10 @@ object ShareUtils {
|
||||||
shareLink(context, text)
|
shareLink(context, text)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fun shareFeedLinkNew(context: Context, feed: Feed) {
|
||||||
|
shareLink(context, feed.downloadUrl?:"")
|
||||||
|
}
|
||||||
|
|
||||||
@JvmStatic
|
@JvmStatic
|
||||||
fun hasLinkToShare(item: Episode?): Boolean {
|
fun hasLinkToShare(item: Episode?): Boolean {
|
||||||
return item?.getLinkWithFallback() != null
|
return item?.getLinkWithFallback() != null
|
||||||
|
|
|
@ -419,6 +419,7 @@
|
||||||
<string name="duration">Duration</string>
|
<string name="duration">Duration</string>
|
||||||
<string name="episode_title">Episode title</string>
|
<string name="episode_title">Episode title</string>
|
||||||
<string name="feed_title">Podcast title</string>
|
<string name="feed_title">Podcast title</string>
|
||||||
|
<string name="show_criteria">Show criteria</string>
|
||||||
<string name="title">Title</string>
|
<string name="title">Title</string>
|
||||||
<string name="author">Author</string>
|
<string name="author">Author</string>
|
||||||
<string name="random">Random</string>
|
<string name="random">Random</string>
|
||||||
|
|
13
changelog.md
13
changelog.md
|
@ -1,3 +1,16 @@
|
||||||
|
# 6.12.6
|
||||||
|
|
||||||
|
* in SearchFragment, made search criteria options are togglable, and added back search online option
|
||||||
|
* further enhanced filtering routines
|
||||||
|
* categories with multi-selections are expandable/collapsable
|
||||||
|
* once expanded, added three icons: <<<, X, >>>
|
||||||
|
* tapping on <<< will select all lower items, >>> all higher items, X to clear selection in the category
|
||||||
|
* manual sorting of Queues is back.
|
||||||
|
* The way to enable/disable it, uncheck/check "Lock queue" in menu
|
||||||
|
* if "Lock queue" doesn't appear, top "Sort" in the menu and then, uncheck "Keep sorted" in the popup
|
||||||
|
* in episodes lists, swipe dialog shows up when the swipe has not been configured
|
||||||
|
* changed the info shared from FeedInfo and FeedEpisodes, now it shares simply the download url of the feed
|
||||||
|
|
||||||
# 6.12.5
|
# 6.12.5
|
||||||
|
|
||||||
* fixed a long-standing issue in the play apk where rewind/forward buttons don't work during cast
|
* fixed a long-standing issue in the play apk where rewind/forward buttons don't work during cast
|
||||||
|
|
|
@ -0,0 +1,12 @@
|
||||||
|
Version 6.12.6
|
||||||
|
|
||||||
|
* in SearchFragment, made search criteria options are togglable, and added back search online option
|
||||||
|
* further enhanced filtering routines
|
||||||
|
* categories with multi-selections are expandable/collapsable
|
||||||
|
* once expanded, added three icons: <<<, X, >>>
|
||||||
|
* tapping on <<< will select all lower items, >>> all higher items, X to clear selection in the category
|
||||||
|
* manual sorting of Queues is back.
|
||||||
|
* The way to enable/disable it, uncheck/check "Lock queue" in menu
|
||||||
|
* if "Lock queue" doesn't appear, top "Sort" in the menu and then, uncheck "Keep sorted" in the popup
|
||||||
|
* in episodes lists, swipe dialog shows up when the swipe has not been configured
|
||||||
|
* changed the info shared from FeedInfo and FeedEpisodes, now it shares simply the download url of the feed
|
Loading…
Reference in New Issue