diff --git a/app/src/main/java/org/oxycblt/auxio/music/locations/MusicSourcesDialog.kt b/app/src/main/java/org/oxycblt/auxio/music/locations/MusicSourcesDialog.kt index 74d3ec0ed..b88ee9501 100644 --- a/app/src/main/java/org/oxycblt/auxio/music/locations/MusicSourcesDialog.kt +++ b/app/src/main/java/org/oxycblt/auxio/music/locations/MusicSourcesDialog.kt @@ -27,6 +27,7 @@ import androidx.activity.result.contract.ActivityResultContracts import androidx.appcompat.app.AlertDialog import androidx.core.view.ViewCompat import androidx.core.view.isVisible +import androidx.recyclerview.widget.ConcatAdapter import dagger.hilt.android.AndroidEntryPoint import javax.inject.Inject import org.oxycblt.auxio.BuildConfig @@ -45,8 +46,9 @@ import timber.log.Timber as L */ @AndroidEntryPoint class MusicSourcesDialog : - ViewBindingMaterialDialogFragment(), LocationAdapter.Listener { + ViewBindingMaterialDialogFragment(), LocationAdapter.Listener, NewLocationFooterAdapter.Listener { private val locationAdapter = LocationAdapter(this) + private val locationFooterAdapter = NewLocationFooterAdapter(this) private var openDocumentTreeLauncher: ActivityResultLauncher? = null @Inject lateinit var musicSettings: MusicSettings @@ -71,26 +73,8 @@ class MusicSourcesDialog : registerForActivityResult( ActivityResultContracts.OpenDocumentTree(), ::addDocumentTreeUriToDirs) - binding.locationsAdd.apply { - ViewCompat.setTooltipText(this, contentDescription) - setOnClickListener { - L.d("Opening launcher") - val launcher = - requireNotNull(openDocumentTreeLauncher) { - "Document tree launcher was not available" - } - - try { - launcher.launch(null) - } catch (e: ActivityNotFoundException) { - // User doesn't have a capable file manager. - requireContext().showToast(R.string.err_no_app) - } - } - } - binding.locationsRecycler.apply { - adapter = locationAdapter + adapter = ConcatAdapter(locationAdapter, locationFooterAdapter) itemAnimator = null } @@ -100,7 +84,6 @@ class MusicSourcesDialog : } ?: musicSettings.musicLocations locationAdapter.addAll(locations) - requireBinding().locationsEmpty.isVisible = locations.isEmpty() } override fun onSaveInstanceState(outState: Bundle) { @@ -117,7 +100,21 @@ class MusicSourcesDialog : override fun onRemoveLocation(location: MusicLocation) { locationAdapter.remove(location) - requireBinding().locationsEmpty.isVisible = locationAdapter.locations.isEmpty() + } + + override fun onNewLocation() { + L.d("Opening launcher") + val launcher = + requireNotNull(openDocumentTreeLauncher) { + "Document tree launcher was not available" + } + + try { + launcher.launch(null) + } catch (e: ActivityNotFoundException) { + // User doesn't have a capable file manager. + requireContext().showToast(R.string.err_no_app) + } } /** @@ -136,7 +133,6 @@ class MusicSourcesDialog : if (location != null) { locationAdapter.add(location) - requireBinding().locationsEmpty.isVisible = false } else { requireContext().showToast(R.string.err_bad_location) } diff --git a/app/src/main/java/org/oxycblt/auxio/music/locations/NewLocationFooterAdapter.kt b/app/src/main/java/org/oxycblt/auxio/music/locations/NewLocationFooterAdapter.kt new file mode 100644 index 000000000..522cdec22 --- /dev/null +++ b/app/src/main/java/org/oxycblt/auxio/music/locations/NewLocationFooterAdapter.kt @@ -0,0 +1,67 @@ +package org.oxycblt.auxio.music.locations + +import android.view.View +import android.view.ViewGroup +import androidx.recyclerview.widget.RecyclerView +import org.oxycblt.auxio.databinding.ItemNewMusicLocationBinding +import org.oxycblt.auxio.databinding.ItemNewPlaylistChoiceBinding +import org.oxycblt.auxio.list.recycler.DialogRecyclerView +import org.oxycblt.auxio.music.decision.AddToPlaylistDialog +import org.oxycblt.auxio.util.inflater + +/** + * A purely-visual [RecyclerView.Adapter] that acts as a footer providing a "New Playlist" choice in + * [AddToPlaylistDialog]. + * + * @author Alexander Capehart (OxygenCobalt) + */ +class NewLocationFooterAdapter(private val listener: Listener) : + RecyclerView.Adapter() { + override fun getItemCount() = 1 + + override fun onCreateViewHolder(parent: ViewGroup, viewType: Int) = + NewLocationFooterViewHolder.from(parent) + + override fun onBindViewHolder(holder: NewLocationFooterViewHolder, position: Int) { + holder.bind(listener) + } + + /** A listener for [NewLocationFooterAdapter] interactions. */ + interface Listener { + /** + * Called when the footer has been pressed, requesting to create a new location. + */ + fun onNewLocation() + } +} + +/** + * A [RecyclerView.ViewHolder] that displays a "New Playlist" choice in [NewPlaylistFooterAdapter]. + * Use [from] to create an instance. + * + * @author Alexander Capehart (OxygenCobalt) + */ +class NewLocationFooterViewHolder +private constructor(private val binding: ItemNewMusicLocationBinding) : + DialogRecyclerView.ViewHolder(binding.root) { + /** + * Bind new data to this instance. + * + * @param listener A [NewLocationFooterAdapter.Listener] to bind interactions to. + */ + fun bind(listener: NewLocationFooterAdapter.Listener) { + binding.root.setOnClickListener { listener.onNewLocation() } + } + + companion object { + /** + * Create a new instance. + * + * @param parent The parent to inflate this instance from. + * @return A new instance. + */ + fun from(parent: View) = + NewLocationFooterViewHolder( + ItemNewMusicLocationBinding.inflate(parent.context.inflater)) + } +} diff --git a/app/src/main/res/layout/dialog_music_locations.xml b/app/src/main/res/layout/dialog_music_locations.xml index 0792b51c0..8f015dec3 100644 --- a/app/src/main/res/layout/dialog_music_locations.xml +++ b/app/src/main/res/layout/dialog_music_locations.xml @@ -1,65 +1,19 @@ - + android:layout_height="match_parent"> - + android:layout_height="match_parent" + android:layout_gravity="center" + android:clipToPadding="false" + android:overScrollMode="never" + app:layout_constraintTop_toBottomOf="@+id/locations_list_header" + tools:listitem="@layout/item_music_location" /> - - - - - - - - - - - - \ No newline at end of file + \ No newline at end of file diff --git a/app/src/main/res/layout/item_new_music_location.xml b/app/src/main/res/layout/item_new_music_location.xml new file mode 100644 index 000000000..2fd5338ed --- /dev/null +++ b/app/src/main/res/layout/item_new_music_location.xml @@ -0,0 +1,17 @@ + + diff --git a/app/src/main/res/values/strings.xml b/app/src/main/res/values/strings.xml index 9c1a1875f..3ce5321cc 100644 --- a/app/src/main/res/values/strings.xml +++ b/app/src/main/res/values/strings.xml @@ -314,6 +314,7 @@ Music folders Manage where music should be loaded from Folders + New folder Refresh music Reload the music library, using cached tags when possible