Recreating xml dialogs in Compose and moved logic in VM
parent
f73e022cfd
commit
ed38e507ae
@ -0,0 +1,217 @@
|
|||||||
|
package org.thoughtcrime.securesms.conversation.v2
|
||||||
|
|
||||||
|
import androidx.compose.foundation.layout.PaddingValues
|
||||||
|
import androidx.compose.runtime.Composable
|
||||||
|
import androidx.compose.runtime.getValue
|
||||||
|
import androidx.compose.runtime.mutableStateOf
|
||||||
|
import androidx.compose.runtime.remember
|
||||||
|
import androidx.compose.runtime.setValue
|
||||||
|
import androidx.compose.ui.res.pluralStringResource
|
||||||
|
import androidx.compose.ui.res.stringResource
|
||||||
|
import androidx.compose.ui.tooling.preview.Preview
|
||||||
|
import androidx.compose.ui.unit.dp
|
||||||
|
import com.squareup.phrase.Phrase
|
||||||
|
import network.loki.messenger.R
|
||||||
|
import network.loki.messenger.libsession_util.util.ExpiryMode
|
||||||
|
import org.session.libsession.utilities.StringSubstitutionConstants.APP_NAME_KEY
|
||||||
|
import org.thoughtcrime.securesms.conversation.disappearingmessages.ExpiryType
|
||||||
|
import org.thoughtcrime.securesms.ui.OpenURLAlertDialog
|
||||||
|
import org.thoughtcrime.securesms.ui.theme.SessionMaterialTheme
|
||||||
|
import org.thoughtcrime.securesms.conversation.v2.ConversationViewModel.Commands.*
|
||||||
|
import org.thoughtcrime.securesms.database.model.MessageRecord
|
||||||
|
import org.thoughtcrime.securesms.ui.AlertDialog
|
||||||
|
import org.thoughtcrime.securesms.ui.DialogButtonModel
|
||||||
|
import org.thoughtcrime.securesms.ui.GetString
|
||||||
|
import org.thoughtcrime.securesms.ui.RadioOption
|
||||||
|
import org.thoughtcrime.securesms.ui.components.TitledRadioButton
|
||||||
|
import org.thoughtcrime.securesms.ui.theme.LocalColors
|
||||||
|
import org.thoughtcrime.securesms.ui.theme.LocalDimensions
|
||||||
|
import org.thoughtcrime.securesms.ui.theme.PreviewTheme
|
||||||
|
import kotlin.time.Duration.Companion.days
|
||||||
|
|
||||||
|
@Composable
|
||||||
|
fun ConversationV2Dialogs(
|
||||||
|
dialogsState: ConversationViewModel.DialogsState,
|
||||||
|
sendCommand: (ConversationViewModel.Commands) -> Unit
|
||||||
|
){
|
||||||
|
SessionMaterialTheme {
|
||||||
|
// open link confirmation
|
||||||
|
if(!dialogsState.openLinkDialogUrl.isNullOrEmpty()){
|
||||||
|
OpenURLAlertDialog(
|
||||||
|
url = dialogsState.openLinkDialogUrl,
|
||||||
|
onDismissRequest = {
|
||||||
|
// hide dialog
|
||||||
|
sendCommand(ShowOpenUrlDialog(null))
|
||||||
|
}
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
// delete message(s) on device only
|
||||||
|
if(dialogsState.deleteDeviceOnly != null){
|
||||||
|
AlertDialog(
|
||||||
|
onDismissRequest = {
|
||||||
|
// hide dialog
|
||||||
|
sendCommand(HideDeleteDeviceOnlyDialog)
|
||||||
|
},
|
||||||
|
title = pluralStringResource(
|
||||||
|
R.plurals.deleteMessage,
|
||||||
|
dialogsState.deleteDeviceOnly.size,
|
||||||
|
dialogsState.deleteDeviceOnly.size
|
||||||
|
),
|
||||||
|
text = stringResource(R.string.deleteMessageDescriptionDevice), //todo DELETION we need the plural version of this here, which currently is not set up in strings
|
||||||
|
buttons = listOf(
|
||||||
|
DialogButtonModel(
|
||||||
|
text = GetString(stringResource(id = R.string.delete)),
|
||||||
|
color = LocalColors.current.danger,
|
||||||
|
onClick = {
|
||||||
|
sendCommand(MarkAsDeletedLocally(dialogsState.deleteDeviceOnly))
|
||||||
|
}
|
||||||
|
),
|
||||||
|
DialogButtonModel(
|
||||||
|
GetString(stringResource(R.string.cancel))
|
||||||
|
)
|
||||||
|
)
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
// delete message(s) for everyone
|
||||||
|
if(dialogsState.deleteEveryone != null){
|
||||||
|
var deleteForEveryone by remember { mutableStateOf(dialogsState.deleteEveryone.defaultToEveryone)}
|
||||||
|
|
||||||
|
AlertDialog(
|
||||||
|
onDismissRequest = {
|
||||||
|
// hide dialog
|
||||||
|
sendCommand(HideDeleteEveryoneDialog)
|
||||||
|
},
|
||||||
|
title = pluralStringResource(
|
||||||
|
R.plurals.deleteMessage,
|
||||||
|
dialogsState.deleteEveryone.messages.size,
|
||||||
|
dialogsState.deleteEveryone.messages.size
|
||||||
|
),
|
||||||
|
text = stringResource(R.string.deleteMessageConfirm), //todo DELETION we need the plural version of this here, which currently is not set up in strings
|
||||||
|
content = {
|
||||||
|
TitledRadioButton(
|
||||||
|
contentPadding = PaddingValues(
|
||||||
|
horizontal = LocalDimensions.current.xxsSpacing,
|
||||||
|
vertical = 0.dp
|
||||||
|
),
|
||||||
|
option = RadioOption(
|
||||||
|
value = Unit,
|
||||||
|
title = GetString(stringResource(R.string.deleteMessageDeviceOnly)),
|
||||||
|
selected = !deleteForEveryone
|
||||||
|
)
|
||||||
|
) {
|
||||||
|
deleteForEveryone = false
|
||||||
|
}
|
||||||
|
|
||||||
|
TitledRadioButton(
|
||||||
|
contentPadding = PaddingValues(
|
||||||
|
horizontal = LocalDimensions.current.xxsSpacing,
|
||||||
|
vertical = 0.dp
|
||||||
|
),
|
||||||
|
option = RadioOption(
|
||||||
|
value = Unit,
|
||||||
|
title = GetString(stringResource(R.string.deleteMessageEveryone)),
|
||||||
|
selected = deleteForEveryone
|
||||||
|
)
|
||||||
|
) {
|
||||||
|
deleteForEveryone = true
|
||||||
|
}
|
||||||
|
},
|
||||||
|
buttons = listOf(
|
||||||
|
DialogButtonModel(
|
||||||
|
text = GetString(stringResource(id = R.string.delete)),
|
||||||
|
color = LocalColors.current.danger,
|
||||||
|
onClick = {
|
||||||
|
// delete messages based on chosen option
|
||||||
|
sendCommand(
|
||||||
|
if(deleteForEveryone) MarkAsDeletedForEveryone(dialogsState.deleteEveryone.messages)
|
||||||
|
else MarkAsDeletedLocally(dialogsState.deleteEveryone.messages)
|
||||||
|
)
|
||||||
|
}
|
||||||
|
),
|
||||||
|
DialogButtonModel(
|
||||||
|
GetString(stringResource(R.string.cancel))
|
||||||
|
)
|
||||||
|
)
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
// delete message(s) for all my devices
|
||||||
|
if(dialogsState.deleteAllDevices != null){
|
||||||
|
var deleteAllDevices by remember { mutableStateOf(false) }
|
||||||
|
|
||||||
|
AlertDialog(
|
||||||
|
onDismissRequest = {
|
||||||
|
// hide dialog
|
||||||
|
sendCommand(HideDeleteAllDevicesDialog)
|
||||||
|
},
|
||||||
|
title = pluralStringResource(
|
||||||
|
R.plurals.deleteMessage,
|
||||||
|
dialogsState.deleteAllDevices.size,
|
||||||
|
dialogsState.deleteAllDevices.size
|
||||||
|
),
|
||||||
|
text = stringResource(R.string.deleteMessageConfirm), //todo DELETION we need the plural version of this here, which currently is not set up in strings
|
||||||
|
content = {
|
||||||
|
TitledRadioButton(
|
||||||
|
contentPadding = PaddingValues(
|
||||||
|
horizontal = LocalDimensions.current.xxsSpacing,
|
||||||
|
vertical = 0.dp
|
||||||
|
),
|
||||||
|
option = RadioOption(
|
||||||
|
value = Unit,
|
||||||
|
title = GetString(stringResource(R.string.deleteMessageDeviceOnly)),
|
||||||
|
selected = !deleteAllDevices
|
||||||
|
)
|
||||||
|
) {
|
||||||
|
deleteAllDevices = false
|
||||||
|
}
|
||||||
|
|
||||||
|
TitledRadioButton(
|
||||||
|
contentPadding = PaddingValues(
|
||||||
|
horizontal = LocalDimensions.current.xxsSpacing,
|
||||||
|
vertical = 0.dp
|
||||||
|
),
|
||||||
|
option = RadioOption(
|
||||||
|
value = Unit,
|
||||||
|
title = GetString(stringResource(R.string.deleteMessageDevicesAll)),
|
||||||
|
selected = deleteAllDevices
|
||||||
|
)
|
||||||
|
) {
|
||||||
|
deleteAllDevices = true
|
||||||
|
}
|
||||||
|
},
|
||||||
|
buttons = listOf(
|
||||||
|
DialogButtonModel(
|
||||||
|
text = GetString(stringResource(id = R.string.delete)),
|
||||||
|
color = LocalColors.current.danger,
|
||||||
|
onClick = {
|
||||||
|
// delete messages based on chosen option
|
||||||
|
sendCommand(
|
||||||
|
if(deleteAllDevices) MarkAsDeletedForEveryone(dialogsState.deleteAllDevices)
|
||||||
|
else MarkAsDeletedLocally(dialogsState.deleteAllDevices)
|
||||||
|
)
|
||||||
|
}
|
||||||
|
),
|
||||||
|
DialogButtonModel(
|
||||||
|
GetString(stringResource(R.string.cancel))
|
||||||
|
)
|
||||||
|
)
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Preview
|
||||||
|
@Composable
|
||||||
|
fun PreviewURLDialog(){
|
||||||
|
PreviewTheme {
|
||||||
|
ConversationV2Dialogs(
|
||||||
|
dialogsState = ConversationViewModel.DialogsState(
|
||||||
|
openLinkDialogUrl = "https://google.com"
|
||||||
|
),
|
||||||
|
sendCommand = {}
|
||||||
|
)
|
||||||
|
}
|
||||||
|
}
|
@ -1,39 +0,0 @@
|
|||||||
package org.thoughtcrime.securesms.conversation.v2.dialogs
|
|
||||||
|
|
||||||
import android.app.Dialog
|
|
||||||
import android.os.Bundle
|
|
||||||
import android.util.TypedValue
|
|
||||||
import androidx.annotation.ColorInt
|
|
||||||
import androidx.fragment.app.DialogFragment
|
|
||||||
import network.loki.messenger.R
|
|
||||||
import org.thoughtcrime.securesms.createSessionDialog
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Shown when deleting a message can only be deleted locally
|
|
||||||
*
|
|
||||||
* @param messageCount The number of messages to be deleted.
|
|
||||||
* @param onDeleteDeviceOnly Callback to be executed when the user chooses to delete only on their device.
|
|
||||||
* @param onCancel Callback to be executed when cancelling the dialog.
|
|
||||||
*/
|
|
||||||
class DeleteMessageDeviceOnlyDialog(
|
|
||||||
private val messageCount: Int,
|
|
||||||
private val onDeleteDeviceOnly: () -> Unit,
|
|
||||||
private val onCancel: () -> Unit
|
|
||||||
) : DialogFragment() {
|
|
||||||
|
|
||||||
override fun onCreateDialog(savedInstanceState: Bundle?): Dialog = createSessionDialog {
|
|
||||||
val typedValue = TypedValue()
|
|
||||||
val theme = context.theme
|
|
||||||
theme.resolveAttribute(R.attr.danger, typedValue, true)
|
|
||||||
@ColorInt val deleteColor = typedValue.data
|
|
||||||
|
|
||||||
title(resources.getQuantityString(R.plurals.deleteMessage, messageCount, messageCount))
|
|
||||||
text(resources.getString(R.string.deleteMessageDescriptionDevice)) //todo DELETION we need the plural version of this here, which currently is not set up in strings
|
|
||||||
button(
|
|
||||||
text = R.string.delete,
|
|
||||||
textColor = deleteColor,
|
|
||||||
listener = onDeleteDeviceOnly
|
|
||||||
)
|
|
||||||
cancelButton(onCancel)
|
|
||||||
}
|
|
||||||
}
|
|
@ -1,80 +0,0 @@
|
|||||||
package org.thoughtcrime.securesms.conversation.v2.dialogs
|
|
||||||
|
|
||||||
import android.app.Dialog
|
|
||||||
import android.content.Context
|
|
||||||
import android.os.Bundle
|
|
||||||
import android.util.TypedValue
|
|
||||||
import androidx.annotation.ColorInt
|
|
||||||
import androidx.fragment.app.DialogFragment
|
|
||||||
import network.loki.messenger.R
|
|
||||||
import org.thoughtcrime.securesms.createSessionDialog
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Shown when deleting a message that can be removed both locally and for everyone
|
|
||||||
*
|
|
||||||
* @param messageCount The number of messages to be deleted.
|
|
||||||
* @param defaultToEveryone Whether the dialog should default to deleting for everyone.
|
|
||||||
* @param onDeleteDeviceOnly Callback to be executed when the user chooses to delete only on their device.
|
|
||||||
* @param onDeleteForEveryone Callback to be executed when the user chooses to delete for everyone.
|
|
||||||
* @param onCancel Callback to be executed when cancelling the dialog.
|
|
||||||
*/
|
|
||||||
class DeleteMessageDialog(
|
|
||||||
private val messageCount: Int,
|
|
||||||
private val defaultToEveryone: Boolean,
|
|
||||||
private val onDeleteDeviceOnly: () -> Unit,
|
|
||||||
private val onDeleteForEveryone: () -> Unit,
|
|
||||||
private val onCancel: () -> Unit
|
|
||||||
) : DialogFragment() {
|
|
||||||
|
|
||||||
// tracking the user choice from the radio buttons
|
|
||||||
private var deleteForEveryone = defaultToEveryone
|
|
||||||
|
|
||||||
override fun onCreateDialog(savedInstanceState: Bundle?): Dialog = createSessionDialog {
|
|
||||||
val typedValue = TypedValue()
|
|
||||||
val theme = context.theme
|
|
||||||
theme.resolveAttribute(R.attr.danger, typedValue, true)
|
|
||||||
@ColorInt val deleteColor = typedValue.data
|
|
||||||
|
|
||||||
title(resources.getQuantityString(R.plurals.deleteMessage, messageCount, messageCount))
|
|
||||||
text(resources.getString(R.string.deleteMessageConfirm)) //todo DELETION we need the plural version of this here, which currently is not set up in strings
|
|
||||||
singleChoiceItems(
|
|
||||||
options = deleteOptions.map { it.label },
|
|
||||||
currentSelected = if (defaultToEveryone) 1 else 0, // some cases require the second option, "delete for everyone", to be the default selected
|
|
||||||
dismissOnRadioSelect = false
|
|
||||||
) { index ->
|
|
||||||
deleteForEveryone = (deleteOptions[index] is DeleteOption.DeleteForEveryone) // we delete for everyone if the selected index is 1
|
|
||||||
}
|
|
||||||
button(
|
|
||||||
text = R.string.delete,
|
|
||||||
textColor = deleteColor,
|
|
||||||
listener = {
|
|
||||||
if (deleteForEveryone) {
|
|
||||||
onDeleteForEveryone()
|
|
||||||
} else {
|
|
||||||
onDeleteDeviceOnly()
|
|
||||||
}
|
|
||||||
}
|
|
||||||
)
|
|
||||||
cancelButton(onCancel)
|
|
||||||
}
|
|
||||||
|
|
||||||
private val deleteOptions: List<DeleteOption> by lazy {
|
|
||||||
listOf(
|
|
||||||
DeleteOption.DeleteDeviceOnly(requireContext()), DeleteOption.DeleteForEveryone(requireContext())
|
|
||||||
)
|
|
||||||
}
|
|
||||||
|
|
||||||
private sealed class DeleteOption(
|
|
||||||
open val label: String
|
|
||||||
){
|
|
||||||
data class DeleteDeviceOnly(
|
|
||||||
val context: Context,
|
|
||||||
override val label: String = context.getString(R.string.deleteMessageDeviceOnly),
|
|
||||||
): DeleteOption(label)
|
|
||||||
|
|
||||||
data class DeleteForEveryone(
|
|
||||||
val context: Context,
|
|
||||||
override val label: String = context.getString(R.string.deleteMessageEveryone),
|
|
||||||
): DeleteOption(label)
|
|
||||||
}
|
|
||||||
}
|
|
@ -1,78 +0,0 @@
|
|||||||
package org.thoughtcrime.securesms.conversation.v2.dialogs
|
|
||||||
|
|
||||||
import android.app.Dialog
|
|
||||||
import android.content.Context
|
|
||||||
import android.os.Bundle
|
|
||||||
import android.util.TypedValue
|
|
||||||
import androidx.annotation.ColorInt
|
|
||||||
import androidx.fragment.app.DialogFragment
|
|
||||||
import network.loki.messenger.R
|
|
||||||
import org.thoughtcrime.securesms.createSessionDialog
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Shown when deleting a 'note to self'
|
|
||||||
*
|
|
||||||
* @param messageCount The number of messages to be deleted.
|
|
||||||
* @param onDeleteDeviceOnly Callback to be executed when the user chooses to delete only on their device.
|
|
||||||
* @param onDeleteAllDevices Callback to be executed when the user chooses to delete for everyone.
|
|
||||||
* @param onCancel Callback to be executed when cancelling the dialog.
|
|
||||||
*/
|
|
||||||
class DeleteNoteToSelfDialog(
|
|
||||||
private val messageCount: Int,
|
|
||||||
private val onDeleteDeviceOnly: () -> Unit,
|
|
||||||
private val onDeleteAllDevices: () -> Unit,
|
|
||||||
private val onCancel: () -> Unit
|
|
||||||
) : DialogFragment() {
|
|
||||||
|
|
||||||
// tracking the user choice from the radio buttons
|
|
||||||
private var deleteOnAllDevices = false
|
|
||||||
|
|
||||||
override fun onCreateDialog(savedInstanceState: Bundle?): Dialog = createSessionDialog {
|
|
||||||
val typedValue = TypedValue()
|
|
||||||
val theme = context.theme
|
|
||||||
theme.resolveAttribute(R.attr.danger, typedValue, true)
|
|
||||||
@ColorInt val deleteColor = typedValue.data
|
|
||||||
|
|
||||||
title(resources.getQuantityString(R.plurals.deleteMessage, messageCount, messageCount))
|
|
||||||
text(resources.getString(R.string.deleteMessageConfirm)) //todo DELETION we need the plural version of this here, which currently is not set up in strings
|
|
||||||
singleChoiceItems(
|
|
||||||
options = deleteOptions.map { it.label },
|
|
||||||
currentSelected = 0,
|
|
||||||
dismissOnRadioSelect = false
|
|
||||||
) { index ->
|
|
||||||
deleteOnAllDevices = (deleteOptions[index] is DeleteOption.DeleteOnAllMyDevices) // we delete for everyone if the selected index is 1
|
|
||||||
}
|
|
||||||
button(
|
|
||||||
text = R.string.delete,
|
|
||||||
textColor = deleteColor,
|
|
||||||
listener = {
|
|
||||||
if (deleteOnAllDevices) {
|
|
||||||
onDeleteAllDevices()
|
|
||||||
} else {
|
|
||||||
onDeleteDeviceOnly()
|
|
||||||
}
|
|
||||||
}
|
|
||||||
)
|
|
||||||
cancelButton(onCancel)
|
|
||||||
}
|
|
||||||
|
|
||||||
private val deleteOptions: List<DeleteOption> by lazy {
|
|
||||||
listOf(
|
|
||||||
DeleteOption.DeleteDeviceOnly(requireContext()), DeleteOption.DeleteOnAllMyDevices(requireContext())
|
|
||||||
)
|
|
||||||
}
|
|
||||||
|
|
||||||
private sealed class DeleteOption(
|
|
||||||
open val label: String
|
|
||||||
){
|
|
||||||
data class DeleteDeviceOnly(
|
|
||||||
val context: Context,
|
|
||||||
override val label: String = context.getString(R.string.deleteMessageDeviceOnly),
|
|
||||||
): DeleteOption(label)
|
|
||||||
|
|
||||||
data class DeleteOnAllMyDevices(
|
|
||||||
val context: Context,
|
|
||||||
override val label: String = context.getString(R.string.deleteMessageDevicesAll),
|
|
||||||
): DeleteOption(label)
|
|
||||||
}
|
|
||||||
}
|
|
Loading…
Reference in New Issue