e-ntfy-android/app/src/main/java/io/heckel/ntfy/ui/AddFragment.kt

500 lines
22 KiB
Kotlin
Raw Normal View History

2021-10-28 05:04:14 +02:00
package io.heckel.ntfy.ui
2021-10-28 04:25:02 +02:00
import android.app.Activity
2021-10-28 04:25:02 +02:00
import android.app.AlertDialog
import android.app.Dialog
import android.content.Context
2021-10-28 04:25:02 +02:00
import android.os.Bundle
import android.text.Editable
import android.text.TextWatcher
import android.util.TypedValue
2021-10-28 04:25:02 +02:00
import android.view.View
import android.view.WindowManager
import android.view.inputmethod.InputMethodManager
import android.widget.*
2021-10-28 04:25:02 +02:00
import androidx.fragment.app.DialogFragment
import androidx.lifecycle.lifecycleScope
2021-10-28 04:25:02 +02:00
import com.google.android.material.textfield.TextInputEditText
2021-11-25 21:45:12 +01:00
import com.google.android.material.textfield.TextInputLayout
import io.heckel.ntfy.BuildConfig
2021-10-28 05:04:14 +02:00
import io.heckel.ntfy.R
2022-01-18 20:28:48 +01:00
import io.heckel.ntfy.db.Repository
2022-01-28 01:57:43 +01:00
import io.heckel.ntfy.db.User
import io.heckel.ntfy.util.Log
2022-01-28 01:57:43 +01:00
import io.heckel.ntfy.msg.ApiService
import io.heckel.ntfy.util.topicUrl
import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.launch
2021-10-28 04:25:02 +02:00
class AddFragment : DialogFragment() {
2022-01-28 01:57:43 +01:00
private val api = ApiService()
private lateinit var repository: Repository
private lateinit var subscribeListener: SubscribeListener
2022-01-28 01:57:43 +01:00
private lateinit var subscribeView: View
private lateinit var loginView: View
private lateinit var positiveButton: Button
private lateinit var negativeButton: Button
2022-01-28 01:57:43 +01:00
2022-01-28 04:42:22 +01:00
// Subscribe page
2022-01-28 06:02:20 +01:00
private lateinit var subscribeTopicText: TextInputEditText
private lateinit var subscribeBaseUrlLayout: TextInputLayout
private lateinit var subscribeBaseUrlText: AutoCompleteTextView
private lateinit var subscribeUseAnotherServerCheckbox: CheckBox
private lateinit var subscribeUseAnotherServerDescription: TextView
private lateinit var subscribeInstantDeliveryBox: View
private lateinit var subscribeInstantDeliveryCheckbox: CheckBox
private lateinit var subscribeInstantDeliveryDescription: View
private lateinit var subscribeProgress: ProgressBar
2022-02-05 01:52:34 +01:00
private lateinit var subscribeErrorText: TextView
private lateinit var subscribeErrorTextImage: View
2021-10-28 04:25:02 +02:00
2022-01-28 04:42:22 +01:00
// Login page
2022-01-28 01:57:43 +01:00
private lateinit var users: List<User>
2022-01-28 06:02:20 +01:00
private lateinit var loginUsernameText: TextInputEditText
private lateinit var loginPasswordText: TextInputEditText
2022-01-28 04:42:22 +01:00
private lateinit var loginProgress: ProgressBar
2022-02-05 01:52:34 +01:00
private lateinit var loginErrorText: TextView
private lateinit var loginErrorTextImage: View
2022-01-28 01:57:43 +01:00
2021-11-25 21:45:12 +01:00
private lateinit var baseUrls: List<String> // List of base URLs already used, excluding app_base_url
interface SubscribeListener {
fun onSubscribe(topic: String, baseUrl: String, instant: Boolean)
}
override fun onAttach(context: Context) {
super.onAttach(context)
subscribeListener = activity as SubscribeListener
}
2021-10-28 04:25:02 +02:00
override fun onCreateDialog(savedInstanceState: Bundle?): Dialog {
if (activity == null) {
throw IllegalStateException("Activity cannot be null")
}
// Dependencies (Fragments need a default constructor)
repository = Repository.getInstance(requireActivity())
// Build root view
2021-11-22 21:45:43 +01:00
val view = requireActivity().layoutInflater.inflate(R.layout.fragment_add_dialog, null)
2022-01-28 01:57:43 +01:00
// Main "pages"
subscribeView = view.findViewById(R.id.add_dialog_subscribe_view)
subscribeView.visibility = View.VISIBLE
2022-01-28 01:57:43 +01:00
loginView = view.findViewById(R.id.add_dialog_login_view)
loginView.visibility = View.GONE
// Fields for "subscribe page"
2022-02-05 01:52:34 +01:00
subscribeTopicText = view.findViewById(R.id.add_dialog_subscribe_topic_text)
subscribeBaseUrlLayout = view.findViewById(R.id.add_dialog_subscribe_base_url_layout)
subscribeBaseUrlLayout.background = view.background
2022-02-05 01:52:34 +01:00
subscribeBaseUrlText = view.findViewById(R.id.add_dialog_subscribe_base_url_text)
subscribeBaseUrlText.background = view.background
2022-02-05 01:52:34 +01:00
subscribeInstantDeliveryBox = view.findViewById(R.id.add_dialog_subscribe_instant_delivery_box)
subscribeInstantDeliveryCheckbox = view.findViewById(R.id.add_dialog_subscribe_instant_delivery_checkbox)
subscribeInstantDeliveryDescription = view.findViewById(R.id.add_dialog_subscribe_instant_delivery_description)
subscribeUseAnotherServerCheckbox = view.findViewById(R.id.add_dialog_subscribe_use_another_server_checkbox)
subscribeUseAnotherServerDescription = view.findViewById(R.id.add_dialog_subscribe_use_another_server_description)
subscribeProgress = view.findViewById(R.id.add_dialog_subscribe_progress)
subscribeErrorText = view.findViewById(R.id.add_dialog_subscribe_error_text)
subscribeErrorText.visibility = View.GONE
subscribeErrorTextImage = view.findViewById(R.id.add_dialog_subscribe_error_text_image)
subscribeErrorTextImage.visibility = View.GONE
// Hack: Make end icon smaller, see https://stackoverflow.com/a/57098715/1440785
val dimension = TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_DIP, 30f, resources.displayMetrics)
val endIconImageView = subscribeBaseUrlLayout.findViewById<ImageView>(R.id.text_input_end_icon)
endIconImageView.minimumHeight = dimension.toInt()
endIconImageView.minimumWidth = dimension.toInt()
subscribeBaseUrlLayout.requestLayout()
2022-01-28 01:57:43 +01:00
// Fields for "login page"
2022-01-28 06:02:20 +01:00
loginUsernameText = view.findViewById(R.id.add_dialog_login_username)
loginPasswordText = view.findViewById(R.id.add_dialog_login_password)
2022-01-28 04:42:22 +01:00
loginProgress = view.findViewById(R.id.add_dialog_login_progress)
2022-02-05 01:52:34 +01:00
loginErrorText = view.findViewById(R.id.add_dialog_login_error_text)
loginErrorTextImage = view.findViewById(R.id.add_dialog_login_error_text_image)
2022-01-28 01:57:43 +01:00
// Set "Use another server" description based on flavor
2022-01-28 06:02:20 +01:00
subscribeUseAnotherServerDescription.text = if (BuildConfig.FIREBASE_AVAILABLE) {
getString(R.string.add_dialog_use_another_server_description)
} else {
getString(R.string.add_dialog_use_another_server_description_noinstant)
}
2021-11-25 21:45:12 +01:00
// Base URL dropdown behavior; Oh my, why is this so complicated?!
val toggleEndIcon = {
2022-01-28 06:02:20 +01:00
if (subscribeBaseUrlText.text.isNotEmpty()) {
subscribeBaseUrlLayout.setEndIconDrawable(R.drawable.ic_cancel_gray_24dp)
2021-11-25 21:45:12 +01:00
} else if (baseUrls.isEmpty()) {
2022-01-28 06:02:20 +01:00
subscribeBaseUrlLayout.setEndIconDrawable(0)
2021-11-25 21:45:12 +01:00
} else {
2022-01-28 06:02:20 +01:00
subscribeBaseUrlLayout.setEndIconDrawable(R.drawable.ic_drop_down_gray_24dp)
2021-11-25 21:45:12 +01:00
}
}
2022-01-28 06:02:20 +01:00
subscribeBaseUrlLayout.setEndIconOnClickListener {
if (subscribeBaseUrlText.text.isNotEmpty()) {
subscribeBaseUrlText.text.clear()
2021-11-25 21:45:12 +01:00
if (baseUrls.isEmpty()) {
2022-01-28 06:02:20 +01:00
subscribeBaseUrlLayout.setEndIconDrawable(0)
2021-11-25 21:45:12 +01:00
} else {
2022-01-28 06:02:20 +01:00
subscribeBaseUrlLayout.setEndIconDrawable(R.drawable.ic_drop_down_gray_24dp)
2021-11-25 21:45:12 +01:00
}
2022-01-28 06:02:20 +01:00
} else if (subscribeBaseUrlText.text.isEmpty() && baseUrls.isNotEmpty()) {
subscribeBaseUrlLayout.setEndIconDrawable(R.drawable.ic_drop_up_gray_24dp)
subscribeBaseUrlText.showDropDown()
2021-11-25 21:45:12 +01:00
}
}
2022-01-28 06:02:20 +01:00
subscribeBaseUrlText.setOnDismissListener { toggleEndIcon() }
subscribeBaseUrlText.addTextChangedListener(object : TextWatcher {
2021-11-25 21:45:12 +01:00
override fun afterTextChanged(s: Editable?) {
toggleEndIcon()
}
override fun onTextChanged(s: CharSequence?, start: Int, before: Int, count: Int) {
// Nothing
}
override fun beforeTextChanged(s: CharSequence?, start: Int, count: Int, after: Int) {
// Nothing
}
})
2022-01-28 01:57:43 +01:00
// Fill autocomplete for base URL & users drop-down
2021-11-25 21:45:12 +01:00
lifecycleScope.launch(Dispatchers.IO) {
2022-01-28 01:57:43 +01:00
// Auto-complete
2021-11-25 21:45:12 +01:00
val appBaseUrl = getString(R.string.app_base_url)
baseUrls = repository.getSubscriptions()
.groupBy { it.baseUrl }
.map { it.key }
2021-11-25 21:45:12 +01:00
.filterNot { it == appBaseUrl }
.sorted()
val activity = activity ?: return@launch // We may have pressed "Cancel"
val adapter = ArrayAdapter(activity, R.layout.fragment_add_dialog_dropdown_item, baseUrls)
activity.runOnUiThread {
2022-01-28 06:02:20 +01:00
subscribeBaseUrlText.threshold = 1
subscribeBaseUrlText.setAdapter(adapter)
if (baseUrls.count() == 1) {
2022-01-28 06:02:20 +01:00
subscribeBaseUrlLayout.setEndIconDrawable(R.drawable.ic_cancel_gray_24dp)
subscribeBaseUrlText.setText(baseUrls.first())
2021-11-27 22:18:09 +01:00
} else if (baseUrls.count() > 1) {
2022-01-28 06:02:20 +01:00
subscribeBaseUrlLayout.setEndIconDrawable(R.drawable.ic_drop_down_gray_24dp)
2021-11-27 22:18:09 +01:00
} else {
2022-01-28 06:02:20 +01:00
subscribeBaseUrlLayout.setEndIconDrawable(0)
2021-11-25 21:45:12 +01:00
}
}
2022-01-28 01:57:43 +01:00
// Users dropdown
users = repository.getUsers()
2021-11-25 21:45:12 +01:00
}
2021-11-24 22:12:51 +01:00
// Show/hide based on flavor
2022-01-28 06:02:20 +01:00
subscribeInstantDeliveryBox.visibility = if (BuildConfig.FIREBASE_AVAILABLE) View.VISIBLE else View.GONE
2021-11-24 22:12:51 +01:00
// Username/password validation on type
2022-02-11 21:55:08 +01:00
val loginTextWatcher = object : TextWatcher {
override fun afterTextChanged(s: Editable?) {
validateInputLoginView()
}
override fun onTextChanged(s: CharSequence?, start: Int, before: Int, count: Int) {
// Nothing
}
override fun beforeTextChanged(s: CharSequence?, start: Int, count: Int, after: Int) {
// Nothing
}
}
2022-02-11 21:55:08 +01:00
loginUsernameText.addTextChangedListener(loginTextWatcher)
loginPasswordText.addTextChangedListener(loginTextWatcher)
// Build dialog
val dialog = AlertDialog.Builder(activity)
.setView(view)
.setPositiveButton(R.string.add_dialog_button_subscribe) { _, _ ->
2022-01-28 01:57:43 +01:00
// This will be overridden below to avoid closing the dialog immediately
}
.setNegativeButton(R.string.add_dialog_button_cancel) { _, _ ->
// This will be overridden below
}
.create()
// Show keyboard when the dialog is shown (see https://stackoverflow.com/a/19573049/1440785)
2022-02-11 21:55:08 +01:00
dialog.window?.setSoftInputMode(WindowManager.LayoutParams.SOFT_INPUT_STATE_VISIBLE)
// Add logic to disable "Subscribe" button on invalid input
dialog.setOnShowListener {
positiveButton = dialog.getButton(AlertDialog.BUTTON_POSITIVE)
positiveButton.isEnabled = false
positiveButton.setOnClickListener {
positiveButtonClick()
}
negativeButton = dialog.getButton(AlertDialog.BUTTON_NEGATIVE)
negativeButton.setOnClickListener {
negativeButtonClick()
2022-01-28 01:57:43 +01:00
}
2022-02-11 21:55:08 +01:00
val subscribeTextWatcher = object : TextWatcher {
override fun afterTextChanged(s: Editable?) {
validateInputSubscribeView()
2021-10-28 04:25:02 +02:00
}
override fun onTextChanged(s: CharSequence?, start: Int, before: Int, count: Int) {
// Nothing
2021-10-28 04:25:02 +02:00
}
override fun beforeTextChanged(s: CharSequence?, start: Int, count: Int, after: Int) {
// Nothing
2021-10-28 04:25:02 +02:00
}
}
2022-02-11 21:55:08 +01:00
subscribeTopicText.addTextChangedListener(subscribeTextWatcher)
subscribeBaseUrlText.addTextChangedListener(subscribeTextWatcher)
2022-01-28 06:02:20 +01:00
subscribeInstantDeliveryCheckbox.setOnCheckedChangeListener { _, isChecked ->
if (isChecked) subscribeInstantDeliveryDescription.visibility = View.VISIBLE
else subscribeInstantDeliveryDescription.visibility = View.GONE
}
2022-01-28 06:02:20 +01:00
subscribeUseAnotherServerCheckbox.setOnCheckedChangeListener { _, isChecked ->
if (isChecked) {
2022-01-28 06:02:20 +01:00
subscribeUseAnotherServerDescription.visibility = View.VISIBLE
subscribeBaseUrlLayout.visibility = View.VISIBLE
subscribeInstantDeliveryBox.visibility = View.GONE
subscribeInstantDeliveryDescription.visibility = View.GONE
} else {
2022-01-28 06:02:20 +01:00
subscribeUseAnotherServerDescription.visibility = View.GONE
subscribeBaseUrlLayout.visibility = View.GONE
subscribeInstantDeliveryBox.visibility = if (BuildConfig.FIREBASE_AVAILABLE) View.VISIBLE else View.GONE
if (subscribeInstantDeliveryCheckbox.isChecked) subscribeInstantDeliveryDescription.visibility = View.VISIBLE
else subscribeInstantDeliveryDescription.visibility = View.GONE
2021-11-14 01:26:37 +01:00
}
validateInputSubscribeView()
2021-10-28 04:25:02 +02:00
}
subscribeUseAnotherServerCheckbox.isChecked = this::baseUrls.isInitialized && baseUrls.count() == 1
// Focus topic text (keyboard is shown too, see above)
subscribeTopicText.requestFocus()
}
2021-10-28 04:25:02 +02:00
return dialog
2021-10-28 04:25:02 +02:00
}
private fun positiveButtonClick() {
2022-01-28 06:02:20 +01:00
val topic = subscribeTopicText.text.toString()
2022-01-28 01:57:43 +01:00
val baseUrl = getBaseUrl()
if (subscribeView.visibility == View.VISIBLE) {
checkReadAndMaybeShowLogin(baseUrl, topic)
2022-01-28 01:57:43 +01:00
} else if (loginView.visibility == View.VISIBLE) {
loginAndMaybeDismiss(baseUrl, topic)
2022-01-28 01:57:43 +01:00
}
}
private fun checkReadAndMaybeShowLogin(baseUrl: String, topic: String) {
2022-01-28 06:02:20 +01:00
subscribeProgress.visibility = View.VISIBLE
2022-02-05 01:52:34 +01:00
subscribeErrorText.visibility = View.GONE
subscribeErrorTextImage.visibility = View.GONE
enableSubscribeView(false)
2022-01-28 01:57:43 +01:00
lifecycleScope.launch(Dispatchers.IO) {
2022-01-28 06:02:20 +01:00
try {
val user = repository.getUser(baseUrl) // May be null
val authorized = api.checkAuth(baseUrl, topic, user)
2022-01-28 06:02:20 +01:00
if (authorized) {
Log.d(TAG, "Access granted to topic ${topicUrl(baseUrl, topic)}")
dismissDialog()
2022-01-28 06:02:20 +01:00
} else {
if (user != null) {
Log.w(TAG, "Access not allowed to topic ${topicUrl(baseUrl, topic)}, but user already exists")
showErrorAndReenableSubscribeView(getString(R.string.add_dialog_login_error_not_authorized, user.username))
} else {
Log.w(TAG, "Access not allowed to topic ${topicUrl(baseUrl, topic)}, showing login dialog")
val activity = activity ?: return@launch // We may have pressed "Cancel"
activity.runOnUiThread {
2022-02-11 21:55:08 +01:00
showLoginView(activity)
}
2022-01-28 06:02:20 +01:00
}
}
} catch (e: Exception) {
Log.w(TAG, "Connection to topic failed: ${e.message}", e)
2022-02-05 01:52:34 +01:00
showErrorAndReenableSubscribeView(e.message)
2022-01-28 01:57:43 +01:00
}
}
}
2022-02-05 01:52:34 +01:00
private fun showErrorAndReenableSubscribeView(message: String?) {
val activity = activity ?: return // We may have pressed "Cancel"
activity.runOnUiThread {
subscribeProgress.visibility = View.GONE
2022-02-05 01:52:34 +01:00
subscribeErrorText.visibility = View.VISIBLE
subscribeErrorText.text = message
subscribeErrorTextImage.visibility = View.VISIBLE
enableSubscribeView(true)
}
}
private fun loginAndMaybeDismiss(baseUrl: String, topic: String) {
2022-01-28 04:42:22 +01:00
loginProgress.visibility = View.VISIBLE
2022-02-05 01:52:34 +01:00
loginErrorText.visibility = View.GONE
loginErrorTextImage.visibility = View.GONE
enableLoginView(false)
val user = User(
baseUrl = baseUrl,
username = loginUsernameText.text.toString(),
password = loginPasswordText.text.toString()
)
2022-01-28 01:57:43 +01:00
lifecycleScope.launch(Dispatchers.IO) {
Log.d(TAG, "Checking read access for user ${user.username} to topic ${topicUrl(baseUrl, topic)}")
2022-01-28 06:02:20 +01:00
try {
val authorized = api.checkAuth(baseUrl, topic, user)
2022-01-28 06:02:20 +01:00
if (authorized) {
Log.d(TAG, "Access granted for user ${user.username} to topic ${topicUrl(baseUrl, topic)}, adding to database")
repository.addUser(user)
dismissDialog()
2022-01-28 06:02:20 +01:00
} else {
Log.w(TAG, "Access not allowed for user ${user.username} to topic ${topicUrl(baseUrl, topic)}")
showErrorAndReenableLoginView(getString(R.string.add_dialog_login_error_not_authorized, user.username))
2022-01-28 01:57:43 +01:00
}
2022-01-28 06:02:20 +01:00
} catch (e: Exception) {
Log.w(TAG, "Connection to topic failed during login: ${e.message}", e)
2022-02-05 01:52:34 +01:00
showErrorAndReenableLoginView(e.message)
2022-01-28 01:57:43 +01:00
}
}
}
2022-02-05 01:52:34 +01:00
private fun showErrorAndReenableLoginView(message: String?) {
val activity = activity ?: return // We may have pressed "Cancel"
activity.runOnUiThread {
loginProgress.visibility = View.GONE
2022-02-05 01:52:34 +01:00
loginErrorText.visibility = View.VISIBLE
loginErrorText.text = message
loginErrorTextImage.visibility = View.VISIBLE
enableLoginView(true)
}
}
private fun negativeButtonClick() {
if (subscribeView.visibility == View.VISIBLE) {
dialog?.cancel()
} else if (loginView.visibility == View.VISIBLE) {
showSubscribeView()
}
}
private fun validateInputSubscribeView() {
2022-02-11 16:46:55 +01:00
if (!this::positiveButton.isInitialized) return // As per crash seen in Google Play
lifecycleScope.launch(Dispatchers.IO) {
val baseUrl = getBaseUrl()
val topic = subscribeTopicText.text.toString()
val subscription = repository.getSubscription(baseUrl, topic)
activity?.let {
it.runOnUiThread {
if (subscription != null || DISALLOWED_TOPICS.contains(topic)) {
positiveButton.isEnabled = false
} else if (subscribeUseAnotherServerCheckbox.isChecked) {
positiveButton.isEnabled = topic.isNotBlank()
&& "[-_A-Za-z0-9]{1,64}".toRegex().matches(topic)
&& baseUrl.isNotBlank()
&& "^https?://.+".toRegex().matches(baseUrl)
} else {
positiveButton.isEnabled = topic.isNotBlank()
&& "[-_A-Za-z0-9]{1,64}".toRegex().matches(topic)
}
}
}
}
}
private fun validateInputLoginView() {
2022-02-11 16:46:55 +01:00
if (!this::positiveButton.isInitialized) return // As per crash seen in Google Play
if (loginUsernameText.visibility == View.GONE) {
positiveButton.isEnabled = true
} else {
positiveButton.isEnabled = (loginUsernameText.text?.isNotEmpty() ?: false)
&& (loginPasswordText.text?.isNotEmpty() ?: false)
}
}
private fun dismissDialog() {
2022-01-28 01:57:43 +01:00
Log.d(TAG, "Closing dialog and calling onSubscribe handler")
val activity = activity?: return // We may have pressed "Cancel"
activity.runOnUiThread {
2022-01-28 06:02:20 +01:00
val topic = subscribeTopicText.text.toString()
2022-01-28 01:57:43 +01:00
val baseUrl = getBaseUrl()
2022-01-28 06:02:20 +01:00
val instant = if (!BuildConfig.FIREBASE_AVAILABLE || subscribeUseAnotherServerCheckbox.isChecked) {
2022-01-28 01:57:43 +01:00
true
} else {
2022-01-28 06:02:20 +01:00
subscribeInstantDeliveryCheckbox.isChecked
2022-01-28 01:57:43 +01:00
}
subscribeListener.onSubscribe(topic, baseUrl, instant)
2022-01-28 01:57:43 +01:00
dialog?.dismiss()
}
}
private fun getBaseUrl(): String {
2022-01-28 06:02:20 +01:00
return if (subscribeUseAnotherServerCheckbox.isChecked) {
subscribeBaseUrlText.text.toString()
} else {
getString(R.string.app_base_url)
}
}
private fun showSubscribeView() {
resetSubscribeView()
positiveButton.text = getString(R.string.add_dialog_button_subscribe)
negativeButton.text = getString(R.string.add_dialog_button_cancel)
loginView.visibility = View.GONE
subscribeView.visibility = View.VISIBLE
if (subscribeTopicText.requestFocus()) {
val imm = activity?.getSystemService(Context.INPUT_METHOD_SERVICE) as? InputMethodManager
imm?.showSoftInput(subscribeTopicText, InputMethodManager.SHOW_IMPLICIT)
}
}
2022-02-11 21:55:08 +01:00
private fun showLoginView(activity: Activity) {
resetLoginView()
loginProgress.visibility = View.INVISIBLE
positiveButton.text = getString(R.string.add_dialog_button_login)
negativeButton.text = getString(R.string.add_dialog_button_back)
subscribeView.visibility = View.GONE
loginView.visibility = View.VISIBLE
if (loginUsernameText.requestFocus()) {
val imm = activity.getSystemService(Context.INPUT_METHOD_SERVICE) as? InputMethodManager
imm?.showSoftInput(loginUsernameText, InputMethodManager.SHOW_IMPLICIT)
}
}
private fun enableSubscribeView(enable: Boolean) {
subscribeTopicText.isEnabled = enable
subscribeBaseUrlText.isEnabled = enable
subscribeInstantDeliveryCheckbox.isEnabled = enable
subscribeUseAnotherServerCheckbox.isEnabled = enable
positiveButton.isEnabled = enable
}
private fun resetSubscribeView() {
subscribeProgress.visibility = View.GONE
2022-02-05 01:52:34 +01:00
subscribeErrorText.visibility = View.GONE
subscribeErrorTextImage.visibility = View.GONE
enableSubscribeView(true)
}
private fun enableLoginView(enable: Boolean) {
loginUsernameText.isEnabled = enable
loginPasswordText.isEnabled = enable
positiveButton.isEnabled = enable
if (enable && loginUsernameText.requestFocus()) {
val imm = activity?.getSystemService(Context.INPUT_METHOD_SERVICE) as? InputMethodManager
imm?.showSoftInput(loginUsernameText, InputMethodManager.SHOW_IMPLICIT)
}
}
private fun resetLoginView() {
loginProgress.visibility = View.GONE
2022-02-05 01:52:34 +01:00
loginErrorText.visibility = View.GONE
loginErrorTextImage.visibility = View.GONE
loginUsernameText.visibility = View.VISIBLE
2022-01-28 19:46:19 +01:00
loginUsernameText.text?.clear()
loginPasswordText.visibility = View.VISIBLE
2022-01-28 19:46:19 +01:00
loginPasswordText.text?.clear()
enableLoginView(true)
}
companion object {
2021-11-24 22:12:51 +01:00
const val TAG = "NtfyAddFragment"
2022-01-28 19:46:19 +01:00
private val DISALLOWED_TOPICS = listOf("docs", "static", "file") // If updated, also update in server
}
2021-10-28 04:25:02 +02:00
}