PlayerAndroid/app/src/main/java/code/name/monkey/retromusic/activities/LyricsActivity.kt

393 lines
14 KiB
Kotlin
Raw Normal View History

2019-04-20 05:29:45 +00:00
package code.name.monkey.retromusic.activities
2018-12-06 08:52:57 +00:00
import android.annotation.SuppressLint
import android.content.res.ColorStateList
2018-12-06 08:52:57 +00:00
import android.os.AsyncTask
2019-04-09 17:29:48 +00:00
import android.os.Build
2018-12-06 08:52:57 +00:00
import android.os.Bundle
import android.text.InputType
import android.text.TextUtils
2018-12-08 03:33:02 +00:00
import android.view.*
2019-04-09 17:29:48 +00:00
import androidx.annotation.StringRes
2018-12-06 08:52:57 +00:00
import androidx.core.content.ContextCompat
2018-12-08 03:33:02 +00:00
import androidx.fragment.app.Fragment
import androidx.fragment.app.FragmentManager
import androidx.fragment.app.FragmentStatePagerAdapter
2018-12-25 14:58:47 +00:00
import androidx.viewpager.widget.ViewPager
2018-12-06 08:52:57 +00:00
import code.name.monkey.appthemehelper.ThemeStore
import code.name.monkey.appthemehelper.util.*
2018-12-08 03:33:02 +00:00
import code.name.monkey.retromusic.App
2018-12-06 08:52:57 +00:00
import code.name.monkey.retromusic.R
2019-05-16 18:52:48 +00:00
import code.name.monkey.retromusic.activities.base.AbsMusicServiceActivity
import code.name.monkey.retromusic.activities.tageditor.WriteTagsAsyncTask
import code.name.monkey.retromusic.fragments.base.AbsMusicServiceFragment
2018-12-06 08:52:57 +00:00
import code.name.monkey.retromusic.helper.MusicPlayerRemote
import code.name.monkey.retromusic.helper.MusicProgressViewUpdateHelper
2019-04-15 02:44:48 +00:00
import code.name.monkey.retromusic.lyrics.LrcHelper
import code.name.monkey.retromusic.lyrics.LrcView
2018-12-06 08:52:57 +00:00
import code.name.monkey.retromusic.model.Song
import code.name.monkey.retromusic.model.lyrics.Lyrics
import code.name.monkey.retromusic.util.LyricUtil
import code.name.monkey.retromusic.util.MusicUtil
2018-12-25 14:58:47 +00:00
import code.name.monkey.retromusic.util.PreferenceUtil
2018-12-06 08:52:57 +00:00
import code.name.monkey.retromusic.util.RetroUtil
2019-10-04 13:08:54 +00:00
import com.afollestad.materialdialogs.LayoutMode
2018-12-06 08:52:57 +00:00
import com.afollestad.materialdialogs.MaterialDialog
2019-05-16 18:52:48 +00:00
import com.afollestad.materialdialogs.bottomsheets.BottomSheet
import com.afollestad.materialdialogs.input.getInputLayout
2019-02-19 10:38:51 +00:00
import com.afollestad.materialdialogs.input.input
2018-12-06 08:52:57 +00:00
import kotlinx.android.synthetic.main.activity_lyrics.*
2018-12-08 03:33:02 +00:00
import kotlinx.android.synthetic.main.fragment_lyrics.*
import kotlinx.android.synthetic.main.fragment_synced.*
2018-12-06 08:52:57 +00:00
import org.jaudiotagger.tag.FieldKey
import java.io.File
import java.util.*
2019-04-09 17:29:48 +00:00
import kotlin.collections.ArrayList
2018-12-06 08:52:57 +00:00
2018-12-25 14:58:47 +00:00
class LyricsActivity : AbsMusicServiceActivity(), View.OnClickListener, ViewPager.OnPageChangeListener {
override fun onPageScrollStateChanged(state: Int) {
when (state) {
ViewPager.SCROLL_STATE_IDLE ->
fab.show()
ViewPager.SCROLL_STATE_DRAGGING,
ViewPager.SCROLL_STATE_SETTLING ->
fab.hide()
}
2018-12-25 14:58:47 +00:00
}
override fun onPageScrolled(position: Int, positionOffset: Float, positionOffsetPixels: Int) {
}
override fun onPageSelected(position: Int) {
PreferenceUtil.getInstance(this).lyricsOptions = position
2019-04-05 05:49:40 +00:00
if (position == 0) fab.text = getString(R.string.synced_lyrics)
else if (position == 1) fab.text = getString(R.string.lyrics)
2018-12-25 14:58:47 +00:00
}
2018-12-08 03:33:02 +00:00
override fun onClick(v: View?) {
when (viewPager.currentItem) {
0 -> showSyncedLyrics()
1 -> showLyricsSaveDialog()
}
}
2018-12-06 08:52:57 +00:00
2018-12-08 03:33:02 +00:00
private lateinit var song: Song
2018-12-25 14:58:47 +00:00
private var lyricsString: String? = null
2018-12-06 08:52:57 +00:00
private val googleSearchLrcUrl: String
get() {
var baseUrl = "http://www.google.com/search?"
2018-12-08 03:33:02 +00:00
var query = song.title + "+" + song.artistName
2018-12-06 08:52:57 +00:00
query = "q=" + query.replace(" ", "+") + " .lrc"
baseUrl += query
return baseUrl
}
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(R.layout.activity_lyrics)
2018-12-08 03:33:02 +00:00
setStatusbarColorAuto()
2018-12-06 08:52:57 +00:00
setTaskDescriptionColorAuto()
2019-09-28 17:52:49 +00:00
setNavigationBarColorPrimary()
2018-12-09 06:38:34 +00:00
val primaryColor = ATHUtil.resolveColor(this, R.attr.colorPrimary)
appBarLayout.setBackgroundColor(primaryColor)
2018-12-10 15:28:13 +00:00
toolbar.apply {
setBackgroundColor(primaryColor)
2018-12-10 15:28:13 +00:00
navigationIcon = TintHelper.createTintedDrawable(ContextCompat.getDrawable(this@LyricsActivity, R.drawable.ic_keyboard_backspace_black_24dp), ThemeStore.textColorSecondary(this@LyricsActivity))
setSupportActionBar(toolbar)
}
2018-12-06 08:52:57 +00:00
fab.backgroundTintList = ColorStateList.valueOf(ThemeStore.accentColor(this))
ColorStateList.valueOf(MaterialValueHelper.getPrimaryTextColor(this, ColorUtil.isColorLight(ThemeStore.accentColor(this)))).apply {
fab.setTextColor(this)
fab.iconTint = this
}
2018-12-06 08:52:57 +00:00
setupWakelock()
2018-12-08 03:33:02 +00:00
viewPager.apply {
adapter = PagerAdapter(supportFragmentManager)
currentItem = PreferenceUtil.getInstance(this@LyricsActivity).lyricsOptions
2018-12-25 14:58:47 +00:00
addOnPageChangeListener(this@LyricsActivity)
2018-12-08 03:33:02 +00:00
}
2018-12-25 14:58:47 +00:00
2018-12-08 03:33:02 +00:00
tabs.apply {
setupWithViewPager(viewPager)
setSelectedTabIndicator(TintHelper.createTintedDrawable(ContextCompat.getDrawable(this@LyricsActivity, R.drawable.tab_indicator), ThemeStore.accentColor(this@LyricsActivity)))
setTabTextColors(ThemeStore.textColorSecondary(this@LyricsActivity), ThemeStore.accentColor(this@LyricsActivity))
setSelectedTabIndicatorColor(ThemeStore.accentColor(context))
}
2018-12-06 08:52:57 +00:00
fab.setOnClickListener(this)
}
2018-12-08 03:33:02 +00:00
override fun onPlayingMetaChanged() {
super.onPlayingMetaChanged()
song = MusicPlayerRemote.currentSong
toolbar.title = song.title
toolbar.subtitle = song.artistName
2018-12-06 08:52:57 +00:00
}
2018-12-08 03:33:02 +00:00
override fun onServiceConnected() {
super.onServiceConnected()
song = MusicPlayerRemote.currentSong
toolbar.title = song.title
toolbar.subtitle = song.artistName
2018-12-06 08:52:57 +00:00
}
private fun setupWakelock() {
window.addFlags(WindowManager.LayoutParams.FLAG_KEEP_SCREEN_ON)
}
2018-12-08 03:33:02 +00:00
override fun onOptionsItemSelected(item: MenuItem): Boolean {
if (item.itemId == android.R.id.home) {
onBackPressed()
2018-12-06 08:52:57 +00:00
}
2018-12-08 03:33:02 +00:00
return super.onOptionsItemSelected(item)
2018-12-06 08:52:57 +00:00
}
2018-12-08 03:33:02 +00:00
private fun showSyncedLyrics() {
var content = ""
try {
2019-09-24 12:58:12 +00:00
content = LyricUtil.getStringFromFile(song.data, song.artistName)
2018-12-08 03:33:02 +00:00
} catch (e: Exception) {
2019-11-12 14:19:33 +00:00
try {
2019-09-24 12:58:12 +00:00
content = LyricUtil.getStringFromFile(song.title, song.artistName)
2019-11-12 14:19:33 +00:00
} catch (e2: Exception) {
2019-09-24 12:58:12 +00:00
}
2018-12-08 03:33:02 +00:00
e.printStackTrace()
}
2018-12-06 08:52:57 +00:00
2019-10-04 13:08:54 +00:00
val materialDialog = MaterialDialog(this, BottomSheet(LayoutMode.WRAP_CONTENT)).show {
2019-04-05 05:49:40 +00:00
title(R.string.add_time_framed_lryics)
negativeButton(R.string.action_search) { RetroUtil.openUrl(this@LyricsActivity, googleSearchLrcUrl) }
input(hint = getString(R.string.paste_lyrics_here),
2019-02-19 10:38:51 +00:00
prefill = content,
inputType = InputType.TYPE_CLASS_TEXT or InputType.TYPE_TEXT_FLAG_MULTI_LINE) { _, input ->
2019-09-24 12:58:12 +00:00
LyricUtil.writeLrcToLoc(song.data, song.artistName, input.toString())
2019-02-19 10:38:51 +00:00
}
2019-04-05 05:49:40 +00:00
positiveButton(android.R.string.ok) {
updateSong()
}
}
2019-05-16 18:52:48 +00:00
MaterialUtil.setTint(materialDialog.getInputLayout(), false)
2019-04-05 05:49:40 +00:00
}
private fun updateSong() {
val page = supportFragmentManager.findFragmentByTag("android:switcher:" + R.id.viewPager + ":" + viewPager.currentItem)
if (viewPager.currentItem == 0 && page != null) {
(page as BaseLyricsFragment).upDateSong()
2019-02-19 10:38:51 +00:00
}
2018-12-06 08:52:57 +00:00
}
2018-12-08 03:33:02 +00:00
private fun showLyricsSaveDialog() {
2018-12-25 14:58:47 +00:00
val content: String = if (lyricsString == null) {
2018-12-08 03:33:02 +00:00
""
} else {
2018-12-25 14:58:47 +00:00
lyricsString!!
2018-12-08 03:33:02 +00:00
}
2019-02-19 10:38:51 +00:00
2019-10-04 13:08:54 +00:00
val materialDialog = MaterialDialog(this, BottomSheet(LayoutMode.WRAP_CONTENT)).show {
2019-04-05 05:49:40 +00:00
title(R.string.add_lyrics)
negativeButton(R.string.action_search) { RetroUtil.openUrl(this@LyricsActivity, getGoogleSearchUrl()) }
input(hint = getString(R.string.paste_lyrics_here),
2019-02-19 10:38:51 +00:00
prefill = content,
inputType = InputType.TYPE_CLASS_TEXT or InputType.TYPE_TEXT_FLAG_MULTI_LINE) { _, input ->
val fieldKeyValueMap = EnumMap<FieldKey, String>(FieldKey::class.java)
fieldKeyValueMap[FieldKey.LYRICS] = input.toString()
WriteTagsAsyncTask(this@LyricsActivity).execute(WriteTagsAsyncTask.LoadingInfo(getSongPaths(song), fieldKeyValueMap, null))
}
2019-04-05 05:49:40 +00:00
positiveButton(android.R.string.ok) {
updateSong()
}
2019-02-19 10:38:51 +00:00
}
2019-05-16 18:52:48 +00:00
MaterialUtil.setTint(materialDialog.getInputLayout(), false)
2018-12-06 08:52:57 +00:00
}
2018-12-08 03:33:02 +00:00
private fun getSongPaths(song: Song): ArrayList<String> {
val paths = ArrayList<String>(1)
2019-04-05 05:49:40 +00:00
paths.add(song.data)
2018-12-08 03:33:02 +00:00
return paths
2018-12-06 08:52:57 +00:00
}
2019-02-23 17:39:02 +00:00
private fun getGoogleSearchUrl(): String {
2018-12-08 03:33:02 +00:00
var baseUrl = "http://www.google.com/search?"
2019-02-23 17:39:02 +00:00
var query = song.title + "+" + song.artistName
2018-12-08 03:33:02 +00:00
query = "q=" + query.replace(" ", "+") + " lyrics"
baseUrl += query
return baseUrl
}
2018-12-25 14:58:47 +00:00
2019-11-12 14:19:33 +00:00
class PagerAdapter(fm: FragmentManager) : FragmentStatePagerAdapter(fm, BEHAVIOR_RESUME_ONLY_CURRENT_FRAGMENT) {
2019-04-09 17:29:48 +00:00
class Tabs(@StringRes val title: Int,
val fragment: Fragment)
private var tabs = ArrayList<Tabs>()
init {
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP_MR1) {
tabs.add(Tabs(R.string.synced_lyrics, SyncedLyricsFragment()))
2018-12-08 03:33:02 +00:00
}
2019-04-09 17:29:48 +00:00
tabs.add(Tabs(R.string.normal_lyrics, OfflineLyricsFragment()))
}
override fun getItem(position: Int): Fragment {
return tabs[position].fragment
2018-12-06 08:52:57 +00:00
}
2018-12-25 14:58:47 +00:00
override fun getPageTitle(position: Int): CharSequence? {
return App.getContext().getString(tabs[position].title)
2018-12-06 08:52:57 +00:00
}
2018-12-25 14:58:47 +00:00
override fun getCount(): Int {
2019-04-09 17:29:48 +00:00
return tabs.size
2018-12-25 14:58:47 +00:00
}
2018-12-06 08:52:57 +00:00
}
2018-12-25 14:58:47 +00:00
abstract class BaseLyricsFragment : AbsMusicServiceFragment() {
abstract fun upDateSong()
2018-12-06 08:52:57 +00:00
2018-12-25 14:58:47 +00:00
override fun onPlayingMetaChanged() {
super.onPlayingMetaChanged()
upDateSong()
}
2018-12-06 08:52:57 +00:00
2018-12-25 14:58:47 +00:00
override fun onServiceConnected() {
super.onServiceConnected()
upDateSong()
}
}
2018-12-06 08:52:57 +00:00
2018-12-25 14:58:47 +00:00
class OfflineLyricsFragment : BaseLyricsFragment() {
override fun upDateSong() {
loadSongLyrics()
2018-12-06 08:52:57 +00:00
}
2018-12-25 14:58:47 +00:00
private var updateLyricsAsyncTask: AsyncTask<*, *, *>? = null
private var lyrics: Lyrics? = null
@SuppressLint("StaticFieldLeak")
private fun loadSongLyrics() {
if (updateLyricsAsyncTask != null) {
updateLyricsAsyncTask!!.cancel(false)
2018-12-06 08:52:57 +00:00
}
2018-12-25 14:58:47 +00:00
val song = MusicPlayerRemote.currentSong
updateLyricsAsyncTask = object : AsyncTask<Void?, Void?, Lyrics?>() {
override fun doInBackground(vararg params: Void?): Lyrics? {
val data = MusicUtil.getLyrics(song)
return if (TextUtils.isEmpty(data)) {
null
2019-03-04 03:55:09 +00:00
} else Lyrics.parse(song, data!!)
2018-12-25 14:58:47 +00:00
}
2018-12-06 08:52:57 +00:00
2018-12-25 14:58:47 +00:00
override fun onPreExecute() {
super.onPreExecute()
lyrics = null
2018-12-06 08:52:57 +00:00
}
2018-12-25 14:58:47 +00:00
override fun onPostExecute(l: Lyrics?) {
lyrics = l
offlineLyrics?.visibility = View.VISIBLE
2018-12-25 14:58:47 +00:00
if (l == null) {
offlineLyrics?.setText(R.string.no_lyrics_found)
2018-12-25 14:58:47 +00:00
return
}
(activity as LyricsActivity).lyricsString = l.text
offlineLyrics?.text = l.text
2018-12-25 14:58:47 +00:00
}
2018-12-06 08:52:57 +00:00
2018-12-25 14:58:47 +00:00
override fun onCancelled(s: Lyrics?) {
onPostExecute(null)
}
}.execute()
2018-12-06 08:52:57 +00:00
}
2019-11-12 17:32:30 +00:00
override fun onActivityCreated(savedInstanceState: Bundle?) {
super.onActivityCreated(savedInstanceState)
loadSongLyrics()
}
2018-12-25 14:58:47 +00:00
override fun onDestroyView() {
super.onDestroyView()
if (updateLyricsAsyncTask != null && !updateLyricsAsyncTask!!.isCancelled) {
updateLyricsAsyncTask!!.cancel(true)
}
}
2018-12-08 03:33:02 +00:00
2018-12-25 14:58:47 +00:00
override fun onCreateView(inflater: LayoutInflater, container: ViewGroup?, savedInstanceState: Bundle?): View? {
return inflater.inflate(R.layout.fragment_lyrics, container, false)
}
2018-12-08 03:33:02 +00:00
}
2018-12-25 14:58:47 +00:00
class SyncedLyricsFragment : BaseLyricsFragment(), MusicProgressViewUpdateHelper.Callback {
override fun upDateSong() {
loadLRCLyrics()
}
2018-12-08 03:33:02 +00:00
2018-12-25 14:58:47 +00:00
private lateinit var updateHelper: MusicProgressViewUpdateHelper
override fun onCreateView(inflater: LayoutInflater, container: ViewGroup?, savedInstanceState: Bundle?): View? {
return inflater.inflate(R.layout.fragment_synced, container, false)
}
2018-12-08 03:33:02 +00:00
2018-12-25 14:58:47 +00:00
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
updateHelper = MusicProgressViewUpdateHelper(this, 500, 1000)
2018-12-06 08:52:57 +00:00
}
2018-12-25 14:58:47 +00:00
override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
super.onViewCreated(view, savedInstanceState)
setupLyricsView()
}
2018-12-06 08:52:57 +00:00
2018-12-25 14:58:47 +00:00
private fun setupLyricsView() {
lyricsView.apply {
2019-04-05 05:49:40 +00:00
val context = activity!!
setCurrentPlayLineColor(ThemeStore.accentColor(context))
setIndicatorTextColor(ThemeStore.accentColor(context))
setCurrentIndicateLineTextColor(ThemeStore.textColorPrimary(context))
2019-04-05 05:49:40 +00:00
setNoLrcTextColor(ThemeStore.textColorPrimary(context))
setOnPlayIndicatorLineListener(object : LrcView.OnPlayIndicatorLineListener {
override fun onPlay(time: Long, content: String) {
MusicPlayerRemote.seekTo(time.toInt())
}
})
2018-12-25 14:58:47 +00:00
}
}
2018-12-08 03:33:02 +00:00
2018-12-25 14:58:47 +00:00
override fun onResume() {
super.onResume()
updateHelper.start()
}
2018-12-08 03:33:02 +00:00
2018-12-25 14:58:47 +00:00
override fun onPause() {
super.onPause()
updateHelper.stop()
}
2018-12-08 03:33:02 +00:00
2018-12-25 14:58:47 +00:00
override fun onUpdateProgressViews(progress: Int, total: Int) {
lyricsView.updateTime(progress.toLong())
2018-12-25 14:58:47 +00:00
}
2018-12-08 03:33:02 +00:00
2018-12-25 14:58:47 +00:00
private fun loadLRCLyrics() {
val song = MusicPlayerRemote.currentSong
2019-09-24 12:58:12 +00:00
if (LyricUtil.isLrcFile2Exist(song.data, song.artistName)) {
showLyricsLocal(LyricUtil.getLocalLyricFile(song.data, song.artistName))
} else {
if (LyricUtil.isLrcFileExist(song.title, song.artistName)) {
showLyricsLocal(LyricUtil.getLocalLyricFile(song.title, song.artistName))
}
2018-12-25 14:58:47 +00:00
}
2018-12-08 03:33:02 +00:00
}
2018-12-25 14:58:47 +00:00
private fun showLyricsLocal(file: File?) {
if (file != null) {
lyricsView.setLrcData(LrcHelper.parseLrcFromFile(file))
2018-12-25 14:58:47 +00:00
}
2018-12-08 03:33:02 +00:00
}
2018-12-06 08:52:57 +00:00
}
2019-09-24 12:58:12 +00:00
}