2023-05-29 18:02:20 +09:30
|
|
|
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
|
2023-05-30 16:49:07 +09:30
|
|
|
import androidx.annotation.AttrRes
|
|
|
|
import androidx.annotation.LayoutRes
|
2023-05-29 18:02:20 +09:30
|
|
|
import androidx.annotation.StringRes
|
|
|
|
import androidx.annotation.StyleRes
|
|
|
|
import androidx.appcompat.app.AlertDialog
|
|
|
|
import androidx.core.view.setMargins
|
2023-05-30 16:49:07 +09:30
|
|
|
import androidx.core.view.setPadding
|
2023-05-29 18:02:20 +09:30
|
|
|
import androidx.core.view.updateMargins
|
|
|
|
import network.loki.messenger.R
|
|
|
|
import org.thoughtcrime.securesms.util.toPx
|
2023-05-30 16:49:07 +09:30
|
|
|
import java.lang.ref.Reference
|
2023-05-29 18:02:20 +09:30
|
|
|
|
2023-05-30 16:49:07 +09:30
|
|
|
|
|
|
|
@DslMarker
|
|
|
|
@Target(AnnotationTarget.CLASS, AnnotationTarget.TYPE)
|
|
|
|
annotation class DialogDsl
|
|
|
|
|
|
|
|
@DialogDsl
|
2023-05-29 18:02:20 +09:30
|
|
|
class SessionDialogBuilder(val context: Context) {
|
|
|
|
|
2023-05-30 16:49:07 +09:30
|
|
|
private val dialogBuilder: AlertDialog.Builder = AlertDialog.Builder(context)
|
|
|
|
|
|
|
|
private var dialog: AlertDialog? = null
|
|
|
|
private fun dismiss() = dialog?.dismiss()
|
|
|
|
|
|
|
|
private val topView = LinearLayout(context).apply { orientation = VERTICAL }
|
|
|
|
.also(dialogBuilder::setCustomTitle)
|
2023-05-29 18:02:20 +09:30
|
|
|
|
|
|
|
private val root = LinearLayout(context).apply { orientation = VERTICAL }
|
2023-05-30 16:49:07 +09:30
|
|
|
.also(dialogBuilder::setView)
|
|
|
|
|
|
|
|
fun title(@StringRes id: Int) = title(context.getString(id))
|
|
|
|
|
|
|
|
fun title(text: CharSequence?) = title(text?.toString())
|
|
|
|
fun title(text: String?) {
|
|
|
|
text(text, R.style.TextAppearance_AppCompat_Title) { setPadding(toPx(20, resources)) }
|
2023-05-29 18:02:20 +09:30
|
|
|
}
|
|
|
|
|
2023-05-30 16:49:07 +09:30
|
|
|
fun text(@StringRes id: Int, style: Int = 0) = text(context.getString(id), style)
|
|
|
|
fun text(text: CharSequence?) = text(text?.toString())
|
|
|
|
fun text(text: String?, @StyleRes style: Int = 0) {
|
|
|
|
text(text, style) {
|
|
|
|
layoutParams = LinearLayout.LayoutParams(MATCH_PARENT, WRAP_CONTENT)
|
2023-05-29 18:02:20 +09:30
|
|
|
.apply { toPx(40, resources).let { updateMargins(it, 0, it, 0) } }
|
2023-05-30 16:49:07 +09:30
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
private fun text(text: String?, @StyleRes style: Int, modify: TextView.() -> Unit) {
|
|
|
|
text ?: return
|
|
|
|
TextView(context, null, 0, style)
|
|
|
|
.apply {
|
|
|
|
setText(text)
|
|
|
|
textAlignment = View.TEXT_ALIGNMENT_CENTER
|
|
|
|
modify()
|
|
|
|
}.let(topView::addView)
|
2023-05-29 18:02:20 +09:30
|
|
|
}
|
|
|
|
|
2023-05-30 16:49:07 +09:30
|
|
|
fun view(view: View) {
|
|
|
|
dialogBuilder.setView(view)
|
2023-05-29 18:02:20 +09:30
|
|
|
}
|
|
|
|
|
2023-05-30 16:49:07 +09:30
|
|
|
fun view(@LayoutRes layout: Int) {
|
|
|
|
dialogBuilder.setView(layout)
|
|
|
|
}
|
|
|
|
|
|
|
|
fun setIconAttribute(@AttrRes icon: Int) {
|
|
|
|
dialogBuilder.setIconAttribute(icon)
|
|
|
|
}
|
|
|
|
|
|
|
|
fun singleChoiceItems(
|
|
|
|
options: Array<String>,
|
|
|
|
currentSelected: Int,
|
|
|
|
onSelect: (Int) -> Unit
|
|
|
|
) {
|
|
|
|
dialogBuilder.setSingleChoiceItems(
|
|
|
|
options,
|
|
|
|
currentSelected
|
|
|
|
) { dialog, it -> onSelect(it); dialog.dismiss() }
|
|
|
|
}
|
|
|
|
|
|
|
|
fun buttons(build: (@DialogDsl ButtonsBuilder).() -> Unit) {
|
|
|
|
ButtonsBuilder(context, ::dismiss).build(build).let(root::addView)
|
|
|
|
}
|
|
|
|
|
|
|
|
fun show(): AlertDialog = dialogBuilder.show()
|
2023-05-29 18:02:20 +09:30
|
|
|
}
|
|
|
|
|
2023-05-30 16:49:07 +09:30
|
|
|
@DialogDsl
|
|
|
|
class ButtonsBuilder(val context: Context, val dismiss: () -> Unit) {
|
2023-05-29 18:02:20 +09:30
|
|
|
val root = LinearLayout(context)
|
|
|
|
|
2023-05-30 16:49:07 +09:30
|
|
|
fun destructiveButton(
|
|
|
|
@StringRes text: Int,
|
|
|
|
@StringRes contentDescription: Int,
|
|
|
|
listener: () -> Unit = {}
|
|
|
|
) {
|
|
|
|
button(
|
|
|
|
text,
|
|
|
|
contentDescription,
|
|
|
|
R.style.Widget_Session_Button_Dialog_DestructiveText,
|
|
|
|
listener
|
|
|
|
)
|
2023-05-29 18:02:20 +09:30
|
|
|
}
|
|
|
|
|
2023-05-30 16:49:07 +09:30
|
|
|
fun cancelButton(listener: (() -> Unit) = {}) = button(android.R.string.cancel, R.string.AccessibilityId_cancel_button, listener = listener)
|
2023-05-29 18:02:20 +09:30
|
|
|
|
|
|
|
fun button(
|
|
|
|
@StringRes text: Int,
|
|
|
|
@StringRes contentDescriptionRes: Int = 0,
|
|
|
|
@StyleRes style: Int = R.style.Widget_Session_Button_Dialog_UnimportantText,
|
2023-05-30 16:49:07 +09:30
|
|
|
listener: (() -> Unit) = {}
|
|
|
|
) {
|
2023-05-29 18:02:20 +09:30
|
|
|
Button(context, null, 0, style)
|
|
|
|
.apply {
|
2023-05-30 16:49:07 +09:30
|
|
|
setText(text)
|
|
|
|
contentDescription = resources.getString(contentDescriptionRes)
|
2023-05-29 18:02:20 +09:30
|
|
|
layoutParams = LinearLayout.LayoutParams(WRAP_CONTENT, WRAP_CONTENT, 1f)
|
|
|
|
.apply { setMargins(toPx(20, resources)) }
|
2023-05-30 16:49:07 +09:30
|
|
|
setOnClickListener {
|
|
|
|
listener.invoke()
|
|
|
|
dismiss()
|
|
|
|
}
|
2023-05-29 18:02:20 +09:30
|
|
|
}
|
|
|
|
.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()
|