reproduccion de audio en lista de audios y fixes varios

This commit is contained in:
erik-everardo 2024-02-17 21:37:25 -06:00
parent bfa0fdcecf
commit cd10aced57
7 changed files with 165 additions and 26 deletions

View File

@ -16,13 +16,72 @@ class AudiosAdapter(
private val onOptionsClick: ((audio: Audio, button: View) -> Boolean)
) : RecyclerView.Adapter<AudiosAdapter.AudiosViewHolder>() {
enum class Payload {
PlayStateChanged, IsLoadingChanged
}
private var data: List<Audio> = listOf()
private var currentPlaying: Audio? = null
fun setData(audios: List<Audio>) {
data = audios
notifyDataSetChanged()
}
fun setIsPlaying(isPlaying: Boolean, audio: Audio) {
if(audio == currentPlaying) {
val index = data.indexOf(audio)
if(index == -1) return
data[index].isPlaying = isPlaying
notifyItemChanged(index, Payload.PlayStateChanged)
return
}
val prevIndex = data.indexOf(currentPlaying)
if(prevIndex != -1) {
data[prevIndex].isPlaying = false
notifyItemChanged(prevIndex, Payload.PlayStateChanged)
}
val newIndex = data.indexOf(audio)
if(newIndex != -1) {
data[newIndex].isPlaying = isPlaying
notifyItemChanged(newIndex, Payload.PlayStateChanged)
}
currentPlaying = audio
}
fun setIsLoadingAudio(isLoading: Boolean, audio: Audio) {
if(audio == currentPlaying) {
val index = data.indexOf(audio)
if(index == -1) return
data[index].isLoading = isLoading
notifyItemChanged(index, Payload.IsLoadingChanged)
return
}
val prevIndex = data.indexOf(currentPlaying)
if(prevIndex != -1) {
data[prevIndex].isLoading = false
notifyItemChanged(prevIndex, Payload.IsLoadingChanged)
}
val newIndex = data.indexOf(audio)
if(newIndex != -1) {
data[newIndex].isLoading = isLoading
notifyItemChanged(newIndex, Payload.IsLoadingChanged)
}
currentPlaying = audio
}
fun updateAudioProgress(total: Int, progress: Int, audio: Audio) {
}
inner class AudiosViewHolder(val binding: AudioListItemBinding) : ViewHolder(binding.root)
override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): AudiosViewHolder {
@ -34,25 +93,53 @@ class AudiosAdapter(
return data.size
}
override fun onBindViewHolder(holder: AudiosViewHolder, position: Int) {
override fun onBindViewHolder(
holder: AudiosViewHolder,
position: Int,
payloads: MutableList<Any>
) {
val audio = data[position]
if(payloads.isEmpty()) {
holder.binding.audioName.text = audio.name
holder.binding.audioAuthor.text = audio.userName
holder.binding.thumbnail.load(audio.thumbnail)
holder.binding.audioItemOptionsButton.setOnClickListener {
onOptionsClick(audio, it)
holder.binding.audioName.text = audio.name
holder.binding.audioAuthor.text = audio.userName
holder.binding.thumbnail.load(audio.thumbnail)
holder.binding.audioItemOptionsButton.setOnClickListener {
onOptionsClick(audio, it)
}
holder.binding.playButton.icon = ResourcesCompat.getDrawable(
holder.itemView.resources,
if(audio.isPlaying) R.drawable.baseline_pause_24 else R.drawable.baseline_play_arrow_24,
null
)
holder.binding.loading.visibility = if(audio.isLoading) View.VISIBLE else View.GONE
holder.binding.playButton.setOnClickListener {
onPlayClick(audio)
}
return
}
holder.binding.playButton.icon = ResourcesCompat.getDrawable(
holder.itemView.resources,
if(audio.isPlaying) R.drawable.baseline_pause_24 else R.drawable.baseline_play_arrow_24,
null
)
// only updates play button
if(payloads.contains(Payload.PlayStateChanged)) {
holder.binding.playButton.icon = ResourcesCompat.getDrawable(
holder.itemView.resources,
if(audio.isPlaying) R.drawable.baseline_pause_24 else R.drawable.baseline_play_arrow_24,
null
)
}
holder.binding.playButton.setOnClickListener {
onPlayClick(audio)
if(payloads.contains(Payload.IsLoadingChanged)) {
holder.binding.loading.visibility = if(audio.isLoading) View.VISIBLE else View.GONE
}
}
override fun onBindViewHolder(holder: AudiosViewHolder, position: Int) {
}
}

View File

@ -8,12 +8,15 @@ import androidx.appcompat.widget.PopupMenu
import androidx.fragment.app.Fragment
import androidx.fragment.app.activityViewModels
import androidx.fragment.app.viewModels
import androidx.navigation.fragment.findNavController
import androidx.navigation.fragment.navArgs
import androidx.recyclerview.widget.LinearLayoutManager
import com.isolaatti.R
import com.isolaatti.audio.audios_list.presentation.AudiosAdapter
import com.isolaatti.audio.audios_list.presentation.AudiosViewModel
import com.isolaatti.audio.common.domain.Audio
import com.isolaatti.audio.common.domain.Playable
import com.isolaatti.audio.player.AudioPlayerConnector
import com.isolaatti.common.ErrorMessageViewModel
import com.isolaatti.databinding.FragmentAudiosBinding
import com.isolaatti.utils.Resource
@ -29,6 +32,8 @@ class AudiosFragment : Fragment() {
private lateinit var adapter: AudiosAdapter
private var privilegedUserId by Delegates.notNull<Int>()
private lateinit var audioPlayerConnector: AudioPlayerConnector
private var loadedFirstTime = false
override fun onCreateView(
inflater: LayoutInflater,
@ -55,13 +60,44 @@ class AudiosFragment : Fragment() {
true
}
private val onAudioPlayClick: ((audio: Audio) -> Unit) = {
// Play audio
private val onAudioPlayClick: (audio: Audio) -> Unit = {
audioPlayerConnector.playPauseAudio(it)
}
private val audioPlayerConnectorListener: AudioPlayerConnector.Listener = object: AudioPlayerConnector.Listener {
override fun onPlaying(isPlaying: Boolean, audio: Playable) {
if(audio is Audio)
adapter.setIsPlaying(isPlaying, audio)
}
override fun isLoading(isLoading: Boolean, audio: Playable) {
if(audio is Audio)
adapter.setIsLoadingAudio(isLoading, audio)
}
override fun progressChanged(second: Int, audio: Playable) {
}
override fun durationChanged(duration: Int, audio: Playable) {
}
override fun onEnded(audio: Playable) {
}
}
override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
super.onViewCreated(view, savedInstanceState)
audioPlayerConnector = AudioPlayerConnector(requireContext())
audioPlayerConnector.addListener(audioPlayerConnectorListener)
viewLifecycleOwner.lifecycle.addObserver(audioPlayerConnector)
adapter = AudiosAdapter(onPlayClick = onAudioPlayClick, onOptionsClick = onOptionsClick)
viewBinding.recyclerAudios.layoutManager = LinearLayoutManager(requireContext(), LinearLayoutManager.VERTICAL, false)
@ -73,6 +109,10 @@ class AudiosFragment : Fragment() {
privilegedUserId = arguments.sourceId.toInt()
viewModel.loadAudios(privilegedUserId)
}
viewBinding.topAppBar.setNavigationOnClickListener {
findNavController().popBackStack()
}
}
private fun setupObservers() {
@ -94,7 +134,7 @@ class AudiosFragment : Fragment() {
}
}
}
companion object {
const val SOURCE_PROFILE = "source_profile"
const val SOURCE_SQUAD = "source_squads"

View File

@ -5,6 +5,7 @@ import android.net.Uri
abstract class Playable {
var isPlaying: Boolean = false
abstract val uri: Uri
var isLoading: Boolean = false
/**
* Image url, null indicating no image should be shown
@ -26,5 +27,4 @@ abstract class Playable {
return result
}
}

View File

@ -22,7 +22,7 @@ class AudioDraftsRepositoryImpl(private val audiosDraftsDao: AudiosDraftsDao) :
}
override fun deleteDrafts(draftIds: LongArray): Flow<Boolean> = flow {
val drafts = audiosDraftsDao.getAudioDraftsByIds(draftIds)
val drafts = audiosDraftsDao.getAudioDraftsByIds(*draftIds)
audiosDraftsDao.deleteDrafts(drafts)
try {

View File

@ -9,20 +9,20 @@ import androidx.room.Update
@Dao
interface AudiosDraftsDao {
@Insert
suspend fun insertAudioDraft(audioDraftEntity: AudioDraftEntity): Long
fun insertAudioDraft(audioDraftEntity: AudioDraftEntity): Long
@Query("SELECT * FROM audio_drafts WHERE id = :draftId")
suspend fun getAudioDraftById(draftId: Long): AudioDraftEntity?
fun getAudioDraftById(draftId: Long): AudioDraftEntity?
@Query("SELECT * FROM audio_drafts WHERE id in (:draftId)")
suspend fun getAudioDraftsByIds(draftId: LongArray): Array<AudioDraftEntity>
fun getAudioDraftsByIds(vararg draftId: Long): Array<AudioDraftEntity>
@Query("SELECT * FROM audio_drafts ORDER BY id DESC")
suspend fun getDrafts(): List<AudioDraftEntity>
fun getDrafts(): List<AudioDraftEntity>
@Delete
suspend fun deleteDrafts(draft: Array<AudioDraftEntity>)
fun deleteDrafts(draft: Array<AudioDraftEntity>)
@Query("UPDATE audio_drafts SET name = :name WHERE id = :id")
suspend fun renameDraft(id: Long, name: String): Int
fun renameDraft(id: Long, name: String): Int
}

View File

@ -12,8 +12,8 @@ interface KeyValueDao {
fun getValue(key: String): Flow<String>
@Insert(onConflict = OnConflictStrategy.REPLACE)
suspend fun setValue(entity: KeyValueEntity)
fun setValue(entity: KeyValueEntity)
@Query("SELECT value FROM key_values WHERE id = :key")
suspend fun getValueAsync(key: String): String?
fun getValueAsync(key: String): String?
}

View File

@ -12,6 +12,18 @@
android:layout_width="match_parent"
android:layout_height="match_parent">
<ProgressBar
android:id="@+id/loading"
android:layout_width="0dp"
android:layout_height="0dp"
android:visibility="gone"
android:translationZ="5dp"
app:layout_constraintTop_toTopOf="@id/play_button"
app:layout_constraintBottom_toBottomOf="@id/play_button"
app:layout_constraintStart_toStartOf="@id/play_button"
app:layout_constraintEnd_toEndOf="@id/play_button"/>
<com.google.android.material.button.MaterialButton
android:id="@+id/play_button"
android:layout_width="wrap_content"