From b520a0faed6b9b4f9e943cb30574e434166bb283 Mon Sep 17 00:00:00 2001 From: Vitor Pamplona Date: Sun, 9 Jul 2023 12:09:21 -0400 Subject: [PATCH] Adds sensitive-content tags to NIP94 and NIP95 media --- .../vitorpamplona/amethyst/model/Account.kt | 2 + .../amethyst/service/FileHeader.kt | 10 ++- .../amethyst/service/model/FileHeaderEvent.kt | 10 ++- .../service/model/FileStorageHeaderEvent.kt | 10 ++- .../amethyst/ui/actions/NewMediaModel.kt | 11 ++- .../amethyst/ui/actions/NewMediaView.kt | 12 +++ .../amethyst/ui/actions/NewPostView.kt | 76 ++++++++++++++++++- .../amethyst/ui/actions/NewPostViewModel.kt | 12 +-- .../ui/components/SensitivityWarning.kt | 13 ++-- .../amethyst/ui/note/MultiSetCompose.kt | 3 +- .../amethyst/ui/note/NoteCompose.kt | 27 ++++--- .../amethyst/ui/screen/ThreadFeedView.kt | 4 +- .../ui/screen/loggedIn/ChannelScreen.kt | 2 +- .../ui/screen/loggedIn/VideoScreen.kt | 8 +- .../vitorpamplona/amethyst/ui/theme/Theme.kt | 10 ++- app/src/main/res/values/strings.xml | 3 + 16 files changed, 168 insertions(+), 45 deletions(-) diff --git a/app/src/main/java/com/vitorpamplona/amethyst/model/Account.kt b/app/src/main/java/com/vitorpamplona/amethyst/model/Account.kt index 48bbd487e..b1a5c9a7f 100644 --- a/app/src/main/java/com/vitorpamplona/amethyst/model/Account.kt +++ b/app/src/main/java/com/vitorpamplona/amethyst/model/Account.kt @@ -474,6 +474,7 @@ class Account( dimensions = headerInfo.dim, blurhash = headerInfo.blurHash, description = headerInfo.description, + sensitiveContent = headerInfo.sensitiveContent, privateKey = loggedIn.privKey!! ) @@ -503,6 +504,7 @@ class Account( dimensions = headerInfo.dim, blurhash = headerInfo.blurHash, description = headerInfo.description, + sensitiveContent = headerInfo.sensitiveContent, privateKey = loggedIn.privKey!! ) diff --git a/app/src/main/java/com/vitorpamplona/amethyst/service/FileHeader.kt b/app/src/main/java/com/vitorpamplona/amethyst/service/FileHeader.kt index dbd5ec342..b0c2d4c14 100644 --- a/app/src/main/java/com/vitorpamplona/amethyst/service/FileHeader.kt +++ b/app/src/main/java/com/vitorpamplona/amethyst/service/FileHeader.kt @@ -16,15 +16,16 @@ class FileHeader( val size: Int, val dim: String?, val blurHash: String?, - val description: String? = null + val description: String? = null, + val sensitiveContent: Boolean = false ) { companion object { - suspend fun prepare(fileUrl: String, mimeType: String?, description: String?, onReady: (FileHeader) -> Unit, onError: () -> Unit) { + suspend fun prepare(fileUrl: String, mimeType: String?, description: String?, sensitiveContent: Boolean, onReady: (FileHeader) -> Unit, onError: () -> Unit) { try { val imageData: ByteArray? = ImageDownloader().waitAndGetImage(fileUrl) if (imageData != null) { - prepare(imageData, fileUrl, mimeType, description, onReady, onError) + prepare(imageData, fileUrl, mimeType, description, sensitiveContent, onReady, onError) } else { onError() } @@ -39,6 +40,7 @@ class FileHeader( fileUrl: String, mimeType: String?, description: String?, + sensitiveContent: Boolean, onReady: (FileHeader) -> Unit, onError: () -> Unit ) { @@ -79,7 +81,7 @@ class FileHeader( Pair(null, null) } - onReady(FileHeader(fileUrl, mimeType, hash, size, dim, blurHash, description)) + onReady(FileHeader(fileUrl, mimeType, hash, size, dim, blurHash, description, sensitiveContent)) } catch (e: Exception) { Log.e("ImageDownload", "Couldn't convert image in to File Header: ${e.message}") onError() diff --git a/app/src/main/java/com/vitorpamplona/amethyst/service/model/FileHeaderEvent.kt b/app/src/main/java/com/vitorpamplona/amethyst/service/model/FileHeaderEvent.kt index ca72864f9..85b6557e3 100644 --- a/app/src/main/java/com/vitorpamplona/amethyst/service/model/FileHeaderEvent.kt +++ b/app/src/main/java/com/vitorpamplona/amethyst/service/model/FileHeaderEvent.kt @@ -50,6 +50,7 @@ class FileHeaderEvent( magnetURI: String? = null, torrentInfoHash: String? = null, encryptionKey: AESGCM? = null, + sensitiveContent: Boolean? = null, privateKey: ByteArray, createdAt: Long = Date().time / 1000 ): FileHeaderEvent { @@ -62,7 +63,14 @@ class FileHeaderEvent( blurhash?.let { listOf(BLUR_HASH, it) }, magnetURI?.let { listOf(MAGNET_URI, it) }, torrentInfoHash?.let { listOf(TORRENT_INFOHASH, it) }, - encryptionKey?.let { listOf(ENCRYPTION_KEY, it.key, it.nonce) } + encryptionKey?.let { listOf(ENCRYPTION_KEY, it.key, it.nonce) }, + sensitiveContent?.let { + if (it) { + listOf("content-warning", "") + } else { + null + } + } ) val content = description ?: "" diff --git a/app/src/main/java/com/vitorpamplona/amethyst/service/model/FileStorageHeaderEvent.kt b/app/src/main/java/com/vitorpamplona/amethyst/service/model/FileStorageHeaderEvent.kt index c84de54ad..c8c5e2c9d 100644 --- a/app/src/main/java/com/vitorpamplona/amethyst/service/model/FileStorageHeaderEvent.kt +++ b/app/src/main/java/com/vitorpamplona/amethyst/service/model/FileStorageHeaderEvent.kt @@ -50,6 +50,7 @@ class FileStorageHeaderEvent( magnetURI: String? = null, torrentInfoHash: String? = null, encryptionKey: AESGCM? = null, + sensitiveContent: Boolean? = null, privateKey: ByteArray, createdAt: Long = Date().time / 1000 ): FileStorageHeaderEvent { @@ -62,7 +63,14 @@ class FileStorageHeaderEvent( blurhash?.let { listOf(BLUR_HASH, it) }, magnetURI?.let { listOf(MAGNET_URI, it) }, torrentInfoHash?.let { listOf(TORRENT_INFOHASH, it) }, - encryptionKey?.let { listOf(ENCRYPTION_KEY, it.key, it.nonce) } + encryptionKey?.let { listOf(ENCRYPTION_KEY, it.key, it.nonce) }, + sensitiveContent?.let { + if (it) { + listOf("content-warning", "") + } else { + null + } + } ) val content = description ?: "" diff --git a/app/src/main/java/com/vitorpamplona/amethyst/ui/actions/NewMediaModel.kt b/app/src/main/java/com/vitorpamplona/amethyst/ui/actions/NewMediaModel.kt index 63cee37b9..a8e8c513c 100644 --- a/app/src/main/java/com/vitorpamplona/amethyst/ui/actions/NewMediaModel.kt +++ b/app/src/main/java/com/vitorpamplona/amethyst/ui/actions/NewMediaModel.kt @@ -26,6 +26,7 @@ open class NewMediaModel : ViewModel() { var selectedServer by mutableStateOf(null) var description by mutableStateOf("") + var sensitiveContent by mutableStateOf(false) // Images and Videos var galleryUri by mutableStateOf(null) @@ -77,7 +78,7 @@ open class NewMediaModel : ViewModel() { uploadingPercentage.value = 0.2f uploadingDescription.value = "Loading" contentResolver.openInputStream(fileUri)?.use { - createNIP95Record(it.readBytes(), contentType, description) + createNIP95Record(it.readBytes(), contentType, description, sensitiveContent) } ?: run { viewModelScope.launch { @@ -97,7 +98,7 @@ open class NewMediaModel : ViewModel() { server = serverToUse, contentResolver = contentResolver, onSuccess = { imageUrl, mimeType -> - createNIP94Record(imageUrl, mimeType, description) + createNIP94Record(imageUrl, mimeType, description, sensitiveContent) }, onError = { isUploadingImage = false @@ -137,7 +138,7 @@ open class NewMediaModel : ViewModel() { return !isUploadingImage && galleryUri != null && selectedServer != null } - fun createNIP94Record(imageUrl: String, mimeType: String?, description: String) { + fun createNIP94Record(imageUrl: String, mimeType: String?, description: String, sensitiveContent: Boolean) { uploadingPercentage.value = 0.40f viewModelScope.launch(Dispatchers.IO) { uploadingDescription.value = "Server Processing" @@ -157,6 +158,7 @@ open class NewMediaModel : ViewModel() { imageUrl, mimeType, description, + sensitiveContent, onReady = { uploadingPercentage.value = 0.90f uploadingDescription.value = "Sending" @@ -189,7 +191,7 @@ open class NewMediaModel : ViewModel() { } } - fun createNIP95Record(bytes: ByteArray, mimeType: String?, description: String) { + fun createNIP95Record(bytes: ByteArray, mimeType: String?, description: String, sensitiveContent: Boolean) { uploadingPercentage.value = 0.30f uploadingDescription.value = "Hashing" @@ -199,6 +201,7 @@ open class NewMediaModel : ViewModel() { "", mimeType, description, + sensitiveContent, onReady = { uploadingDescription.value = "Signing" uploadingPercentage.value = 0.40f diff --git a/app/src/main/java/com/vitorpamplona/amethyst/ui/actions/NewMediaView.kt b/app/src/main/java/com/vitorpamplona/amethyst/ui/actions/NewMediaView.kt index 259087bc7..29741ad58 100644 --- a/app/src/main/java/com/vitorpamplona/amethyst/ui/actions/NewMediaView.kt +++ b/app/src/main/java/com/vitorpamplona/amethyst/ui/actions/NewMediaView.kt @@ -203,6 +203,18 @@ fun ImageVideoPost(postViewModel: NewMediaModel, acc: Account) { ) } + Row( + verticalAlignment = Alignment.CenterVertically, + modifier = Modifier.fillMaxWidth() + ) { + SettingSwitchItem( + checked = postViewModel.sensitiveContent, + onCheckedChange = { postViewModel.sensitiveContent = it }, + title = R.string.add_sensitive_content_label, + description = R.string.add_sensitive_content_description + ) + } + if (isNIP94Server(postViewModel.selectedServer) || postViewModel.selectedServer == ServersAvailable.NIP95 ) { diff --git a/app/src/main/java/com/vitorpamplona/amethyst/ui/actions/NewPostView.kt b/app/src/main/java/com/vitorpamplona/amethyst/ui/actions/NewPostView.kt index 7f007a737..0b06b28b6 100644 --- a/app/src/main/java/com/vitorpamplona/amethyst/ui/actions/NewPostView.kt +++ b/app/src/main/java/com/vitorpamplona/amethyst/ui/actions/NewPostView.kt @@ -13,6 +13,7 @@ import androidx.compose.foundation.layout.* import androidx.compose.foundation.lazy.LazyColumn import androidx.compose.foundation.lazy.itemsIndexed import androidx.compose.foundation.rememberScrollState +import androidx.compose.foundation.selection.toggleable import androidx.compose.foundation.shape.RoundedCornerShape import androidx.compose.foundation.text.KeyboardOptions import androidx.compose.foundation.verticalScroll @@ -41,6 +42,7 @@ import androidx.compose.runtime.setValue import androidx.compose.ui.Alignment import androidx.compose.ui.ExperimentalComposeUiApi import androidx.compose.ui.Modifier +import androidx.compose.ui.draw.alpha import androidx.compose.ui.draw.clip import androidx.compose.ui.focus.FocusRequester import androidx.compose.ui.focus.focusRequester @@ -52,11 +54,13 @@ import androidx.compose.ui.platform.LocalContext import androidx.compose.ui.platform.LocalSoftwareKeyboardController import androidx.compose.ui.res.painterResource import androidx.compose.ui.res.stringResource +import androidx.compose.ui.semantics.Role import androidx.compose.ui.text.font.FontWeight import androidx.compose.ui.text.input.KeyboardCapitalization import androidx.compose.ui.text.input.TextFieldValue import androidx.compose.ui.text.style.TextAlign import androidx.compose.ui.text.style.TextDirection +import androidx.compose.ui.text.style.TextOverflow import androidx.compose.ui.unit.dp import androidx.compose.ui.unit.sp import androidx.compose.ui.window.Dialog @@ -257,8 +261,8 @@ fun NewPostView(onClose: () -> Unit, baseReplyTo: Note? = null, quote: Note? = n ImageVideoDescription( url, account.defaultFileServer, - onAdd = { description, server -> - postViewModel.upload(url, description, server, context) + onAdd = { description, server, sensitiveContent -> + postViewModel.upload(url, description, sensitiveContent, server, context) account.changeDefaultFileServer(server) }, onCancel = { @@ -830,7 +834,7 @@ enum class ServersAvailable { fun ImageVideoDescription( uri: Uri, defaultServer: ServersAvailable, - onAdd: (String, ServersAvailable) -> Unit, + onAdd: (String, ServersAvailable, Boolean) -> Unit, onCancel: () -> Unit, onError: (String) -> Unit ) { @@ -859,6 +863,7 @@ fun ImageVideoDescription( var selectedServer by remember { mutableStateOf(defaultServer) } var message by remember { mutableStateOf("") } + var sensitiveContent by remember { mutableStateOf(false) } Column( modifier = Modifier @@ -983,6 +988,18 @@ fun ImageVideoDescription( ) } + Row( + verticalAlignment = Alignment.CenterVertically, + modifier = Modifier.fillMaxWidth() + ) { + SettingSwitchItem( + checked = sensitiveContent, + onCheckedChange = { sensitiveContent = it }, + title = R.string.add_sensitive_content_label, + description = R.string.add_sensitive_content_description + ) + } + if (isNIP94Server(selectedServer) || selectedServer == ServersAvailable.NIP95 ) { @@ -1017,7 +1034,7 @@ fun ImageVideoDescription( .fillMaxWidth() .padding(vertical = 10.dp), onClick = { - onAdd(message, selectedServer) + onAdd(message, selectedServer, sensitiveContent) }, shape = QuoteBorder, colors = ButtonDefaults.buttonColors( @@ -1036,3 +1053,54 @@ data class ImmutableListOfLists(val lists: List> = emptyList()) fun List>.toImmutableListOfLists(): ImmutableListOfLists { return ImmutableListOfLists(this) } + +@Composable +fun SettingSwitchItem( + modifier: Modifier = Modifier, + checked: Boolean, + onCheckedChange: (Boolean) -> Unit, + title: Int, + description: Int, + enabled: Boolean = true +) { + Row( + modifier = modifier + .fillMaxWidth() + .padding(horizontal = 16.dp, vertical = 8.dp) + .toggleable( + value = checked, + enabled = enabled, + role = Role.Switch, + onValueChange = onCheckedChange + ), + verticalAlignment = Alignment.CenterVertically + ) { + Column( + modifier = Modifier.weight(1.0f), + verticalArrangement = Arrangement.spacedBy(3.dp) + ) { + val contentAlpha = if (enabled) ContentAlpha.high else ContentAlpha.disabled + + Text( + text = stringResource(id = title), + maxLines = 1, + overflow = TextOverflow.Ellipsis, + modifier = Modifier.alpha(contentAlpha) + ) + Text( + text = stringResource(id = description), + style = MaterialTheme.typography.caption, + color = Color.Gray, + maxLines = 2, + overflow = TextOverflow.Ellipsis, + modifier = Modifier.alpha(contentAlpha) + ) + } + + Switch( + checked = checked, + onCheckedChange = null, + enabled = enabled + ) + } +} diff --git a/app/src/main/java/com/vitorpamplona/amethyst/ui/actions/NewPostViewModel.kt b/app/src/main/java/com/vitorpamplona/amethyst/ui/actions/NewPostViewModel.kt index 04b7319bd..ec1cbb04a 100644 --- a/app/src/main/java/com/vitorpamplona/amethyst/ui/actions/NewPostViewModel.kt +++ b/app/src/main/java/com/vitorpamplona/amethyst/ui/actions/NewPostViewModel.kt @@ -179,7 +179,7 @@ open class NewPostViewModel() : ViewModel() { cancel() } - fun upload(galleryUri: Uri, description: String, server: ServersAvailable, context: Context) { + fun upload(galleryUri: Uri, description: String, sensitiveContent: Boolean, server: ServersAvailable, context: Context) { isUploadingImage = true contentToAddUrl = null @@ -194,7 +194,7 @@ open class NewPostViewModel() : ViewModel() { onReady = { fileUri, contentType, size -> if (server == ServersAvailable.NIP95) { contentResolver.openInputStream(fileUri)?.use { - createNIP95Record(it.readBytes(), contentType, description) + createNIP95Record(it.readBytes(), contentType, description, sensitiveContent) } } else { ImageUploader.uploadImage( @@ -205,7 +205,7 @@ open class NewPostViewModel() : ViewModel() { contentResolver = contentResolver, onSuccess = { imageUrl, mimeType -> if (isNIP94Server(server)) { - createNIP94Record(imageUrl, mimeType, description) + createNIP94Record(imageUrl, mimeType, description, sensitiveContent) } else { isUploadingImage = false message = TextFieldValue(message.text + "\n\n" + imageUrl) @@ -370,13 +370,14 @@ open class NewPostViewModel() : ViewModel() { } } - fun createNIP94Record(imageUrl: String, mimeType: String?, description: String) { + fun createNIP94Record(imageUrl: String, mimeType: String?, description: String, sensitiveContent: Boolean) { viewModelScope.launch(Dispatchers.IO) { // Images don't seem to be ready immediately after upload FileHeader.prepare( imageUrl, mimeType, description, + sensitiveContent, onReady = { val note = account?.sendHeader(it) @@ -400,13 +401,14 @@ open class NewPostViewModel() : ViewModel() { } } - fun createNIP95Record(bytes: ByteArray, mimeType: String?, description: String) { + fun createNIP95Record(bytes: ByteArray, mimeType: String?, description: String, sensitiveContent: Boolean) { viewModelScope.launch(Dispatchers.IO) { FileHeader.prepare( bytes, "", mimeType, description, + sensitiveContent, onReady = { val nip95 = account?.createNip95(bytes, headerInfo = it) val note = nip95?.let { it1 -> account?.sendNip95(it1.first, it1.second) } diff --git a/app/src/main/java/com/vitorpamplona/amethyst/ui/components/SensitivityWarning.kt b/app/src/main/java/com/vitorpamplona/amethyst/ui/components/SensitivityWarning.kt index 06a387780..653aa61f2 100644 --- a/app/src/main/java/com/vitorpamplona/amethyst/ui/components/SensitivityWarning.kt +++ b/app/src/main/java/com/vitorpamplona/amethyst/ui/components/SensitivityWarning.kt @@ -1,5 +1,6 @@ package com.vitorpamplona.amethyst.ui.components +import androidx.compose.animation.Crossfade import androidx.compose.foundation.layout.Arrangement import androidx.compose.foundation.layout.Box import androidx.compose.foundation.layout.Column @@ -75,12 +76,14 @@ fun SensitivityWarning( mutableStateOf(accountState?.account?.showSensitiveContent != true) } - if (showContentWarningNote) { - ContentWarningNote() { - showContentWarningNote = false + Crossfade(targetState = showContentWarningNote) { + if (it) { + ContentWarningNote() { + showContentWarningNote = false + } + } else { + content() } - } else { - content() } } diff --git a/app/src/main/java/com/vitorpamplona/amethyst/ui/note/MultiSetCompose.kt b/app/src/main/java/com/vitorpamplona/amethyst/ui/note/MultiSetCompose.kt index 1fe5246c2..7015c9cd6 100644 --- a/app/src/main/java/com/vitorpamplona/amethyst/ui/note/MultiSetCompose.kt +++ b/app/src/main/java/com/vitorpamplona/amethyst/ui/note/MultiSetCompose.kt @@ -71,6 +71,7 @@ import com.vitorpamplona.amethyst.ui.theme.Size35dp import com.vitorpamplona.amethyst.ui.theme.StdStartPadding import com.vitorpamplona.amethyst.ui.theme.WidthAuthorPictureModifier import com.vitorpamplona.amethyst.ui.theme.WidthAuthorPictureModifierWithPadding +import com.vitorpamplona.amethyst.ui.theme.bitcoinColor import com.vitorpamplona.amethyst.ui.theme.newItemBackgroundColor import com.vitorpamplona.amethyst.ui.theme.overPictureBackground import com.vitorpamplona.amethyst.ui.theme.profile35dpModifier @@ -445,7 +446,7 @@ fun CrossfadeToDisplayAmount(authorComment: MutableState BadgeDisplay(baseNote = baseNote) - is FileHeaderEvent -> FileHeaderDisplay(baseNote) - is FileStorageHeaderEvent -> FileStorageHeaderDisplay(baseNote) + is FileHeaderEvent -> FileHeaderDisplay(baseNote, accountViewModel) + is FileStorageHeaderEvent -> FileStorageHeaderDisplay(baseNote, accountViewModel) else -> LongPressToQuickAction(baseNote = baseNote, accountViewModel = accountViewModel) { showPopup -> CheckNewAndRenderNote( @@ -2870,7 +2870,7 @@ private fun RenderBadge( } @Composable -fun FileHeaderDisplay(note: Note) { +fun FileHeaderDisplay(note: Note, accountViewModel: AccountViewModel) { val event = (note.event as? FileHeaderEvent) ?: return val fullUrl = event.url() ?: return @@ -2901,13 +2901,15 @@ fun FileHeaderDisplay(note: Note) { Crossfade(targetState = content) { if (it != null) { - ZoomableContentView(content = it) + SensitivityWarning(note = note, accountViewModel = accountViewModel) { + ZoomableContentView(content = it) + } } } } @Composable -fun FileStorageHeaderDisplay(baseNote: Note) { +fun FileStorageHeaderDisplay(baseNote: Note, accountViewModel: AccountViewModel) { val eventHeader = (baseNote.event as? FileStorageHeaderEvent) ?: return var fileNote by remember { mutableStateOf(null) } @@ -2925,20 +2927,21 @@ fun FileStorageHeaderDisplay(baseNote: Note) { Crossfade(targetState = fileNote) { if (it != null) { - RenderNIP95(it, eventHeader, baseNote) + RenderNIP95(it, eventHeader, baseNote, accountViewModel) } } } @Composable private fun RenderNIP95( - it: Note, + content: Note, eventHeader: FileStorageHeaderEvent, - baseNote: Note + header: Note, + accountViewModel: AccountViewModel ) { val appContext = LocalContext.current.applicationContext - val noteState by it.live().metadata.observeAsState() + val noteState by content.live().metadata.observeAsState() val note = remember(noteState) { noteState?.note } var content by remember { mutableStateOf(null) } @@ -2946,7 +2949,7 @@ private fun RenderNIP95( if (content == null) { LaunchedEffect(key1 = eventHeader.id, key2 = noteState, key3 = note?.event) { launch(Dispatchers.IO) { - val uri = "nostr:" + baseNote.toNEvent() + val uri = "nostr:" + header.toNEvent() val localDir = note?.idHex?.let { File(File(appContext.externalCacheDir, "NIP95"), it) } val blurHash = eventHeader.blurhash() @@ -2984,7 +2987,9 @@ private fun RenderNIP95( Crossfade(targetState = content) { if (it != null) { - ZoomableContentView(content = it) + SensitivityWarning(note = header, accountViewModel = accountViewModel) { + ZoomableContentView(content = it) + } } } } diff --git a/app/src/main/java/com/vitorpamplona/amethyst/ui/screen/ThreadFeedView.kt b/app/src/main/java/com/vitorpamplona/amethyst/ui/screen/ThreadFeedView.kt index 6ba967721..f2146c86a 100644 --- a/app/src/main/java/com/vitorpamplona/amethyst/ui/screen/ThreadFeedView.kt +++ b/app/src/main/java/com/vitorpamplona/amethyst/ui/screen/ThreadFeedView.kt @@ -399,9 +399,9 @@ fun NoteMaster( if ((noteEvent is ChannelCreateEvent || noteEvent is ChannelMetadataEvent) && note.channelHex() != null) { ChannelHeader(channelHex = note.channelHex()!!, showVideo = true, showBottomDiviser = false, accountViewModel = accountViewModel, nav = nav) } else if (noteEvent is FileHeaderEvent) { - FileHeaderDisplay(baseNote) + FileHeaderDisplay(baseNote, accountViewModel) } else if (noteEvent is FileStorageHeaderEvent) { - FileStorageHeaderDisplay(baseNote) + FileStorageHeaderDisplay(baseNote, accountViewModel) } else if (noteEvent is PeopleListEvent) { DisplayPeopleList(baseNote, backgroundColor, accountViewModel, nav) } else if (noteEvent is AudioTrackEvent) { diff --git a/app/src/main/java/com/vitorpamplona/amethyst/ui/screen/loggedIn/ChannelScreen.kt b/app/src/main/java/com/vitorpamplona/amethyst/ui/screen/loggedIn/ChannelScreen.kt index ac251bd75..68139c1cc 100644 --- a/app/src/main/java/com/vitorpamplona/amethyst/ui/screen/loggedIn/ChannelScreen.kt +++ b/app/src/main/java/com/vitorpamplona/amethyst/ui/screen/loggedIn/ChannelScreen.kt @@ -421,7 +421,7 @@ fun EditFieldRow( accountViewModel.account.defaultFileServer } - channelScreenModel.upload(it, "", fileServer, context) + channelScreenModel.upload(it, "", false, fileServer, context) } }, colors = TextFieldDefaults.textFieldColors( diff --git a/app/src/main/java/com/vitorpamplona/amethyst/ui/screen/loggedIn/VideoScreen.kt b/app/src/main/java/com/vitorpamplona/amethyst/ui/screen/loggedIn/VideoScreen.kt index 0a189642e..a734b065f 100644 --- a/app/src/main/java/com/vitorpamplona/amethyst/ui/screen/loggedIn/VideoScreen.kt +++ b/app/src/main/java/com/vitorpamplona/amethyst/ui/screen/loggedIn/VideoScreen.kt @@ -259,16 +259,16 @@ private fun RenderVideoOrPictureNote( Row(remember { Modifier.weight(1f) }, verticalAlignment = Alignment.CenterVertically) { val noteEvent = remember { note.event } if (noteEvent is FileHeaderEvent) { - FileHeaderDisplay(note) + FileHeaderDisplay(note, accountViewModel) } else if (noteEvent is FileStorageHeaderEvent) { - FileStorageHeaderDisplay(note) + FileStorageHeaderDisplay(note, accountViewModel) } } } Row(verticalAlignment = Alignment.Bottom, modifier = remember { Modifier.fillMaxSize(1f) }) { Column(remember { Modifier.weight(1f) }) { - RenderVideoOrPicture(note, nav, accountViewModel) + RenderAuthorInformation(note, nav, accountViewModel) } Column( @@ -287,7 +287,7 @@ private fun RenderVideoOrPictureNote( } @Composable -private fun RenderVideoOrPicture( +private fun RenderAuthorInformation( note: Note, nav: (String) -> Unit, accountViewModel: AccountViewModel diff --git a/app/src/main/java/com/vitorpamplona/amethyst/ui/theme/Theme.kt b/app/src/main/java/com/vitorpamplona/amethyst/ui/theme/Theme.kt index ae2d0f8fc..46471728e 100644 --- a/app/src/main/java/com/vitorpamplona/amethyst/ui/theme/Theme.kt +++ b/app/src/main/java/com/vitorpamplona/amethyst/ui/theme/Theme.kt @@ -32,16 +32,19 @@ private val DarkColorPalette = darkColors( primary = Purple200, primaryVariant = Purple700, secondary = Teal200, - secondaryVariant = Color(0xFFF7931A) + secondaryVariant = Purple200 ) private val LightColorPalette = lightColors( primary = Purple500, primaryVariant = Purple700, secondary = Teal200, - secondaryVariant = Color(0xFFB66605) + secondaryVariant = Purple500 ) +private val BitcoinDark = Color(0xFFF7931A) +private val BitcoinLight = Color(0xFFB66605) + private val DarkNewItemBackground = DarkColorPalette.primary.copy(0.12f) private val LightNewItemBackground = LightColorPalette.primary.copy(0.12f) @@ -279,6 +282,9 @@ val Colors.hashVerified: Color val Colors.overPictureBackground: Color get() = if (isLight) LightOverPictureBackground else DarkOverPictureBackground +val Colors.bitcoinColor: Color + get() = if (isLight) BitcoinLight else BitcoinDark + val Colors.markdownStyle: RichTextStyle get() = if (isLight) MarkDownStyleOnLight else MarkDownStyleOnDark diff --git a/app/src/main/res/values/strings.xml b/app/src/main/res/values/strings.xml index d03ad8ab7..748189d02 100644 --- a/app/src/main/res/values/strings.xml +++ b/app/src/main/res/values/strings.xml @@ -480,4 +480,7 @@ This group does not have a description or rules. Talk to the owner to add one This community does not have a description. Talk to the owner to add one + + Sensitive Content + Adds sensitive content warning before showing this content