Browse Source

Create a default playback action for audio media and playlists

Fixes #876
merge-requests/2174/head
Nicolas Pomepuy 1 year ago
parent
commit
9b1d60203b
  1. 2
      application/resources/src/main/res/values/strings.xml
  2. 67
      application/vlc-android/res/layout/dialog_display_settings.xml
  3. 33
      application/vlc-android/src/org/videolan/vlc/gui/PlaylistFragment.kt
  4. 46
      application/vlc-android/src/org/videolan/vlc/gui/audio/AudioAlbumsSongsFragment.kt
  5. 60
      application/vlc-android/src/org/videolan/vlc/gui/audio/AudioBrowserFragment.kt
  6. 24
      application/vlc-android/src/org/videolan/vlc/gui/audio/BaseAudioBrowser.kt
  7. 52
      application/vlc-android/src/org/videolan/vlc/gui/dialogs/DisplaySettingsDialog.kt
  8. 100
      application/vlc-android/src/org/videolan/vlc/gui/helpers/DefaultPlaybackAction.kt

2
application/resources/src/main/res/values/strings.xml

@ -1385,4 +1385,6 @@
<string name="body">Message</string>
<string name="rate_us">Rate the app</string>
<string name="generating_logs">Generating logs. Please wait.</string>
<string name="default_playback_action">Playback action</string>
<string name="files">Files</string>
</resources>

67
application/vlc-android/res/layout/dialog_display_settings.xml

@ -318,6 +318,69 @@
app:layout_constraintStart_toStartOf="@+id/guideline16"
app:layout_constraintTop_toBottomOf="@+id/only_favs_group" />
<View
android:id="@+id/default_actions_group"
android:layout_width="0dp"
android:layout_height="wrap_content"
android:background="?attr/selectableItemBackground"
android:minHeight="48dp"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintHorizontal_bias="0.0"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toBottomOf="@+id/video_groups_group" />
<ImageView
android:id="@+id/default_actions_image"
android:layout_width="24dp"
android:layout_height="24dp"
android:layout_marginStart="24dp"
app:layout_constraintBottom_toBottomOf="@+id/default_actions_group"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="@+id/default_actions_group"
app:srcCompat="@drawable/ic_play" />
<TextView
android:id="@+id/default_actions_text"
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_marginStart="24dp"
android:ellipsize="end"
android:maxLines="1"
android:text="@string/default_playback_action"
android:textColor="?attr/font_default"
android:textSize="16sp"
app:layout_constraintBottom_toTopOf="@+id/default_actions_subtitle"
app:layout_constraintEnd_toStartOf="@+id/guideline16"
app:layout_constraintHorizontal_bias="0.5"
app:layout_constraintStart_toEndOf="@+id/default_actions_image"
app:layout_constraintTop_toBottomOf="@+id/video_groups_group" />
<TextView
android:id="@+id/default_actions_subtitle"
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_marginStart="24dp"
android:ellipsize="end"
android:text="@string/default_playback_action"
android:textColor="?attr/font_default"
android:alpha="0.7"
android:textSize="12sp"
app:layout_constraintBottom_toBottomOf="@+id/default_actions_group"
app:layout_constraintEnd_toStartOf="@+id/guideline16"
app:layout_constraintHorizontal_bias="0.5"
app:layout_constraintStart_toEndOf="@+id/default_actions_image"
app:layout_constraintTop_toBottomOf="@+id/default_actions_text" />
<Spinner
android:id="@+id/default_actions_spinner"
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_marginStart="8dp"
app:layout_constraintBottom_toBottomOf="@+id/default_actions_group"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="@+id/guideline16"
app:layout_constraintTop_toTopOf="@+id/default_actions_group" />
<TextView
android:id="@+id/sorts_title"
style="@style/Theme.VLC.BottomSheetTitle"
@ -328,14 +391,14 @@
android:text="@string/sortby"
android:textColor="?attr/colorPrimary"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toBottomOf="@+id/video_groups_group" />
app:layout_constraintTop_toBottomOf="@+id/default_actions_group" />
<LinearLayout
android:id="@+id/sorts_container"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:orientation="vertical"
android:layout_marginBottom="16dp"
android:orientation="vertical"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"

33
application/vlc-android/src/org/videolan/vlc/gui/PlaylistFragment.kt

@ -23,7 +23,11 @@ package org.videolan.vlc.gui
import android.content.Intent
import android.os.Bundle
import android.view.*
import android.view.LayoutInflater
import android.view.Menu
import android.view.MenuItem
import android.view.View
import android.view.ViewGroup
import androidx.appcompat.view.ActionMode
import androidx.coordinatorlayout.widget.CoordinatorLayout
import androidx.core.content.ContextCompat
@ -48,7 +52,15 @@ import org.videolan.vlc.databinding.PlaylistsFragmentBinding
import org.videolan.vlc.gui.audio.AudioBrowserAdapter
import org.videolan.vlc.gui.audio.AudioBrowserFragment
import org.videolan.vlc.gui.audio.BaseAudioBrowser
import org.videolan.vlc.gui.dialogs.*
import org.videolan.vlc.gui.dialogs.CONFIRM_PLAYLIST_RENAME_DIALOG_RESULT
import org.videolan.vlc.gui.dialogs.CURRENT_SORT
import org.videolan.vlc.gui.dialogs.DISPLAY_IN_CARDS
import org.videolan.vlc.gui.dialogs.DisplaySettingsDialog
import org.videolan.vlc.gui.dialogs.ONLY_FAVS
import org.videolan.vlc.gui.dialogs.RENAME_DIALOG_MEDIA
import org.videolan.vlc.gui.dialogs.RENAME_DIALOG_NEW_NAME
import org.videolan.vlc.gui.dialogs.RenameDialog
import org.videolan.vlc.gui.helpers.DefaultPlaybackActionMediaType
import org.videolan.vlc.gui.helpers.INavigator
import org.videolan.vlc.gui.video.VideoBrowserFragment
import org.videolan.vlc.gui.view.EmptyLoadingState
@ -59,7 +71,8 @@ import org.videolan.vlc.media.MediaUtils
import org.videolan.vlc.providers.medialibrary.MedialibraryProvider
import org.videolan.vlc.reloadLibrary
import org.videolan.vlc.util.ContextOption
import org.videolan.vlc.util.ContextOption.*
import org.videolan.vlc.util.ContextOption.CTX_PLAY_ALL
import org.videolan.vlc.util.ContextOption.CTX_RENAME
import org.videolan.vlc.util.getScreenWidth
import org.videolan.vlc.util.onAnyChange
import org.videolan.vlc.viewmodels.mobile.PlaylistsViewModel
@ -192,11 +205,13 @@ class PlaylistFragment : BaseAudioBrowser<PlaylistsViewModel>(), SwipeRefreshLay
}
//Open the display settings Bottom sheet
DisplaySettingsDialog.newInstance(
displayInCards = viewModel.providerInCard,
onlyFavs = viewModel.provider.onlyFavorites,
sorts = sorts,
currentSort = viewModel.provider.sort,
currentSortDesc = viewModel.provider.desc
displayInCards = viewModel.providerInCard,
onlyFavs = viewModel.provider.onlyFavorites,
sorts = sorts,
currentSort = viewModel.provider.sort,
currentSortDesc = viewModel.provider.desc,
defaultPlaybackActions = getDefaultActionMediaType().getDefaultPlaybackActions(Settings.getInstance(requireActivity())),
defaultActionType = getString(getDefaultActionMediaType().title)
)
.show(requireActivity().supportFragmentManager, "DisplaySettingsDialog")
true
@ -273,6 +288,8 @@ class PlaylistFragment : BaseAudioBrowser<PlaylistsViewModel>(), SwipeRefreshLay
override fun getCurrentRV(): RecyclerView = playlists
override fun getDefaultActionMediaType() = DefaultPlaybackActionMediaType.PLAYLIST
override fun hasFAB() = false
companion object {

46
application/vlc-android/src/org/videolan/vlc/gui/audio/AudioAlbumsSongsFragment.kt

@ -22,7 +22,11 @@ package org.videolan.vlc.gui.audio
import android.content.Intent
import android.os.Bundle
import android.view.*
import android.view.LayoutInflater
import android.view.Menu
import android.view.MenuItem
import android.view.View
import android.view.ViewGroup
import android.widget.TextView
import androidx.coordinatorlayout.widget.CoordinatorLayout
import androidx.lifecycle.asFlow
@ -42,13 +46,21 @@ import org.videolan.medialibrary.interfaces.media.Album
import org.videolan.medialibrary.interfaces.media.MediaWrapper
import org.videolan.medialibrary.media.MediaLibraryItem
import org.videolan.resources.KEY_AUDIO_ALBUM_SONG_CURRENT_TAB
import org.videolan.resources.KEY_AUDIO_CURRENT_TAB
import org.videolan.resources.util.parcelable
import org.videolan.tools.*
import org.videolan.tools.PLAYLIST_MODE_AUDIO
import org.videolan.tools.Settings
import org.videolan.tools.dp
import org.videolan.tools.putSingle
import org.videolan.vlc.R
import org.videolan.vlc.gui.ContentActivity
import org.videolan.vlc.gui.HeaderMediaListActivity
import org.videolan.vlc.gui.dialogs.*
import org.videolan.vlc.gui.dialogs.CURRENT_SORT
import org.videolan.vlc.gui.dialogs.DEFAULT_ACTIONS
import org.videolan.vlc.gui.dialogs.DISPLAY_IN_CARDS
import org.videolan.vlc.gui.dialogs.DisplaySettingsDialog
import org.videolan.vlc.gui.dialogs.ONLY_FAVS
import org.videolan.vlc.gui.helpers.DefaultPlaybackAction
import org.videolan.vlc.gui.helpers.DefaultPlaybackActionMediaType
import org.videolan.vlc.gui.helpers.UiTools
import org.videolan.vlc.gui.helpers.UiTools.addFavoritesIcon
import org.videolan.vlc.gui.helpers.UiTools.removeDrawables
@ -58,7 +70,7 @@ import org.videolan.vlc.media.MediaUtils
import org.videolan.vlc.media.PlaylistManager
import org.videolan.vlc.providers.medialibrary.MedialibraryProvider
import org.videolan.vlc.util.ContextOption
import org.videolan.vlc.util.ContextOption.*
import org.videolan.vlc.util.ContextOption.CTX_PLAY_ALL
import org.videolan.vlc.util.getScreenWidth
import org.videolan.vlc.util.launchWhenStarted
import org.videolan.vlc.viewmodels.PlaylistModel
@ -212,13 +224,15 @@ class AudioAlbumsSongsFragment : BaseAudioBrowser<AlbumSongsViewModel>(), SwipeR
}
//Open the display settings Bottom sheet
DisplaySettingsDialog.newInstance(
displayInCards = viewModel.providersInCard[currentTab],
onlyFavs = viewModel.providers[currentTab].onlyFavorites,
sorts = sorts,
currentSort = viewModel.providers[currentTab].sort,
currentSortDesc = viewModel.providers[currentTab].desc
displayInCards = viewModel.providersInCard[currentTab],
onlyFavs = viewModel.providers[currentTab].onlyFavorites,
sorts = sorts,
currentSort = viewModel.providers[currentTab].sort,
currentSortDesc = viewModel.providers[currentTab].desc,
defaultPlaybackActions = getDefaultActionMediaType().getDefaultPlaybackActions(Settings.getInstance(requireActivity())),
defaultActionType = getString(getDefaultActionMediaType().title)
)
.show(requireActivity().supportFragmentManager, "DisplaySettingsDialog")
.show(requireActivity().supportFragmentManager, "DisplaySettingsDialog")
true
}
else -> super.onOptionsItemSelected(item)
@ -251,6 +265,9 @@ class AudioAlbumsSongsFragment : BaseAudioBrowser<AlbumSongsViewModel>(), SwipeR
viewModel.providers[currentTab].saveSort()
viewModel.refresh()
}
DEFAULT_ACTIONS -> {
Settings.getInstance(requireActivity()).putSingle(getDefaultActionMediaType().defaultActionKey, (value as DefaultPlaybackAction).name)
}
}
}
@ -321,6 +338,13 @@ class AudioAlbumsSongsFragment : BaseAudioBrowser<AlbumSongsViewModel>(), SwipeR
override fun getCurrentRV() = lists[currentTab]
override fun getDefaultActionMediaType() = when (currentTab) {
0 -> DefaultPlaybackActionMediaType.ALBUM
else -> DefaultPlaybackActionMediaType.TRACK
}
override fun getCurrentProvider() = viewModel.providers[currentTab] as? MedialibraryProvider<MediaWrapper>
override fun onFabPlayClick(view: View) {
if (currentTab == 0)
MediaUtils.playAlbums(activity, viewModel.albumsProvider, 0, false)

60
application/vlc-android/src/org/videolan/vlc/gui/audio/AudioBrowserFragment.kt

@ -24,9 +24,12 @@ import android.content.Intent
import android.content.SharedPreferences
import android.content.res.Configuration
import android.os.Bundle
import android.util.Log
import android.util.SparseArray
import android.view.*
import android.view.LayoutInflater
import android.view.Menu
import android.view.MenuItem
import android.view.View
import android.view.ViewGroup
import android.widget.TextView
import androidx.coordinatorlayout.widget.CoordinatorLayout
import androidx.lifecycle.asFlow
@ -50,14 +53,26 @@ import org.videolan.resources.AppContextProvider
import org.videolan.resources.KEY_AUDIO_CURRENT_TAB
import org.videolan.resources.KEY_AUDIO_LAST_PLAYLIST
import org.videolan.resources.util.waitForML
import org.videolan.tools.*
import org.videolan.tools.KEY_ARTISTS_SHOW_ALL
import org.videolan.tools.RESULT_RESTART
import org.videolan.tools.Settings
import org.videolan.tools.putSingle
import org.videolan.vlc.R
import org.videolan.vlc.databinding.AudioBrowserBinding
import org.videolan.vlc.gui.AudioPlayerContainerActivity
import org.videolan.vlc.gui.ContentActivity
import org.videolan.vlc.gui.HeaderMediaListActivity
import org.videolan.vlc.gui.SecondaryActivity
import org.videolan.vlc.gui.dialogs.*
import org.videolan.vlc.gui.dialogs.CONFIRM_PERMISSION_CHANGED
import org.videolan.vlc.gui.dialogs.CURRENT_SORT
import org.videolan.vlc.gui.dialogs.DEFAULT_ACTIONS
import org.videolan.vlc.gui.dialogs.DISPLAY_IN_CARDS
import org.videolan.vlc.gui.dialogs.DisplaySettingsDialog
import org.videolan.vlc.gui.dialogs.KEY_PERMISSION_CHANGED
import org.videolan.vlc.gui.dialogs.ONLY_FAVS
import org.videolan.vlc.gui.dialogs.SHOW_ALL_ARTISTS
import org.videolan.vlc.gui.helpers.DefaultPlaybackAction
import org.videolan.vlc.gui.helpers.DefaultPlaybackActionMediaType
import org.videolan.vlc.gui.helpers.UiTools
import org.videolan.vlc.gui.helpers.UiTools.addFavoritesIcon
import org.videolan.vlc.gui.helpers.UiTools.removeDrawables
@ -66,7 +81,7 @@ import org.videolan.vlc.media.MediaUtils
import org.videolan.vlc.media.PlaylistManager
import org.videolan.vlc.providers.medialibrary.MedialibraryProvider
import org.videolan.vlc.util.ContextOption
import org.videolan.vlc.util.ContextOption.*
import org.videolan.vlc.util.ContextOption.CTX_PLAY_ALL
import org.videolan.vlc.util.Permissions
import org.videolan.vlc.util.isTalkbackIsEnabled
import org.videolan.vlc.util.launchWhenStarted
@ -204,6 +219,9 @@ class AudioBrowserFragment : BaseAudioBrowser<AudioBrowserViewModel>() {
viewModel.providers[currentTab].saveSort()
viewModel.refresh()
}
DEFAULT_ACTIONS -> {
settings.putSingle(getDefaultActionMediaType().defaultActionKey, (value as DefaultPlaybackAction).name)
}
}
}
@ -321,14 +339,17 @@ class AudioBrowserFragment : BaseAudioBrowser<AudioBrowserViewModel>() {
val sorts = arrayListOf(Medialibrary.SORT_ALPHA, Medialibrary.SORT_FILENAME, Medialibrary.SORT_ARTIST, Medialibrary.SORT_ALBUM, Medialibrary.SORT_DURATION, Medialibrary.SORT_RELEASEDATE, Medialibrary.SORT_LASTMODIFICATIONDATE, Medialibrary.SORT_FILESIZE, Medialibrary.NbMedia, Medialibrary.SORT_INSERTIONDATE).filter {
viewModel.providers[currentTab].canSortBy(it)
}
//Open the display settings Bottom sheet
DisplaySettingsDialog.newInstance(
displayInCards = viewModel.providersInCard[currentTab],
showAllArtists = if (currentTab == 0) Settings.getInstance(requireActivity()).getBoolean(KEY_ARTISTS_SHOW_ALL, false) else null,
onlyFavs = viewModel.providers[currentTab].onlyFavorites,
sorts = sorts,
currentSort = viewModel.providers[currentTab].sort,
currentSortDesc = viewModel.providers[currentTab].desc
displayInCards = viewModel.providersInCard[currentTab],
showAllArtists = if (currentTab == 0) Settings.getInstance(requireActivity()).getBoolean(KEY_ARTISTS_SHOW_ALL, false) else null,
onlyFavs = viewModel.providers[currentTab].onlyFavorites,
sorts = sorts,
currentSort = viewModel.providers[currentTab].sort,
currentSortDesc = viewModel.providers[currentTab].desc,
defaultPlaybackActions = getDefaultActionMediaType().getDefaultPlaybackActions(settings),
defaultActionType = getString(getDefaultActionMediaType().title)
)
.show(requireActivity().supportFragmentManager, "DisplaySettingsDialog")
true
@ -438,12 +459,7 @@ class AudioBrowserFragment : BaseAudioBrowser<AudioBrowserViewModel>() {
UiTools.snackerMissing(requireActivity())
return
}
if (Settings.getInstance(requireContext()).getBoolean(PLAYLIST_MODE_AUDIO, false)) {
MediaUtils.playAll(activity,
viewModel.providers[currentTab] as MedialibraryProvider<MediaWrapper>, position, false)
} else {
MediaUtils.openMedia(activity, item as MediaWrapper)
}
onMainActionClick(v, position, item)
return
}
val i: Intent
@ -475,6 +491,16 @@ class AudioBrowserFragment : BaseAudioBrowser<AudioBrowserViewModel>() {
override fun getCurrentRV() = lists[currentTab]
override fun getDefaultActionMediaType() = when (currentTab) {
0 -> DefaultPlaybackActionMediaType.ARTIST
1 -> DefaultPlaybackActionMediaType.ALBUM
2 -> DefaultPlaybackActionMediaType.TRACK
3 -> DefaultPlaybackActionMediaType.GENRE
else -> DefaultPlaybackActionMediaType.PLAYLIST
}
override fun getCurrentProvider() = viewModel.providers[currentTab] as? MedialibraryProvider<MediaWrapper>
override fun getCurrentAdapter() = adapters[currentTab]
override fun allowedToExpand() = getCurrentRV().scrollState == RecyclerView.SCROLL_STATE_IDLE

24
application/vlc-android/src/org/videolan/vlc/gui/audio/BaseAudioBrowser.kt

@ -75,6 +75,8 @@ import org.videolan.vlc.gui.dialogs.RenameDialog
import org.videolan.vlc.gui.dialogs.SavePlaylistDialog
import org.videolan.vlc.gui.dialogs.showContext
import org.videolan.vlc.gui.helpers.AudioUtil.setRingtone
import org.videolan.vlc.gui.helpers.DefaultPlaybackAction
import org.videolan.vlc.gui.helpers.DefaultPlaybackActionMediaType
import org.videolan.vlc.gui.helpers.INavigator
import org.videolan.vlc.gui.helpers.UiTools
import org.videolan.vlc.gui.helpers.UiTools.addToPlaylist
@ -131,6 +133,20 @@ abstract class BaseAudioBrowser<T : MedialibraryViewModel> : MediaBrowserFragmen
private val tcl = TabLayout.TabLayoutOnPageChangeListener(tabLayout)
protected abstract fun getCurrentRV(): RecyclerView
/**
* Get the default action media type for this fragment
*
* @return the default action media type
*/
protected abstract fun getDefaultActionMediaType(): DefaultPlaybackActionMediaType
/**
* Get the current provider. Useful when the default action is PLAY_ALL
*
* @return the current provider
*/
open fun getCurrentProvider(): MedialibraryProvider<MediaWrapper>? = null
protected var adapter: AudioBrowserAdapter? = null
open fun getCurrentAdapter() = adapter
@ -460,7 +476,13 @@ abstract class BaseAudioBrowser<T : MedialibraryViewModel> : MediaBrowserFragmen
}
override fun onMainActionClick(v: View, position: Int, item: MediaLibraryItem) {
MediaUtils.openList(activity, listOf(*item.tracks), 0)
when(getDefaultActionMediaType().getCurrentPlaybackAction(Settings.getInstance(requireActivity()))) {
DefaultPlaybackAction.PLAY -> MediaUtils.openList(activity, listOf(*item.tracks), 0)
DefaultPlaybackAction.ADD_TO_QUEUE -> MediaUtils.appendMedia(activity, listOf(*item.tracks))
DefaultPlaybackAction.INSERT_NEXT -> MediaUtils.insertNext(activity, listOf(*item.tracks).toTypedArray())
DefaultPlaybackAction.PLAY_ALL -> getCurrentProvider() ?.let { MediaUtils.playAll(activity, it, position, false) }
}
}
override fun onUpdateFinished(adapter: RecyclerView.Adapter<*>) {

52
application/vlc-android/src/org/videolan/vlc/gui/dialogs/DisplaySettingsDialog.kt

@ -48,10 +48,11 @@ import org.videolan.resources.GROUP_VIDEOS_FOLDER
import org.videolan.resources.GROUP_VIDEOS_NAME
import org.videolan.resources.GROUP_VIDEOS_NONE
import org.videolan.tools.setGone
import org.videolan.tools.setVisible
import org.videolan.vlc.R
import org.videolan.vlc.databinding.DialogDisplaySettingsBinding
import org.videolan.vlc.databinding.SortDisplaySettingBinding
import org.videolan.vlc.gui.dialogs.DisplaySettingsDialog.VideoGroup.values
import org.videolan.vlc.gui.helpers.DefaultPlaybackAction
import org.videolan.vlc.gui.helpers.UiTools.showPinIfNeeded
import org.videolan.vlc.viewmodels.DisplaySettingsViewModel
import org.videolan.vlc.viewmodels.mobile.VideoGroupingType
@ -67,6 +68,8 @@ const val CURRENT_SORT = "current_sort"
const val CURRENT_SORT_DESC = "current_sort_desc"
const val SHOW_ONLY_MULTIMEDIA_FILES = "show_only_multimedia_files"
const val SHOW_HIDDEN_FILES = "show_hidden_files"
const val DEFAULT_ACTIONS = "default_actions"
const val DEFAULT_ACTION_TYPE = "default_action_type"
/**
* Dialog showing the display settings for a media list (audio video)
@ -83,6 +86,8 @@ class DisplaySettingsDialog : VLCBottomSheetDialogFragment() {
private var showOnlyMultimediaFiles: Boolean? = null
private var showHiddenFiles: Boolean? = null
private var showVideoGroups: String? = null
private var defaultPlaybackActions: List<DefaultPlaybackAction>? = null
private var defaultActionType: String? = null
private lateinit var binding: DialogDisplaySettingsBinding
@ -90,13 +95,15 @@ class DisplaySettingsDialog : VLCBottomSheetDialogFragment() {
companion object {
fun newInstance(displayInCards: Boolean, showAllArtists: Boolean? = null, onlyFavs: Boolean?, sorts: List<Int>, currentSort: Int, currentSortDesc: Boolean, videoGroup: String? = null, showOnlyMultimediaFiles:Boolean? = null, showHiddenFiles:Boolean? = null): DisplaySettingsDialog {
fun newInstance(displayInCards: Boolean, showAllArtists: Boolean? = null, onlyFavs: Boolean?, sorts: List<Int>, currentSort: Int, currentSortDesc: Boolean, videoGroup: String? = null, showOnlyMultimediaFiles:Boolean? = null, showHiddenFiles:Boolean? = null, defaultPlaybackActions: List<DefaultPlaybackAction>? = null, defaultActionType: String? = null): DisplaySettingsDialog {
return DisplaySettingsDialog().apply {
arguments = bundleOf(DISPLAY_IN_CARDS to displayInCards, SORTS to sorts, CURRENT_SORT to currentSort, CURRENT_SORT_DESC to currentSortDesc, VIDEO_GROUPING to videoGroup)
if (onlyFavs != null) arguments!!.putBoolean(ONLY_FAVS, onlyFavs)
if (showAllArtists != null) arguments!!.putBoolean(SHOW_ALL_ARTISTS, showAllArtists)
if (showOnlyMultimediaFiles != null) arguments!!.putBoolean(SHOW_ONLY_MULTIMEDIA_FILES, showOnlyMultimediaFiles)
if (showHiddenFiles != null) arguments!!.putBoolean(SHOW_HIDDEN_FILES, showHiddenFiles)
if (defaultPlaybackActions != null) arguments!!.putStringArrayList(DEFAULT_ACTIONS, ArrayList(defaultPlaybackActions.map { it.name }))
if(defaultActionType != null) arguments!!.putString(DEFAULT_ACTION_TYPE, defaultActionType)
}
}
}
@ -127,6 +134,12 @@ class DisplaySettingsDialog : VLCBottomSheetDialogFragment() {
showOnlyMultimediaFiles = if (arguments?.containsKey(SHOW_ONLY_MULTIMEDIA_FILES) == true) arguments?.getBoolean(SHOW_ONLY_MULTIMEDIA_FILES) else null
showHiddenFiles = if (arguments?.containsKey(SHOW_HIDDEN_FILES) == true) arguments?.getBoolean(SHOW_HIDDEN_FILES) else null
showVideoGroups = arguments?.getString(VIDEO_GROUPING, null)
val defaultActionsKeys = arguments?.getStringArrayList(DEFAULT_ACTIONS)?.toTypedArray()
defaultPlaybackActions = when(defaultActionsKeys) {
null -> null
else -> DefaultPlaybackAction.entries.filter { defaultActionsKeys.contains(it.name) }
}
defaultActionType = arguments?.getString(DEFAULT_ACTION_TYPE)
}
override fun onCreateView(inflater: LayoutInflater, container: ViewGroup?, savedInstanceState: Bundle?): View {
@ -142,6 +155,7 @@ class DisplaySettingsDialog : VLCBottomSheetDialogFragment() {
updateShowAllFiles()
updateShowHiddenFiles()
updateSorts()
updateDefaultActions()
binding.displayModeGroup.setOnClickListener {
displayInCards = !displayInCards
@ -213,6 +227,26 @@ class DisplaySettingsDialog : VLCBottomSheetDialogFragment() {
override fun onNothingSelected(parent: AdapterView<*>?) {}
}
//Default actions
defaultPlaybackActions?.let {
val defaultActionsArrayAdapter = ArrayAdapter(requireActivity(), android.R.layout.simple_spinner_item, it)
defaultActionsArrayAdapter.setDropDownViewResource(android.R.layout.simple_spinner_dropdown_item)
binding.defaultActionsSpinner.adapter = defaultActionsArrayAdapter
binding.defaultActionsGroup.setOnClickListener {
binding.defaultActionsSpinner.performClick()
}
binding.defaultActionsSpinner.setSelection(it.indexOf(it.find { it.selected }))
binding.defaultActionsSpinner.onItemSelectedListener = object : OnItemSelectedListener {
override fun onItemSelected(parent: AdapterView<*>?, view: View?, position: Int, id: Long) {
val defaultPlaybackAction = defaultActionsArrayAdapter.getItem(position) as DefaultPlaybackAction
lifecycleScope.launch { displaySettingsViewModel.send(DEFAULT_ACTIONS, defaultPlaybackAction) }
}
override fun onNothingSelected(parent: AdapterView<*>?) {}
}
}
}
/**
@ -281,6 +315,20 @@ class DisplaySettingsDialog : VLCBottomSheetDialogFragment() {
} else binding.onlyFavsCheckbox.isChecked = onlyFavs!!
}
/**
* Update the view for the "default actions" item
*
*/
private fun updateDefaultActions() {
if (defaultPlaybackActions == null) {
binding.defaultActionsGroup.setGone()
binding.defaultActionsImage.setGone()
binding.defaultActionsText.setGone()
binding.defaultActionsSpinner.setGone()
}
binding.defaultActionsSubtitle.text = defaultActionType
}
/**
* Update the views for the sort items
*

100
application/vlc-android/src/org/videolan/vlc/gui/helpers/DefaultPlaybackAction.kt

@ -0,0 +1,100 @@
/*
* ************************************************************************
* DefaultAction.kt
* *************************************************************************
* Copyright © 2025 VLC authors and VideoLAN
* Author: Nicolas POMEPUY
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston MA 02110-1301, USA.
* **************************************************************************
*
*
*/
package org.videolan.vlc.gui.helpers
import android.content.SharedPreferences
import androidx.annotation.StringRes
import org.videolan.resources.AppContextProvider
import org.videolan.vlc.R
import org.videolan.vlc.gui.helpers.DefaultPlaybackAction.entries
/**
* Default playback action for items
*
* @property title the action title
* @property selected true if this action is selected
* @constructor Create empty Default action
*/
enum class DefaultPlaybackAction(@StringRes val title: Int, var selected: Boolean = false) {
PLAY(R.string.play), PLAY_ALL(R.string.play_all), ADD_TO_QUEUE(R.string.append), INSERT_NEXT(R.string.insert_next);
override fun toString(): String {
return AppContextProvider.appContext.getString(title)
}
companion object {
/**
* Get entries without play all. Select the given [DefaultPlaybackAction]
*
* @param selection the [DefaultPlaybackAction] to select
*/
fun getEntriesWithoutPlayAll(selection: DefaultPlaybackAction) = entries.filter { it != PLAY_ALL }.map { it.apply { selected = it == selection } }
/**
* Get entries with selection
*
* @param selection the [DefaultPlaybackAction] to select
*/
fun getEntriesWithSelection(selection: DefaultPlaybackAction) = entries.map { it.apply { selected = it == selection } }
}
}
/**
* Default playback action media type
*
* @property title the title of the media type to display in the Display Settings
* @property defaultActionKey the key of the default action in the SharedPreferences
* @property allowPlayAll true if the "Play all" action is allowed for this media type
* @constructor Create empty Default playback action media type
*/
enum class DefaultPlaybackActionMediaType(@StringRes val title: Int, val defaultActionKey: String, val allowPlayAll: Boolean = true) {
VIDEO(R.string.videos, "default_playback_action_video"),
ARTIST(R.string.artists, "default_playback_action_artist", false),
ALBUM(R.string.albums, "default_playback_action_album", false),
TRACK(R.string.tracks, "default_playback_action_track"),
GENRE(R.string.genres, "default_playback_action_genre", false),
PLAYLIST(R.string.playlists, "default_playback_action_playlist", false),
FILE(R.string.files, "default_playback_action_file");
/**
* Get default playback actions for this media type
*
* @param prefs the shared preferences to use
* @return the default playback actions
*/
fun getDefaultPlaybackActions(prefs: SharedPreferences): List<DefaultPlaybackAction> {
return if (allowPlayAll)
DefaultPlaybackAction.getEntriesWithSelection(getCurrentPlaybackAction(prefs))
else
DefaultPlaybackAction.getEntriesWithoutPlayAll(getCurrentPlaybackAction(prefs))
}
/**
* Get current playback action for this media type
*
* @param prefs the shared preferences to use
*/
fun getCurrentPlaybackAction(prefs: SharedPreferences) = DefaultPlaybackAction.valueOf(prefs.getString(defaultActionKey, DefaultPlaybackAction.PLAY.name) ?: DefaultPlaybackAction.PLAY.name)
}
Loading…
Cancel
Save