Make kotlin code use dialog dsl

This commit is contained in:
andrew 2023-05-30 21:39:03 +09:30
parent 4ee68cbbb1
commit 1d8d678047
12 changed files with 160 additions and 225 deletions

View file

@ -417,7 +417,7 @@ public class MediaPreviewActivity extends PassphraseRequiredActionBarActivity im
MediaItem mediaItem = getCurrentMediaItem();
if (mediaItem == null) return;
SaveAttachmentTask.showWarningDialog(this, () -> {
SaveAttachmentTask.showWarningDialog(this, 1, () -> {
Permissions.with(this)
.request(android.Manifest.permission.WRITE_EXTERNAL_STORAGE)
.maxSdkVersion(Build.VERSION_CODES.P)

View file

@ -1,6 +1,7 @@
package org.thoughtcrime.securesms
import android.content.Context
import android.view.LayoutInflater
import android.view.View
import android.view.ViewGroup.LayoutParams.MATCH_PARENT
import android.view.ViewGroup.LayoutParams.WRAP_CONTENT
@ -18,7 +19,6 @@ import androidx.core.view.setPadding
import androidx.core.view.updateMargins
import network.loki.messenger.R
import org.thoughtcrime.securesms.util.toPx
import java.lang.ref.Reference
@DslMarker
@ -35,9 +35,15 @@ class SessionDialogBuilder(val context: Context) {
private val topView = LinearLayout(context).apply { orientation = VERTICAL }
.also(dialogBuilder::setCustomTitle)
private val contentView = LinearLayout(context).apply { orientation = VERTICAL }
private val buttonLayout = LinearLayout(context)
private val root = LinearLayout(context).apply { orientation = VERTICAL }
.also(dialogBuilder::setView)
.apply {
addView(contentView)
addView(buttonLayout)
}
fun title(@StringRes id: Int) = title(context.getString(id))
@ -65,52 +71,31 @@ class SessionDialogBuilder(val context: Context) {
}.let(topView::addView)
}
fun view(view: View) {
dialogBuilder.setView(view)
}
fun view(view: View) = contentView.addView(view)
fun view(@LayoutRes layout: Int) {
dialogBuilder.setView(layout)
}
fun view(@LayoutRes layout: Int) = contentView.addView(LayoutInflater.from(context).inflate(layout, contentView))
fun setIconAttribute(@AttrRes icon: Int) {
dialogBuilder.setIconAttribute(icon)
}
fun iconAttribute(@AttrRes icon: Int): AlertDialog.Builder = dialogBuilder.setIconAttribute(icon)
fun singleChoiceItems(
options: Array<String>,
currentSelected: Int,
onSelect: (Int) -> Unit
) {
dialogBuilder.setSingleChoiceItems(
): AlertDialog.Builder = 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()
}
@DialogDsl
class ButtonsBuilder(val context: Context, val dismiss: () -> Unit) {
val root = LinearLayout(context)
fun destructiveButton(
@StringRes text: Int,
@StringRes contentDescription: Int,
listener: () -> Unit = {}
) {
button(
) = button(
text,
contentDescription,
R.style.Widget_Session_Button_Dialog_DestructiveText,
listener
)
}
fun cancelButton(listener: (() -> Unit) = {}) = button(android.R.string.cancel, R.string.AccessibilityId_cancel_button, listener = listener)
@ -119,9 +104,7 @@ class ButtonsBuilder(val context: Context, val dismiss: () -> Unit) {
@StringRes contentDescriptionRes: Int = 0,
@StyleRes style: Int = R.style.Widget_Session_Button_Dialog_UnimportantText,
listener: (() -> Unit) = {}
) {
Button(context, null, 0, style)
.apply {
) = Button(context, null, 0, style).apply {
setText(text)
contentDescription = resources.getString(contentDescriptionRes)
layoutParams = LinearLayout.LayoutParams(WRAP_CONTENT, WRAP_CONTENT, 1f)
@ -130,14 +113,9 @@ class ButtonsBuilder(val context: Context, val dismiss: () -> Unit) {
listener.invoke()
dismiss()
}
}
.let(root::addView)
}
}.let(buttonLayout::addView)
internal fun build(build: ButtonsBuilder.() -> Unit): LinearLayout {
build()
return root
}
fun show(): AlertDialog = dialogBuilder.show()
}
fun Context.sessionDialog(build: SessionDialogBuilder.() -> Unit): AlertDialog =

View file

@ -965,7 +965,6 @@ class ConversationActivityV2 : PassphraseRequiredActionBarActivity(), InputBarDe
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) {
@ -976,7 +975,6 @@ class ConversationActivityV2 : PassphraseRequiredActionBarActivity(), InputBarDe
cancelButton()
}
}
}
override fun copySessionID(sessionId: String) {
val clip = ClipData.newPlainText("Session ID", sessionId)
@ -1018,7 +1016,6 @@ class ConversationActivityV2 : PassphraseRequiredActionBarActivity(), InputBarDe
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
@ -1026,7 +1023,6 @@ class ConversationActivityV2 : PassphraseRequiredActionBarActivity(), InputBarDe
cancelButton()
}
}
}
// `position` is the adapter position; not the visual position
private fun handlePress(message: MessageRecord, position: Int, view: VisibleMessageView, event: MotionEvent) {
@ -1464,14 +1460,12 @@ class ConversationActivityV2 : PassphraseRequiredActionBarActivity(), InputBarDe
sessionDialog {
title(R.string.giphy_permission_title)
text(R.string.giphy_permission_message)
buttons {
button(R.string.continue_2) {
textSecurePreferences.setHasSeenGIFMetaDataWarning()
selectGif()
}
cancelButton()
}
}
} else {
selectGif()
}
@ -1629,11 +1623,9 @@ class ConversationActivityV2 : PassphraseRequiredActionBarActivity(), InputBarDe
sessionDialog {
title(resources.getQuantityString(R.plurals.ConversationFragment_delete_selected_messages, messageCount, messageCount))
text(resources.getQuantityString(R.plurals.ConversationFragment_this_will_permanently_delete_all_n_selected_messages, messageCount, messageCount))
buttons {
button(R.string.delete) { messages.forEach(viewModel::deleteForEveryone); endActionMode() }
cancelButton { endActionMode() }
}
}
} else if (allSentByCurrentUser && allHasHash) {
val bottomSheet = DeleteOptionsBottomSheet()
bottomSheet.recipient = recipient
@ -1658,35 +1650,29 @@ class ConversationActivityV2 : PassphraseRequiredActionBarActivity(), InputBarDe
sessionDialog {
title(resources.getQuantityString(R.plurals.ConversationFragment_delete_selected_messages, messageCount, messageCount))
text(resources.getQuantityString(R.plurals.ConversationFragment_this_will_permanently_delete_all_n_selected_messages, messageCount, messageCount))
buttons {
button(R.string.delete) { messages.forEach(viewModel::deleteLocally); endActionMode() }
cancelButton(::endActionMode)
}
}
}
}
override fun banUser(messages: Set<MessageRecord>) {
sessionDialog {
title(R.string.ConversationFragment_ban_selected_user)
text("This will ban the selected user from this room. It won't ban them from other rooms.")
buttons {
button(R.string.ban) { viewModel.banUser(messages.first().individualRecipient); endActionMode() }
cancelButton(::endActionMode)
}
}
}
override fun banAndDeleteAll(messages: Set<MessageRecord>) {
sessionDialog {
title(R.string.ConversationFragment_ban_selected_user)
text("This will ban the selected user from this room and delete all messages sent by them. It won't ban them from other rooms or delete the messages they sent there.")
buttons {
button(R.string.ban) { viewModel.banAndDeleteAll(messages.first().individualRecipient); endActionMode() }
cancelButton(::endActionMode)
}
}
}
override fun copyMessages(messages: Set<MessageRecord>) {
val sortedMessages = messages.sortedBy { it.dateSent }

View file

@ -150,7 +150,6 @@ class ConversationAdapter(
context.sessionDialog {
title(R.string.CallNotificationBuilder_first_call_title)
text(R.string.CallNotificationBuilder_first_call_message)
buttons {
button(R.string.activity_settings_title) {
Intent(context, PrivacySettingsActivity::class.java)
.let(context::startActivity)
@ -158,7 +157,6 @@ class ConversationAdapter(
cancelButton()
}
}
}
} else {
viewHolder.view.setOnClickListener(null)
}

View file

@ -190,13 +190,11 @@ object ConversationMenuHelper {
context.sessionDialog {
title(R.string.ConversationActivity_call_title)
text(R.string.ConversationActivity_call_prompt)
buttons {
button(R.string.activity_settings_title, R.string.AccessibilityId_settings) {
Intent(context, PrivacySettingsActivity::class.java).let(context::startActivity)
}
cancelButton()
}
}
return
}
@ -308,7 +306,6 @@ object ConversationMenuHelper {
context.sessionDialog {
title(R.string.ConversationActivity_leave_group)
text(message)
buttons {
button(R.string.yes) {
try {
val groupPublicKey = doubleDecodeGroupID(thread.address.toString()).toHexString()
@ -323,7 +320,6 @@ object ConversationMenuHelper {
button(R.string.no)
}
}
}
private fun inviteContacts(context: Context, thread: Recipient) {
if (!thread.isOpenGroupRecipient) { return }

View file

@ -492,7 +492,6 @@ class HomeActivity : PassphraseRequiredActionBarActivity(),
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 {
button(R.string.RecipientPreferenceActivity_block) {
lifecycleScope.launch(Dispatchers.IO) {
recipientDatabase.setBlocked(thread.recipient, true)
@ -504,13 +503,11 @@ class HomeActivity : PassphraseRequiredActionBarActivity(),
cancelButton()
}
}
}
private fun unblockConversation(thread: ThreadRecord) {
sessionDialog {
title(R.string.RecipientPreferenceActivity_unblock_this_contact_question)
text(R.string.RecipientPreferenceActivity_you_will_once_again_be_able_to_receive_messages_and_calls_from_this_contact)
buttons {
button(R.string.RecipientPreferenceActivity_unblock) {
lifecycleScope.launch(Dispatchers.IO) {
recipientDatabase.setBlocked(thread.recipient, false)
@ -522,7 +519,6 @@ class HomeActivity : PassphraseRequiredActionBarActivity(),
cancelButton()
}
}
}
private fun setConversationMuted(thread: ThreadRecord, isMuted: Boolean) {
if (isMuted) {
@ -582,7 +578,6 @@ class HomeActivity : PassphraseRequiredActionBarActivity(),
sessionDialog {
text(message)
buttons {
button(R.string.yes) {
lifecycleScope.launch(Dispatchers.Main) {
val context = this@HomeActivity as Context
@ -637,7 +632,6 @@ class HomeActivity : PassphraseRequiredActionBarActivity(),
button(R.string.no)
}
}
}
private fun openSettings() {
val intent = Intent(this, SettingsActivity::class.java)
@ -651,7 +645,6 @@ class HomeActivity : PassphraseRequiredActionBarActivity(),
private fun hideMessageRequests() {
sessionDialog {
text("Hide message requests?")
buttons {
button(R.string.yes) {
textSecurePreferences.setHasHiddenMessageRequests()
setupMessageRequestsBanner()
@ -660,7 +653,6 @@ class HomeActivity : PassphraseRequiredActionBarActivity(),
button(R.string.no)
}
}
}
private fun showNewConversation() {
NewConversationFragment().show(supportFragmentManager, "NewConversationFragment")

View file

@ -86,12 +86,10 @@ class MessageRequestsActivity : PassphraseRequiredActionBarActivity(), Conversat
sessionDialog {
title(R.string.RecipientPreferenceActivity_block_this_contact_question)
text(R.string.message_requests_block_message)
buttons {
button(R.string.recipient_preferences__block) { doBlock() }
button(R.string.no)
}
}
}
override fun onDeleteConversationClick(thread: ThreadRecord) {
fun doDecline() {
@ -105,12 +103,10 @@ class MessageRequestsActivity : PassphraseRequiredActionBarActivity(), Conversat
sessionDialog {
title(R.string.decline)
text(resources.getString(R.string.message_requests_decline_message))
buttons {
button(R.string.decline) { doDecline() }
button(R.string.no)
}
}
}
private fun updateEmptyState() {
val threadCount = (binding.recyclerView.adapter as MessageRequestsAdapter).itemCount
@ -129,10 +125,8 @@ class MessageRequestsActivity : PassphraseRequiredActionBarActivity(), Conversat
sessionDialog {
text(resources.getString(R.string.message_requests_clear_all_message))
buttons {
button(R.string.yes) { doDeleteAllAndBlock() }
button(R.string.no)
}
}
}
}

View file

@ -154,10 +154,8 @@ class PNModeActivity : BaseActionBarActivity() {
if (selectedOptionView == null) {
sessionDialog {
title(R.string.activity_pn_mode_no_option_picked_dialog_title)
buttons {
button(R.string.ok)
}
}
return
}

View file

@ -55,13 +55,11 @@ class BlockedContactsActivity: PassphraseRequiredActionBarActivity(), View.OnCli
sessionDialog {
title(title)
text(message)
buttons {
button(R.string.continue_2) { viewModel.unblock(contactsToUnblock) }
cancelButton()
}
}
}
}
override fun onCreate(savedInstanceState: Bundle?, ready: Boolean) {
super.onCreate(savedInstanceState, ready)

View file

@ -264,13 +264,11 @@ class SettingsActivity : PassphraseRequiredActionBarActivity() {
sessionDialog {
title(R.string.activity_settings_set_display_picture)
view(R.layout.dialog_change_avatar)
buttons {
button(R.string.activity_settings_upload) { startAvatarSelection() }
if (TextSecurePreferences.getProfileAvatarId(context) != 0) {
button(R.string.activity_settings_remove) { removeAvatar() }
}
cancelButton()
}
}.apply {
findViewById<ProfilePictureView>(R.id.profile_picture_view)?.let(::setupProfilePictureView)
}

View file

@ -3,7 +3,6 @@ package org.thoughtcrime.securesms.util
import android.content.ContentResolver
import android.content.ContentValues
import android.content.Context
import android.content.DialogInterface.OnClickListener
import android.media.MediaScannerConnection
import android.net.Uri
import android.os.Build
@ -12,7 +11,6 @@ import android.provider.MediaStore
import android.text.TextUtils
import android.webkit.MimeTypeMap
import android.widget.Toast
import androidx.appcompat.app.AlertDialog
import network.loki.messenger.R
import org.session.libsession.utilities.task.ProgressDialogAsyncTask
import org.session.libsignal.utilities.ExternalStorageUtil
@ -31,7 +29,12 @@ import java.util.concurrent.TimeUnit
* Saves attachment files to an external storage using [MediaStore] API.
* Requires [android.Manifest.permission.WRITE_EXTERNAL_STORAGE] on API 28 and below.
*/
class SaveAttachmentTask : ProgressDialogAsyncTask<SaveAttachmentTask.Attachment, Void, Pair<Int, String?>> {
class SaveAttachmentTask @JvmOverloads constructor(context: Context, count: Int = 1) :
ProgressDialogAsyncTask<SaveAttachmentTask.Attachment, Void, Pair<Int, String?>>(
context,
context.resources.getQuantityString(R.plurals.ConversationFragment_saving_n_attachments, count, count),
context.resources.getQuantityString(R.plurals.ConversationFragment_saving_n_attachments_to_sd_card, count, count)
) {
companion object {
@JvmStatic
@ -42,31 +45,25 @@ class SaveAttachmentTask : ProgressDialogAsyncTask<SaveAttachmentTask.Attachment
@JvmStatic
@JvmOverloads
fun showWarningDialog(context: Context, count: Int = 1, onAcceptListener: () -> Unit) {
fun showWarningDialog(context: Context, count: Int = 1, onAcceptListener: () -> Unit = {}) {
context.sessionDialog {
title(R.string.ConversationFragment_save_to_sd_card)
setIconAttribute(R.attr.dialog_alert_icon)
iconAttribute(R.attr.dialog_alert_icon)
text(context.resources.getQuantityString(
R.plurals.ConversationFragment_saving_n_media_to_storage_warning,
count,
count))
buttons {
button(R.string.yes) { onAcceptListener() }
button(R.string.no)
}
}
}
}
private val contextReference: WeakReference<Context>
private val attachmentCount: Int
private val attachmentCount: Int = count
@JvmOverloads
constructor(context: Context, count: Int = 1): super(context,
context.resources.getQuantityString(R.plurals.ConversationFragment_saving_n_attachments, count, count),
context.resources.getQuantityString(R.plurals.ConversationFragment_saving_n_attachments_to_sd_card, count, count)) {
init {
this.contextReference = WeakReference(context)
this.attachmentCount = count
}
override fun doInBackground(vararg attachments: Attachment?): Pair<Int, String?> {