6.12.2 commit
This commit is contained in:
parent
79c1bf43f9
commit
d3ca132b7c
|
@ -31,8 +31,8 @@ android {
|
|||
testApplicationId "ac.mdiq.podcini.tests"
|
||||
testInstrumentationRunner "androidx.test.runner.AndroidJUnitRunner"
|
||||
|
||||
versionCode 3020279
|
||||
versionName "6.12.1"
|
||||
versionCode 3020280
|
||||
versionName "6.12.2"
|
||||
|
||||
applicationId "ac.mdiq.podcini.R"
|
||||
def commit = ""
|
||||
|
|
|
@ -45,7 +45,7 @@ abstract class ServiceStatusHandler(private val activity: FragmentActivity) {
|
|||
Logd(TAG, "statusUpdate onReceive doing updates")
|
||||
MediaPlayerBase.status = info.playerStatus
|
||||
prevStatus = MediaPlayerBase.status
|
||||
curMedia = info.playable
|
||||
// curMedia = info.playable
|
||||
handleStatus()
|
||||
}
|
||||
} else {
|
||||
|
@ -177,7 +177,7 @@ abstract class ServiceStatusHandler(private val activity: FragmentActivity) {
|
|||
Logd(TAG, "Querying service info")
|
||||
if (playbackService != null && PlaybackService.mPlayerInfo != null) {
|
||||
MediaPlayerBase.status = PlaybackService.mPlayerInfo!!.playerStatus
|
||||
curMedia = PlaybackService.mPlayerInfo!!.playable
|
||||
// curMedia = PlaybackService.mPlayerInfo!!.playable
|
||||
// make sure that new media is loaded if it's available
|
||||
mediaInfoLoaded = false
|
||||
handleStatus()
|
||||
|
|
|
@ -271,13 +271,15 @@ abstract class MediaPlayerBase protected constructor(protected val context: Cont
|
|||
Log.d(TAG, "${this.javaClass.simpleName}: Setting player status to $newStatus")
|
||||
this.oldStatus = status
|
||||
status = newStatus
|
||||
if (newMedia != null) setPlayable(newMedia)
|
||||
if (newMedia != null && newStatus != PlayerStatus.INDETERMINATE) {
|
||||
if (newMedia != null) {
|
||||
setPlayable(newMedia)
|
||||
if (newStatus != PlayerStatus.INDETERMINATE) {
|
||||
when {
|
||||
oldStatus == PlayerStatus.PLAYING && newStatus != PlayerStatus.PLAYING -> callback.onPlaybackPause(newMedia, position)
|
||||
oldStatus != PlayerStatus.PLAYING && newStatus == PlayerStatus.PLAYING -> callback.onPlaybackStart(newMedia, position)
|
||||
}
|
||||
}
|
||||
}
|
||||
callback.statusChanged(MediaPlayerInfo(oldStatus, status, curMedia))
|
||||
}
|
||||
|
||||
|
|
|
@ -389,15 +389,23 @@ class PlaybackService : MediaLibraryService() {
|
|||
}
|
||||
}
|
||||
if (item != null) {
|
||||
// fun shouldSkipKeepEpisode(): Boolean {
|
||||
// return appPrefs.getBoolean(UserPreferences.Prefs.prefSkipKeepsEpisode.name, true)
|
||||
// }
|
||||
// fun shouldFavoriteKeepEpisode(): Boolean {
|
||||
// return appPrefs.getBoolean(UserPreferences.Prefs.prefFavoriteKeepsEpisode.name, true)
|
||||
// }
|
||||
runOnIOScope {
|
||||
if (ended || smartMarkAsPlayed || autoSkipped || (skipped && !shouldSkipKeepEpisode())) {
|
||||
val shouldSkipKeepEpisode = appPrefs.getBoolean(UserPreferences.Prefs.prefSkipKeepsEpisode.name, true)
|
||||
val shouldFavoriteKeepEpisode = appPrefs.getBoolean(UserPreferences.Prefs.prefFavoriteKeepsEpisode.name, true)
|
||||
if (ended || smartMarkAsPlayed || autoSkipped || (skipped && !shouldSkipKeepEpisode)) {
|
||||
Logd(TAG, "onPostPlayback ended: $ended smartMarkAsPlayed: $smartMarkAsPlayed autoSkipped: $autoSkipped skipped: $skipped")
|
||||
// only mark the item as played if we're not keeping it anyways
|
||||
item = setPlayStateSync(PlayState.PLAYED.code, ended || (skipped && smartMarkAsPlayed), item!!)
|
||||
val action = item?.feed?.preferences?.autoDeleteAction
|
||||
val shouldAutoDelete = (action == AutoDeleteAction.ALWAYS ||
|
||||
(action == AutoDeleteAction.GLOBAL && item?.feed != null && shouldAutoDeleteItem(item!!.feed!!)))
|
||||
if (playable is EpisodeMedia && shouldAutoDelete && (item?.isFavorite != true || !shouldFavoriteKeepEpisode())) {
|
||||
if (playable is EpisodeMedia && shouldAutoDelete && (item?.isFavorite != true || !shouldFavoriteKeepEpisode)) {
|
||||
item = deleteMediaSync(this@PlaybackService, item!!)
|
||||
if (shouldDeleteRemoveFromQueue()) removeFromQueueSync(null, item!!)
|
||||
}
|
||||
|
@ -407,14 +415,6 @@ class PlaybackService : MediaLibraryService() {
|
|||
}
|
||||
}
|
||||
|
||||
fun shouldSkipKeepEpisode(): Boolean {
|
||||
return appPrefs.getBoolean(UserPreferences.Prefs.prefSkipKeepsEpisode.name, true)
|
||||
}
|
||||
|
||||
fun shouldFavoriteKeepEpisode(): Boolean {
|
||||
return appPrefs.getBoolean(UserPreferences.Prefs.prefFavoriteKeepsEpisode.name, true)
|
||||
}
|
||||
|
||||
override fun onPlaybackStart(playable: Playable, position: Int) {
|
||||
Logd(TAG, "onPlaybackStart position: $position")
|
||||
taskManager.startWidgetUpdater()
|
||||
|
@ -747,12 +747,10 @@ class PlaybackService : MediaLibraryService() {
|
|||
|
||||
override fun onDestroy() {
|
||||
Logd(TAG, "Service is about to be destroyed")
|
||||
|
||||
playbackService = null
|
||||
isRunning = false
|
||||
currentMediaType = MediaType.UNKNOWN
|
||||
castStateListener.destroy()
|
||||
|
||||
currentitem = null
|
||||
|
||||
LocalMediaPlayer.cleanup()
|
||||
|
@ -1967,8 +1965,8 @@ class PlaybackService : MediaLibraryService() {
|
|||
}
|
||||
override fun onIsPlayingChanged(isPlaying: Boolean) {
|
||||
// val stat = if (isPlaying) PlayerStatus.PLAYING else PlayerStatus.PAUSED
|
||||
// TODO: test
|
||||
val stat = if (isPlaying) PlayerStatus.PLAYING else PlayerStatus.INDETERMINATE
|
||||
// TODO: test: changing PAUSED to STOPPED or INDETERMINATE makes resume not possible if interrupted
|
||||
val stat = if (isPlaying) PlayerStatus.PLAYING else PlayerStatus.PAUSED
|
||||
setPlayerStatus(stat, curMedia)
|
||||
Logd(TAG, "onIsPlayingChanged $isPlaying")
|
||||
}
|
||||
|
|
|
@ -20,6 +20,8 @@ class EpisodeFilter(vararg properties: String) : Serializable {
|
|||
val showNotAutoDownloadable: Boolean = hasProperty(States.not_auto_downloadable.name)
|
||||
val showHasMedia: Boolean = hasProperty(States.has_media.name)
|
||||
val showNoMedia: Boolean = hasProperty(States.no_media.name)
|
||||
val showHasComments: Boolean = hasProperty(States.has_comments.name)
|
||||
val showNoComments: Boolean = hasProperty(States.no_comments.name)
|
||||
val showIsFavorite: Boolean = hasProperty(States.is_favorite.name)
|
||||
val showNotFavorite: Boolean = hasProperty(States.not_favorite.name)
|
||||
|
||||
|
@ -48,6 +50,8 @@ class EpisodeFilter(vararg properties: String) : Serializable {
|
|||
showNotAutoDownloadable && item.isAutoDownloadEnabled -> return false
|
||||
showHasMedia && item.media == null -> return false
|
||||
showNoMedia && item.media != null -> return false
|
||||
showHasComments && item.comment.isEmpty() -> return false
|
||||
showNoComments && item.comment.isNotEmpty() -> return false
|
||||
showIsFavorite && !item.isFavorite -> return false
|
||||
showNotFavorite && item.isFavorite -> return false
|
||||
showQueued && !inAnyQueue(item) -> return false
|
||||
|
@ -69,7 +73,7 @@ class EpisodeFilter(vararg properties: String) : Serializable {
|
|||
val statements: MutableList<String> = ArrayList()
|
||||
when {
|
||||
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 ")
|
||||
}
|
||||
when {
|
||||
|
@ -93,8 +97,12 @@ class EpisodeFilter(vararg properties: String) : Serializable {
|
|||
showNoMedia -> statements.add("media == nil ")
|
||||
}
|
||||
when {
|
||||
showIsFavorite -> statements.add("isFavorite == true ")
|
||||
showNotFavorite -> statements.add("isFavorite == false ")
|
||||
showHasComments -> statements.add(" comment != '' ")
|
||||
showNoComments -> statements.add(" comment == '' ")
|
||||
}
|
||||
when {
|
||||
showIsFavorite -> statements.add("rating == ${Rating.FAVORITE.code} ")
|
||||
showNotFavorite -> statements.add("rating != ${Rating.FAVORITE.code} ")
|
||||
}
|
||||
|
||||
if (statements.isEmpty()) return "id > 0"
|
||||
|
@ -120,6 +128,8 @@ class EpisodeFilter(vararg properties: String) : Serializable {
|
|||
not_favorite,
|
||||
has_media,
|
||||
no_media,
|
||||
has_comments,
|
||||
no_comments,
|
||||
queued,
|
||||
not_queued,
|
||||
downloaded,
|
||||
|
|
|
@ -11,6 +11,8 @@ class FeedFilter(vararg properties: String) : Serializable {
|
|||
val showNotKeepUpdated: Boolean = hasProperty(States.not_keepUpdated.name)
|
||||
val showGlobalPlaySpeed: Boolean = hasProperty(States.global_playSpeed.name)
|
||||
val showCustomPlaySpeed: Boolean = hasProperty(States.custom_playSpeed.name)
|
||||
val showHasComments: Boolean = hasProperty(States.has_comments.name)
|
||||
val showNoComments: Boolean = hasProperty(States.no_comments.name)
|
||||
val showHasSkips: Boolean = hasProperty(States.has_skips.name)
|
||||
val showNoSkips: Boolean = hasProperty(States.no_skips.name)
|
||||
val showAlwaysAutoDelete: Boolean = hasProperty(States.always_auto_delete.name)
|
||||
|
@ -36,6 +38,8 @@ class FeedFilter(vararg properties: String) : Serializable {
|
|||
showNotKeepUpdated && feed.preferences?.keepUpdated != false -> return false
|
||||
showGlobalPlaySpeed && feed.preferences?.playSpeed != SPEED_USE_GLOBAL -> return false
|
||||
showCustomPlaySpeed && feed.preferences?.playSpeed == SPEED_USE_GLOBAL -> return false
|
||||
showHasComments && feed.comment.isEmpty() -> return false
|
||||
showNoComments && feed.comment.isEmpty() -> return false
|
||||
showHasSkips && feed.preferences?.introSkip == 0 && feed.preferences?.endingSkip == 0 -> return false
|
||||
showNoSkips && (feed.preferences?.introSkip != 0 || feed.preferences?.endingSkip != 0) -> return false
|
||||
showAlwaysAutoDelete && feed.preferences?.autoDeleteAction != FeedPreferences.AutoDeleteAction.ALWAYS -> return false
|
||||
|
@ -60,6 +64,10 @@ class FeedFilter(vararg properties: String) : Serializable {
|
|||
showHasSkips -> statements.add(" preferences.introSkip != 0 OR preferences.endingSkip != 0 ")
|
||||
showNoSkips -> statements.add(" preferences.introSkip == 0 AND preferences.endingSkip == 0 ")
|
||||
}
|
||||
when {
|
||||
showHasComments -> statements.add(" comment != '' ")
|
||||
showNoComments -> statements.add(" comment == '' ")
|
||||
}
|
||||
when {
|
||||
showAlwaysAutoDelete -> statements.add(" preferences.autoDelete == ${FeedPreferences.AutoDeleteAction.ALWAYS.code} ")
|
||||
showNeverAutoDelete -> statements.add(" preferences.playSpeed == ${FeedPreferences.AutoDeleteAction.NEVER.code} ")
|
||||
|
@ -89,6 +97,8 @@ class FeedFilter(vararg properties: String) : Serializable {
|
|||
custom_playSpeed,
|
||||
has_skips,
|
||||
no_skips,
|
||||
has_comments,
|
||||
no_comments,
|
||||
// global_auto_delete,
|
||||
always_auto_delete,
|
||||
never_auto_delete,
|
||||
|
|
|
@ -1,92 +1,99 @@
|
|||
package ac.mdiq.podcini.ui.dialog
|
||||
|
||||
import ac.mdiq.podcini.R
|
||||
import ac.mdiq.podcini.databinding.FilterDialogBinding
|
||||
import ac.mdiq.podcini.databinding.FilterDialogRowBinding
|
||||
import ac.mdiq.podcini.storage.model.EpisodeFilter
|
||||
import ac.mdiq.podcini.storage.model.FeedFilter
|
||||
import ac.mdiq.podcini.ui.compose.CustomTheme
|
||||
import ac.mdiq.podcini.ui.fragment.SubscriptionsFragment.Companion.TAG
|
||||
import ac.mdiq.podcini.ui.fragment.SubscriptionsFragment.FeedFilterDialog.FeedFilterGroup.ItemProperties
|
||||
import ac.mdiq.podcini.util.Logd
|
||||
import android.os.Bundle
|
||||
import android.view.LayoutInflater
|
||||
import android.view.View
|
||||
import android.view.ViewGroup
|
||||
import android.widget.Button
|
||||
import android.widget.LinearLayout
|
||||
import androidx.compose.foundation.BorderStroke
|
||||
import androidx.compose.foundation.layout.*
|
||||
import androidx.compose.material3.MaterialTheme
|
||||
import androidx.compose.material3.OutlinedButton
|
||||
import androidx.compose.material3.Text
|
||||
import androidx.compose.runtime.*
|
||||
import androidx.compose.ui.Alignment
|
||||
import androidx.compose.ui.Modifier
|
||||
import androidx.compose.ui.graphics.Color
|
||||
import androidx.compose.ui.platform.ComposeView
|
||||
import androidx.compose.ui.res.stringResource
|
||||
import androidx.compose.ui.unit.dp
|
||||
import com.google.android.material.bottomsheet.BottomSheetDialogFragment
|
||||
import com.google.android.material.button.MaterialButtonToggleGroup
|
||||
|
||||
abstract class EpisodeFilterDialog : BottomSheetDialogFragment() {
|
||||
private lateinit var rows: LinearLayout
|
||||
private var _binding: FilterDialogBinding? = null
|
||||
private val binding get() = _binding!!
|
||||
|
||||
var filter: EpisodeFilter? = null
|
||||
private val buttonMap: MutableMap<String, Button> = mutableMapOf()
|
||||
val filtersDisabled: MutableSet<FeedItemFilterGroup> = mutableSetOf()
|
||||
|
||||
private val newFilterValues: Set<String>
|
||||
get() {
|
||||
val newFilterValues: MutableSet<String> = HashSet()
|
||||
for (i in 0 until rows.childCount) {
|
||||
if (rows.getChildAt(i) !is MaterialButtonToggleGroup) continue
|
||||
val group = rows.getChildAt(i) as MaterialButtonToggleGroup
|
||||
if (group.checkedButtonId == View.NO_ID) continue
|
||||
val tag = group.findViewById<View>(group.checkedButtonId).tag as? String ?: continue
|
||||
newFilterValues.add(tag)
|
||||
}
|
||||
return newFilterValues
|
||||
}
|
||||
private val filterValues: MutableSet<String> = mutableSetOf()
|
||||
|
||||
override fun onCreateView(inflater: LayoutInflater, container: ViewGroup?, savedInstanceState: Bundle?): View? {
|
||||
val layout = inflater.inflate(R.layout.filter_dialog, container, false)
|
||||
_binding = FilterDialogBinding.bind(layout)
|
||||
rows = binding.filterRows
|
||||
Logd("EpisodeFilterDialog", "fragment onCreateView")
|
||||
val composeView = ComposeView(requireContext()).apply {
|
||||
setContent {
|
||||
CustomTheme(requireContext()) {
|
||||
MainView()
|
||||
}
|
||||
}
|
||||
}
|
||||
return composeView
|
||||
}
|
||||
|
||||
//add filter rows
|
||||
@Composable
|
||||
fun MainView() {
|
||||
val textColor = MaterialTheme.colorScheme.onSurface
|
||||
Column {
|
||||
for (item in FeedItemFilterGroup.entries) {
|
||||
// Logd("EpisodeFilterDialog", "FeedItemFilterGroup: ${item.values[0].filterId} ${item.values[1].filterId}")
|
||||
if (item in filtersDisabled) continue
|
||||
|
||||
val rBinding = FilterDialogRowBinding.inflate(inflater)
|
||||
rBinding.filterButton1.setOnClickListener { onFilterChanged(newFilterValues) }
|
||||
rBinding.filterButton2.setOnClickListener { onFilterChanged(newFilterValues) }
|
||||
|
||||
rBinding.filterButton1.setText(item.values[0].displayName)
|
||||
rBinding.filterButton1.tag = item.values[0].filterId
|
||||
buttonMap[item.values[0].filterId] = rBinding.filterButton1
|
||||
rBinding.filterButton2.setText(item.values[1].displayName)
|
||||
rBinding.filterButton2.tag = item.values[1].filterId
|
||||
buttonMap[item.values[1].filterId] = rBinding.filterButton2
|
||||
rBinding.filterButton1.maxLines = 3
|
||||
rBinding.filterButton1.isSingleLine = false
|
||||
rBinding.filterButton2.maxLines = 3
|
||||
rBinding.filterButton2.isSingleLine = false
|
||||
rows.addView(rBinding.root, rows.childCount - 1)
|
||||
}
|
||||
|
||||
binding.confirmFiltermenu.setOnClickListener { dismiss() }
|
||||
binding.resetFiltermenu.setOnClickListener {
|
||||
onFilterChanged(emptySet())
|
||||
for (i in 0 until rows.childCount) {
|
||||
if (rows.getChildAt(i) is MaterialButtonToggleGroup) (rows.getChildAt(i) as MaterialButtonToggleGroup).clearChecked()
|
||||
}
|
||||
}
|
||||
|
||||
Row(modifier = Modifier.padding(2.dp).fillMaxWidth(), horizontalArrangement = Arrangement.Center, verticalAlignment = Alignment.CenterVertically) {
|
||||
var selectedIndex by remember { mutableStateOf(-1) }
|
||||
LaunchedEffect(Unit) {
|
||||
if (filter != null) {
|
||||
for (filterId in filter!!.values) {
|
||||
if (filterId.isNotEmpty()) {
|
||||
val button = buttonMap[filterId]
|
||||
if (button != null) (button.parent as MaterialButtonToggleGroup).check(button.id)
|
||||
if (item.values[0].filterId in filter!!.values) selectedIndex = 0
|
||||
else if (item.values[1].filterId in filter!!.values) selectedIndex = 1
|
||||
}
|
||||
}
|
||||
OutlinedButton(modifier = Modifier.padding(2.dp), border = BorderStroke(2.dp, if (selectedIndex != 0) textColor else Color.Green),
|
||||
onClick = {
|
||||
if (selectedIndex != 0) {
|
||||
selectedIndex = 0
|
||||
filterValues.add(item.values[0].filterId)
|
||||
filterValues.remove(item.values[1].filterId)
|
||||
} else {
|
||||
selectedIndex = -1
|
||||
filterValues.remove(item.values[0].filterId)
|
||||
}
|
||||
onFilterChanged(filterValues)
|
||||
},
|
||||
) {
|
||||
Text(text = stringResource(item.values[0].displayName), color = textColor)
|
||||
}
|
||||
Spacer(Modifier.width(5.dp))
|
||||
OutlinedButton(modifier = Modifier.padding(2.dp), border = BorderStroke(2.dp, if (selectedIndex != 1) textColor else Color.Green),
|
||||
onClick = {
|
||||
if (selectedIndex != 1) {
|
||||
selectedIndex = 1
|
||||
filterValues.add(item.values[1].filterId)
|
||||
filterValues.remove(item.values[0].filterId)
|
||||
} else {
|
||||
selectedIndex = -1
|
||||
filterValues.remove(item.values[1].filterId)
|
||||
}
|
||||
onFilterChanged(filterValues)
|
||||
},
|
||||
) {
|
||||
Text(text = stringResource(item.values[1].displayName), color = textColor)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
return layout
|
||||
}
|
||||
|
||||
override fun onDestroyView() {
|
||||
Logd(TAG, "onDestroyView")
|
||||
_binding = null
|
||||
super.onDestroyView()
|
||||
}
|
||||
|
||||
|
@ -97,6 +104,7 @@ abstract class EpisodeFilterDialog : BottomSheetDialogFragment() {
|
|||
PAUSED(ItemProperties(R.string.hide_paused_episodes_label, EpisodeFilter.States.paused.name), ItemProperties(R.string.not_paused, EpisodeFilter.States.not_paused.name)),
|
||||
FAVORITE(ItemProperties(R.string.hide_is_favorite_label, EpisodeFilter.States.is_favorite.name), ItemProperties(R.string.not_favorite, EpisodeFilter.States.not_favorite.name)),
|
||||
MEDIA(ItemProperties(R.string.has_media, EpisodeFilter.States.has_media.name), ItemProperties(R.string.no_media, EpisodeFilter.States.no_media.name)),
|
||||
OPINION(ItemProperties(R.string.has_comments, EpisodeFilter.States.has_comments.name), ItemProperties(R.string.no_comments, EpisodeFilter.States.no_comments.name)),
|
||||
QUEUED(ItemProperties(R.string.queued_label, EpisodeFilter.States.queued.name), ItemProperties(R.string.not_queued_label, EpisodeFilter.States.not_queued.name)),
|
||||
DOWNLOADED(ItemProperties(R.string.downloaded_label, EpisodeFilter.States.downloaded.name), ItemProperties(R.string.not_downloaded_label, EpisodeFilter.States.not_downloaded.name)),
|
||||
AUTO_DOWNLOADABLE(ItemProperties(R.string.auto_downloadable_label, EpisodeFilter.States.auto_downloadable.name), ItemProperties(R.string.not_auto_downloadable_label, EpisodeFilter.States.not_auto_downloadable.name));
|
||||
|
|
|
@ -6,6 +6,7 @@ import ac.mdiq.podcini.playback.PlaybackServiceStarter
|
|||
import ac.mdiq.podcini.playback.ServiceStatusHandler
|
||||
import ac.mdiq.podcini.playback.base.InTheatre.curEpisode
|
||||
import ac.mdiq.podcini.playback.base.InTheatre.curMedia
|
||||
import ac.mdiq.podcini.playback.base.InTheatre.isCurrentlyPlaying
|
||||
import ac.mdiq.podcini.playback.base.MediaPlayerBase.Companion.status
|
||||
import ac.mdiq.podcini.playback.base.PlayerStatus
|
||||
import ac.mdiq.podcini.playback.base.VideoMode
|
||||
|
@ -510,7 +511,7 @@ class AudioPlayerFragment : Fragment() {
|
|||
fun onPositionUpdate(event: FlowEvent.PlaybackPositionEvent) {
|
||||
Logd(TAG, "onPositionUpdate")
|
||||
if (!playButInit && playButRes == R.drawable.ic_play_48dp && curMedia is EpisodeMedia) {
|
||||
playButRes = R.drawable.ic_pause
|
||||
if (isCurrentlyPlaying(curMedia as? EpisodeMedia)) playButRes = R.drawable.ic_pause
|
||||
playButInit = true
|
||||
}
|
||||
|
||||
|
@ -753,14 +754,15 @@ class AudioPlayerFragment : Fragment() {
|
|||
Logd(TAG, "loadMediaInfo() curMedia: ${curMedia?.getIdentifier()}")
|
||||
val actMain = (activity as MainActivity)
|
||||
var i = 0
|
||||
while (curMedia == null && i++ < 6) runBlocking { delay(500) }
|
||||
// while (curMedia == null && i++ < 6) runBlocking { delay(500) }
|
||||
if (curMedia == null) {
|
||||
if (actMain.isPlayerVisible()) actMain.setPlayerVisible(false)
|
||||
return
|
||||
}
|
||||
if (!actMain.isPlayerVisible()) actMain.setPlayerVisible(true)
|
||||
if (!loadItemsRunning) {
|
||||
loadItemsRunning = true
|
||||
if (!actMain.isPlayerVisible()) actMain.setPlayerVisible(true)
|
||||
// if (!actMain.isPlayerVisible()) actMain.setPlayerVisible(true)
|
||||
val curMediaChanged = currentMedia == null || curMedia?.getIdentifier() != currentMedia?.getIdentifier()
|
||||
if (curMedia?.getIdentifier() != currentMedia?.getIdentifier()) updateUi(curMedia!!)
|
||||
if (!isCollapsed && curMediaChanged) {
|
||||
|
|
|
@ -72,6 +72,7 @@ import androidx.compose.ui.Alignment
|
|||
import androidx.compose.ui.Modifier
|
||||
import androidx.compose.ui.graphics.Color
|
||||
import androidx.compose.ui.graphics.vector.ImageVector
|
||||
import androidx.compose.ui.platform.ComposeView
|
||||
import androidx.compose.ui.platform.LocalContext
|
||||
import androidx.compose.ui.res.painterResource
|
||||
import androidx.compose.ui.res.stringResource
|
||||
|
@ -650,7 +651,7 @@ class SubscriptionsFragment : Fragment(), Toolbar.OnMenuItemClickListener {
|
|||
Dialog(onDismissRequest = onDismissRequest) {
|
||||
Surface(shape = RoundedCornerShape(16.dp)) {
|
||||
Column(modifier = Modifier.padding(16.dp), verticalArrangement = Arrangement.spacedBy(16.dp)) {
|
||||
for (rating in Rating.entries) {
|
||||
for (rating in Rating.entries.reversed()) {
|
||||
Row(verticalAlignment = Alignment.CenterVertically, modifier = Modifier.padding(4.dp).clickable {
|
||||
for (item in selected) Feeds.setRating(item, rating.code)
|
||||
onDismissRequest()
|
||||
|
@ -1105,77 +1106,72 @@ class SubscriptionsFragment : Fragment(), Toolbar.OnMenuItemClickListener {
|
|||
}
|
||||
|
||||
class FeedFilterDialog : BottomSheetDialogFragment() {
|
||||
private lateinit var rows: LinearLayout
|
||||
private var _binding: FilterDialogBinding? = null
|
||||
private val binding get() = _binding!!
|
||||
|
||||
var filter: FeedFilter? = null
|
||||
private val buttonMap: MutableMap<String, Button> = mutableMapOf()
|
||||
|
||||
private val newFilterValues: Set<String>
|
||||
get() {
|
||||
val newFilterValues: MutableSet<String> = HashSet()
|
||||
for (i in 0 until rows.childCount) {
|
||||
if (rows.getChildAt(i) !is MaterialButtonToggleGroup) continue
|
||||
val group = rows.getChildAt(i) as MaterialButtonToggleGroup
|
||||
if (group.checkedButtonId == View.NO_ID) continue
|
||||
val tag = group.findViewById<View>(group.checkedButtonId).tag as? String ?: continue
|
||||
newFilterValues.add(tag)
|
||||
}
|
||||
return newFilterValues
|
||||
}
|
||||
private val filterValues: MutableSet<String> = mutableSetOf()
|
||||
|
||||
override fun onCreateView(inflater: LayoutInflater, container: ViewGroup?, savedInstanceState: Bundle?): View? {
|
||||
val layout = inflater.inflate(R.layout.filter_dialog, container, false)
|
||||
_binding = FilterDialogBinding.bind(layout)
|
||||
rows = binding.filterRows
|
||||
Logd("FeedFilterDialog", "fragment onCreateView")
|
||||
val composeView = ComposeView(requireContext()).apply {
|
||||
setContent {
|
||||
CustomTheme(requireContext()) {
|
||||
MainView()
|
||||
}
|
||||
}
|
||||
}
|
||||
return composeView
|
||||
}
|
||||
|
||||
//add filter rows
|
||||
@Composable
|
||||
fun MainView() {
|
||||
val textColor = MaterialTheme.colorScheme.onSurface
|
||||
Column {
|
||||
for (item in FeedFilterGroup.entries) {
|
||||
// Logd("EpisodeFilterDialog", "FeedItemFilterGroup: ${item.values[0].filterId} ${item.values[1].filterId}")
|
||||
val rBinding = FilterDialogRowBinding.inflate(inflater)
|
||||
// rowBinding.root.addOnButtonCheckedListener { _: MaterialButtonToggleGroup?, _: Int, _: Boolean ->
|
||||
// onFilterChanged(newFilterValues)
|
||||
// }
|
||||
rBinding.filterButton1.setOnClickListener { onFilterChanged(newFilterValues) }
|
||||
rBinding.filterButton2.setOnClickListener { onFilterChanged(newFilterValues) }
|
||||
|
||||
rBinding.filterButton1.setText(item.values[0].displayName)
|
||||
rBinding.filterButton1.tag = item.values[0].filterId
|
||||
buttonMap[item.values[0].filterId] = rBinding.filterButton1
|
||||
rBinding.filterButton2.setText(item.values[1].displayName)
|
||||
rBinding.filterButton2.tag = item.values[1].filterId
|
||||
buttonMap[item.values[1].filterId] = rBinding.filterButton2
|
||||
rBinding.filterButton1.maxLines = 3
|
||||
rBinding.filterButton1.isSingleLine = false
|
||||
rBinding.filterButton2.maxLines = 3
|
||||
rBinding.filterButton2.isSingleLine = false
|
||||
rows.addView(rBinding.root, rows.childCount - 1)
|
||||
}
|
||||
|
||||
binding.confirmFiltermenu.setOnClickListener { dismiss() }
|
||||
binding.resetFiltermenu.setOnClickListener {
|
||||
onFilterChanged(emptySet())
|
||||
for (i in 0 until rows.childCount) {
|
||||
if (rows.getChildAt(i) is MaterialButtonToggleGroup) (rows.getChildAt(i) as MaterialButtonToggleGroup).clearChecked()
|
||||
}
|
||||
}
|
||||
|
||||
Row(modifier = Modifier.padding(2.dp).fillMaxWidth(), horizontalArrangement = Arrangement.Center, verticalAlignment = Alignment.CenterVertically) {
|
||||
var selectedIndex by remember { mutableStateOf(-1) }
|
||||
LaunchedEffect(Unit) {
|
||||
if (filter != null) {
|
||||
for (filterId in filter!!.values) {
|
||||
if (filterId.isNotEmpty()) {
|
||||
val button = buttonMap[filterId]
|
||||
if (button != null) (button.parent as MaterialButtonToggleGroup).check(button.id)
|
||||
if (item.values[0].filterId in filter!!.values) selectedIndex = 0
|
||||
else if (item.values[1].filterId in filter!!.values) selectedIndex = 1
|
||||
}
|
||||
}
|
||||
OutlinedButton(modifier = Modifier.padding(2.dp), border = BorderStroke(2.dp, if (selectedIndex != 0) textColor else Color.Green),
|
||||
onClick = {
|
||||
if (selectedIndex != 0) {
|
||||
selectedIndex = 0
|
||||
filterValues.add(item.values[0].filterId)
|
||||
filterValues.remove(item.values[1].filterId)
|
||||
} else {
|
||||
selectedIndex = -1
|
||||
filterValues.remove(item.values[0].filterId)
|
||||
}
|
||||
onFilterChanged(filterValues)
|
||||
},
|
||||
) {
|
||||
Text(text = stringResource(item.values[0].displayName), color = textColor)
|
||||
}
|
||||
Spacer(Modifier.width(5.dp))
|
||||
OutlinedButton(modifier = Modifier.padding(2.dp), border = BorderStroke(2.dp, if (selectedIndex != 1) textColor else Color.Green),
|
||||
onClick = {
|
||||
if (selectedIndex != 1) {
|
||||
selectedIndex = 1
|
||||
filterValues.add(item.values[1].filterId)
|
||||
filterValues.remove(item.values[0].filterId)
|
||||
} else {
|
||||
selectedIndex = -1
|
||||
filterValues.remove(item.values[1].filterId)
|
||||
}
|
||||
onFilterChanged(filterValues)
|
||||
},
|
||||
) {
|
||||
Text(text = stringResource(item.values[1].displayName), color = textColor)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
return layout
|
||||
}
|
||||
|
||||
override fun onDestroyView() {
|
||||
Logd(TAG, "onDestroyView")
|
||||
_binding = null
|
||||
// _binding = null
|
||||
super.onDestroyView()
|
||||
}
|
||||
|
||||
|
@ -1188,6 +1184,7 @@ class SubscriptionsFragment : Fragment(), Toolbar.OnMenuItemClickListener {
|
|||
enum class FeedFilterGroup(vararg values: ItemProperties) {
|
||||
KEEP_UPDATED(ItemProperties(R.string.keep_updated, FeedFilter.States.keepUpdated.name), ItemProperties(R.string.not_keep_updated, FeedFilter.States.not_keepUpdated.name)),
|
||||
PLAY_SPEED(ItemProperties(R.string.global_speed, FeedFilter.States.global_playSpeed.name), ItemProperties(R.string.custom_speed, FeedFilter.States.custom_playSpeed.name)),
|
||||
OPINION(ItemProperties(R.string.has_comments, FeedFilter.States.has_comments.name), ItemProperties(R.string.no_comments, FeedFilter.States.no_comments.name)),
|
||||
SKIPS(ItemProperties(R.string.has_skips, FeedFilter.States.has_skips.name), ItemProperties(R.string.no_skips, FeedFilter.States.no_skips.name)),
|
||||
AUTO_DELETE(ItemProperties(R.string.always_auto_delete, FeedFilter.States.always_auto_delete.name), ItemProperties(R.string.never_auto_delete, FeedFilter.States.never_auto_delete.name)),
|
||||
AUTO_DOWNLOAD(ItemProperties(R.string.auto_download, FeedFilter.States.autoDownload.name), ItemProperties(R.string.not_auto_download, FeedFilter.States.not_autoDownload.name));
|
||||
|
|
|
@ -1,43 +0,0 @@
|
|||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<ScrollView
|
||||
xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="match_parent"
|
||||
android:id="@+id/filter_dialog">
|
||||
|
||||
<LinearLayout
|
||||
android:id="@+id/filter_rows"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:orientation="vertical"
|
||||
android:paddingLeft="24dp"
|
||||
android:paddingTop="24dp"
|
||||
android:paddingRight="24dp"
|
||||
android:paddingBottom="8dp">
|
||||
|
||||
<LinearLayout
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="match_parent"
|
||||
android:orientation="horizontal">
|
||||
|
||||
<com.google.android.material.button.MaterialButton
|
||||
android:id="@+id/resetFiltermenu"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_weight="1"
|
||||
android:text="@string/reset"
|
||||
style="@style/Widget.MaterialComponents.Button.TextButton" />
|
||||
|
||||
<com.google.android.material.button.MaterialButton
|
||||
android:id="@+id/confirmFiltermenu"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_weight="1"
|
||||
android:text="@string/confirm_label"
|
||||
style="@style/Widget.MaterialComponents.Button.TextButton" />
|
||||
|
||||
</LinearLayout>
|
||||
|
||||
</LinearLayout>
|
||||
|
||||
</ScrollView>
|
|
@ -1,25 +0,0 @@
|
|||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<com.google.android.material.button.MaterialButtonToggleGroup
|
||||
xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
xmlns:app="http://schemas.android.com/apk/res-auto"
|
||||
android:id="@+id/buttonGroup"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:weightSum="2"
|
||||
app:singleSelection="true">
|
||||
|
||||
<Button
|
||||
android:id="@+id/filterButton1"
|
||||
android:layout_width="0dp"
|
||||
android:layout_height="match_parent"
|
||||
android:layout_weight="1"
|
||||
style="@style/OutlinedButtonBetterContrast" />
|
||||
|
||||
<Button
|
||||
android:id="@+id/filterButton2"
|
||||
android:layout_width="0dp"
|
||||
android:layout_height="match_parent"
|
||||
android:layout_weight="1"
|
||||
style="@style/OutlinedButtonBetterContrast" />
|
||||
|
||||
</com.google.android.material.button.MaterialButtonToggleGroup>
|
|
@ -903,6 +903,8 @@
|
|||
<string name="custom_speed">Custom play speed</string>
|
||||
<string name="has_skips">Skips set</string>
|
||||
<string name="no_skips">No Skips set</string>
|
||||
<string name="has_comments">Has commented</string>
|
||||
<string name="no_comments">Not commented</string>
|
||||
<string name="always_auto_delete">Always auto delete</string>
|
||||
<string name="never_auto_delete">Never auto delete</string>
|
||||
<string name="auto_download">Auto download enabled</string>
|
||||
|
|
10
changelog.md
10
changelog.md
|
@ -1,3 +1,13 @@
|
|||
# 6.12.2
|
||||
|
||||
* fixed play not resuming after interruption (watch for any side effects)
|
||||
* fixed incorrect initial play button on PlayerUI
|
||||
* fixed startup delay when curMedia is null
|
||||
* rating list in popup for Subscriptions is reversed (favorite on top)
|
||||
* first migration of Episodes and Feeds filters to Jetpack Compose
|
||||
* added has/no comments in the filters
|
||||
* fixed some errors in Episodes filter
|
||||
|
||||
# 6.12.1
|
||||
|
||||
* fixed circular calling functions when PlayerDetailed view is open
|
||||
|
|
|
@ -0,0 +1,9 @@
|
|||
Version 6.12.2
|
||||
|
||||
* fixed play not resuming after interruption (watch for any side effects)
|
||||
* fixed incorrect initial play button on PlayerUI
|
||||
* fixed startup delay when curMedia is null
|
||||
* rating list in popup for Subscriptions is reversed (favorite on top)
|
||||
* first migration of Episodes and Feeds filters to Jetpack Compose
|
||||
* added has/no comments in the filters
|
||||
* fixed some errors in Episodes filter
|
Loading…
Reference in New Issue