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

270 lines
9.1 KiB
Kotlin
Raw Blame History

This file contains invisible Unicode characters

This file contains invisible Unicode characters that are indistinguishable to humans but may be processed differently by a computer. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

package jp.juggler.subwaytooter
import android.app.Activity
import android.app.AlertDialog
import android.content.Intent
import android.graphics.Color
import android.media.RingtoneManager
import android.os.Bundle
import android.widget.CompoundButton
import androidx.appcompat.app.AppCompatActivity
import com.jrummyapps.android.colorpicker.dialogColorPicker
import jp.juggler.subwaytooter.databinding.ActHighlightEditBinding
import jp.juggler.subwaytooter.table.HighlightWord
import jp.juggler.subwaytooter.table.daoHighlightWord
import jp.juggler.util.backPressed
import jp.juggler.util.coroutine.launchAndShowError
import jp.juggler.util.data.decodeJsonObject
import jp.juggler.util.data.mayUri
import jp.juggler.util.data.notEmpty
import jp.juggler.util.data.notZero
import jp.juggler.util.log.LogCategory
import jp.juggler.util.log.showToast
import jp.juggler.util.long
import jp.juggler.util.string
import jp.juggler.util.ui.ActivityResultHandler
import jp.juggler.util.ui.attrColor
import jp.juggler.util.ui.decodeRingtonePickerResult
import jp.juggler.util.ui.isEnabledAlpha
import jp.juggler.util.ui.setNavigationBack
import org.jetbrains.anko.textColor
class ActHighlightWordEdit
: AppCompatActivity(),
CompoundButton.OnCheckedChangeListener {
companion object {
internal val log = LogCategory("ActHighlightWordEdit")
private const val COLOR_DIALOG_ID_TEXT = 1
private const val COLOR_DIALOG_ID_BACKGROUND = 2
private const val STATE_ITEM = "item"
private const val EXTRA_ITEM_ID = "itemId"
private const val EXTRA_INITIAL_TEXT = "initialText"
fun createIntent(activity: Activity, itemId: Long) =
Intent(activity, ActHighlightWordEdit::class.java).apply {
putExtra(EXTRA_ITEM_ID, itemId)
}
fun createIntent(activity: Activity, initialText: String) =
Intent(activity, ActHighlightWordEdit::class.java).apply {
putExtra(EXTRA_INITIAL_TEXT, initialText)
}
}
internal lateinit var item: HighlightWord
private val views by lazy {
ActHighlightEditBinding.inflate(layoutInflater)
}
private var bBusy = false
private val arNotificationSound = ActivityResultHandler(log) { r ->
r.decodeRingtonePickerResult?.let { uri ->
item.sound_uri = uri.toString()
item.sound_type = HighlightWord.SOUND_TYPE_CUSTOM
showSound()
}
}
override fun onCreate(savedInstanceState: Bundle?) {
backPressed {
AlertDialog.Builder(this)
.setCancelable(true)
.setMessage(R.string.discard_changes)
.setPositiveButton(R.string.no, null)
.setNegativeButton(R.string.yes) { _, _ -> finish() }
.show()
}
super.onCreate(savedInstanceState)
arNotificationSound.register(this)
App1.setActivityTheme(this)
initUI()
setResult(RESULT_CANCELED)
launchAndShowError {
fun loadData(): HighlightWord? {
savedInstanceState?.getString(STATE_ITEM)
?.decodeJsonObject()
?.let { return HighlightWord(it) }
intent?.string(EXTRA_INITIAL_TEXT)
?.let { return HighlightWord(it) }
intent?.long(EXTRA_ITEM_ID)
?.let { return daoHighlightWord.load(it) }
return null
}
val item = loadData()
if (item == null) {
log.d("missing source data")
finish()
return@launchAndShowError
}
this@ActHighlightWordEdit.item = item
views.etName.setText(item.name)
showSound()
showColor()
}
}
override fun onSaveInstanceState(outState: Bundle) {
super.onSaveInstanceState(outState)
try {
// ui may not initialized yet.
uiToData()
} catch (ex: Throwable) {
log.e(ex, "uiToData failed.")
}
item.encodeJson().toString().let { outState.putString(STATE_ITEM, it) }
}
private fun initUI() {
setContentView(views.root)
setSupportActionBar(views.toolbar)
setNavigationBack(views.toolbar)
fixHorizontalMargin(views.llContent)
views.swSound.setOnCheckedChangeListener(this)
views.swSpeech.setOnCheckedChangeListener(this)
setSwitchColor(views.swSound)
setSwitchColor(views.swSpeech)
views.btnDiscard.setOnClickListener { finish() }
views.btnSave.setOnClickListener { save() }
views.btnTextColorEdit.setOnClickListener {
launchAndShowError {
item.color_fg = Color.BLACK or dialogColorPicker(
colorInitial = item.color_fg.notZero(),
alphaEnabled = false,
)
showColor()
}
}
views.btnTextColorReset.setOnClickListener {
item.color_fg = 0
showColor()
}
views.btnBackgroundColorEdit.setOnClickListener {
launchAndShowError {
item.color_bg = dialogColorPicker(
colorInitial = item.color_bg.notZero(),
alphaEnabled = true,
).notZero() ?: 0x01000000
showColor()
}
}
views.btnBackgroundColorReset.setOnClickListener {
item.color_bg = 0
showColor()
}
views.btnNotificationSoundEdit.setOnClickListener { openNotificationSoundPicker() }
views.btnNotificationSoundReset.setOnClickListener {
item.sound_uri = null
item.sound_type = when {
views.swSound.isChecked -> HighlightWord.SOUND_TYPE_DEFAULT
else -> HighlightWord.SOUND_TYPE_NONE
}
showSound()
}
views.btnNotificationSoundTest.setOnClickListener {
ActHighlightWordList.sound(this, item)
}
}
override fun onCheckedChanged(buttonView: CompoundButton, isChecked: Boolean) {
if (bBusy) return
uiToData()
showSound()
}
//////////////////////////////////////////////////////////////////
private fun showSound() {
bBusy = true
try {
val isSoundEnabled = item.sound_type != HighlightWord.SOUND_TYPE_NONE
views.btnNotificationSoundTest.isEnabledAlpha = isSoundEnabled
views.swSound.isChecked = isSoundEnabled
views.swSpeech.isChecked = item.speech != 0
} finally {
bBusy = false
}
}
private fun showColor() {
bBusy = true
try {
views.etName.setBackgroundColor(item.color_bg) // may 0
views.etName.textColor =
item.color_fg.notZero() ?: attrColor(android.R.attr.textColorPrimary)
} finally {
bBusy = false
}
}
private fun openNotificationSoundPicker() {
val intent = Intent(RingtoneManager.ACTION_RINGTONE_PICKER)
intent.putExtra(RingtoneManager.EXTRA_RINGTONE_TYPE, RingtoneManager.TYPE_NOTIFICATION)
intent.putExtra(RingtoneManager.EXTRA_RINGTONE_TITLE, R.string.notification_sound)
intent.putExtra(RingtoneManager.EXTRA_RINGTONE_SHOW_SILENT, false)
intent.putExtra(RingtoneManager.EXTRA_RINGTONE_SHOW_DEFAULT, false)
item.sound_uri.mayUri()?.let { uri ->
intent.putExtra(RingtoneManager.EXTRA_RINGTONE_EXISTING_URI, uri)
}
val chooser = Intent.createChooser(intent, getString(R.string.notification_sound))
arNotificationSound.launch(chooser)
}
private fun uiToData() {
item.name = views.etName.text.toString().trim { it <= ' ' || it == ' ' }
item.sound_type = when {
!views.swSound.isChecked -> HighlightWord.SOUND_TYPE_NONE
item.sound_uri?.notEmpty() == null -> HighlightWord.SOUND_TYPE_DEFAULT
else -> HighlightWord.SOUND_TYPE_CUSTOM
}
item.speech = when (views.swSpeech.isChecked) {
false -> 0
else -> 1
}
}
private fun save() {
launchAndShowError {
uiToData()
val name = item.name
if (name.isNullOrBlank()) {
showToast(true, R.string.cant_leave_empty_keyword)
return@launchAndShowError
}
val other = daoHighlightWord.load(name)
if (other != null && other.id != item.id) {
showToast(true, R.string.cant_save_duplicated_keyword)
return@launchAndShowError
}
daoHighlightWord.save(applicationContext, item)
App1.getAppState(applicationContext).enableSpeech()
showToast(false, R.string.saved)
setResult(RESULT_OK)
finish()
}
}
}