Merge remote-tracking branch 'origin/dev' into closed_groups

# Conflicts:
#	app/src/main/java/org/thoughtcrime/securesms/conversation/v2/ConversationActivityV2.kt
#	app/src/main/java/org/thoughtcrime/securesms/conversation/v2/dialogs/DownloadDialog.kt
#	app/src/main/java/org/thoughtcrime/securesms/home/HomeActivity.kt
#	app/src/main/java/org/thoughtcrime/securesms/recoverypassword/RecoveryPasswordActivity.kt
This commit is contained in:
SessionHero01
2024-10-08 10:26:11 +11:00
30 changed files with 281 additions and 159 deletions

View File

@@ -15,8 +15,8 @@ configurations.configureEach {
exclude module: "commons-logging"
}
def canonicalVersionCode = 382
def canonicalVersionName = "1.20.0"
def canonicalVersionCode = 383
def canonicalVersionName = "1.20.1"
def postFixSize = 10
def abiPostFix = ['armeabi-v7a' : 1,
@@ -59,7 +59,7 @@ android {
splits {
abi {
enable true
enable !project.hasProperty('huawei') // huawei builds do not need the split variants
reset()
include 'armeabi-v7a', 'arm64-v8a', 'x86', 'x86_64'
universalApk true
@@ -122,6 +122,25 @@ android {
}
}
signingConfigs {
play {
if (project.hasProperty('SESSION_STORE_FILE')) {
storeFile file(SESSION_STORE_FILE)
storePassword SESSION_STORE_PASSWORD
keyAlias SESSION_KEY_ALIAS
keyPassword SESSION_KEY_PASSWORD
}
}
huawei {
if (project.hasProperty('SESSION_HUAWEI_STORE_FILE')) {
storeFile file(SESSION_HUAWEI_STORE_FILE)
storePassword SESSION_HUAWEI_STORE_PASSWORD
keyAlias SESSION_HUAWEI_KEY_ALIAS
keyPassword SESSION_HUAWEI_KEY_PASSWORD
}
}
}
flavorDimensions "distribution"
productFlavors {
play {
@@ -133,6 +152,7 @@ android {
buildConfigField "org.session.libsession.utilities.Device", "DEVICE", "org.session.libsession.utilities.Device.ANDROID"
buildConfigField "String", "NOPLAY_UPDATE_URL", "$ext.websiteUpdateUrl"
buildConfigField 'String', 'PUSH_KEY_SUFFIX', '\"\"'
signingConfig signingConfigs.play
}
huawei {
@@ -142,6 +162,7 @@ android {
buildConfigField "org.session.libsession.utilities.Device", "DEVICE", "org.session.libsession.utilities.Device.HUAWEI"
buildConfigField "String", "NOPLAY_UPDATE_URL", "$ext.websiteUpdateUrl"
buildConfigField 'String', 'PUSH_KEY_SUFFIX', '\"_HUAWEI\"'
signingConfig signingConfigs.huawei
}
website {
@@ -159,8 +180,10 @@ android {
def abiName = output.getFilter("ABI") ?: 'universal'
def postFix = abiPostFix.get(abiName, 0)
def flavour = (variant.flavorName == 'huawei') ? "-huawei" : ""
if (postFix >= postFixSize) throw new AssertionError("postFix is too large")
output.outputFileName = output.outputFileName = "session-${variant.versionName}-${abiName}.apk"
output.outputFileName = output.outputFileName = "session-${variant.versionName}-${abiName}${flavour}.apk"
output.versionCodeOverride = canonicalVersionCode * postFixSize + postFix
}
}

View File

@@ -62,7 +62,10 @@ class SessionDialogBuilder(val context: Context) {
// Main title entry point
fun title(text: String?) {
text(text, R.style.TextAppearance_Session_Dialog_Title) { setPadding(dp20, 0, dp20, 0) }
text(
text = text,
qaTag = context.getString(R.string.AccessibilityId_modalTitle),
style = R.style.TextAppearance_Session_Dialog_Title) { setPadding(dp20, 0, dp20, 0) }
}
// Convenience assessor for title that takes a string resource
@@ -74,18 +77,24 @@ class SessionDialogBuilder(val context: Context) {
fun text(@StringRes id: Int, style: Int? = null) = text(context.getString(id), style)
fun text(text: CharSequence?, @StyleRes style: Int? = null) {
text(text, style) {
text(text = text, style = style) {
layoutParams = LinearLayout.LayoutParams(MATCH_PARENT, WRAP_CONTENT)
.apply { updateMargins(dp40, 0, dp40, 0) }
}
}
private fun text(text: CharSequence?, @StyleRes style: Int? = null, modify: TextView.() -> Unit) {
private fun text(
text: CharSequence?,
qaTag: String = context.getString(R.string.AccessibilityId_modalMessage),
@StyleRes style: Int? = null,
modify: TextView.() -> Unit
) {
text ?: return
TextView(context, null, 0, style ?: R.style.TextAppearance_Session_Dialog_Message)
.apply {
setText(text)
textAlignment = View.TEXT_ALIGNMENT_CENTER
contentDescription = qaTag
modify()
}.let(topView::addView)
@@ -166,7 +175,7 @@ class SessionDialogBuilder(val context: Context) {
textColor?.let{
setTextColor(it)
}
contentDescription = resources.getString(contentDescriptionRes)
contentDescription = resources.getString(text) // QA now wants the qa tag to mtch the button's text
layoutParams = LinearLayout.LayoutParams(WRAP_CONTENT, dp60, 1f)
setOnClickListener {
listener.invoke()

View File

@@ -38,7 +38,6 @@ import androidx.compose.runtime.mutableStateOf
import androidx.compose.runtime.setValue
import androidx.compose.ui.platform.ViewCompositionStrategy
import androidx.core.content.ContextCompat
import androidx.core.view.drawToBitmap
import androidx.core.view.isGone
import androidx.core.view.isVisible
import androidx.fragment.app.DialogFragment
@@ -60,6 +59,7 @@ import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.channels.BufferOverflow
import kotlinx.coroutines.channels.Channel
import kotlinx.coroutines.flow.collect
import kotlinx.coroutines.delay
import kotlinx.coroutines.flow.collectLatest
import kotlinx.coroutines.flow.distinctUntilChanged
import kotlinx.coroutines.flow.filter
@@ -192,6 +192,7 @@ import org.thoughtcrime.securesms.util.DateUtils
import org.thoughtcrime.securesms.util.MediaUtil
import org.thoughtcrime.securesms.util.NetworkUtils
import org.thoughtcrime.securesms.util.SaveAttachmentTask
import org.thoughtcrime.securesms.util.drawToBitmap
import org.thoughtcrime.securesms.util.isScrolledToBottom
import org.thoughtcrime.securesms.util.isScrolledToWithin30dpOfBottom
import org.thoughtcrime.securesms.util.push
@@ -750,9 +751,10 @@ class ConversationActivityV2 : PassphraseRequiredActionBarActivity(), InputBarDe
private fun restoreDraftIfNeeded() {
val mediaURI = intent.data
val mediaType = AttachmentManager.MediaType.from(intent.type)
val mimeType = MediaUtil.getMimeType(this, mediaURI)
if (mediaURI != null && mediaType != null) {
if (AttachmentManager.MediaType.IMAGE == mediaType || AttachmentManager.MediaType.GIF == mediaType || AttachmentManager.MediaType.VIDEO == mediaType) {
val media = Media(mediaURI, MediaUtil.getMimeType(this, mediaURI)!!, 0, 0, 0, 0, Optional.absent(), Optional.absent())
if (mimeType != null && (AttachmentManager.MediaType.IMAGE == mediaType || AttachmentManager.MediaType.GIF == mediaType || AttachmentManager.MediaType.VIDEO == mediaType)) {
val media = Media(mediaURI, mimeType, 0, 0, 0, 0, Optional.absent(), Optional.absent())
startActivityForResult(MediaSendActivity.buildEditorIntent(this, listOf( media ), viewModel.recipient!!, ""), PICK_FROM_LIBRARY)
return
} else {
@@ -829,7 +831,7 @@ class ConversationActivityV2 : PassphraseRequiredActionBarActivity(), InputBarDe
if (shouldShowLegacy) {
val txt = Phrase.from(applicationContext, R.string.disappearingMessagesLegacy)
.put(NAME_KEY, legacyRecipient!!.name)
.put(NAME_KEY, legacyRecipient!!.toShortString())
.format()
binding.outdatedBannerTextView.text = txt
}
@@ -1248,7 +1250,7 @@ class ConversationActivityV2 : PassphraseRequiredActionBarActivity(), InputBarDe
val name = if (recipient.isClosedGroupV2Recipient && invitingAdmin != null) {
invitingAdmin.getSearchName()
} else {
recipient.name
recipient.toShortString()
}
showSessionDialog {
@@ -1314,7 +1316,7 @@ class ConversationActivityV2 : PassphraseRequiredActionBarActivity(), InputBarDe
title(R.string.blockUnblock)
text(
Phrase.from(context, R.string.blockUnblockName)
.put(NAME_KEY, recipient.name)
.put(NAME_KEY, recipient.toShortString())
.format()
)
dangerButton(R.string.blockUnblock, R.string.AccessibilityId_unblockConfirm) { viewModel.unblock() }
@@ -1793,10 +1795,19 @@ class ConversationActivityV2 : PassphraseRequiredActionBarActivity(), InputBarDe
binding.inputBar.text = ""
binding.inputBar.cancelQuoteDraft()
binding.inputBar.cancelLinkPreviewDraft()
// Put the message in the database
message.id = smsDb.insertMessageOutbox(viewModel.threadId, outgoingTextMessage, false, message.sentTimestamp!!, null, true)
// Send it
MessageSender.send(message, recipient.address)
lifecycleScope.launch(Dispatchers.Default) {
// Put the message in the database
message.id = smsDb.insertMessageOutbox(
viewModel.threadId,
outgoingTextMessage,
false,
message.sentTimestamp!!,
null,
true
)
// Send it
MessageSender.send(message, recipient.address)
}
// Send a typing stopped message
ApplicationContext.getInstance(this).typingStatusSender.onTypingStopped(viewModel.threadId)
return Pair(recipient.address, sentTimestamp)

View File

@@ -151,14 +151,17 @@ public class ThreadRecord extends DisplayRecord {
.format().toString();
} else if (MmsSmsColumns.Types.isMessageRequestResponse(type)) {
if (lastMessage.getRecipient().getAddress().serialize().equals(
TextSecurePreferences.getLocalNumber(context))) {
return UtilKt.getSubbedCharSequence(
context,
R.string.messageRequestYouHaveAccepted,
new Pair<>(NAME_KEY, getName())
);
try {
if (lastMessage.getRecipient().getAddress().serialize().equals(
TextSecurePreferences.getLocalNumber(context))) {
return UtilKt.getSubbedCharSequence(
context,
R.string.messageRequestYouHaveAccepted,
new Pair<>(NAME_KEY, getName())
);
}
}
catch (Exception e){} // the above can throw a null exception
return context.getString(R.string.messageRequestsAccepted);
} else if (getCount() == 0) {

View File

@@ -74,12 +74,10 @@ fun DebugMenu(
buttons = listOf(
DialogButtonModel(
text = GetString(R.string.cancel),
contentDescription = GetString(R.string.cancel),
onClick = { sendCommand(HideEnvironmentWarningDialog) }
),
DialogButtonModel(
text = GetString(R.string.ok),
contentDescription = GetString(R.string.ok),
onClick = { sendCommand(ChangeEnvironment) }
)
)

View File

@@ -66,6 +66,10 @@ import org.thoughtcrime.securesms.home.search.GlobalSearchInputLayout
import org.thoughtcrime.securesms.home.search.GlobalSearchResult
import org.thoughtcrime.securesms.home.search.GlobalSearchViewModel
import org.thoughtcrime.securesms.messagerequests.MessageRequestsActivity
import com.bumptech.glide.Glide
import com.bumptech.glide.RequestManager
import org.session.libsession.utilities.truncateIdForDisplay
import org.thoughtcrime.securesms.notifications.PushRegistry
import org.thoughtcrime.securesms.permissions.Permissions
import org.thoughtcrime.securesms.preferences.SettingsActivity
import org.thoughtcrime.securesms.recoverypassword.RecoveryPasswordActivity
@@ -498,7 +502,7 @@ class HomeActivity : PassphraseRequiredActionBarActivity(),
showSessionDialog {
title(R.string.block)
text(Phrase.from(context, R.string.blockDescription)
.put(NAME_KEY, thread.recipient.name)
.put(NAME_KEY, thread.recipient.toShortString())
.format())
dangerButton(R.string.block, R.string.AccessibilityId_blockConfirm) {
lifecycleScope.launch(Dispatchers.Default) {
@@ -509,7 +513,7 @@ class HomeActivity : PassphraseRequiredActionBarActivity(),
}
}
// Block confirmation toast added as per SS-64
val txt = Phrase.from(context, R.string.blockBlockedUser).put(NAME_KEY, thread.recipient.name).format().toString()
val txt = Phrase.from(context, R.string.blockBlockedUser).put(NAME_KEY, thread.recipient.toShortString()).format().toString()
Toast.makeText(context, txt, Toast.LENGTH_LONG).show()
}
cancelButton()
@@ -519,7 +523,7 @@ class HomeActivity : PassphraseRequiredActionBarActivity(),
private fun unblockConversation(thread: ThreadRecord) {
showSessionDialog {
title(R.string.blockUnblock)
text(Phrase.from(context, R.string.blockUnblockName).put(NAME_KEY, thread.recipient.name).format())
text(Phrase.from(context, R.string.blockUnblockName).put(NAME_KEY, thread.recipient.toShortString()).format())
dangerButton(R.string.blockUnblock, R.string.AccessibilityId_unblockConfirm) {
lifecycleScope.launch(Dispatchers.Default) {
storage.setBlocked(listOf(thread.recipient), false)
@@ -597,28 +601,40 @@ class HomeActivity : PassphraseRequiredActionBarActivity(),
var positiveButtonId: Int = R.string.yes
var negativeButtonId: Int = R.string.no
if (recipient.isCommunityRecipient) {
title =
if (recipient.isCommunityRecipient) getString(R.string.communityLeave) else getString(
R.string.groupLeave
)
message = Phrase.from(this.applicationContext, R.string.groupLeaveDescription)
.put(GROUP_NAME_KEY, recipient.name.orEmpty())
.format()
}
// If this is a 1-on-1 conversation
else if (recipient.name != null) {
title = getString(R.string.conversationsDelete)
message = Phrase.from(this.applicationContext, R.string.conversationsDeleteDescription)
.put(NAME_KEY, recipient.name)
.format()
}
else {
// If not group-related and we don't have a recipient name then this must be our Note to Self conversation
title = getString(R.string.clearMessages)
message = getString(R.string.clearMessagesNoteToSelfDescription)
positiveButtonId = R.string.clear
if (recipient.isGroupRecipient) {
val group = groupDatabase.getGroup(recipient.address.toString()).orNull()
// If you are an admin of this group you can delete it
if (group != null && group.admins.map { it.toString() }.contains(textSecurePreferences.getLocalNumber())) {
title = getString(R.string.groupLeave)
message = Phrase.from(this.applicationContext, R.string.groupDeleteDescription)
.put(GROUP_NAME_KEY, group.title)
.format()
} else {
// Otherwise this is either a community, or it's a group you're not an admin of
title = if (recipient.isCommunityRecipient) getString(R.string.communityLeave) else getString(R.string.groupLeave)
message = Phrase.from(this.applicationContext, R.string.groupLeaveDescription)
.put(GROUP_NAME_KEY, group.title)
.format()
}
positiveButtonId = R.string.leave
negativeButtonId = R.string.cancel
} else {
// If this is a 1-on-1 conversation
if (recipient.name != null) {
title = getString(R.string.conversationsDelete)
message = Phrase.from(this.applicationContext, R.string.conversationsDeleteDescription)
.put(NAME_KEY, recipient.toShortString())
.format()
}
else {
// If not group-related and we don't have a recipient name then this must be our Note to Self conversation
title = getString(R.string.clearMessages)
message = getString(R.string.clearMessagesNoteToSelfDescription)
positiveButtonId = R.string.clear
negativeButtonId = R.string.cancel
}
}
showSessionDialog {

View File

@@ -3,6 +3,7 @@ package org.thoughtcrime.securesms.home.search
import androidx.lifecycle.ViewModel
import androidx.lifecycle.viewModelScope
import dagger.hilt.android.lifecycle.HiltViewModel
import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.ExperimentalCoroutinesApi
import kotlinx.coroutines.SupervisorJob
import kotlinx.coroutines.channels.BufferOverflow
@@ -13,11 +14,13 @@ import kotlinx.coroutines.flow.MutableStateFlow
import kotlinx.coroutines.flow.buffer
import kotlinx.coroutines.flow.flatMapLatest
import kotlinx.coroutines.flow.flowOf
import kotlinx.coroutines.flow.flowOn
import kotlinx.coroutines.flow.map
import kotlinx.coroutines.flow.mapLatest
import kotlinx.coroutines.flow.merge
import kotlinx.coroutines.launch
import kotlinx.coroutines.plus
import kotlinx.coroutines.withContext
import org.thoughtcrime.securesms.search.SearchRepository
import org.thoughtcrime.securesms.search.model.SearchResult
import javax.inject.Inject
@@ -38,9 +41,14 @@ class GlobalSearchViewModel @Inject constructor(
.buffer(onBufferOverflow = BufferOverflow.DROP_OLDEST)
.mapLatest { query ->
if (query.trim().isEmpty()) {
// searching for 05 as contactDb#getAllContacts was not returning contacts
// without a nickname/name who haven't approved us.
GlobalSearchResult(query.toString(), searchRepository.queryContacts("05").first.toList())
withContext(Dispatchers.Default) {
// searching for 05 as contactDb#getAllContacts was not returning contacts
// without a nickname/name who haven't approved us.
GlobalSearchResult(
query.toString(),
searchRepository.queryContacts("05").first.toList()
)
}
} else {
// User input delay in case we get a new query within a few hundred ms this
// coroutine will be cancelled and the expensive query will not be run.

View File

@@ -231,8 +231,8 @@ private fun SaveAttachmentWarningDialog(
title = context.getString(R.string.warning),
text = context.resources.getString(R.string.attachmentsWarning),
buttons = listOf(
DialogButtonModel(GetString(R.string.save), GetString(R.string.AccessibilityId_saveAttachment), color = LocalColors.current.danger, onClick = onAccepted),
DialogButtonModel(GetString(android.R.string.cancel), GetString(R.string.AccessibilityId_cancel), dismissOnClick = true)
DialogButtonModel(GetString(R.string.save), color = LocalColors.current.danger, onClick = onAccepted),
DialogButtonModel(GetString(android.R.string.cancel), dismissOnClick = true)
)
)
}

View File

@@ -92,7 +92,7 @@ class MessageRequestsActivity : PassphraseRequiredActionBarActivity(), Conversat
showSessionDialog {
title(R.string.block)
text(Phrase.from(context, R.string.blockDescription)
.put(NAME_KEY, thread.recipient.name)
.put(NAME_KEY, thread.recipient.toShortString())
.format())
dangerButton(R.string.block, R.string.AccessibilityId_blockConfirm) {
doBlock()

View File

@@ -85,12 +85,10 @@ internal fun LandingScreen(
buttons = listOf(
DialogButtonModel(
text = GetString(R.string.onboardingTos),
contentDescription = GetString(R.string.AccessibilityId_onboardingTos),
onClick = openTerms
),
DialogButtonModel(
text = GetString(R.string.onboardingPrivacy),
contentDescription = GetString(R.string.AccessibilityId_onboardingPrivacy),
onClick = openPrivacyPolicy
)
)

View File

@@ -566,13 +566,11 @@ class SettingsActivity : PassphraseRequiredActionBarActivity() {
buttons = listOf(
DialogButtonModel(
text = GetString(R.string.save),
contentDescription = GetString(R.string.AccessibilityId_save),
enabled = state is TempAvatar,
onClick = saveAvatar
),
DialogButtonModel(
text = GetString(R.string.remove),
contentDescription = GetString(R.string.AccessibilityId_remove),
color = LocalColors.current.danger,
enabled = state is UserAvatar || // can remove is the user has an avatar set
(state is TempAvatar && state.hasAvatar),

View File

@@ -26,7 +26,10 @@ import androidx.compose.ui.tooling.preview.Preview
import androidx.compose.ui.tooling.preview.PreviewParameter
import androidx.compose.ui.unit.dp
import network.loki.messenger.R
import org.thoughtcrime.securesms.ui.AlertDialog
import org.thoughtcrime.securesms.ui.Cell
import org.thoughtcrime.securesms.ui.DialogButtonModel
import org.thoughtcrime.securesms.ui.GetString
import org.thoughtcrime.securesms.ui.SessionShieldIcon
import org.thoughtcrime.securesms.ui.components.QrImage
import org.thoughtcrime.securesms.ui.components.SlimOutlineButton
@@ -45,8 +48,8 @@ import org.thoughtcrime.securesms.ui.theme.monospace
internal fun RecoveryPasswordScreen(
mnemonic: String,
seed: String? = null,
copyMnemonic:() -> Unit = {},
onHide:() -> Unit = {}
confirmHideRecovery: () -> Unit,
copyMnemonic:() -> Unit = {}
) {
Column(
verticalArrangement = Arrangement.spacedBy(LocalDimensions.current.smallSpacing),
@@ -57,7 +60,7 @@ internal fun RecoveryPasswordScreen(
.padding(horizontal = LocalDimensions.current.spacing)
) {
RecoveryPasswordCell(mnemonic, seed, copyMnemonic)
HideRecoveryPasswordCell(onHide)
HideRecoveryPasswordCell(confirmHideRecovery = confirmHideRecovery)
}
}
@@ -151,7 +154,12 @@ private fun RecoveryPassword(mnemonic: String) {
}
@Composable
private fun HideRecoveryPasswordCell(onHide: () -> Unit = {}) {
private fun HideRecoveryPasswordCell(
confirmHideRecovery:() -> Unit
) {
var showHideRecoveryDialog by remember { mutableStateOf(false) }
var showHideRecoveryConfirmationDialog by remember { mutableStateOf(false) }
Cell {
Row(
modifier = Modifier.padding(LocalDimensions.current.smallSpacing)
@@ -176,10 +184,44 @@ private fun HideRecoveryPasswordCell(onHide: () -> Unit = {}) {
.align(Alignment.CenterVertically)
.contentDescription(R.string.AccessibilityId_recoveryPasswordHideRecoveryPassword),
color = LocalColors.current.danger,
onClick = onHide
onClick = { showHideRecoveryDialog = true }
)
}
}
// recovery hide dialog
if(showHideRecoveryDialog) {
AlertDialog(
onDismissRequest = { showHideRecoveryDialog = false },
title = stringResource(R.string.recoveryPasswordHidePermanently),
text = stringResource(R.string.recoveryPasswordHidePermanentlyDescription1),
buttons = listOf(
DialogButtonModel(
GetString(R.string.theContinue),
color = LocalColors.current.danger,
onClick = { showHideRecoveryConfirmationDialog = true }
),
DialogButtonModel(GetString(android.R.string.cancel))
)
)
}
// recovery hide confirmation dialog
if(showHideRecoveryConfirmationDialog) {
AlertDialog(
onDismissRequest = { showHideRecoveryConfirmationDialog = false },
title = stringResource(R.string.recoveryPasswordHidePermanently),
text = stringResource(R.string.recoveryPasswordHidePermanentlyDescription2),
buttons = listOf(
DialogButtonModel(
GetString(R.string.yes),
color = LocalColors.current.danger,
onClick = confirmHideRecovery
),
DialogButtonModel(GetString(android.R.string.cancel))
)
)
}
}
@Preview
@@ -188,6 +230,9 @@ private fun PreviewRecoveryPasswordScreen(
@PreviewParameter(SessionColorsParameterProvider::class) colors: ThemeColors
) {
PreviewTheme(colors) {
RecoveryPasswordScreen(mnemonic = "voyage urban toyed maverick peculiar tuxedo penguin tree grass building listen speak withdraw terminal plane")
RecoveryPasswordScreen(
mnemonic = "voyage urban toyed maverick peculiar tuxedo penguin tree grass building listen speak withdraw terminal plane",
confirmHideRecovery = {}
)
}
}

View File

@@ -24,33 +24,12 @@ class RecoveryPasswordActivity : BaseActionBarActivity() {
RecoveryPasswordScreen(
mnemonic = mnemonic,
seed = seed,
copyMnemonic = viewModel::copyMnemonic,
onHide = ::onHide
confirmHideRecovery = {
viewModel.permanentlyHidePassword()
finish()
},
copyMnemonic = viewModel::copyMnemonic
)
}
}
private fun onHide() {
showSessionDialog {
title(R.string.recoveryPasswordHidePermanently)
text(R.string.recoveryPasswordHidePermanentlyDescription1)
dangerButton(R.string.theContinue, R.string.AccessibilityId_theContinue) { onHideConfirm() }
cancelButton()
}
}
private fun onHideConfirm() {
showSessionDialog {
title(R.string.recoveryPasswordHidePermanently)
text(R.string.recoveryPasswordHidePermanentlyDescription2)
cancelButton()
dangerButton(
R.string.yes,
contentDescriptionRes = R.string.AccessibilityId_recoveryPasswordHidePermanentlyConfirm
) {
viewModel.permanentlyHidePassword()
finish()
}
}
}
}

View File

@@ -55,7 +55,6 @@ import org.thoughtcrime.securesms.ui.theme.bold
class DialogButtonModel(
val text: GetString,
val contentDescription: GetString = text,
val color: Color = Color.Unspecified,
val dismissOnClick: Boolean = true,
val enabled: Boolean = true,
@@ -130,6 +129,7 @@ fun AlertDialog(
textAlign = TextAlign.Center,
style = LocalType.current.h7,
modifier = Modifier.padding(bottom = LocalDimensions.current.xxsSpacing)
.qaTag(stringResource(R.string.AccessibilityId_modalTitle))
)
}
text?.let {
@@ -152,6 +152,7 @@ fun AlertDialog(
textAlign = TextAlign.Center,
style = textStyle,
modifier = textModifier
.qaTag(stringResource(R.string.AccessibilityId_modalMessage))
)
}
content()
@@ -163,7 +164,7 @@ fun AlertDialog(
text = it.text(),
modifier = Modifier
.fillMaxHeight()
.contentDescription(it.contentDescription())
.qaTag(it.text.string())
.weight(1f),
color = it.color,
enabled = it.enabled
@@ -201,13 +202,11 @@ fun OpenURLAlertDialog(
buttons = listOf(
DialogButtonModel(
text = GetString(R.string.open),
contentDescription = GetString(R.string.AccessibilityId_urlOpenBrowser),
color = LocalColors.current.danger,
onClick = { context.openUrl(url) }
),
DialogButtonModel(
text = GetString(android.R.string.copyUrl),
contentDescription = GetString(R.string.AccessibilityId_copy),
onClick = {
context.copyURLToClipboard(url)
Toast.makeText(context, R.string.copied, Toast.LENGTH_SHORT).show()
@@ -297,7 +296,8 @@ fun LoadingDialog(
title?.let {
Text(
it,
modifier = Modifier.align(Alignment.CenterHorizontally),
modifier = Modifier.align(Alignment.CenterHorizontally)
.qaTag(stringResource(R.string.AccessibilityId_modalTitle)),
style = LocalType.current.large
)
}
@@ -340,12 +340,10 @@ fun PreviewXCloseDialog() {
buttons = listOf(
DialogButtonModel(
text = GetString(R.string.onboardingTos),
contentDescription = GetString(R.string.AccessibilityId_onboardingTos),
onClick = {}
),
DialogButtonModel(
text = GetString(R.string.onboardingPrivacy),
contentDescription = GetString(R.string.AccessibilityId_onboardingPrivacy),
onClick = {}
)
),