diff --git a/app/src/main/java/org/thoughtcrime/securesms/SessionDialogBuilder.kt b/app/src/main/java/org/thoughtcrime/securesms/SessionDialogBuilder.kt
new file mode 100644
index 0000000000..71b48c6bb6
--- /dev/null
+++ b/app/src/main/java/org/thoughtcrime/securesms/SessionDialogBuilder.kt
@@ -0,0 +1,86 @@
+package org.thoughtcrime.securesms
+
+import android.content.Context
+import android.view.View
+import android.view.ViewGroup.LayoutParams.MATCH_PARENT
+import android.view.ViewGroup.LayoutParams.WRAP_CONTENT
+import android.widget.Button
+import android.widget.LinearLayout
+import android.widget.LinearLayout.VERTICAL
+import android.widget.TextView
+import androidx.annotation.StringRes
+import androidx.annotation.StyleRes
+import androidx.appcompat.app.AlertDialog
+import androidx.core.view.setMargins
+import androidx.core.view.updateMargins
+import network.loki.messenger.R
+import org.thoughtcrime.securesms.util.toPx
+
+class SessionDialogBuilder(val context: Context) {
+
+ private val dialog: AlertDialog = AlertDialog.Builder(context).create()
+
+ private val root = LinearLayout(context).apply { orientation = VERTICAL }
+ .also(dialog::setView)
+
+ fun title(@StringRes id: Int) {
+ TextView(context, null, 0, R.style.TextAppearance_AppCompat_Title)
+ .apply { textAlignment = View.TEXT_ALIGNMENT_CENTER }
+ .apply { setText(id) }
+ .apply { layoutParams = LinearLayout.LayoutParams(MATCH_PARENT, WRAP_CONTENT)
+ .apply { setMargins(toPx(20, resources)) }
+ }.let(root::addView)
+ }
+
+ fun text(@StringRes id: Int, style: Int = 0) {
+ TextView(context, null, 0, style)
+ .apply { textAlignment = View.TEXT_ALIGNMENT_CENTER }
+ .apply { setText(id) }
+ .apply { layoutParams = LinearLayout.LayoutParams(MATCH_PARENT, WRAP_CONTENT)
+ .apply { toPx(40, resources).let { updateMargins(it, 0, it, 0) } }
+ }.let(root::addView)
+ }
+
+ fun buttons(build: ButtonsBuilder.() -> Unit) {
+ ButtonsBuilder(context, dialog).build(build).let(root::addView)
+ }
+
+ fun show(): AlertDialog = dialog.apply { show() }
+}
+
+class ButtonsBuilder(val context: Context, val dialog: AlertDialog) {
+ val root = LinearLayout(context)
+
+ fun destructiveButton(@StringRes text: Int, @StringRes contentDescription: Int, listener: () -> Unit = {}) {
+ button(text, contentDescription, R.style.Widget_Session_Button_Dialog_DestructiveText, listener)
+ }
+
+ fun cancelButton() = button(android.R.string.cancel)
+
+ fun button(
+ @StringRes text: Int,
+ @StringRes contentDescriptionRes: Int = 0,
+ @StyleRes style: Int = R.style.Widget_Session_Button_Dialog_UnimportantText,
+ listener: (() -> Unit) = {}) {
+ Button(context, null, 0, style)
+ .apply { setText(text) }
+ .apply { setOnClickListener {
+ listener.invoke()
+ dialog.dismiss()
+ contentDescription = resources.getString(contentDescriptionRes)
+ } }
+ .apply {
+ layoutParams = LinearLayout.LayoutParams(WRAP_CONTENT, WRAP_CONTENT, 1f)
+ .apply { setMargins(toPx(20, resources)) }
+ }
+ .let(root::addView)
+ }
+
+ internal fun build(build: ButtonsBuilder.() -> Unit): LinearLayout {
+ build()
+ return root
+ }
+}
+
+fun Context.sessionDialog(build: SessionDialogBuilder.() -> Unit): AlertDialog =
+ SessionDialogBuilder(this).apply { build() }.show()
diff --git a/app/src/main/java/org/thoughtcrime/securesms/conversation/v2/ConversationActivityV2.kt b/app/src/main/java/org/thoughtcrime/securesms/conversation/v2/ConversationActivityV2.kt
index f9385d14bc..0ad0542eaf 100644
--- a/app/src/main/java/org/thoughtcrime/securesms/conversation/v2/ConversationActivityV2.kt
+++ b/app/src/main/java/org/thoughtcrime/securesms/conversation/v2/ConversationActivityV2.kt
@@ -21,7 +21,6 @@ import android.widget.Toast
import androidx.activity.viewModels
import androidx.annotation.DimenRes
import androidx.appcompat.app.AlertDialog
-import androidx.core.view.isGone
import androidx.core.view.isVisible
import androidx.lifecycle.Observer
import androidx.lifecycle.ViewModelProvider
@@ -113,6 +112,7 @@ import org.thoughtcrime.securesms.mms.*
import org.thoughtcrime.securesms.permissions.Permissions
import org.thoughtcrime.securesms.reactions.ReactionsDialogFragment
import org.thoughtcrime.securesms.reactions.any.ReactWithAnyEmojiDialogFragment
+import org.thoughtcrime.securesms.sessionDialog
import org.thoughtcrime.securesms.util.*
import java.lang.ref.WeakReference
import java.util.*
@@ -962,21 +962,20 @@ class ConversationActivityV2 : PassphraseRequiredActionBarActivity(), InputBarDe
}
override fun block(deleteThread: Boolean) {
- val title = R.string.RecipientPreferenceActivity_block_this_contact_question
- val message = R.string.RecipientPreferenceActivity_you_will_no_longer_receive_messages_and_calls_from_this_contact
- val dialog = AlertDialog.Builder(this)
- .setTitle(title)
- .setMessage(message)
- .setNegativeButton(android.R.string.cancel, null)
- .setPositiveButton(R.string.RecipientPreferenceActivity_block) { _, _ ->
- viewModel.block()
- if (deleteThread) {
- viewModel.deleteThread()
- finish()
+ sessionDialog {
+ title(R.string.RecipientPreferenceActivity_block_this_contact_question)
+ text(R.string.RecipientPreferenceActivity_you_will_no_longer_receive_messages_and_calls_from_this_contact)
+ buttons {
+ destructiveButton(R.string.RecipientPreferenceActivity_block, R.string.AccessibilityId_block_confirm) {
+ viewModel.block()
+ if (deleteThread) {
+ viewModel.deleteThread()
+ finish()
+ }
}
- }.show()
- val button = dialog.getButton(DialogInterface.BUTTON_POSITIVE)
- button.setContentDescription("Confirm block")
+ cancelButton()
+ }
+ }
}
override fun copySessionID(sessionId: String) {
@@ -1016,15 +1015,17 @@ class ConversationActivityV2 : PassphraseRequiredActionBarActivity(), InputBarDe
}
override fun unblock() {
- val title = R.string.ConversationActivity_unblock_this_contact_question
- val message = R.string.ConversationActivity_you_will_once_again_be_able_to_receive_messages_and_calls_from_this_contact
- AlertDialog.Builder(this)
- .setTitle(title)
- .setMessage(message)
- .setNegativeButton(android.R.string.cancel, null)
- .setPositiveButton(R.string.ConversationActivity_unblock) { _, _ ->
- viewModel.unblock()
- }.show()
+ sessionDialog {
+ title(R.string.ConversationActivity_unblock_this_contact_question)
+ text(R.string.ConversationActivity_you_will_once_again_be_able_to_receive_messages_and_calls_from_this_contact)
+ buttons {
+ destructiveButton(
+ R.string.ConversationActivity_unblock,
+ R.string.AccessibilityId_block_confirm
+ ) { viewModel.unblock() }
+ cancelButton()
+ }
+ }
}
// `position` is the adapter position; not the visual position
diff --git a/app/src/main/res/values/styles.xml b/app/src/main/res/values/styles.xml
index 8c79423d55..5da603275b 100644
--- a/app/src/main/res/values/styles.xml
+++ b/app/src/main/res/values/styles.xml
@@ -71,6 +71,7 @@