[Lyrics] Added lyrics editing on A11+ devices
This commit is contained in:
parent
39a2c45081
commit
af4347c4ff
6 changed files with 147 additions and 14 deletions
|
@ -21,9 +21,9 @@ fun Fragment.createNewFile(
|
|||
registerForActivityResult(ActivityResultContracts.StartActivityForResult())
|
||||
{ result: ActivityResult ->
|
||||
if (result.resultCode == Activity.RESULT_OK) {
|
||||
val outputStream: OutputStream? =
|
||||
context?.contentResolver?.openOutputStream(result.data?.data!!)
|
||||
write(outputStream, result.data?.data)
|
||||
context?.contentResolver?.openOutputStream(result.data?.data!!)?.use { os->
|
||||
write(os, result.data?.data)
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -0,0 +1,6 @@
|
|||
package code.name.monkey.retromusic.extensions
|
||||
|
||||
import code.name.monkey.retromusic.model.Song
|
||||
import code.name.monkey.retromusic.util.MusicUtil
|
||||
|
||||
val Song.uri get() = MusicUtil.getSongFileUri(songId = id)
|
|
@ -15,9 +15,16 @@
|
|||
package code.name.monkey.retromusic.fragments.other
|
||||
|
||||
import android.annotation.SuppressLint
|
||||
import android.app.Activity
|
||||
import android.content.Intent
|
||||
import android.net.Uri
|
||||
import android.os.Bundle
|
||||
import android.provider.MediaStore
|
||||
import android.text.InputType
|
||||
import android.view.*
|
||||
import androidx.activity.result.ActivityResultLauncher
|
||||
import androidx.activity.result.IntentSenderRequest
|
||||
import androidx.activity.result.contract.ActivityResultContracts
|
||||
import androidx.core.view.ViewCompat
|
||||
import androidx.core.view.isVisible
|
||||
import androidx.fragment.app.Fragment
|
||||
|
@ -36,14 +43,14 @@ import code.name.monkey.retromusic.databinding.FragmentSyncedLyricsBinding
|
|||
import code.name.monkey.retromusic.extensions.accentColor
|
||||
import code.name.monkey.retromusic.extensions.surfaceColor
|
||||
import code.name.monkey.retromusic.extensions.textColorSecondary
|
||||
import code.name.monkey.retromusic.extensions.uri
|
||||
import code.name.monkey.retromusic.fragments.base.AbsMusicServiceFragment
|
||||
import code.name.monkey.retromusic.helper.MusicPlayerRemote
|
||||
import code.name.monkey.retromusic.helper.MusicProgressViewUpdateHelper
|
||||
import code.name.monkey.retromusic.lyrics.LrcView
|
||||
import code.name.monkey.retromusic.model.AudioTagInfo
|
||||
import code.name.monkey.retromusic.model.Song
|
||||
import code.name.monkey.retromusic.util.LyricUtil
|
||||
import code.name.monkey.retromusic.util.RetroUtil
|
||||
import code.name.monkey.retromusic.util.*
|
||||
import com.afollestad.materialdialogs.LayoutMode
|
||||
import com.afollestad.materialdialogs.MaterialDialog
|
||||
import com.afollestad.materialdialogs.bottomsheets.BottomSheet
|
||||
|
@ -55,6 +62,7 @@ import kotlinx.coroutines.*
|
|||
import org.jaudiotagger.audio.AudioFileIO
|
||||
import org.jaudiotagger.tag.FieldKey
|
||||
import java.io.File
|
||||
import java.io.FileOutputStream
|
||||
import java.util.*
|
||||
|
||||
class LyricsFragment : AbsMusicServiceFragment(R.layout.fragment_lyrics) {
|
||||
|
@ -95,6 +103,43 @@ class LyricsFragment : AbsMusicServiceFragment(R.layout.fragment_lyrics) {
|
|||
return transform
|
||||
}
|
||||
|
||||
private lateinit var normalLyricsLauncher: ActivityResultLauncher<IntentSenderRequest>
|
||||
private lateinit var newSyncedLyricsLauncher: ActivityResultLauncher<Intent>
|
||||
private lateinit var editSyncedLyricsLauncher: ActivityResultLauncher<IntentSenderRequest>
|
||||
|
||||
private lateinit var cacheFile: File
|
||||
private var syncedLyrics: String = ""
|
||||
private lateinit var syncedFileUri: Uri
|
||||
|
||||
override fun onCreate(savedInstanceState: Bundle?) {
|
||||
super.onCreate(savedInstanceState)
|
||||
// Normal lyrics launcher
|
||||
normalLyricsLauncher =
|
||||
registerForActivityResult(ActivityResultContracts.StartIntentSenderForResult()) {
|
||||
if (it.resultCode == Activity.RESULT_OK) {
|
||||
FileUtils.copyFileToUri(requireContext(), cacheFile, song.uri)
|
||||
}
|
||||
}
|
||||
newSyncedLyricsLauncher =
|
||||
registerForActivityResult(ActivityResultContracts.StartActivityForResult()) { result ->
|
||||
if (result.resultCode == Activity.RESULT_OK) {
|
||||
context?.contentResolver?.openOutputStream(result.data?.data!!)?.use {
|
||||
it.write(syncedLyrics.toByteArray())
|
||||
}
|
||||
}
|
||||
}
|
||||
editSyncedLyricsLauncher =
|
||||
registerForActivityResult(ActivityResultContracts.StartIntentSenderForResult()) {
|
||||
if (it.resultCode == Activity.RESULT_OK) {
|
||||
requireContext().contentResolver.openOutputStream(syncedFileUri)?.use { os ->
|
||||
(os as FileOutputStream).channel.truncate(0)
|
||||
os.write(syncedLyrics.toByteArray())
|
||||
os.flush()
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
|
||||
super.onViewCreated(view, savedInstanceState)
|
||||
setHasOptionsMenu(true)
|
||||
|
@ -111,9 +156,6 @@ class LyricsFragment : AbsMusicServiceFragment(R.layout.fragment_lyrics) {
|
|||
setupViews()
|
||||
setupToolbar()
|
||||
updateTitleSong()
|
||||
if (VersionUtils.hasR()) {
|
||||
binding.editButton.isVisible = false
|
||||
}
|
||||
}
|
||||
|
||||
private fun setupViews() {
|
||||
|
@ -213,7 +255,24 @@ class LyricsFragment : AbsMusicServiceFragment(R.layout.fragment_lyrics) {
|
|||
) { _, input ->
|
||||
val fieldKeyValueMap = EnumMap<FieldKey, String>(FieldKey::class.java)
|
||||
fieldKeyValueMap[FieldKey.LYRICS] = input.toString()
|
||||
syncedLyrics = input.toString()
|
||||
GlobalScope.launch {
|
||||
if (VersionUtils.hasR()) {
|
||||
cacheFile = TagWriter.writeTagsToFilesR(
|
||||
requireContext(), AudioTagInfo(
|
||||
listOf(song.data), fieldKeyValueMap, null
|
||||
)
|
||||
)[0]
|
||||
val pendingIntent =
|
||||
MediaStore.createWriteRequest(
|
||||
requireContext().contentResolver,
|
||||
listOf(song.uri)
|
||||
)
|
||||
|
||||
normalLyricsLauncher.launch(
|
||||
IntentSenderRequest.Builder(pendingIntent).build()
|
||||
)
|
||||
} else {
|
||||
TagWriter.writeTagsToFiles(
|
||||
requireContext(), AudioTagInfo(
|
||||
listOf(song.data), fieldKeyValueMap, null
|
||||
|
@ -221,6 +280,7 @@ class LyricsFragment : AbsMusicServiceFragment(R.layout.fragment_lyrics) {
|
|||
)
|
||||
}
|
||||
}
|
||||
}
|
||||
positiveButton(res = R.string.save) {
|
||||
(lyricsSectionsAdapter.fragments[1].first as NormalLyrics).loadNormalLyrics()
|
||||
}
|
||||
|
@ -240,8 +300,34 @@ class LyricsFragment : AbsMusicServiceFragment(R.layout.fragment_lyrics) {
|
|||
prefill = content,
|
||||
inputType = InputType.TYPE_TEXT_FLAG_MULTI_LINE or InputType.TYPE_CLASS_TEXT
|
||||
) { _, input ->
|
||||
if (VersionUtils.hasR()) {
|
||||
syncedLyrics = input.toString()
|
||||
val lrcFile = LyricUtil.getSyncedLyricsFile(song)
|
||||
if (lrcFile?.exists() == true) {
|
||||
syncedFileUri =
|
||||
UriUtil.getUriFromPath(requireContext(), lrcFile.absolutePath)
|
||||
val pendingIntent =
|
||||
MediaStore.createWriteRequest(
|
||||
requireContext().contentResolver,
|
||||
listOf(syncedFileUri)
|
||||
)
|
||||
editSyncedLyricsLauncher.launch(
|
||||
IntentSenderRequest.Builder(pendingIntent).build()
|
||||
)
|
||||
} else {
|
||||
val intent = Intent(Intent.ACTION_CREATE_DOCUMENT)
|
||||
intent.addCategory(Intent.CATEGORY_OPENABLE)
|
||||
intent.type = "*/*"
|
||||
intent.putExtra(
|
||||
Intent.EXTRA_TITLE,
|
||||
LyricUtil.getLrcOriginalPath(File(song.data).name)
|
||||
)
|
||||
newSyncedLyricsLauncher.launch(intent)
|
||||
}
|
||||
} else {
|
||||
LyricUtil.writeLrc(song, input.toString())
|
||||
}
|
||||
}
|
||||
positiveButton(res = R.string.save) {
|
||||
(lyricsSectionsAdapter.fragments[0].first as SyncedLyrics).loadLRCLyrics()
|
||||
}
|
||||
|
|
|
@ -0,0 +1,16 @@
|
|||
package code.name.monkey.retromusic.util
|
||||
|
||||
import android.content.Context
|
||||
import android.net.Uri
|
||||
import java.io.File
|
||||
|
||||
object FileUtils {
|
||||
fun copyFileToUri(context: Context, fromFile: File, toUri: Uri) {
|
||||
context.contentResolver.openOutputStream(toUri)
|
||||
?.use { output ->
|
||||
fromFile.inputStream().use { input ->
|
||||
input.copyTo(output)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
|
@ -118,7 +118,7 @@ object LyricUtil {
|
|||
return "$lrcRootPath$title - $artist.lrc"
|
||||
}
|
||||
|
||||
private fun getLrcOriginalPath(filePath: String): String {
|
||||
fun getLrcOriginalPath(filePath: String): String {
|
||||
return filePath.replace(filePath.substring(filePath.lastIndexOf(".") + 1), "lrc")
|
||||
}
|
||||
|
||||
|
|
|
@ -0,0 +1,25 @@
|
|||
package code.name.monkey.retromusic.util
|
||||
|
||||
import android.content.ContentUris
|
||||
import android.content.Context
|
||||
import android.net.Uri
|
||||
import android.os.Build
|
||||
import android.provider.MediaStore
|
||||
import androidx.annotation.RequiresApi
|
||||
|
||||
object UriUtil {
|
||||
@RequiresApi(Build.VERSION_CODES.Q)
|
||||
fun getUriFromPath(context: Context, path: String): Uri {
|
||||
val uri = MediaStore.Files.getContentUri(MediaStore.VOLUME_EXTERNAL)
|
||||
val proj = arrayOf(MediaStore.Files.FileColumns._ID)
|
||||
context.contentResolver.query(
|
||||
uri, proj, MediaStore.Files.FileColumns.DATA + "=?", arrayOf(path), null
|
||||
)?.use { cursor ->
|
||||
if (cursor.count != 0) {
|
||||
cursor.moveToFirst()
|
||||
return ContentUris.withAppendedId(uri, cursor.getLong(0))
|
||||
}
|
||||
}
|
||||
return Uri.EMPTY
|
||||
}
|
||||
}
|
Loading…
Add table
Add a link
Reference in a new issue