mirror of
https://gitlab.com/ultrasonic/ultrasonic.git
synced 2025-05-16 15:26:35 +03:00
loads music folder list
Signed-off-by: James Wells <james@jameswells.net>
This commit is contained in:
parent
580fc1aa89
commit
f00a487b51
@ -76,7 +76,7 @@ public class CachedMusicService implements MusicService
|
||||
private final TimeLimitedCache<List<Genre>> cachedGenres = new TimeLimitedCache<>(10 * 3600, TimeUnit.SECONDS);
|
||||
|
||||
private String restUrl;
|
||||
private String musicFolderId;
|
||||
private String cachedMusicFolderId;
|
||||
|
||||
public CachedMusicService(MusicService musicService)
|
||||
{
|
||||
@ -372,7 +372,7 @@ public class CachedMusicService implements MusicService
|
||||
{
|
||||
String newUrl = activeServerProvider.getValue().getRestUrl(null);
|
||||
String newFolderId = activeServerProvider.getValue().getActiveServer().getMusicFolderId();
|
||||
if (!Util.equals(newUrl, restUrl) || !Util.equals(musicFolderId,newFolderId))
|
||||
if (!Util.equals(newUrl, restUrl) || !Util.equals(cachedMusicFolderId,newFolderId))
|
||||
{
|
||||
cachedMusicFolders.clear();
|
||||
cachedMusicDirectories.clear();
|
||||
@ -384,7 +384,7 @@ public class CachedMusicService implements MusicService
|
||||
cachedArtist.clear();
|
||||
cachedUserInfo.clear();
|
||||
restUrl = newUrl;
|
||||
musicFolderId = newFolderId;
|
||||
cachedMusicFolderId = newFolderId;
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -43,7 +43,6 @@ import org.moire.ultrasonic.view.SelectMusicFolderView
|
||||
*/
|
||||
class ArtistRowAdapter(
|
||||
private var artistList: List<Artist>,
|
||||
private var folderName: String,
|
||||
private var selectFolderHeader: SelectMusicFolderView?,
|
||||
val onArtistClick: (Artist) -> Unit,
|
||||
val onContextMenuClick: (MenuItem, Artist) -> Boolean,
|
||||
@ -58,14 +57,6 @@ class ArtistRowAdapter(
|
||||
notifyDataSetChanged()
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the name of the folder to be displayed n the Header (first) row
|
||||
*/
|
||||
fun setFolderName(name: String) {
|
||||
folderName = name
|
||||
notifyDataSetChanged()
|
||||
}
|
||||
|
||||
/**
|
||||
* Holds the view properties of an Artist row
|
||||
*/
|
||||
|
@ -1,6 +1,8 @@
|
||||
package org.moire.ultrasonic.fragment
|
||||
|
||||
import android.os.Bundle
|
||||
import android.os.Handler
|
||||
import android.os.Looper
|
||||
import android.view.ContextMenu
|
||||
import android.view.ContextMenu.ContextMenuInfo
|
||||
import android.view.LayoutInflater
|
||||
@ -16,6 +18,9 @@ import android.widget.ImageView
|
||||
import android.widget.ListView
|
||||
import android.widget.TextView
|
||||
import androidx.fragment.app.Fragment
|
||||
import androidx.lifecycle.MutableLiveData
|
||||
import androidx.lifecycle.Observer
|
||||
import androidx.lifecycle.viewModelScope
|
||||
import androidx.navigation.Navigation
|
||||
import androidx.swiperefreshlayout.widget.SwipeRefreshLayout
|
||||
import androidx.swiperefreshlayout.widget.SwipeRefreshLayout.OnRefreshListener
|
||||
@ -23,6 +28,9 @@ import java.security.SecureRandom
|
||||
import java.util.Collections
|
||||
import java.util.LinkedList
|
||||
import java.util.Random
|
||||
import kotlinx.coroutines.Dispatchers
|
||||
import kotlinx.coroutines.launch
|
||||
import kotlinx.coroutines.withContext
|
||||
import org.koin.android.ext.android.inject
|
||||
import org.koin.android.viewmodel.ext.android.viewModel
|
||||
import org.moire.ultrasonic.R
|
||||
@ -30,8 +38,10 @@ import org.moire.ultrasonic.api.subsonic.models.AlbumListType
|
||||
import org.moire.ultrasonic.data.ActiveServerProvider
|
||||
import org.moire.ultrasonic.data.ActiveServerProvider.Companion.isOffline
|
||||
import org.moire.ultrasonic.domain.MusicDirectory
|
||||
import org.moire.ultrasonic.domain.MusicFolder
|
||||
import org.moire.ultrasonic.fragment.FragmentTitle.Companion.getTitle
|
||||
import org.moire.ultrasonic.fragment.FragmentTitle.Companion.setTitle
|
||||
import org.moire.ultrasonic.service.CommunicationErrorHandler
|
||||
import org.moire.ultrasonic.service.MediaPlayerController
|
||||
import org.moire.ultrasonic.service.MusicService
|
||||
import org.moire.ultrasonic.service.MusicServiceFactory
|
||||
@ -81,6 +91,7 @@ class SelectAlbumFragment : Fragment() {
|
||||
private var showHeader = true
|
||||
private var showSelectFolderHeader = false
|
||||
private val random: Random = SecureRandom()
|
||||
private val musicFolders: MutableLiveData<List<MusicFolder>> = MutableLiveData()
|
||||
|
||||
private val mediaPlayerController: MediaPlayerController by inject()
|
||||
private val videoPlayer: VideoPlayer by inject()
|
||||
@ -128,11 +139,7 @@ class SelectAlbumFragment : Fragment() {
|
||||
|
||||
selectFolderHeader = SelectMusicFolderView(
|
||||
requireContext(), albumListView!!,
|
||||
MusicServiceFactory.getMusicService(requireContext()).getMusicFolders(
|
||||
false, requireContext()
|
||||
),
|
||||
activeServerProvider.getActiveServer().musicFolderId,
|
||||
{ _, selectedFolderId ->
|
||||
{ selectedFolderId ->
|
||||
if (!ActiveServerProvider.isOffline(context)) {
|
||||
val currentSetting = activeServerProvider.getActiveServer()
|
||||
currentSetting.musicFolderId = selectedFolderId
|
||||
@ -141,6 +148,17 @@ class SelectAlbumFragment : Fragment() {
|
||||
this.updateDisplay(true)
|
||||
}
|
||||
)
|
||||
musicFolders.observe(
|
||||
viewLifecycleOwner,
|
||||
Observer { changedFolders ->
|
||||
if (changedFolders != null) {
|
||||
selectFolderHeader!!.setData(
|
||||
activeServerProvider.getActiveServer().musicFolderId,
|
||||
changedFolders
|
||||
)
|
||||
}
|
||||
}
|
||||
)
|
||||
|
||||
albumListView!!.setChoiceMode(ListView.CHOICE_MODE_MULTIPLE)
|
||||
albumListView!!.setOnItemClickListener(
|
||||
@ -294,6 +312,8 @@ class SelectAlbumFragment : Fragment() {
|
||||
Constants.INTENT_EXTRA_NAME_ALBUM_LIST_OFFSET, 0
|
||||
)
|
||||
|
||||
backgroundLoadMusicFolders(refresh)
|
||||
|
||||
if (playlistId != null) {
|
||||
getPlaylist(playlistId, playlistName)
|
||||
} else if (podcastChannelId != null) {
|
||||
@ -323,6 +343,29 @@ class SelectAlbumFragment : Fragment() {
|
||||
}
|
||||
}
|
||||
|
||||
private fun backgroundLoadMusicFolders(refresh: Boolean) {
|
||||
serverSettingsModel.viewModelScope.launch {
|
||||
refreshAlbumListView!!.isRefreshing = true
|
||||
loadMusicFolders(refresh)
|
||||
refreshAlbumListView!!.isRefreshing = false
|
||||
}
|
||||
}
|
||||
|
||||
private suspend fun loadMusicFolders(refresh: Boolean) {
|
||||
withContext(Dispatchers.IO) {
|
||||
if (!isOffline(context)) {
|
||||
val musicService = MusicServiceFactory.getMusicService(requireContext())
|
||||
try {
|
||||
musicFolders.postValue(musicService.getMusicFolders(refresh, context))
|
||||
} catch (exception: Exception) {
|
||||
Handler(Looper.getMainLooper()).post {
|
||||
CommunicationErrorHandler.handleError(exception, requireContext())
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
override fun onCreateContextMenu(menu: ContextMenu, view: View, menuInfo: ContextMenuInfo?) {
|
||||
super.onCreateContextMenu(menu, view, menuInfo)
|
||||
val info = menuInfo as AdapterContextMenuInfo?
|
||||
|
@ -16,9 +16,7 @@ import org.koin.android.viewmodel.ext.android.viewModel
|
||||
import org.moire.ultrasonic.R
|
||||
import org.moire.ultrasonic.data.ActiveServerProvider
|
||||
import org.moire.ultrasonic.domain.Artist
|
||||
import org.moire.ultrasonic.domain.MusicFolder
|
||||
import org.moire.ultrasonic.fragment.FragmentTitle.Companion.setTitle
|
||||
import org.moire.ultrasonic.service.MusicServiceFactory
|
||||
import org.moire.ultrasonic.subsonic.DownloadHandler
|
||||
import org.moire.ultrasonic.subsonic.ImageLoaderProvider
|
||||
import org.moire.ultrasonic.util.Constants
|
||||
@ -37,7 +35,6 @@ class SelectArtistFragment : Fragment() {
|
||||
|
||||
private var refreshArtistListView: SwipeRefreshLayout? = null
|
||||
private var artistListView: RecyclerView? = null
|
||||
private var musicFolders: List<MusicFolder>? = null
|
||||
private lateinit var viewManager: RecyclerView.LayoutManager
|
||||
private lateinit var viewAdapter: ArtistRowAdapter
|
||||
private var selectFolderHeader: SelectMusicFolderView? = null
|
||||
@ -67,17 +64,13 @@ class SelectArtistFragment : Fragment() {
|
||||
) {
|
||||
selectFolderHeader = SelectMusicFolderView(
|
||||
requireContext(), view as ViewGroup,
|
||||
MusicServiceFactory.getMusicService(requireContext()).getMusicFolders(
|
||||
false, requireContext()
|
||||
),
|
||||
activeServerProvider.getActiveServer().musicFolderId,
|
||||
{ musicFolderName, selectedFolderId ->
|
||||
{ selectedFolderId ->
|
||||
if (!ActiveServerProvider.isOffline(context)) {
|
||||
val currentSetting = activeServerProvider.getActiveServer()
|
||||
currentSetting.musicFolderId = selectedFolderId
|
||||
serverSettingsModel.updateItem(currentSetting)
|
||||
}
|
||||
viewAdapter.setFolderName(musicFolderName)
|
||||
viewAdapter.notifyDataSetChanged()
|
||||
artistListModel.refresh(refreshArtistListView!!)
|
||||
}
|
||||
)
|
||||
@ -96,8 +89,6 @@ class SelectArtistFragment : Fragment() {
|
||||
setTitle(this, title)
|
||||
}
|
||||
|
||||
musicFolders = null
|
||||
|
||||
val refresh = arguments?.getBoolean(Constants.INTENT_EXTRA_NAME_REFRESH) ?: false
|
||||
|
||||
artistListModel.getMusicFolders()
|
||||
@ -105,8 +96,11 @@ class SelectArtistFragment : Fragment() {
|
||||
viewLifecycleOwner,
|
||||
Observer { changedFolders ->
|
||||
if (changedFolders != null) {
|
||||
musicFolders = changedFolders
|
||||
viewAdapter.setFolderName(getMusicFolderName(changedFolders))
|
||||
viewAdapter.notifyDataSetChanged()
|
||||
selectFolderHeader!!.setData(
|
||||
activeServerProvider.getActiveServer().musicFolderId,
|
||||
changedFolders
|
||||
)
|
||||
}
|
||||
}
|
||||
)
|
||||
@ -119,7 +113,6 @@ class SelectArtistFragment : Fragment() {
|
||||
viewManager = LinearLayoutManager(this.context)
|
||||
viewAdapter = ArtistRowAdapter(
|
||||
artists.value ?: listOf(),
|
||||
getText(R.string.select_artist_all_folders).toString(),
|
||||
selectFolderHeader,
|
||||
{ artist -> onItemClick(artist) },
|
||||
{ menuItem, artist -> onArtistMenuItemSelected(menuItem, artist) },
|
||||
@ -134,18 +127,6 @@ class SelectArtistFragment : Fragment() {
|
||||
super.onViewCreated(view, savedInstanceState)
|
||||
}
|
||||
|
||||
private fun getMusicFolderName(musicFolders: List<MusicFolder>): String {
|
||||
val musicFolderId = activeServerProvider.getActiveServer().musicFolderId
|
||||
if (musicFolderId != null && musicFolderId != "") {
|
||||
for ((id, name) in musicFolders) {
|
||||
if (id == musicFolderId) {
|
||||
return name
|
||||
}
|
||||
}
|
||||
}
|
||||
return getText(R.string.select_artist_all_folders).toString()
|
||||
}
|
||||
|
||||
private fun onItemClick(artist: Artist) {
|
||||
val bundle = Bundle()
|
||||
bundle.putString(Constants.INTENT_EXTRA_NAME_ID, artist.id)
|
||||
|
@ -114,7 +114,9 @@ open class RESTMusicService(
|
||||
refresh: Boolean,
|
||||
context: Context
|
||||
): Indexes {
|
||||
val cachedIndexes = fileStorage.load(INDEXES_STORAGE_NAME, getIndexesSerializer())
|
||||
val indexName = INDEXES_STORAGE_NAME + (musicFolderId ?: "")
|
||||
|
||||
val cachedIndexes = fileStorage.load(indexName, getIndexesSerializer())
|
||||
if (cachedIndexes != null && !refresh) return cachedIndexes
|
||||
|
||||
val response = responseChecker.callWithResponseCheck { api ->
|
||||
@ -122,7 +124,7 @@ open class RESTMusicService(
|
||||
}
|
||||
|
||||
val indexes = response.body()!!.indexes.toDomainEntity()
|
||||
fileStorage.store(INDEXES_STORAGE_NAME, indexes, getIndexesSerializer())
|
||||
fileStorage.store(indexName, indexes, getIndexesSerializer())
|
||||
return indexes
|
||||
}
|
||||
|
||||
@ -938,6 +940,7 @@ open class RESTMusicService(
|
||||
companion object {
|
||||
private const val MUSIC_FOLDER_STORAGE_NAME = "music_folder"
|
||||
private const val INDEXES_STORAGE_NAME = "indexes"
|
||||
private const val INDEXES_FOLDER_STORAGE_NAME = "indexes_folder"
|
||||
private const val ARTISTS_STORAGE_NAME = "artists"
|
||||
}
|
||||
}
|
||||
|
@ -19,19 +19,26 @@ import org.moire.ultrasonic.domain.MusicFolder
|
||||
class SelectMusicFolderView(
|
||||
private val context: Context,
|
||||
root: ViewGroup,
|
||||
private val musicFolders: List<MusicFolder>,
|
||||
private var selectedFolderId: String?,
|
||||
private val onUpdate: (String, String?) -> Unit
|
||||
private val onUpdate: (String?) -> Unit
|
||||
) : RecyclerView.ViewHolder(
|
||||
LayoutInflater.from(context).inflate(
|
||||
R.layout.select_folder_header, root, false
|
||||
)
|
||||
) {
|
||||
private var musicFolders: List<MusicFolder> = mutableListOf<MusicFolder>()
|
||||
private var selectedFolderId: String? = null
|
||||
private val folderName: TextView = itemView.findViewById(R.id.select_folder_name)
|
||||
private val layout: LinearLayout = itemView.findViewById(R.id.select_folder_header)
|
||||
private val MENU_GROUP_MUSIC_FOLDER = 10
|
||||
|
||||
init {
|
||||
folderName.text = context.getString(R.string.select_artist_all_folders)
|
||||
layout.setOnClickListener { onFolderClick() }
|
||||
}
|
||||
|
||||
fun setData(selectedId: String?, folders: List<MusicFolder>) {
|
||||
selectedFolderId = selectedId
|
||||
musicFolders = folders
|
||||
if (selectedFolderId != null) {
|
||||
for ((id, name) in musicFolders) {
|
||||
if (id == selectedFolderId) {
|
||||
@ -42,7 +49,6 @@ class SelectMusicFolderView(
|
||||
} else {
|
||||
folderName.text = context.getString(R.string.select_artist_all_folders)
|
||||
}
|
||||
layout.setOnClickListener { onFolderClick() }
|
||||
}
|
||||
|
||||
private fun onFolderClick() {
|
||||
@ -76,7 +82,7 @@ class SelectMusicFolderView(
|
||||
|
||||
menuItem.isChecked = true
|
||||
folderName.text = musicFolderName
|
||||
onUpdate(musicFolderName, selectedFolderId)
|
||||
onUpdate(selectedFolderId)
|
||||
|
||||
return true
|
||||
}
|
||||
|
Loading…
x
Reference in New Issue
Block a user