Add Block button and dialog

This commit is contained in:
maxmoney21m
2023-03-15 13:40:59 +08:00
parent e94d2b5340
commit ad4e6d6596
7 changed files with 160 additions and 59 deletions
@@ -47,7 +47,8 @@ private object PrefKeys {
const val TRANSLATE_TO = "translateTo"
const val ZAP_AMOUNTS = "zapAmounts"
const val LATEST_CONTACT_LIST = "latestContactList"
const val HIDE_DELETE_REQUEST_INFO = "hideDeleteRequestInfo"
const val HIDE_DELETE_REQUEST_DIALOG = "hide_delete_request_dialog"
const val HIDE_BLOCK_ALERT_DIALOG = "hide_block_alert_dialog"
val LAST_READ: (String) -> String = { route -> "last_read_route_$route" }
}
@@ -183,7 +184,8 @@ object LocalPreferences {
putString(PrefKeys.TRANSLATE_TO, account.translateTo)
putString(PrefKeys.ZAP_AMOUNTS, gson.toJson(account.zapAmountChoices))
putString(PrefKeys.LATEST_CONTACT_LIST, Event.gson.toJson(account.backupContactList))
putBoolean(PrefKeys.HIDE_DELETE_REQUEST_INFO, account.hideDeleteRequestInfo)
putBoolean(PrefKeys.HIDE_DELETE_REQUEST_DIALOG, account.hideDeleteRequestDialog)
putBoolean(PrefKeys.HIDE_BLOCK_ALERT_DIALOG, account.hideBlockAlertDialog)
putString(PrefKeys.DISPLAY_NAME, account.userProfile().toBestDisplayName())
putString(PrefKeys.PROFILE_PICTURE_URL, account.userProfile().profilePicture())
}.apply()
@@ -230,7 +232,8 @@ object LocalPreferences {
mapOf()
}
val hideDeleteRequestInfo = getBoolean(PrefKeys.HIDE_DELETE_REQUEST_INFO, false)
val hideDeleteRequestDialog = getBoolean(PrefKeys.HIDE_DELETE_REQUEST_DIALOG, false)
val hideBlockAlertDialog = getBoolean(PrefKeys.HIDE_BLOCK_ALERT_DIALOG, false)
return Account(
Persona(privKey = privKey?.toByteArray(), pubKey = pubKey.toByteArray()),
@@ -241,7 +244,8 @@ object LocalPreferences {
languagePreferences,
translateTo,
zapAmountChoices,
hideDeleteRequestInfo,
hideDeleteRequestDialog,
hideBlockAlertDialog,
latestContactList
)
}
@@ -289,8 +293,8 @@ object LocalPreferences {
stringPrefs.forEach { userPrefs.putString(it, appPrefs.getString(it, null)) }
stringSetPrefs.forEach { userPrefs.putStringSet(it, appPrefs.getStringSet(it, null)) }
userPrefs.putBoolean(
PrefKeys.HIDE_DELETE_REQUEST_INFO,
appPrefs.getBoolean(PrefKeys.HIDE_DELETE_REQUEST_INFO, false)
PrefKeys.HIDE_DELETE_REQUEST_DIALOG,
appPrefs.getBoolean(PrefKeys.HIDE_DELETE_REQUEST_DIALOG, false)
)
}.apply()
}
@@ -59,7 +59,8 @@ class Account(
var languagePreferences: Map<String, String> = mapOf(),
var translateTo: String = Locale.getDefault().language,
var zapAmountChoices: List<Long> = listOf(500L, 1000L, 5000L),
var hideDeleteRequestInfo: Boolean = false,
var hideDeleteRequestDialog: Boolean = false,
var hideBlockAlertDialog: Boolean = false,
var backupContactList: ContactListEvent? = null
) {
var transientHiddenUsers: Set<String> = setOf()
@@ -553,8 +554,13 @@ class Account(
saveable.invalidateData()
}
fun setHideDeleteRequestInfo() {
hideDeleteRequestInfo = true
fun setHideDeleteRequestDialog() {
hideDeleteRequestDialog = true
saveable.invalidateData()
}
fun setHideBlockAlertDialog() {
hideBlockAlertDialog = true
saveable.invalidateData()
}
@@ -7,6 +7,7 @@ import androidx.compose.foundation.layout.Arrangement
import androidx.compose.foundation.layout.Column
import androidx.compose.foundation.layout.IntrinsicSize
import androidx.compose.foundation.layout.Row
import androidx.compose.foundation.layout.Spacer
import androidx.compose.foundation.layout.fillMaxHeight
import androidx.compose.foundation.layout.fillMaxWidth
import androidx.compose.foundation.layout.height
@@ -16,6 +17,8 @@ import androidx.compose.foundation.layout.width
import androidx.compose.foundation.shape.RoundedCornerShape
import androidx.compose.material.AlertDialog
import androidx.compose.material.Button
import androidx.compose.material.ButtonColors
import androidx.compose.material.ButtonDefaults
import androidx.compose.material.Card
import androidx.compose.material.Divider
import androidx.compose.material.Icon
@@ -30,6 +33,7 @@ import androidx.compose.material.icons.filled.Delete
import androidx.compose.material.icons.filled.FormatQuote
import androidx.compose.material.icons.filled.PersonAdd
import androidx.compose.material.icons.filled.PersonRemove
import androidx.compose.material.icons.filled.Report
import androidx.compose.material.icons.filled.Share
import androidx.compose.runtime.Composable
import androidx.compose.runtime.getValue
@@ -59,9 +63,10 @@ import com.vitorpamplona.amethyst.model.Note
import com.vitorpamplona.amethyst.ui.components.SelectTextDialog
import com.vitorpamplona.amethyst.ui.screen.loggedIn.AccountViewModel
import com.vitorpamplona.amethyst.ui.screen.loggedIn.ReportNoteDialog
import com.vitorpamplona.amethyst.ui.theme.WarningColor
import kotlinx.coroutines.launch
fun lightenColor(color: Color, amount: Float): Color {
private fun lightenColor(color: Color, amount: Float): Color {
var argb = color.toArgb()
val hslOut = floatArrayOf(0f, 0f, 0f)
ColorUtils.colorToHSL(argb, hslOut)
@@ -73,7 +78,7 @@ fun lightenColor(color: Color, amount: Float): Color {
val externalLinkForNote = { note: Note -> "https://snort.social/e/${note.idNote()}" }
@Composable
fun VerticalDivider(color: Color) =
private fun VerticalDivider(color: Color) =
Divider(
color = color,
modifier = Modifier
@@ -90,8 +95,9 @@ fun NoteQuickActionMenu(note: Note, popupExpanded: Boolean, onDismiss: () -> Uni
val scope = rememberCoroutineScope()
var showSelectTextDialog by remember { mutableStateOf(false) }
var showDeleteAlertDialog by remember { mutableStateOf(false) }
var showBlockAlertDialog by remember { mutableStateOf(false) }
var showReportDialog by remember { mutableStateOf(false) }
val isOwnNote = note.author == accountViewModel.userProfile()
val isOwnNote = note.author == accountViewModel.accountLiveData.value?.account?.userProfile()
val isFollowingUser = !isOwnNote && accountViewModel.isFollowing(note.author!!)
val showToast = { stringResource: Int ->
@@ -138,11 +144,16 @@ fun NoteQuickActionMenu(note: Note, popupExpanded: Boolean, onDismiss: () -> Uni
onDismiss()
}
if (note.author != accountViewModel.accountLiveData.value?.account?.userProfile()) {
if (!isOwnNote) {
VerticalDivider(primaryLight)
NoteQuickActionItem(Icons.Default.Block, "Block") {
showReportDialog = true
NoteQuickActionItem(Icons.Default.Block, stringResource(R.string.quick_action_block)) {
if (accountViewModel.hideBlockAlertDialog) {
note.author?.let { accountViewModel.hide(it) }
onDismiss()
} else {
showBlockAlertDialog = true
}
}
}
}
@@ -155,7 +166,7 @@ fun NoteQuickActionMenu(note: Note, popupExpanded: Boolean, onDismiss: () -> Uni
Row(modifier = Modifier.height(IntrinsicSize.Min)) {
if (isOwnNote) {
NoteQuickActionItem(Icons.Default.Delete, stringResource(R.string.quick_action_delete)) {
if (accountViewModel.hideDeleteRequestInfo()) {
if (accountViewModel.hideDeleteRequestDialog) {
accountViewModel.delete(note)
onDismiss()
} else {
@@ -198,7 +209,14 @@ fun NoteQuickActionMenu(note: Note, popupExpanded: Boolean, onDismiss: () -> Uni
ContextCompat.startActivity(context, shareIntent, null)
onDismiss()
}
VerticalDivider(primaryLight)
if (!isOwnNote) {
VerticalDivider(primaryLight)
NoteQuickActionItem(Icons.Default.Report, stringResource(R.string.quick_action_report)) {
showReportDialog = true
}
}
}
}
}
@@ -212,7 +230,17 @@ fun NoteQuickActionMenu(note: Note, popupExpanded: Boolean, onDismiss: () -> Uni
}
if (showDeleteAlertDialog) {
DeleteAlertDialog(note, accountViewModel, onDismiss)
DeleteAlertDialog(note, accountViewModel) {
showDeleteAlertDialog = false
onDismiss()
}
}
if (showBlockAlertDialog) {
BlockAlertDialog(note, accountViewModel) {
showBlockAlertDialog = false
onDismiss()
}
}
if (showReportDialog) {
@@ -245,14 +273,65 @@ fun NoteQuickActionItem(icon: ImageVector, label: String, onClick: () -> Unit) {
}
@Composable
fun DeleteAlertDialog(note: Note, accountViewModel: AccountViewModel, onDismiss: () -> Unit) {
fun DeleteAlertDialog(note: Note, accountViewModel: AccountViewModel, onDismiss: () -> Unit) =
QuickActionAlertDialog(
title = stringResource(R.string.quick_action_request_deletion_alert_title),
textContent = stringResource(R.string.quick_action_request_deletion_alert_body),
buttonIcon = Icons.Default.Delete,
buttonText = stringResource(R.string.quick_action_delete_dialog_btn),
onClickDoOnce = {
accountViewModel.delete(note)
onDismiss()
},
onClickDontShowAgain = {
accountViewModel.delete(note)
accountViewModel.dontShowDeleteRequestDialog()
onDismiss()
},
onDismiss = onDismiss
)
@Composable
private fun BlockAlertDialog(note: Note, accountViewModel: AccountViewModel, onDismiss: () -> Unit) =
QuickActionAlertDialog(
title = stringResource(R.string.report_dialog_block_hide_user_btn),
textContent = stringResource(R.string.report_dialog_blocking_a_user),
buttonIcon = Icons.Default.Block,
buttonText = stringResource(R.string.quick_action_block_dialog_btn),
buttonColors = ButtonDefaults.buttonColors(
backgroundColor = WarningColor,
contentColor = Color.White
),
onClickDoOnce = {
note.author?.let { accountViewModel.hide(it) }
onDismiss()
},
onClickDontShowAgain = {
note.author?.let { accountViewModel.hide(it) }
accountViewModel.dontShowBlockAlertDialog()
onDismiss()
},
onDismiss = onDismiss
)
@Composable
private fun QuickActionAlertDialog(
title: String,
textContent: String,
buttonIcon: ImageVector,
buttonText: String,
buttonColors: ButtonColors = ButtonDefaults.buttonColors(),
onClickDoOnce: () -> Unit,
onClickDontShowAgain: () -> Unit,
onDismiss: () -> Unit
) {
AlertDialog(
onDismissRequest = onDismiss,
title = {
Text(text = stringResource(R.string.quick_action_request_deletion_alert_title))
Text(title)
},
text = {
Text(text = stringResource(R.string.quick_action_request_deletion_alert_body))
Text(textContent)
},
buttons = {
Row(
@@ -261,19 +340,20 @@ fun DeleteAlertDialog(note: Note, accountViewModel: AccountViewModel, onDismiss:
.fillMaxWidth(),
horizontalArrangement = Arrangement.SpaceBetween
) {
TextButton(
onClick = {
accountViewModel.setHideDeleteRequestInfo()
accountViewModel.delete(note)
onDismiss()
}
) {
TextButton(onClick = onClickDontShowAgain) {
Text(stringResource(R.string.quick_action_dont_show_again_button))
}
Button(
onClick = { accountViewModel.delete(note); onDismiss() }
) {
Text(stringResource(R.string.quick_action_delete_button))
Button(onClick = onClickDoOnce, colors = buttonColors) {
Row(
verticalAlignment = Alignment.CenterVertically
) {
Icon(
imageVector = buttonIcon,
contentDescription = null
)
Spacer(Modifier.width(8.dp))
Text(buttonText)
}
}
}
}
@@ -129,11 +129,17 @@ class AccountViewModel(private val account: Account) : ViewModel() {
return account.userProfile().isFollowing(user)
}
fun hideDeleteRequestInfo(): Boolean {
return account.hideDeleteRequestInfo
val hideDeleteRequestDialog: Boolean
get() = account.hideDeleteRequestDialog
fun dontShowDeleteRequestDialog() {
account.setHideDeleteRequestDialog()
}
fun setHideDeleteRequestInfo() {
account.setHideDeleteRequestInfo()
val hideBlockAlertDialog: Boolean
get() = account.hideBlockAlertDialog
fun dontShowBlockAlertDialog() {
account.setHideBlockAlertDialog()
}
}
@@ -40,6 +40,7 @@ import androidx.compose.ui.window.DialogProperties
import com.vitorpamplona.amethyst.R
import com.vitorpamplona.amethyst.model.Note
import com.vitorpamplona.amethyst.service.model.ReportEvent
import com.vitorpamplona.amethyst.ui.theme.WarningColor
@Composable
fun ReportNoteDialog(note: Note, accountViewModel: AccountViewModel, onDismiss: () -> Unit) {
@@ -138,8 +139,6 @@ fun ReportNoteDialog(note: Note, accountViewModel: AccountViewModel, onDismiss:
}
}
private val warningColor = Color(0xFFC62828)
@Composable
private fun SpacerH16() = Spacer(modifier = Modifier.height(16.dp))
@@ -155,7 +154,7 @@ private fun SectionHeader(text: String) = Text(
private fun ActionButton(text: String, icon: ImageVector, enabled: Boolean = true, onClick: () -> Unit) = Button(
onClick = onClick,
enabled = enabled,
colors = ButtonDefaults.buttonColors(backgroundColor = warningColor),
colors = ButtonDefaults.buttonColors(backgroundColor = WarningColor),
modifier = Modifier.fillMaxWidth()
) {
Row(
@@ -12,3 +12,5 @@ val Following = Color(0xFF03DAC5)
val Nip05 = Color(0xFF01BAFF)
val FollowsFollow = Color.Yellow
val NIP05Verified = Color.Blue
val WarningColor = Color(0xFFC62828)
+24 -20
View File
@@ -198,6 +198,23 @@
<string name="copied_user_id_to_clipboard" tools:ignore="Typos">Copied authors @npub to clipboard</string>
<string name="copied_note_id_to_clipboard" tools:ignore="Typos">Copied note ID (@note1) to clipboard</string>
<string name="select_text_dialog_top">Select Text</string>
<string name="github" translatable="false">Github Gist w/ Proof</string>
<string name="telegram" translatable="false">Telegram</string>
<string name="mastodon" translatable="false">Mastodon Post ID w/ Proof</string>
<string name="twitter" translatable="false">Twitter Status w/ Proof</string>
<string name="github_proof_url_template" translatable="false">https://gist.github.com/&lt;user&gt;/&lt;gist&gt;</string>
<string name="telegram_proof_url_template" translatable="false">https://t.me/&lt;proof post&gt;</string>
<string name="mastodon_proof_url_template" translatable="false">https://&lt;server&gt;/&lt;user&gt;/&lt;proof post&gt;</string>
<string name="twitter_proof_url_template" translatable="false">https://twitter.com/&lt;user&gt;/status/&lt;proof post&gt;</string>
<string name="private_conversation_notification">"&lt;Unable to decrypt private message&gt;\n\nYou were cited in a private/encrypted conversation between %1$s and %2$s."</string>
<string name="account_switch_add_account_dialog_title">Add New Account</string>
<string name="drawer_accounts">Accounts</string>
<string name="account_switch_select_account">Select Account</string>
<string name="account_switch_add_account_btn">Add New Account</string>
<string name="account_switch_active_account">Active account</string>
<string name="account_switch_has_private_key">Has private key</string>
<string name="account_switch_pubkey_only">Read only, no private key</string>
<string name="back">Back</string>
<string name="quick_action_select">Select</string>
<string name="quick_action_share_browser_link">Share Browser Link</string>
<string name="quick_action_share">Share</string>
@@ -209,38 +226,25 @@
<string name="quick_action_follow">Follow</string>
<string name="quick_action_request_deletion_alert_title">Request Deletion</string>
<string name="quick_action_request_deletion_alert_body">Amethyst will request that your note be deleted from the relays you are currently connected to. There is no guarantee that your note will be permanently deleted from those relays, or from other relays where it may be stored.</string>
<string name="github" translatable="false">Github Gist w/ Proof</string>
<string name="telegram" translatable="false">Telegram</string>
<string name="mastodon" translatable="false">Mastodon Post ID w/ Proof</string>
<string name="twitter" translatable="false">Twitter Status w/ Proof</string>
<string name="github_proof_url_template" translatable="false">https://gist.github.com/&lt;user&gt;/&lt;gist&gt;</string>
<string name="telegram_proof_url_template" translatable="false">https://t.me/&lt;proof post&gt;</string>
<string name="mastodon_proof_url_template" translatable="false">https://&lt;server&gt;/&lt;user&gt;/&lt;proof post&gt;</string>
<string name="twitter_proof_url_template" translatable="false">https://twitter.com/&lt;user&gt;/status/&lt;proof post&gt;</string>
<string name="private_conversation_notification">"&lt;Unable to decrypt private message&gt;\n\nYou were cited in a private/encrypted conversation between %1$s and %2$s."</string>
<string name="quick_action_block_dialog_btn">Block</string>
<string name="quick_action_delete_dialog_btn">Delete</string>
<string name="quick_action_block">Block</string>
<string name="quick_action_report">Report</string>
<string name="quick_action_delete_button">Delete</string>
<string name="quick_action_dont_show_again_button">Don\'t show again</string>
<string name="account_switch_add_account_dialog_title">Add New Account</string>
<string name="drawer_accounts">Accounts</string>
<string name="account_switch_select_account">Select Account</string>
<string name="account_switch_add_account_btn">Add New Account</string>
<string name="account_switch_active_account">Active account</string>
<string name="account_switch_has_private_key">Has private key</string>
<string name="account_switch_pubkey_only">Read only, no private key</string>
<string name="back">Back</string>
<string name="report_dialog_spam">Spam or scams</string>
<string name="report_dialog_profanity">Profanity or hateful conduct</string>
<string name="report_dialog_impersonation">Malicious impersonation</string>
<string name="report_dialog_nudity">Nudity or graphic content</string>
<string name="report_dialog_illegal">Illegal Behavior</string>
<string name="report_dialog_blocking_a_user">Blocking a user will hide their content in your app. Your notes are still publicly viewable, including to people you block.</string>
<string name="report_dialog_blocking_a_user">Blocking a user will hide their content in your app. Your notes are still publicly viewable, including to people you block. Blocked users are listed on the Security Filters screen.</string>
<string name="report_dialog_block_hide_user_btn"><![CDATA[Block & Hide User]]></string>
<string name="report_dialog_report_btn">Report Abuse</string>
<string name="report_dialog_reminder_public">All reports posted will be publicly visible.</string>
<string name="report_dialog_additional_reason_placeholder">Optionally provide additional context about your report...</string>
<string name="report_dialog_additional_reason_placeholder">Optionally provide additional context about your report</string>
<string name="report_dialog_additional_reason_label">Additional Context</string>
<string name="report_dialog_select_reason_label">Reason</string>
<string name="report_dialog_select_reason_placeholder">Select a reason...</string>
<string name="report_dialog_select_reason_placeholder">Select a reason</string>
<string name="report_dialog_post_report_btn">Post Report</string>
</resources>