diff --git a/app/src/main/java/code/name/monkey/retromusic/fragments/other/CoverLyricsFragment.kt b/app/src/main/java/code/name/monkey/retromusic/fragments/other/CoverLyricsFragment.kt new file mode 100644 index 000000000..c7aabefd1 --- /dev/null +++ b/app/src/main/java/code/name/monkey/retromusic/fragments/other/CoverLyricsFragment.kt @@ -0,0 +1,174 @@ +package code.name.monkey.retromusic.fragments.other + +import android.content.SharedPreferences +import android.os.Bundle +import android.text.TextUtils +import android.view.View +import android.widget.FrameLayout +import android.widget.TextView +import androidx.core.view.isVisible +import androidx.lifecycle.lifecycleScope +import androidx.preference.PreferenceManager +import code.name.monkey.retromusic.R +import code.name.monkey.retromusic.SHOW_LYRICS +import code.name.monkey.retromusic.databinding.FragmentCoverLyricsBinding +import code.name.monkey.retromusic.fragments.base.AbsMusicServiceFragment +import code.name.monkey.retromusic.fragments.base.AbsPlayerFragment +import code.name.monkey.retromusic.helper.MusicPlayerRemote +import code.name.monkey.retromusic.helper.MusicProgressViewUpdateHelper +import code.name.monkey.retromusic.model.lyrics.AbsSynchronizedLyrics +import code.name.monkey.retromusic.model.lyrics.Lyrics +import code.name.monkey.retromusic.util.LyricUtil +import code.name.monkey.retromusic.util.PreferenceUtil +import kotlinx.coroutines.Dispatchers +import kotlinx.coroutines.launch +import org.jaudiotagger.audio.exceptions.CannotReadException +import java.io.File +import java.io.FileNotFoundException + +class CoverLyricsFragment : AbsMusicServiceFragment(R.layout.fragment_cover_lyrics), + MusicProgressViewUpdateHelper.Callback, SharedPreferences.OnSharedPreferenceChangeListener { + private var progressViewUpdateHelper: MusicProgressViewUpdateHelper? = null + private var _binding: FragmentCoverLyricsBinding? = null + private val binding get() = _binding!! + + private val lyricsLayout: FrameLayout get() = binding.playerLyrics + private val lyricsLine1: TextView get() = binding.playerLyricsLine1 + private val lyricsLine2: TextView get() = binding.playerLyricsLine2 + + private var lyrics: Lyrics? = null + + override fun onViewCreated(view: View, savedInstanceState: Bundle?) { + super.onViewCreated(view, savedInstanceState) + _binding = FragmentCoverLyricsBinding.bind(view) + progressViewUpdateHelper = MusicProgressViewUpdateHelper(this, 500, 1000) + if (PreferenceUtil.showLyrics) { + progressViewUpdateHelper?.start() + } + } + + override fun onSharedPreferenceChanged(sharedPreferences: SharedPreferences?, key: String?) { + if (key == SHOW_LYRICS) { + if (sharedPreferences?.getBoolean(key, false) == true) { + progressViewUpdateHelper?.start() + binding.root.isVisible = true + updateLyrics() + } else { + progressViewUpdateHelper?.stop() + binding.root.isVisible = false + } + } + } + + override fun onPlayingMetaChanged() { + super.onPlayingMetaChanged() + if (PreferenceUtil.showLyrics) { + updateLyrics() + } + } + + override fun onServiceConnected() { + super.onServiceConnected() + if (PreferenceUtil.showLyrics) { + updateLyrics() + } + } + + private fun updateLyrics() { + lyrics = null + lifecycleScope.launch(Dispatchers.IO) { + val song = MusicPlayerRemote.currentSong + lyrics = try { + val lrcFile: File? = LyricUtil.getSyncedLyricsFile(song) + val data: String = LyricUtil.getStringFromLrc(lrcFile) + Lyrics.parse(song, + if (!TextUtils.isEmpty(data)) { + data + } else { + // Get Embedded Lyrics + LyricUtil.getEmbeddedSyncedLyrics(song.data) + } + ) + } catch (err: FileNotFoundException) { + null + } catch (e: CannotReadException) { + null + } + } + + + } + + override fun onUpdateProgressViews(progress: Int, total: Int) { + if (_binding == null) return + + if (!isLyricsLayoutVisible()) { + hideLyricsLayout() + return + } + + if (lyrics !is AbsSynchronizedLyrics) return + val synchronizedLyrics = lyrics as AbsSynchronizedLyrics + + lyricsLayout.visibility = View.VISIBLE + lyricsLayout.alpha = 1f + + val oldLine = lyricsLine2.text.toString() + val line = synchronizedLyrics.getLine(progress) + + if (oldLine != line || oldLine.isEmpty()) { + lyricsLine1.text = oldLine + lyricsLine2.text = line + + lyricsLine1.isVisible = true + lyricsLine2.isVisible = true + + lyricsLine2.measure( + View.MeasureSpec.makeMeasureSpec( + lyricsLine2.measuredWidth, + View.MeasureSpec.EXACTLY + ), + View.MeasureSpec.UNSPECIFIED + ) + val h: Float = lyricsLine2.measuredHeight.toFloat() + + lyricsLine1.alpha = 1f + lyricsLine1.translationY = 0f + lyricsLine1.animate().alpha(0f).translationY(-h).duration = + AbsPlayerFragment.VISIBILITY_ANIM_DURATION + + lyricsLine2.alpha = 0f + lyricsLine2.translationY = h + lyricsLine2.animate().alpha(1f).translationY(0f).duration = + AbsPlayerFragment.VISIBILITY_ANIM_DURATION + } + } + + private fun isLyricsLayoutVisible(): Boolean { + return lyrics != null && lyrics!!.isSynchronized && lyrics!!.isValid + } + + private fun hideLyricsLayout() { + lyricsLayout.animate().alpha(0f).setDuration(AbsPlayerFragment.VISIBILITY_ANIM_DURATION) + .withEndAction { + if (_binding == null) return@withEndAction + lyricsLayout.isVisible = false + lyricsLine1.text = null + lyricsLine2.text = null + } + } + + override fun onResume() { + super.onResume() + PreferenceManager.getDefaultSharedPreferences(requireContext()) + .registerOnSharedPreferenceChangeListener(this) + } + + override fun onDestroyView() { + super.onDestroyView() + PreferenceManager.getDefaultSharedPreferences(requireContext()) + .unregisterOnSharedPreferenceChangeListener(this) + progressViewUpdateHelper?.stop() + _binding = null + } +} \ No newline at end of file diff --git a/app/src/main/res/layout/fragment_adaptive_player.xml b/app/src/main/res/layout/fragment_adaptive_player.xml index 4f71baf8a..5975ae228 100644 --- a/app/src/main/res/layout/fragment_adaptive_player.xml +++ b/app/src/main/res/layout/fragment_adaptive_player.xml @@ -57,6 +57,14 @@ android:layout_width="match_parent" android:layout_height="match_parent" tools:layout="@layout/fragment_album_full_card_cover" /> + + + \ No newline at end of file diff --git a/app/src/main/res/layout/fragment_card_blur_player.xml b/app/src/main/res/layout/fragment_card_blur_player.xml index 13b743113..ffc79346c 100644 --- a/app/src/main/res/layout/fragment_card_blur_player.xml +++ b/app/src/main/res/layout/fragment_card_blur_player.xml @@ -73,6 +73,14 @@ android:layout_width="match_parent" android:layout_height="wrap_content" tools:layout="@layout/fragment_album_card_cover" /> + + diff --git a/app/src/main/res/layout/fragment_card_player.xml b/app/src/main/res/layout/fragment_card_player.xml index 8318ede85..b67ed8db6 100644 --- a/app/src/main/res/layout/fragment_card_player.xml +++ b/app/src/main/res/layout/fragment_card_player.xml @@ -19,6 +19,13 @@ android:layout_height="match_parent" tools:layout="@layout/fragment_album_full_cover" /> + + + + + + + + \ No newline at end of file diff --git a/app/src/main/res/layout/fragment_fit.xml b/app/src/main/res/layout/fragment_fit.xml index b9b42ea01..6d540aef9 100644 --- a/app/src/main/res/layout/fragment_fit.xml +++ b/app/src/main/res/layout/fragment_fit.xml @@ -30,6 +30,15 @@ tools:layout="@layout/fragment_album_full_cover" /> + + + - - - - - - - + android:elevation="20dp" + app:layout_constraintTop_toBottomOf="@id/playerToolbar"/> diff --git a/app/src/main/res/layout/fragment_gradient_player.xml b/app/src/main/res/layout/fragment_gradient_player.xml index e9aad0649..0f00d905d 100644 --- a/app/src/main/res/layout/fragment_gradient_player.xml +++ b/app/src/main/res/layout/fragment_gradient_player.xml @@ -58,6 +58,17 @@ layout="@layout/status_bar" /> + +