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

196 lines
5.7 KiB
Kotlin

package jp.juggler.subwaytooter.dialog
import android.annotation.SuppressLint
import android.app.Activity
import android.app.Dialog
import android.support.annotation.StringRes
import android.text.InputType
import android.view.View
import android.view.WindowManager
import android.view.inputmethod.EditorInfo
import android.widget.*
import jp.juggler.subwaytooter.R
import jp.juggler.util.LogCategory
import jp.juggler.util.showToast
import java.io.BufferedReader
import java.io.InputStreamReader
import java.util.*
object LoginForm {
private val log = LogCategory("LoginForm")
private class StringArray : ArrayList<String>()
enum class Action(
val pos : Int,
@StringRes val idName : Int,
@StringRes val idDesc : Int
) {
Existing(0, R.string.existing_account, R.string.existing_account_desc),
Pseudo(1, R.string.pseudo_account, R.string.pseudo_account_desc),
Create(2, R.string.create_account, R.string.create_account_desc),
Token(3, R.string.input_access_token, R.string.input_access_token_desc),
}
@SuppressLint("InflateParams")
fun showLoginForm(
activity : Activity,
instanceArg : String?,
onClickOk : (
dialog : Dialog,
instance : String,
action : Action
) -> Unit
) {
val view = activity.layoutInflater.inflate(R.layout.dlg_account_add, null, false)
val etInstance : AutoCompleteTextView = view.findViewById(R.id.etInstance)
val btnOk : View = view.findViewById(R.id.btnOk)
val tvActionDesc : TextView = view.findViewById(R.id.tvActionDesc)
fun Spinner.getActionDesc() : String =
Action.values()
.find { it.pos == selectedItemPosition }
?.let { activity.getString(it.idDesc) }
?: "(null)"
val spAction = view.findViewById<Spinner>(R.id.spAction).also { sp ->
sp.adapter = ArrayAdapter(
activity,
android.R.layout.simple_spinner_item,
Action.values().map { activity.getString(it.idName) }.toTypedArray()
).apply {
setDropDownViewResource(R.layout.lv_spinner_dropdown)
}
sp.onItemSelectedListener = object : AdapterView.OnItemSelectedListener {
override fun onNothingSelected(parent : AdapterView<*>?) { // TODO
tvActionDesc.text = sp.getActionDesc()
}
override fun onItemSelected(
parent : AdapterView<*>?,
view : View?,
position : Int,
id : Long
) {
tvActionDesc.text = sp.getActionDesc()
}
}
}
tvActionDesc.text = spAction.getActionDesc()
if(instanceArg != null && instanceArg.isNotEmpty()) {
etInstance.setText(instanceArg)
etInstance.inputType = InputType.TYPE_NULL
etInstance.isEnabled = false
etInstance.isFocusable = false
} else {
etInstance.setOnEditorActionListener(TextView.OnEditorActionListener { _, actionId, _ ->
if(actionId == EditorInfo.IME_ACTION_DONE) {
btnOk.performClick()
return@OnEditorActionListener true
}
false
})
}
val dialog = Dialog(activity)
dialog.setContentView(view)
// 警告がでるが、パラメータ名の指定を削ってはいけない
btnOk.setOnClickListener { _ ->
val instance = etInstance.text.toString().trim { it <= ' ' }
when {
instance.isEmpty() ->
showToast(activity, true, R.string.instance_not_specified)
instance.contains("/") || instance.contains("@") ->
showToast(activity, true, R.string.instance_not_need_slash)
else -> {
val actionPos = spAction.selectedItemPosition
when(val action = Action.values().find { it.pos == actionPos }) {
null -> {
} // will no happened
else -> onClickOk(dialog, instance, action)
}
}
}
}
view.findViewById<View>(R.id.btnCancel).setOnClickListener { dialog.cancel() }
val instance_list = ArrayList<String>()
try {
activity.resources.openRawResource(R.raw.server_list).use { inStream ->
val br = BufferedReader(InputStreamReader(inStream, "UTF-8"))
while(true) {
val s : String = br.readLine()?.trim { it <= ' ' }?.toLowerCase() ?: break
if(s.isNotEmpty()) instance_list.add(s)
}
}
} catch(ex : Throwable) {
log.trace(ex)
}
val adapter = object : ArrayAdapter<String>(
activity, R.layout.lv_spinner_dropdown, ArrayList()
) {
val nameFilter : Filter = object : Filter() {
override fun convertResultToString(value : Any) : CharSequence {
return value as String
}
override fun performFiltering(constraint : CharSequence?) : Filter.FilterResults {
val result = Filter.FilterResults()
if(constraint?.isNotEmpty() == true) {
val key = constraint.toString().toLowerCase()
// suggestions リストは毎回生成する必要がある。publishResultsと同時にアクセスされる場合がある
val suggestions = StringArray()
for(s in instance_list) {
if(s.contains(key)) {
suggestions.add(s)
if(suggestions.size >= 20) break
}
}
result.values = suggestions
result.count = suggestions.size
}
return result
}
override fun publishResults(
constraint : CharSequence?,
results : Filter.FilterResults?
) {
clear()
val values = results?.values
if(values is StringArray) {
for(s in values) {
add(s)
}
}
notifyDataSetChanged()
}
}
override fun getFilter() : Filter {
return nameFilter
}
}
adapter.setDropDownViewResource(R.layout.lv_spinner_dropdown)
etInstance.setAdapter<ArrayAdapter<String>>(adapter)
dialog.window?.setLayout(
WindowManager.LayoutParams.MATCH_PARENT,
WindowManager.LayoutParams.WRAP_CONTENT
)
dialog.show()
}
}