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

231 lines
7.3 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.subwaytooter.table.daoHighlightWord
import jp.juggler.util.coroutine.AppDispatchers
import jp.juggler.util.coroutine.launchAndShowError
import jp.juggler.util.data.cast
import jp.juggler.util.data.mayUri
import jp.juggler.util.data.notBlank
import jp.juggler.util.data.notZero
import jp.juggler.util.log.LogCategory
import jp.juggler.util.ui.*
import kotlinx.coroutines.withContext
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
}
}
private 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() {
launchAndShowError {
listAdapter.items = withContext(AppDispatchers.IO) {
daoHighlightWord.listAll()
}
}
}
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))
daoHighlightWord.delete(applicationContext, item)
listAdapter.remove(item)
App1.getAppState(activity).enableSpeech()
}
}
private fun speech(item: HighlightWord?) {
item?.name?.notBlank()?.let {
App1.getAppState(this@ActHighlightWordList)
.addSpeech(it, 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))
}
}
}