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
This commit is contained in:
Ryan Harg 2021-07-15 13:25:02 +00:00
commit 1b6251259e
2 changed files with 258 additions and 203 deletions

View File

@ -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
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>() {
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>() {
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>() {
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)
}
}
}
}
}
}

View File

@ -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">
android:layout_height="match_parent"
android:clipChildren="false"
android:clipToPadding="false"
android:orientation="vertical">
<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"
<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" />
android:background="?attr/colorSurface"
android:elevation="1dp">
<TextView
android:id="@+id/title"
style="@style/AppTheme.Title"
<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>