diff --git a/app/build.gradle b/app/build.gradle
index d9c17d7..63912ea 100644
--- a/app/build.gradle
+++ b/app/build.gradle
@@ -66,7 +66,7 @@ dependencies {
implementation project(':client')
implementation 'androidx.appcompat:appcompat:1.5.1'
implementation 'androidx.core:core-splashscreen:1.0.0'
- implementation 'com.google.android.material:material:1.4.0'
+ implementation 'com.google.android.material:material:1.7.0'
implementation 'androidx.constraintlayout:constraintlayout:2.1.4'
implementation 'androidx.swiperefreshlayout:swiperefreshlayout:1.1.0'
implementation 'androidx.vectordrawable:vectordrawable:1.1.0'
diff --git a/app/src/main/kotlin/com/github/gotify/init/InitializationActivity.kt b/app/src/main/kotlin/com/github/gotify/init/InitializationActivity.kt
index ac88631..49e6d1f 100644
--- a/app/src/main/kotlin/com/github/gotify/init/InitializationActivity.kt
+++ b/app/src/main/kotlin/com/github/gotify/init/InitializationActivity.kt
@@ -5,7 +5,6 @@ import android.app.NotificationManager
import android.content.Intent
import android.os.Build
import android.os.Bundle
-import androidx.appcompat.app.AlertDialog
import androidx.appcompat.app.AppCompatActivity
import androidx.core.splashscreen.SplashScreen.Companion.installSplashScreen
import androidx.preference.PreferenceManager
@@ -24,6 +23,7 @@ import com.github.gotify.login.LoginActivity
import com.github.gotify.messages.MessagesActivity
import com.github.gotify.service.WebSocketService
import com.github.gotify.settings.ThemeHelper
+import com.google.android.material.dialog.MaterialAlertDialogBuilder
import com.livinglifetechway.quickpermissionskotlin.runWithPermissions
import com.livinglifetechway.quickpermissionskotlin.util.QuickPermissionsOptions
import com.livinglifetechway.quickpermissionskotlin.util.QuickPermissionsRequest
@@ -98,7 +98,7 @@ internal class InitializationActivity : AppCompatActivity() {
}
private fun dialog(message: String) {
- AlertDialog.Builder(this)
+ MaterialAlertDialogBuilder(this)
.setTitle(R.string.oops)
.setMessage(message)
.setPositiveButton(R.string.retry) { _, _ -> tryAuthenticate() }
@@ -176,7 +176,7 @@ internal class InitializationActivity : AppCompatActivity() {
}
private fun processPermissionRationale(req: QuickPermissionsRequest) {
- AlertDialog.Builder(this)
+ MaterialAlertDialogBuilder(this)
.setMessage(getString(R.string.permissions_denied_temp))
.setPositiveButton(getString(R.string.permissions_dialog_grant)) { _, _ ->
req.proceed()
@@ -186,7 +186,7 @@ internal class InitializationActivity : AppCompatActivity() {
}
private fun processPermissionsPermanentDenied(req: QuickPermissionsRequest) {
- AlertDialog.Builder(this)
+ MaterialAlertDialogBuilder(this)
.setMessage(getString(R.string.permissions_denied_permanent))
.setPositiveButton(getString(R.string.permissions_dialog_grant)) { _, _ ->
req.openAppSettings()
diff --git a/app/src/main/kotlin/com/github/gotify/login/AdvancedDialog.kt b/app/src/main/kotlin/com/github/gotify/login/AdvancedDialog.kt
index 6a1910d..8c4809f 100644
--- a/app/src/main/kotlin/com/github/gotify/login/AdvancedDialog.kt
+++ b/app/src/main/kotlin/com/github/gotify/login/AdvancedDialog.kt
@@ -1,11 +1,11 @@
package com.github.gotify.login
-import android.app.AlertDialog
import android.content.Context
import android.view.LayoutInflater
import android.widget.CompoundButton
import com.github.gotify.R
import com.github.gotify.databinding.AdvancedSettingsDialogBinding
+import com.google.android.material.dialog.MaterialAlertDialogBuilder
internal class AdvancedDialog(
private val context: Context,
@@ -42,7 +42,7 @@ internal class AdvancedDialog(
} else {
showRemoveCACertificate(selectedCertificate)
}
- AlertDialog.Builder(context)
+ MaterialAlertDialogBuilder(context)
.setView(binding.root)
.setTitle(R.string.advanced_settings)
.setPositiveButton(context.getString(R.string.done), null)
diff --git a/app/src/main/kotlin/com/github/gotify/login/LoginActivity.kt b/app/src/main/kotlin/com/github/gotify/login/LoginActivity.kt
index ed84f7b..ac31707 100644
--- a/app/src/main/kotlin/com/github/gotify/login/LoginActivity.kt
+++ b/app/src/main/kotlin/com/github/gotify/login/LoginActivity.kt
@@ -8,10 +8,7 @@ import android.os.Bundle
import android.text.Editable
import android.text.TextWatcher
import android.view.View
-import android.widget.EditText
-import androidx.appcompat.app.AlertDialog
import androidx.appcompat.app.AppCompatActivity
-import androidx.appcompat.view.ContextThemeWrapper
import com.github.gotify.R
import com.github.gotify.SSLSettings
import com.github.gotify.Settings
@@ -27,10 +24,13 @@ import com.github.gotify.client.api.UserApi
import com.github.gotify.client.model.Client
import com.github.gotify.client.model.VersionInfo
import com.github.gotify.databinding.ActivityLoginBinding
+import com.github.gotify.databinding.ClientNameDialogBinding
import com.github.gotify.init.InitializationActivity
import com.github.gotify.log.Log
import com.github.gotify.log.LogsActivity
import com.github.gotify.log.UncaughtExceptionHandler
+import com.google.android.material.dialog.MaterialAlertDialogBuilder
+import com.google.android.material.textfield.TextInputEditText
import okhttp3.HttpUrl
import java.security.cert.X509Certificate
@@ -59,7 +59,7 @@ internal class LoginActivity : AppCompatActivity() {
override fun onPostCreate(savedInstanceState: Bundle?) {
super.onPostCreate(savedInstanceState)
- binding.gotifyUrl.addTextChangedListener(object : TextWatcher {
+ binding.gotifyUrlEditext.addTextChangedListener(object : TextWatcher {
override fun beforeTextChanged(charSequence: CharSequence, i: Int, i1: Int, i2: Int) {}
override fun onTextChanged(charSequence: CharSequence, i: Int, i1: Int, i2: Int) {
@@ -83,7 +83,7 @@ internal class LoginActivity : AppCompatActivity() {
}
private fun doCheckUrl() {
- val url = binding.gotifyUrl.text.toString().trim().trimEnd('/')
+ val url = binding.gotifyUrlEditext.text.toString().trim().trimEnd('/')
val parsedUrl = HttpUrl.parse(url)
if (parsedUrl == null) {
Utils.showSnackBar(this, "Invalid URL (include http:// or https://)")
@@ -110,7 +110,7 @@ internal class LoginActivity : AppCompatActivity() {
}
private fun showHttpWarning() {
- AlertDialog.Builder(ContextThemeWrapper(this, R.style.AppTheme_Dialog))
+ MaterialAlertDialogBuilder(this)
.setTitle(R.string.warning)
.setCancelable(true)
.setMessage(R.string.http_warning)
@@ -213,8 +213,8 @@ internal class LoginActivity : AppCompatActivity() {
}
private fun doLogin() {
- val username = binding.username.text.toString()
- val password = binding.password.text.toString()
+ val username = binding.usernameEditext.text.toString()
+ val password = binding.passwordEditext.text.toString()
binding.login.visibility = View.GONE
binding.loginProgress.visibility = View.VISIBLE
@@ -238,21 +238,23 @@ internal class LoginActivity : AppCompatActivity() {
}
private fun newClientDialog(client: ApiClient) {
- val clientName = EditText(this)
- clientName.setText(Build.MODEL)
+ val clientDialogBinding = ClientNameDialogBinding.inflate(layoutInflater)
+ val clientDialogEditext = clientDialogBinding.clientNameEditext
+ clientDialogEditext.setText(Build.MODEL)
- AlertDialog.Builder(ContextThemeWrapper(this, R.style.AppTheme_Dialog))
+ MaterialAlertDialogBuilder(this)
.setTitle(R.string.create_client_title)
.setMessage(R.string.create_client_message)
- .setView(clientName)
- .setPositiveButton(R.string.create, doCreateClient(client, clientName))
+ .setView(clientDialogBinding.root)
+ .setPositiveButton(R.string.create, doCreateClient(client, clientDialogEditext))
.setNegativeButton(R.string.cancel) { _, _ -> onCancelClientDialog() }
+ .setCancelable(false)
.show()
}
private fun doCreateClient(
client: ApiClient,
- nameProvider: EditText
+ nameProvider: TextInputEditText
): DialogInterface.OnClickListener {
return DialogInterface.OnClickListener { _, _ ->
val newClient = Client().name(nameProvider.text.toString())
diff --git a/app/src/main/kotlin/com/github/gotify/messages/ListMessageAdapter.kt b/app/src/main/kotlin/com/github/gotify/messages/ListMessageAdapter.kt
index e36916d..15451ea 100644
--- a/app/src/main/kotlin/com/github/gotify/messages/ListMessageAdapter.kt
+++ b/app/src/main/kotlin/com/github/gotify/messages/ListMessageAdapter.kt
@@ -101,6 +101,13 @@ internal class ListMessageAdapter(
return currentItem.message.id
}
+ // Fix for message not being selectable (https://issuetracker.google.com/issues/37095917)
+ override fun onViewAttachedToWindow(holder: ViewHolder) {
+ super.onViewAttachedToWindow(holder)
+ holder.message.isEnabled = false
+ holder.message.isEnabled = true
+ }
+
class ViewHolder(binding: ViewBinding) : RecyclerView.ViewHolder(binding.root) {
lateinit var image: ImageView
lateinit var message: TextView
diff --git a/app/src/main/kotlin/com/github/gotify/messages/MessagesActivity.kt b/app/src/main/kotlin/com/github/gotify/messages/MessagesActivity.kt
index 78b13bf..5b5704c 100644
--- a/app/src/main/kotlin/com/github/gotify/messages/MessagesActivity.kt
+++ b/app/src/main/kotlin/com/github/gotify/messages/MessagesActivity.kt
@@ -16,9 +16,7 @@ import android.view.View
import android.widget.ImageButton
import android.widget.TextView
import androidx.appcompat.app.ActionBarDrawerToggle
-import androidx.appcompat.app.AlertDialog
import androidx.appcompat.app.AppCompatActivity
-import androidx.appcompat.view.ContextThemeWrapper
import androidx.core.content.ContextCompat
import androidx.core.graphics.drawable.DrawableCompat
import androidx.core.view.GravityCompat
@@ -53,6 +51,7 @@ import com.github.gotify.messages.provider.MessageWithImage
import com.github.gotify.service.WebSocketService
import com.github.gotify.settings.SettingsActivity
import com.github.gotify.sharing.ShareActivity
+import com.google.android.material.dialog.MaterialAlertDialogBuilder
import com.google.android.material.navigation.NavigationView
import com.google.android.material.snackbar.BaseTransientBottomBar.BaseCallback
import com.google.android.material.snackbar.Snackbar
@@ -260,7 +259,7 @@ internal class MessagesActivity :
startLoading()
binding.appBarDrawer.toolbar.subtitle = ""
} else if (id == R.id.logout) {
- AlertDialog.Builder(ContextThemeWrapper(this, R.style.AppTheme_Dialog))
+ MaterialAlertDialogBuilder(this)
.setTitle(R.string.logout)
.setMessage(getString(R.string.logout_confirm))
.setPositiveButton(R.string.yes) { _, _ -> doLogout() }
@@ -523,12 +522,12 @@ internal class MessagesActivity :
}
}
if (item.itemId == R.id.action_delete_app) {
- val alert = android.app.AlertDialog.Builder(this)
- alert.setTitle(R.string.delete_app)
- alert.setMessage(R.string.ack)
- alert.setPositiveButton(R.string.yes) { _, _ -> deleteApp(viewModel.appId) }
- alert.setNegativeButton(R.string.no, null)
- alert.show()
+ MaterialAlertDialogBuilder(this)
+ .setTitle(R.string.delete_app)
+ .setMessage(R.string.ack)
+ .setPositiveButton(R.string.yes) { _, _ -> deleteApp(viewModel.appId) }
+ .setNegativeButton(R.string.no, null)
+ .show()
}
return super.onContextItemSelected(item)
}
diff --git a/app/src/main/kotlin/com/github/gotify/settings/SettingsActivity.kt b/app/src/main/kotlin/com/github/gotify/settings/SettingsActivity.kt
index fa88d2b..bb4a825 100644
--- a/app/src/main/kotlin/com/github/gotify/settings/SettingsActivity.kt
+++ b/app/src/main/kotlin/com/github/gotify/settings/SettingsActivity.kt
@@ -1,6 +1,7 @@
package com.github.gotify.settings
-import android.app.AlertDialog
+import android.app.Dialog
+import android.content.DialogInterface
import android.content.Intent
import android.content.SharedPreferences
import android.content.SharedPreferences.OnSharedPreferenceChangeListener
@@ -9,11 +10,13 @@ import android.view.MenuItem
import android.view.View
import androidx.appcompat.app.AppCompatActivity
import androidx.preference.ListPreference
+import androidx.preference.ListPreferenceDialogFragmentCompat
import androidx.preference.Preference
import androidx.preference.PreferenceFragmentCompat
import androidx.preference.PreferenceManager
import com.github.gotify.R
import com.github.gotify.databinding.SettingsActivityBinding
+import com.google.android.material.dialog.MaterialAlertDialogBuilder
internal class SettingsActivity : AppCompatActivity(), OnSharedPreferenceChangeListener {
private lateinit var binding: SettingsActivityBinding
@@ -64,7 +67,7 @@ internal class SettingsActivity : AppCompatActivity(), OnSharedPreferenceChangeL
findPreference(getString(R.string.setting_key_message_layout))
messageLayout?.onPreferenceChangeListener =
Preference.OnPreferenceChangeListener { _, _ ->
- AlertDialog.Builder(context)
+ MaterialAlertDialogBuilder(requireContext())
.setTitle(R.string.setting_message_layout_dialog_title)
.setMessage(R.string.setting_message_layout_dialog_message)
.setPositiveButton(
@@ -81,6 +84,24 @@ internal class SettingsActivity : AppCompatActivity(), OnSharedPreferenceChangeL
}
}
+ override fun onDisplayPreferenceDialog(preference: Preference) {
+ if (preference is ListPreference) {
+ showListPreferenceDialog(preference)
+ } else {
+ super.onDisplayPreferenceDialog(preference)
+ }
+ }
+
+ private fun showListPreferenceDialog(preference: ListPreference) {
+ val dialogFragment = MaterialListPreference()
+ dialogFragment.arguments = Bundle(1).apply { putString("key", preference.key) }
+ dialogFragment.setTargetFragment(this, 0)
+ dialogFragment.show(
+ parentFragmentManager,
+ "androidx.preference.PreferenceFragment.DIALOG"
+ )
+ }
+
private fun restartApp() {
val packageManager = requireContext().packageManager
val packageName = requireContext().packageName
@@ -91,4 +112,46 @@ internal class SettingsActivity : AppCompatActivity(), OnSharedPreferenceChangeL
Runtime.getRuntime().exit(0)
}
}
+
+ class MaterialListPreference : ListPreferenceDialogFragmentCompat() {
+ private var mWhichButtonClicked = 0
+
+ override fun onCreateDialog(savedInstanceState: Bundle?): Dialog {
+ mWhichButtonClicked = DialogInterface.BUTTON_NEGATIVE
+ val builder = MaterialAlertDialogBuilder(requireActivity())
+ .setTitle(preference.dialogTitle)
+ .setPositiveButton(preference.positiveButtonText, this)
+ .setNegativeButton(preference.negativeButtonText, this)
+
+ val contentView = context?.let { onCreateDialogView(it) }
+ if (contentView != null) {
+ onBindDialogView(contentView)
+ builder.setView(contentView)
+ } else {
+ builder.setMessage(preference.dialogMessage)
+ }
+ onPrepareDialogBuilder(builder)
+ return builder.create()
+ }
+
+ override fun onClick(dialog: DialogInterface, which: Int) {
+ mWhichButtonClicked = which
+ }
+
+ override fun onDismiss(dialog: DialogInterface) {
+ onDialogClosedWasCalledFromOnDismiss = true
+ super.onDismiss(dialog)
+ }
+
+ private var onDialogClosedWasCalledFromOnDismiss = false
+
+ override fun onDialogClosed(positiveResult: Boolean) {
+ if (onDialogClosedWasCalledFromOnDismiss) {
+ onDialogClosedWasCalledFromOnDismiss = false
+ super.onDialogClosed(mWhichButtonClicked == DialogInterface.BUTTON_POSITIVE)
+ } else {
+ super.onDialogClosed(positiveResult)
+ }
+ }
+ }
}
diff --git a/app/src/main/res/layout/activity_login.xml b/app/src/main/res/layout/activity_login.xml
index 1ce90e8..8c23990 100644
--- a/app/src/main/res/layout/activity_login.xml
+++ b/app/src/main/res/layout/activity_login.xml
@@ -13,19 +13,18 @@
tools:context=".login.LoginActivity"
tools:layout_editor_absoluteY="25dp">
-
-
-
-
+ tools:text="Gotify URL">
-
+
+
+
+
+ app:layout_constraintWidth_max="280dp">
-
+
+
+
+
+ app:layout_constraintWidth_max="280dp">
-
+
+
+
+
-