SubwayTooter-Android-App/app/src/main/java/jp/juggler/subwaytooter/ActHighlightWordList.kt

237 lines
7.5 KiB
Kotlin
Raw Normal View History

package jp.juggler.subwaytooter
import android.content.Context
import android.media.Ringtone
import android.media.RingtoneManager
import android.net.Uri
import android.os.Bundle
import android.view.View
import android.view.ViewGroup
import android.widget.AdapterView
import android.widget.BaseAdapter
import androidx.appcompat.app.AppCompatActivity
import jp.juggler.subwaytooter.databinding.ActHighlightListBinding
import jp.juggler.subwaytooter.databinding.LvHighlightWordBinding
import jp.juggler.subwaytooter.dialog.DlgConfirm.confirm
import jp.juggler.subwaytooter.table.HighlightWord
import jp.juggler.util.coroutine.launchAndShowError
import jp.juggler.util.data.cast
import jp.juggler.util.data.mayUri
import jp.juggler.util.data.notZero
import jp.juggler.util.log.LogCategory
import jp.juggler.util.log.errorEx
import jp.juggler.util.ui.*
2018-12-01 00:02:18 +01:00
import java.lang.ref.WeakReference
class ActHighlightWordList : AppCompatActivity() {
companion object {
private val log = LogCategory("ActHighlightWordList")
private var lastRingtone: WeakReference<Ringtone>? = null
private fun stopLastRingtone() {
try {
lastRingtone?.get()?.stop()
} catch (ex: Throwable) {
log.e(ex, "stopLastRingtone failed.")
} finally {
lastRingtone = null
}
}
fun tryRingTone(context: Context, uri: Uri?): Boolean {
try {
uri?.let { RingtoneManager.getRingtone(context, it) }
?.let { ringtone ->
stopLastRingtone()
lastRingtone = WeakReference(ringtone)
ringtone.play()
return true
}
} catch (ex: Throwable) {
log.e(ex, "tryRingTone failed.")
}
// fall null case
return false
}
fun sound(context: Context, item: HighlightWord?) {
if (lastRingtone?.get()?.isPlaying == true) {
stopLastRingtone()
return
}
item ?: return
val soundType = item.sound_type
when {
// サウンドなし
soundType == HighlightWord.SOUND_TYPE_NONE -> Unit
// カスタムサウンドを鳴らせた
soundType == HighlightWord.SOUND_TYPE_CUSTOM && tryRingTone(
context,
item.sound_uri.mayUri()
) -> Unit
// 失敗した場合も通常の音を鳴らす
else -> tryRingTone(
context,
RingtoneManager.getDefaultUri(RingtoneManager.TYPE_NOTIFICATION)
)
}
}
}
private val views by lazy {
ActHighlightListBinding.inflate(layoutInflater)
}
private lateinit var listAdapter: MyListAdapter
private val arEdit = ActivityResultHandler(log) { r ->
if (r.isNotOk) return@ActivityResultHandler
loadData()
}
// @Override public void onBackPressed(){
// setResult( RESULT_OK );
// super.onBackPressed();
// }
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
arEdit.register(this)
App1.setActivityTheme(this)
initUI()
loadData()
}
override fun onDestroy() {
super.onDestroy()
stopLastRingtone()
}
private fun initUI() {
setContentView(views.root)
setSupportActionBar(views.toolbar)
setNavigationBack(views.toolbar)
fixHorizontalMargin(views.llContent)
// リストのアダプター
listAdapter = MyListAdapter()
// ハンドル部分をドラッグで並べ替えできるRecyclerView
views.listView.adapter = listAdapter
views.listView.onItemClickListener = listAdapter
views.btnAdd.setOnClickListener { create() }
}
private fun loadData() {
try {
listAdapter.items = buildList {
HighlightWord.createCursor().use { cursor ->
val colIdx = HighlightWord.ColIdx(cursor)
while (cursor.moveToNext()) {
try {
add(HighlightWord(cursor, colIdx))
} catch (ex: Throwable) {
log.e(ex, "load error.")
}
}
}
}
} catch (ex: Throwable) {
errorEx(ex, "query error.")
}
}
private fun create() {
arEdit.launch(ActHighlightWordEdit.createIntent(this, ""))
}
private fun edit(item: HighlightWord?) {
item ?: return
arEdit.launch(ActHighlightWordEdit.createIntent(this, item.id))
}
private fun delete(item: HighlightWord?) {
item ?: return
val activity = this
launchAndShowError {
confirm(getString(R.string.delete_confirm, item.name))
item.delete(activity)
listAdapter.remove(item)
}
}
private fun speech(item: HighlightWord?) {
item ?: return
App1.getAppState(this@ActHighlightWordList)
.addSpeech(item.name, dedupMode = DedupMode.None)
}
// リスト要素のViewHolder
private inner class MyViewHolder(
parent: ViewGroup?,
) {
val views = LvHighlightWordBinding.inflate(layoutInflater, parent, false)
private var lastItem: HighlightWord? = null
init {
views.root.tag = this
views.btnSound.setOnClickListener { sound(this@ActHighlightWordList, lastItem) }
views.btnSpeech.setOnClickListener { speech(lastItem) }
views.btnDelete.setOnClickListener { delete(lastItem) }
}
fun bind(item: HighlightWord?) {
item ?: return
lastItem = item
views.tvName.text = item.name
views.tvName.setBackgroundColor(item.color_bg)
views.tvName.setTextColor(
item.color_fg.notZero()
?: attrColor(android.R.attr.textColorPrimary)
)
views.btnSound.isEnabledAlpha = item.sound_type != HighlightWord.SOUND_TYPE_NONE
views.btnSpeech.isEnabledAlpha = item.speech != 0
}
}
private inner class MyListAdapter : BaseAdapter(), AdapterView.OnItemClickListener {
var items: List<HighlightWord> = emptyList()
set(value) {
field = value
notifyDataSetChanged()
}
fun remove(item: HighlightWord) {
items = items.filter { it != item }
}
override fun getCount() = items.size
override fun getItem(position: Int) = items.elementAtOrNull(position)
override fun getItemId(position: Int) = 0L
override fun getView(position: Int, convertView: View?, parent: ViewGroup?) =
(convertView?.tag?.cast() ?: MyViewHolder(parent))
.also { it.bind(items.elementAtOrNull(position)) }
.views.root
override fun onItemClick(
parent: AdapterView<*>?,
view: View?,
position: Int,
id: Long,
) {
edit(items.elementAtOrNull(position))
}
}
}