Moves Content Sensitivity setting to the Security filter screen

This commit is contained in:
Vitor Pamplona
2025-05-13 20:09:14 -04:00
parent f3e2327676
commit d7d8f02a80
8 changed files with 160 additions and 92 deletions
@@ -1144,11 +1144,16 @@ class Account(
fun isWriteable(): Boolean = settings.isWriteable()
fun updateOptOutOptions(
warnReports: Boolean,
filterSpam: Boolean,
): Boolean {
if (settings.updateOptOutOptions(warnReports, filterSpam)) {
fun updateWarnReports(warnReports: Boolean): Boolean {
if (settings.updateWarnReports(warnReports)) {
sendNewAppSpecificData()
return true
}
return false
}
fun updateFilterSpam(filterSpam: Boolean): Boolean {
if (settings.updateFilterSpam(filterSpam)) {
if (!settings.syncedSettings.security.filterSpamFromStrangers.value) {
transientHiddenUsers.update {
emptySet()
@@ -538,11 +538,16 @@ class AccountSettings(
return false
}
fun updateOptOutOptions(
warnReports: Boolean,
filterSpam: Boolean,
): Boolean =
if (syncedSettings.security.updateOptOutOptions(warnReports, filterSpam)) {
fun updateWarnReports(warnReports: Boolean): Boolean =
if (syncedSettings.security.updateWarnReports(warnReports)) {
saveAccountSettings()
true
} else {
false
}
fun updateFilterSpam(filterSpam: Boolean): Boolean =
if (syncedSettings.security.updateFilterSpam(filterSpam)) {
saveAccountSettings()
true
} else {
@@ -190,17 +190,17 @@ class AccountSecurityPreferences(
return false
}
// ---
// filters
// ---
fun updateOptOutOptions(
warnReports: Boolean,
filterSpam: Boolean,
): Boolean =
if (warnAboutPostsWithReports != warnReports || filterSpam != filterSpamFromStrangers.value) {
fun updateWarnReports(warnReports: Boolean): Boolean =
if (warnAboutPostsWithReports != warnReports) {
warnAboutPostsWithReports = warnReports
filterSpamFromStrangers.tryEmit(filterSpam)
true
} else {
false
}
fun updateFilterSpam(filterSpam: Boolean): Boolean =
if (filterSpam != filterSpamFromStrangers.value) {
filterSpamFromStrangers.tryEmit(filterSpam)
true
} else {
false
@@ -149,3 +149,33 @@ fun parseBooleanType(screenCode: Int): BooleanType =
BooleanType.ALWAYS
}
}
enum class WarningType(
val prefCode: Boolean?,
val screenCode: Int,
val resourceId: Int,
) {
WARN(null, 0, R.string.content_warning_see_warnings_option),
SHOW(true, 1, R.string.content_warning_show_all_sensitive_content_option),
HIDE(false, 2, R.string.content_warning_hide_all_sensitive_content_option),
}
fun parseWarningType(screenCode: Int): WarningType =
when (screenCode) {
WarningType.WARN.screenCode -> WarningType.WARN
WarningType.SHOW.screenCode -> WarningType.SHOW
WarningType.HIDE.screenCode -> WarningType.HIDE
else -> {
WarningType.WARN
}
}
fun parseWarningType(code: Boolean?): WarningType =
when (code) {
WarningType.WARN.prefCode -> WarningType.WARN
WarningType.HIDE.prefCode -> WarningType.HIDE
WarningType.SHOW.prefCode -> WarningType.SHOW
else -> {
WarningType.WARN
}
}
@@ -324,34 +324,6 @@ fun NoteDropDownMenu(
)
}
HorizontalDivider(thickness = DividerThickness)
if (state.showSensitiveContent == null || state.showSensitiveContent == true) {
DropdownMenuItem(
text = { Text(stringRes(R.string.content_warning_hide_all_sensitive_content)) },
onClick = {
accountViewModel.hideSensitiveContent()
onDismiss()
},
)
}
if (state.showSensitiveContent == null || state.showSensitiveContent == false) {
DropdownMenuItem(
text = { Text(stringRes(R.string.content_warning_show_all_sensitive_content)) },
onClick = {
accountViewModel.disableContentWarnings()
onDismiss()
},
)
}
if (state.showSensitiveContent != null) {
DropdownMenuItem(
text = { Text(stringRes(R.string.content_warning_see_warnings)) },
onClick = {
accountViewModel.seeContentWarnings()
onDismiss()
},
)
}
HorizontalDivider(thickness = DividerThickness)
if (state.isLoggedUser) {
DropdownMenuItem(
text = { Text(stringRes(R.string.request_deletion)) },
@@ -52,6 +52,7 @@ import com.vitorpamplona.amethyst.model.Note
import com.vitorpamplona.amethyst.model.PublicChatChannel
import com.vitorpamplona.amethyst.model.UrlCachedPreviewer
import com.vitorpamplona.amethyst.model.User
import com.vitorpamplona.amethyst.model.WarningType
import com.vitorpamplona.amethyst.model.observables.CreatedAtComparator
import com.vitorpamplona.amethyst.service.CashuProcessor
import com.vitorpamplona.amethyst.service.CashuToken
@@ -886,21 +887,9 @@ class AccountViewModel(
fun isFollowing(user: HexKey): Boolean = account.isFollowing(user)
fun hideSensitiveContent() {
fun updateContentWarnings(value: WarningType) {
viewModelScope.launch(Dispatchers.IO) {
account.updateShowSensitiveContent(false)
}
}
fun disableContentWarnings() {
viewModelScope.launch(Dispatchers.IO) {
account.updateShowSensitiveContent(true)
}
}
fun seeContentWarnings() {
viewModelScope.launch(Dispatchers.IO) {
account.updateShowSensitiveContent(null)
account.updateShowSensitiveContent(value.prefCode)
}
}
@@ -924,12 +913,15 @@ class AccountViewModel(
fun filterSpamFromStrangers() = account.settings.syncedSettings.security.filterSpamFromStrangers
fun updateOptOutOptions(
warnReports: Boolean,
filterSpam: Boolean,
) {
fun updateWarnReports(warnReports: Boolean) {
viewModelScope.launch(Dispatchers.IO) {
if (account.updateOptOutOptions(warnReports, filterSpam)) {
account.updateWarnReports(warnReports)
}
}
fun updateFilterSpam(filterSpam: Boolean) {
viewModelScope.launch(Dispatchers.IO) {
if (account.updateFilterSpam(filterSpam)) {
LocalCache.antiSpam.active = filterSpamFromStrangers().value
}
}
@@ -22,6 +22,7 @@ package com.vitorpamplona.amethyst.ui.screen.loggedIn.settings
import androidx.compose.foundation.ExperimentalFoundationApi
import androidx.compose.foundation.layout.Arrangement
import androidx.compose.foundation.layout.Arrangement.Absolute.spacedBy
import androidx.compose.foundation.layout.Column
import androidx.compose.foundation.layout.Row
import androidx.compose.foundation.layout.fillMaxHeight
@@ -33,11 +34,11 @@ import androidx.compose.foundation.text.KeyboardActions
import androidx.compose.foundation.text.KeyboardOptions
import androidx.compose.material3.Button
import androidx.compose.material3.ButtonDefaults
import androidx.compose.material3.Checkbox
import androidx.compose.material3.HorizontalDivider
import androidx.compose.material3.MaterialTheme
import androidx.compose.material3.OutlinedTextField
import androidx.compose.material3.ScrollableTabRow
import androidx.compose.material3.Switch
import androidx.compose.material3.Tab
import androidx.compose.material3.Text
import androidx.compose.runtime.Composable
@@ -64,6 +65,8 @@ import androidx.lifecycle.LifecycleEventObserver
import androidx.lifecycle.compose.collectAsStateWithLifecycle
import androidx.lifecycle.viewmodel.compose.viewModel
import com.vitorpamplona.amethyst.R
import com.vitorpamplona.amethyst.model.WarningType
import com.vitorpamplona.amethyst.model.parseWarningType
import com.vitorpamplona.amethyst.service.relayClient.reqCommand.account.observeAccountIsHiddenWord
import com.vitorpamplona.amethyst.ui.feeds.RefresheableBox
import com.vitorpamplona.amethyst.ui.layouts.DisappearingScaffold
@@ -72,6 +75,8 @@ import com.vitorpamplona.amethyst.ui.navigation.TopBarWithBackButton
import com.vitorpamplona.amethyst.ui.note.elements.AddButton
import com.vitorpamplona.amethyst.ui.screen.RefreshingFeedUserFeedView
import com.vitorpamplona.amethyst.ui.screen.loggedIn.AccountViewModel
import com.vitorpamplona.amethyst.ui.screen.loggedIn.TextSpinner
import com.vitorpamplona.amethyst.ui.screen.loggedIn.TitleExplainer
import com.vitorpamplona.amethyst.ui.screen.loggedIn.settings.dal.HiddenAccountsFeedViewModel
import com.vitorpamplona.amethyst.ui.screen.loggedIn.settings.dal.HiddenWordsFeedViewModel
import com.vitorpamplona.amethyst.ui.screen.loggedIn.settings.dal.SpammerAccountsFeedViewModel
@@ -80,9 +85,12 @@ import com.vitorpamplona.amethyst.ui.theme.ButtonBorder
import com.vitorpamplona.amethyst.ui.theme.ButtonPadding
import com.vitorpamplona.amethyst.ui.theme.DividerThickness
import com.vitorpamplona.amethyst.ui.theme.HorzPadding
import com.vitorpamplona.amethyst.ui.theme.Size10dp
import com.vitorpamplona.amethyst.ui.theme.Size15dp
import com.vitorpamplona.amethyst.ui.theme.StdPadding
import com.vitorpamplona.amethyst.ui.theme.TabRowHeight
import com.vitorpamplona.amethyst.ui.theme.placeholderText
import kotlinx.collections.immutable.persistentListOf
import kotlinx.coroutines.launch
@Composable
@@ -153,35 +161,17 @@ fun SecurityFiltersScreen(
},
accountViewModel = accountViewModel,
) {
Column(Modifier.padding(it).fillMaxHeight()) {
Column(
Modifier
.padding(it)
.fillMaxHeight(),
) {
val pagerState = rememberPagerState { 3 }
val coroutineScope = rememberCoroutineScope()
var warnAboutReports by remember { mutableStateOf(accountViewModel.account.settings.syncedSettings.security.warnAboutPostsWithReports) }
var filterSpam by remember { mutableStateOf(accountViewModel.account.settings.syncedSettings.security.filterSpamFromStrangers.value) }
Row(verticalAlignment = Alignment.CenterVertically) {
Checkbox(
checked = warnAboutReports,
onCheckedChange = {
warnAboutReports = it
accountViewModel.updateOptOutOptions(warnAboutReports, filterSpam)
},
)
HeaderOptions(accountViewModel)
Text(stringRes(R.string.warn_when_posts_have_reports_from_your_follows))
}
Row(verticalAlignment = Alignment.CenterVertically) {
Checkbox(
checked = filterSpam,
onCheckedChange = {
filterSpam = it
accountViewModel.updateOptOutOptions(warnAboutReports, filterSpam)
},
)
Text(stringRes(R.string.filter_spam_from_strangers))
}
HorizontalDivider()
ScrollableTabRow(
containerColor = MaterialTheme.colorScheme.background,
@@ -218,6 +208,69 @@ fun SecurityFiltersScreen(
}
}
@Composable
private fun HeaderOptions(accountViewModel: AccountViewModel) {
Column(
Modifier
.padding(top = Size10dp, bottom = Size10dp, start = Size15dp, end = Size15dp),
horizontalAlignment = Alignment.CenterHorizontally,
verticalArrangement = spacedBy(10.dp),
) {
SettingsRow(
R.string.warn_when_posts_have_reports_from_your_follows_title,
R.string.warn_when_posts_have_reports_from_your_follows_explainer,
) {
var warnAboutReports by remember { mutableStateOf(accountViewModel.account.settings.syncedSettings.security.warnAboutPostsWithReports) }
Switch(
checked = warnAboutReports,
onCheckedChange = {
warnAboutReports = it
accountViewModel.updateWarnReports(warnAboutReports)
},
)
}
SettingsRow(
R.string.filter_spam_from_strangers_title,
R.string.filter_spam_from_strangers_explainer,
) {
var filterSpam by remember { mutableStateOf(accountViewModel.account.settings.syncedSettings.security.filterSpamFromStrangers.value) }
Switch(
checked = filterSpam,
onCheckedChange = {
filterSpam = it
accountViewModel.updateFilterSpam(filterSpam)
},
)
}
SettingsRow(
R.string.show_sensitive_content_title,
R.string.show_sensitive_content_explainer,
) {
var sensitive by remember { mutableStateOf(accountViewModel.account.settings.syncedSettings.security.showSensitiveContent.value) }
val selectedItens =
persistentListOf(
TitleExplainer(stringRes(WarningType.WARN.resourceId)),
TitleExplainer(stringRes(WarningType.SHOW.resourceId)),
TitleExplainer(stringRes(WarningType.HIDE.resourceId)),
)
TextSpinner(
label = "",
placeholder = selectedItens[parseWarningType(sensitive).screenCode].title,
options = selectedItens,
onSelect = {
accountViewModel.updateContentWarnings(parseWarningType(it))
},
)
}
}
}
@Composable
private fun HiddenWordsFeed(
hiddenWordsViewModel: HiddenWordsFeedViewModel,
+11
View File
@@ -585,10 +585,21 @@
<string name="content_warning_show_all_sensitive_content">Always show sensitive content</string>
<string name="content_warning_see_warnings">Always show content warnings</string>
<string name="content_warning_hide_all_sensitive_content_option">Hide</string>
<string name="content_warning_show_all_sensitive_content_option">Show</string>
<string name="content_warning_see_warnings_option">Warn</string>
<string name="recommended_apps">Recommends: </string>
<string name="filter_spam_from_strangers">Filter spam from strangers</string>
<string name="warn_when_posts_have_reports_from_your_follows">Warn when posts have reports from your follows</string>
<string name="filter_spam_from_strangers_title">Filter spam</string>
<string name="filter_spam_from_strangers_explainer">Hides posts from strangers that were exactly the same for 5 or more times</string>
<string name="warn_when_posts_have_reports_from_your_follows_title">Warn on reports</string>
<string name="warn_when_posts_have_reports_from_your_follows_explainer">Shows a warning message when posts have 5 or more reports your follows</string>
<string name="show_sensitive_content_title">Show sensitive content</string>
<string name="show_sensitive_content_explainer">Shows a warning message when the author of the post marked it as sensitive</string>
<string name="new_reaction_symbol">New Reaction Symbol</string>
<string name="no_reaction_type_setup_long_press_to_change">No reaction types pre-selected for this user. Long press on the heart button to change</string>