diff --git a/amethyst/src/main/java/com/vitorpamplona/amethyst/ui/components/SensitivityWarning.kt b/amethyst/src/main/java/com/vitorpamplona/amethyst/ui/components/SensitivityWarning.kt
index 4b7e59b38..29eb4d8a1 100644
--- a/amethyst/src/main/java/com/vitorpamplona/amethyst/ui/components/SensitivityWarning.kt
+++ b/amethyst/src/main/java/com/vitorpamplona/amethyst/ui/components/SensitivityWarning.kt
@@ -60,6 +60,7 @@ import com.vitorpamplona.amethyst.ui.theme.ButtonPadding
import com.vitorpamplona.amethyst.ui.theme.PaddingHorizontal12Modifier
import com.vitorpamplona.amethyst.ui.theme.ThemeComparisonColumn
import com.vitorpamplona.quartz.nip01Core.core.Event
+import com.vitorpamplona.quartz.nip36SensitiveContent.contentWarningReason
import com.vitorpamplona.quartz.nip36SensitiveContent.isSensitiveOrNSFW
@Composable
@@ -79,17 +80,9 @@ fun SensitivityWarning(
) {
val hasSensitiveContent = remember(event) { event.isSensitiveOrNSFW() }
- SensitivityWarning(hasSensitiveContent, accountViewModel, content)
-}
-
-@Composable
-fun SensitivityWarning(
- hasSensitiveContent: Boolean,
- accountViewModel: AccountViewModel,
- content: @Composable () -> Unit,
-) {
if (hasSensitiveContent) {
- SensitivityWarning(accountViewModel, content)
+ val reason = remember(event) { event.contentWarningReason() }
+ ObserveSensitivityWarning(reason, accountViewModel, content)
} else {
content()
}
@@ -97,6 +90,20 @@ fun SensitivityWarning(
@Composable
fun SensitivityWarning(
+ reason: String?,
+ accountViewModel: AccountViewModel,
+ content: @Composable () -> Unit,
+) {
+ if (reason != null) {
+ ObserveSensitivityWarning(reason, accountViewModel, content)
+ } else {
+ content()
+ }
+}
+
+@Composable
+fun ObserveSensitivityWarning(
+ reason: String?,
accountViewModel: AccountViewModel,
content: @Composable () -> Unit,
) {
@@ -106,7 +113,7 @@ fun SensitivityWarning(
CrossfadeIfEnabled(targetState = showContentWarningNote, accountViewModel = accountViewModel) {
if (it) {
- ContentWarningNote { showContentWarningNote = false }
+ ContentWarningNote(reason) { showContentWarningNote = false }
} else {
content()
}
@@ -117,12 +124,31 @@ fun SensitivityWarning(
@Composable
fun ContentWarningNotePreview() {
ThemeComparisonColumn {
- ContentWarningNote {}
+ ContentWarningNote(null) {}
+ }
+}
+
+@Preview
+@Composable
+fun ContentWarningNoteWithReasonPreview() {
+ ThemeComparisonColumn {
+ ContentWarningNote("Spoilers") {}
+ }
+}
+
+@Preview
+@Composable
+fun ContentWarningNoteWithBigReasonPreview() {
+ ThemeComparisonColumn {
+ ContentWarningNote("Spoilers, monkeys, bannanas, and other things") {}
}
}
@Composable
-fun ContentWarningNote(onDismiss: () -> Unit) {
+fun ContentWarningNote(
+ reason: String?,
+ onDismiss: () -> Unit,
+) {
Column {
Row(modifier = PaddingHorizontal12Modifier) {
Column(modifier = Modifier.padding(start = 10.dp)) {
@@ -155,19 +181,28 @@ fun ContentWarningNote(onDismiss: () -> Unit) {
Row(Modifier.fillMaxWidth(), horizontalArrangement = Arrangement.Center) {
Text(
- text = stringRes(R.string.content_warning),
+ text =
+ if (reason.isNullOrBlank()) {
+ stringRes(R.string.content_warning)
+ } else {
+ stringRes(R.string.content_warning_with_reason, reason)
+ },
fontWeight = FontWeight.Bold,
fontSize = 18.sp,
+ softWrap = true,
+ textAlign = TextAlign.Center,
)
}
- Row {
- Text(
- text = stringRes(R.string.content_warning_explanation),
- color = Color.Gray,
- modifier = Modifier.padding(top = 10.dp),
- textAlign = TextAlign.Center,
- )
+ if (reason.isNullOrBlank()) {
+ Row {
+ Text(
+ text = stringRes(R.string.content_warning_explanation),
+ color = Color.Gray,
+ modifier = Modifier.padding(top = 10.dp),
+ textAlign = TextAlign.Center,
+ )
+ }
}
Row(Modifier.fillMaxWidth(), horizontalArrangement = Arrangement.Center) {
diff --git a/amethyst/src/main/java/com/vitorpamplona/amethyst/ui/components/ZoomableContentView.kt b/amethyst/src/main/java/com/vitorpamplona/amethyst/ui/components/ZoomableContentView.kt
index f8cc1c82a..e998711ae 100644
--- a/amethyst/src/main/java/com/vitorpamplona/amethyst/ui/components/ZoomableContentView.kt
+++ b/amethyst/src/main/java/com/vitorpamplona/amethyst/ui/components/ZoomableContentView.kt
@@ -140,7 +140,7 @@ fun ZoomableContentView(
when (content) {
is MediaUrlImage -> {
- SensitivityWarning(content.contentWarning != null, accountViewModel) {
+ SensitivityWarning(content.contentWarning, accountViewModel) {
TwoSecondController(content) { controllerVisible ->
val mainImageModifier =
Modifier
@@ -153,7 +153,7 @@ fun ZoomableContentView(
}
is MediaUrlVideo -> {
- SensitivityWarning(content.contentWarning != null, accountViewModel) {
+ SensitivityWarning(content.contentWarning, accountViewModel) {
Box(modifier = Modifier.fillMaxWidth(), contentAlignment = Alignment.Center) {
VideoView(
videoUri = content.url,
diff --git a/amethyst/src/main/java/com/vitorpamplona/amethyst/ui/screen/loggedIn/profile/gallery/GalleryThumb.kt b/amethyst/src/main/java/com/vitorpamplona/amethyst/ui/screen/loggedIn/profile/gallery/GalleryThumb.kt
index 2ab349bb5..b153ef37e 100644
--- a/amethyst/src/main/java/com/vitorpamplona/amethyst/ui/screen/loggedIn/profile/gallery/GalleryThumb.kt
+++ b/amethyst/src/main/java/com/vitorpamplona/amethyst/ui/screen/loggedIn/profile/gallery/GalleryThumb.kt
@@ -171,10 +171,13 @@ fun GalleryContentView(
AutoNonlazyGrid(contentList.size, modifier = Modifier.fillMaxSize()) { contentIndex ->
when (val content = contentList[contentIndex]) {
is MediaUrlContent -> {
- val hasSensitiveContent =
- (content is MediaUrlVideo && content.contentWarning != null) ||
- (content is MediaUrlImage && content.contentWarning != null)
- SensitivityWarning(hasSensitiveContent, accountViewModel) {
+ val sensitivityReason =
+ when (content) {
+ is MediaUrlVideo -> content.contentWarning
+ is MediaUrlImage -> content.contentWarning
+ else -> null
+ }
+ SensitivityWarning(sensitivityReason, accountViewModel) {
UrlImageView(content, accountViewModel)
}
}
diff --git a/amethyst/src/main/res/values/strings.xml b/amethyst/src/main/res/values/strings.xml
index c4b7440bf..799135f7d 100644
--- a/amethyst/src/main/res/values/strings.xml
+++ b/amethyst/src/main/res/values/strings.xml
@@ -743,6 +743,7 @@
Today
Content warning
+ Warning: %1$s
This post contains sensitive content which some people may find offensive or disturbing
Always hide sensitive content
Always show sensitive content
diff --git a/quartz/src/commonMain/kotlin/com/vitorpamplona/quartz/nip36SensitiveContent/ContentWarningTag.kt b/quartz/src/commonMain/kotlin/com/vitorpamplona/quartz/nip36SensitiveContent/ContentWarningTag.kt
index 54ebe8424..af4214f66 100644
--- a/quartz/src/commonMain/kotlin/com/vitorpamplona/quartz/nip36SensitiveContent/ContentWarningTag.kt
+++ b/quartz/src/commonMain/kotlin/com/vitorpamplona/quartz/nip36SensitiveContent/ContentWarningTag.kt
@@ -22,6 +22,7 @@ package com.vitorpamplona.quartz.nip36SensitiveContent
import com.vitorpamplona.quartz.nip01Core.core.has
import com.vitorpamplona.quartz.utils.arrayOfNotNull
+import com.vitorpamplona.quartz.utils.ensure
class ContentWarningTag(
val reason: String? = null,
@@ -33,9 +34,9 @@ class ContentWarningTag(
fun isTag(tag: Array) = tag.has(0) && tag[0] == TAG_NAME
- fun parse(tags: Array): ContentWarningTag {
- require(tags[0] == TAG_NAME)
- return ContentWarningTag(tags.getOrNull(1))
+ fun parse(tags: Array): ContentWarningTag? {
+ ensure(tags[0] == TAG_NAME) { return null }
+ return ContentWarningTag(tags.getOrNull(1).ifBlank { null })
}
fun assemble() = arrayOfNotNull(TAG_NAME)
diff --git a/quartz/src/commonMain/kotlin/com/vitorpamplona/quartz/nip36SensitiveContent/TagArrayExt.kt b/quartz/src/commonMain/kotlin/com/vitorpamplona/quartz/nip36SensitiveContent/TagArrayExt.kt
index a44200487..9251bb305 100644
--- a/quartz/src/commonMain/kotlin/com/vitorpamplona/quartz/nip36SensitiveContent/TagArrayExt.kt
+++ b/quartz/src/commonMain/kotlin/com/vitorpamplona/quartz/nip36SensitiveContent/TagArrayExt.kt
@@ -29,4 +29,4 @@ fun TagArray.isSensitive() = this.any(ContentWarningTag::isTag)
fun TagArray.isSensitiveOrNSFW() = this.any { ContentWarningTag.isTag(it) || HashtagTag.isAnyTagged(it, nsfwTags) }
-fun TagArray.contentWarningReason() = this.firstOrNull(ContentWarningTag::isTag)?.getOrNull(1)
+fun TagArray.contentWarningReason() = this.firstNotNullOfOrNull(ContentWarningTag::parse)?.reason