Browse Source

Merge branch 'feature/50-display-if-album-is-available-offline' into 'develop'

#50 - Display if whole album is downloaded or cached

Closes #50

See merge request funkwhale/funkwhale-android!37
housekeeping/remove-warnings
Ryan Harg 3 years ago
parent
commit
1b6251259e
  1. 68
      app/src/main/java/audio/funkwhale/ffa/fragments/TracksFragment.kt
  2. 395
      app/src/main/res/layout/fragment_tracks.xml

68
app/src/main/java/audio/funkwhale/ffa/fragments/TracksFragment.kt

@ -1,5 +1,7 @@ @@ -1,5 +1,7 @@
package audio.funkwhale.ffa.fragments
import android.graphics.PorterDuff
import android.graphics.PorterDuffColorFilter
import android.os.Bundle
import android.view.Gravity
import android.view.View
@ -12,12 +14,31 @@ import audio.funkwhale.ffa.adapters.TracksAdapter @@ -12,12 +14,31 @@ import audio.funkwhale.ffa.adapters.TracksAdapter
import audio.funkwhale.ffa.repositories.FavoritedRepository
import audio.funkwhale.ffa.repositories.FavoritesRepository
import audio.funkwhale.ffa.repositories.TracksRepository
import audio.funkwhale.ffa.utils.*
import audio.funkwhale.ffa.utils.Album
import audio.funkwhale.ffa.utils.Command
import audio.funkwhale.ffa.utils.CommandBus
import audio.funkwhale.ffa.utils.Event
import audio.funkwhale.ffa.utils.EventBus
import audio.funkwhale.ffa.utils.Request
import audio.funkwhale.ffa.utils.RequestBus
import audio.funkwhale.ffa.utils.Response
import audio.funkwhale.ffa.utils.Track
import audio.funkwhale.ffa.utils.getMetadata
import audio.funkwhale.ffa.utils.maybeLoad
import audio.funkwhale.ffa.utils.maybeNormalizeUrl
import audio.funkwhale.ffa.utils.toast
import audio.funkwhale.ffa.utils.wait
import com.google.android.exoplayer2.offline.Download
import com.preference.PowerPreference
import com.squareup.picasso.Picasso
import jp.wasabeef.picasso.transformations.RoundedCornersTransformation
import kotlinx.android.synthetic.main.fragment_tracks.*
import kotlinx.android.synthetic.main.fragment_tracks.actions
import kotlinx.android.synthetic.main.fragment_tracks.artist
import kotlinx.android.synthetic.main.fragment_tracks.cover
import kotlinx.android.synthetic.main.fragment_tracks.play
import kotlinx.android.synthetic.main.fragment_tracks.scroller
import kotlinx.android.synthetic.main.fragment_tracks.title
import kotlinx.android.synthetic.main.fragment_tracks.tracks
import kotlinx.coroutines.Dispatchers.IO
import kotlinx.coroutines.Dispatchers.Main
import kotlinx.coroutines.flow.collect
@ -67,6 +88,35 @@ class TracksFragment : OtterFragment<Track, TracksAdapter>() { @@ -67,6 +88,35 @@ class TracksFragment : OtterFragment<Track, TracksAdapter>() {
watchEventBus()
}
override fun onDataFetched(data: List<Track>) {
when {
data.all { it.downloaded } -> {
title.setCompoundDrawablesWithIntrinsicBounds(R.drawable.downloaded, 0, 0, 0)
title.compoundDrawables.forEach {
it?.colorFilter =
PorterDuffColorFilter(
requireContext().getColor(R.color.downloaded),
PorterDuff.Mode.SRC_IN
)
}
}
data.all { it.cached } -> {
title.setCompoundDrawablesWithIntrinsicBounds(R.drawable.downloaded, 0, 0, 0)
title.compoundDrawables.forEach {
it?.colorFilter =
PorterDuffColorFilter(
requireContext().getColor(R.color.cached),
PorterDuff.Mode.SRC_IN
)
}
}
else -> {
title.setCompoundDrawablesWithIntrinsicBounds(0, 0, 0, 0)
}
}
}
override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
super.onViewCreated(view, savedInstanceState)
@ -136,7 +186,8 @@ class TracksFragment : OtterFragment<Track, TracksAdapter>() { @@ -136,7 +186,8 @@ class TracksFragment : OtterFragment<Track, TracksAdapter>() {
setOnMenuItemClickListener {
when (it.itemId) {
R.id.play_secondary -> when (PowerPreference.getDefaultFile().getString("play_order")) {
R.id.play_secondary -> when (PowerPreference.getDefaultFile()
.getString("play_order")) {
"in_order" -> CommandBus.send(Command.ReplaceQueue(adapter.data.shuffled()))
else -> CommandBus.send(Command.ReplaceQueue(adapter.data))
}
@ -196,12 +247,13 @@ class TracksFragment : OtterFragment<Track, TracksAdapter>() { @@ -196,12 +247,13 @@ class TracksFragment : OtterFragment<Track, TracksAdapter>() {
private suspend fun refreshDownloadedTrack(download: Download) {
if (download.state == Download.STATE_COMPLETED) {
download.getMetadata()?.let { info ->
adapter.data.withIndex().associate { it.value to it.index }.filter { it.key.id == info.id }.toList().getOrNull(0)?.let { match ->
withContext(Main) {
adapter.data[match.second].downloaded = true
adapter.notifyItemChanged(match.second)
adapter.data.withIndex().associate { it.value to it.index }.filter { it.key.id == info.id }
.toList().getOrNull(0)?.let { match ->
withContext(Main) {
adapter.data[match.second].downloaded = true
adapter.notifyItemChanged(match.second)
}
}
}
}
}
}

395
app/src/main/res/layout/fragment_tracks.xml

@ -1,214 +1,217 @@ @@ -1,214 +1,217 @@
<?xml version="1.0" encoding="utf-8"?>
<androidx.swiperefreshlayout.widget.SwipeRefreshLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools"
android:id="@+id/swiper"
style="@style/AppTheme.Fragment"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:background="?attr/colorSurface"
android:clipChildren="false"
android:clipToPadding="false"
android:transitionGroup="true">
<androidx.core.widget.NestedScrollView
android:id="@+id/scroller"
xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools"
android:id="@+id/swiper"
style="@style/AppTheme.Fragment"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:fillViewport="true">
android:background="?attr/colorSurface"
android:clipChildren="false"
android:clipToPadding="false"
android:transitionGroup="true">
<LinearLayout
android:layout_width="match_parent"
android:layout_height="match_parent"
android:clipChildren="false"
android:clipToPadding="false"
android:orientation="vertical">
<com.google.android.material.card.MaterialCardView
<androidx.core.widget.NestedScrollView
android:id="@+id/scroller"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:background="?attr/colorSurface"
android:elevation="1dp">
android:layout_height="match_parent"
android:fillViewport="true">
<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:orientation="vertical">
<androidx.constraintlayout.widget.ConstraintLayout
android:layout_width="match_parent"
android:layout_height="wrap_content">
<ImageView
android:id="@+id/cover"
android:layout_width="match_parent"
android:layout_height="250dp"
android:layout_margin="8dp"
android:contentDescription="@string/alt_album_cover"
android:scaleType="centerCrop"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent"
app:layout_constraintVertical_bias="0"
tools:src="@tools:sample/avatars"
tools:visibility="invisible" />
<androidx.constraintlayout.widget.ConstraintLayout
android:id="@+id/covers"
android:layout_width="match_parent"
android:layout_height="250dp"
android:layout_margin="8dp"
android:visibility="gone"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent"
app:layout_constraintVertical_bias="0"
tools:visibility="visible">
<androidx.constraintlayout.widget.Guideline
android:id="@+id/horizontal"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:orientation="vertical"
app:layout_constraintGuide_percent=".50" />
android:layout_height="match_parent"
android:clipChildren="false"
android:clipToPadding="false"
android:orientation="vertical">
<androidx.constraintlayout.widget.Guideline
android:id="@+id/vertical"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:orientation="horizontal"
app:layout_constraintGuide_percent=".50" />
<audio.funkwhale.ffa.views.SquareImageView
android:id="@+id/cover_top_left"
android:layout_width="0dp"
android:layout_height="0dp"
android:scaleType="centerCrop"
android:src="@drawable/cover"
app:layout_constraintBottom_toBottomOf="@id/vertical"
app:layout_constraintLeft_toLeftOf="parent"
app:layout_constraintRight_toRightOf="@id/horizontal"
app:layout_constraintTop_toTopOf="parent"
tools:src="@tools:sample/avatars" />
<audio.funkwhale.ffa.views.SquareImageView
android:id="@+id/cover_top_right"
android:layout_width="0dp"
android:layout_height="0dp"
android:scaleType="centerCrop"
android:src="@drawable/cover"
app:layout_constraintBottom_toBottomOf="@id/vertical"
app:layout_constraintLeft_toLeftOf="@id/horizontal"
app:layout_constraintRight_toRightOf="parent"
app:layout_constraintTop_toTopOf="parent"
tools:src="@tools:sample/avatars" />
<audio.funkwhale.ffa.views.SquareImageView
android:id="@+id/cover_bottom_left"
android:layout_width="0dp"
android:layout_height="0dp"
android:scaleType="centerCrop"
android:src="@drawable/cover"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintLeft_toLeftOf="parent"
app:layout_constraintRight_toRightOf="@id/horizontal"
app:layout_constraintTop_toTopOf="@id/vertical"
tools:src="@tools:sample/avatars" />
<audio.funkwhale.ffa.views.SquareImageView
android:id="@+id/cover_bottom_right"
android:layout_width="0dp"
android:layout_height="0dp"
android:scaleType="centerCrop"
android:src="@drawable/cover"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintLeft_toLeftOf="@id/horizontal"
app:layout_constraintRight_toRightOf="parent"
app:layout_constraintTop_toTopOf="@id/vertical"
tools:src="@tools:sample/avatars" />
</androidx.constraintlayout.widget.ConstraintLayout>
<com.google.android.material.button.MaterialButton
android:id="@+id/play"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:backgroundTint="@color/colorPrimary"
android:paddingHorizontal="16dp"
android:paddingVertical="8dp"
android:text="@string/playback_shuffle"
android:textColor="@android:color/white"
app:icon="@drawable/play"
app:iconTint="@android:color/white"
app:layout_constraintBottom_toBottomOf="@id/cover"
app:layout_constraintLeft_toLeftOf="@id/cover"
app:layout_constraintRight_toRightOf="@id/cover"
app:layout_constraintTop_toBottomOf="@id/cover"
app:rippleColor="@color/ripple" />
</androidx.constraintlayout.widget.ConstraintLayout>
<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:gravity="center_vertical"
android:orientation="horizontal">
<LinearLayout
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_weight="1"
android:orientation="vertical">
<TextView
android:id="@+id/artist"
<com.google.android.material.card.MaterialCardView
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginStart="16dp"
android:layout_marginTop="16dp"
android:layout_marginEnd="16dp"
android:textAllCaps="true"
android:textSize="14sp"
tools:text="Muse" />
<TextView
android:id="@+id/title"
style="@style/AppTheme.Title"
android:background="?attr/colorSurface"
android:elevation="1dp">
<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:orientation="vertical">
<androidx.constraintlayout.widget.ConstraintLayout
android:layout_width="match_parent"
android:layout_height="wrap_content">
<ImageView
android:id="@+id/cover"
android:layout_width="match_parent"
android:layout_height="250dp"
android:layout_margin="8dp"
android:contentDescription="@string/alt_album_cover"
android:scaleType="centerCrop"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent"
app:layout_constraintVertical_bias="0"
tools:src="@tools:sample/avatars"
tools:visibility="invisible" />
<androidx.constraintlayout.widget.ConstraintLayout
android:id="@+id/covers"
android:layout_width="match_parent"
android:layout_height="250dp"
android:layout_margin="8dp"
android:visibility="gone"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent"
app:layout_constraintVertical_bias="0"
tools:visibility="visible">
<androidx.constraintlayout.widget.Guideline
android:id="@+id/horizontal"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:orientation="vertical"
app:layout_constraintGuide_percent=".50" />
<androidx.constraintlayout.widget.Guideline
android:id="@+id/vertical"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:orientation="horizontal"
app:layout_constraintGuide_percent=".50" />
<audio.funkwhale.ffa.views.SquareImageView
android:id="@+id/cover_top_left"
android:layout_width="0dp"
android:layout_height="0dp"
android:scaleType="centerCrop"
android:src="@drawable/cover"
app:layout_constraintBottom_toBottomOf="@id/vertical"
app:layout_constraintLeft_toLeftOf="parent"
app:layout_constraintRight_toRightOf="@id/horizontal"
app:layout_constraintTop_toTopOf="parent"
tools:src="@tools:sample/avatars" />
<audio.funkwhale.ffa.views.SquareImageView
android:id="@+id/cover_top_right"
android:layout_width="0dp"
android:layout_height="0dp"
android:scaleType="centerCrop"
android:src="@drawable/cover"
app:layout_constraintBottom_toBottomOf="@id/vertical"
app:layout_constraintLeft_toLeftOf="@id/horizontal"
app:layout_constraintRight_toRightOf="parent"
app:layout_constraintTop_toTopOf="parent"
tools:src="@tools:sample/avatars" />
<audio.funkwhale.ffa.views.SquareImageView
android:id="@+id/cover_bottom_left"
android:layout_width="0dp"
android:layout_height="0dp"
android:scaleType="centerCrop"
android:src="@drawable/cover"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintLeft_toLeftOf="parent"
app:layout_constraintRight_toRightOf="@id/horizontal"
app:layout_constraintTop_toTopOf="@id/vertical"
tools:src="@tools:sample/avatars" />
<audio.funkwhale.ffa.views.SquareImageView
android:id="@+id/cover_bottom_right"
android:layout_width="0dp"
android:layout_height="0dp"
android:scaleType="centerCrop"
android:src="@drawable/cover"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintLeft_toLeftOf="@id/horizontal"
app:layout_constraintRight_toRightOf="parent"
app:layout_constraintTop_toTopOf="@id/vertical"
tools:src="@tools:sample/avatars" />
</androidx.constraintlayout.widget.ConstraintLayout>
<com.google.android.material.button.MaterialButton
android:id="@+id/play"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:backgroundTint="@color/colorPrimary"
android:paddingHorizontal="16dp"
android:paddingVertical="8dp"
android:text="@string/playback_shuffle"
android:textColor="@android:color/white"
app:icon="@drawable/play"
app:iconTint="@android:color/white"
app:layout_constraintBottom_toBottomOf="@id/cover"
app:layout_constraintLeft_toLeftOf="@id/cover"
app:layout_constraintRight_toRightOf="@id/cover"
app:layout_constraintTop_toBottomOf="@id/cover"
app:rippleColor="@color/ripple" />
</androidx.constraintlayout.widget.ConstraintLayout>
<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:gravity="center_vertical"
android:orientation="horizontal">
<LinearLayout
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_weight="1"
android:orientation="vertical">
<TextView
android:id="@+id/artist"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginStart="16dp"
android:layout_marginTop="16dp"
android:layout_marginEnd="16dp"
android:textAllCaps="true"
android:textSize="14sp"
tools:text="Muse" />
<TextView
android:id="@+id/title"
style="@style/AppTheme.Title"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginStart="16dp"
android:layout_marginEnd="16dp"
android:layout_marginBottom="16dp"
app:drawableStartCompat="@drawable/downloaded"
app:drawableTint="@color/controlColor"
tools:text="Absolution"
android:drawablePadding="8dp"/>
</LinearLayout>
<ImageButton
android:id="@+id/actions"
style="@style/IconButton"
android:layout_width="24dp"
android:layout_height="24dp"
android:layout_marginEnd="16dp"
android:contentDescription="@string/alt_more_options"
android:src="@drawable/more" />
</LinearLayout>
</LinearLayout>
</com.google.android.material.card.MaterialCardView>
<androidx.recyclerview.widget.RecyclerView
android:id="@+id/tracks"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginStart="16dp"
android:layout_marginEnd="16dp"
android:layout_marginBottom="16dp"
tools:text="Absolution" />
</LinearLayout>
<ImageButton
android:id="@+id/actions"
style="@style/IconButton"
android:layout_width="24dp"
android:layout_height="24dp"
android:layout_marginEnd="16dp"
android:contentDescription="@string/alt_more_options"
android:src="@drawable/more" />
</LinearLayout>
android:layout_height="match_parent"
tools:itemCount="10"
tools:listitem="@layout/row_track" />
</LinearLayout>
</com.google.android.material.card.MaterialCardView>
<androidx.recyclerview.widget.RecyclerView
android:id="@+id/tracks"
android:layout_width="match_parent"
android:layout_height="match_parent"
tools:itemCount="10"
tools:listitem="@layout/row_track" />
</LinearLayout>
</androidx.core.widget.NestedScrollView>
</androidx.core.widget.NestedScrollView>
</androidx.swiperefreshlayout.widget.SwipeRefreshLayout>

Loading…
Cancel
Save