Adds Copy URL and Copy Note ID popups for images and videos

This commit is contained in:
Vitor Pamplona 2023-08-20 11:18:31 -04:00
parent 5d061a79e2
commit 7cfad373f2
3 changed files with 89 additions and 9 deletions

View File

@ -29,11 +29,18 @@ import androidx.compose.foundation.pager.PagerState
import androidx.compose.foundation.pager.rememberPagerState import androidx.compose.foundation.pager.rememberPagerState
import androidx.compose.foundation.text.InlineTextContent import androidx.compose.foundation.text.InlineTextContent
import androidx.compose.foundation.text.appendInlineContent import androidx.compose.foundation.text.appendInlineContent
import androidx.compose.material.Button
import androidx.compose.material.ButtonDefaults
import androidx.compose.material.DropdownMenu
import androidx.compose.material.DropdownMenuItem
import androidx.compose.material.Icon
import androidx.compose.material.IconButton import androidx.compose.material.IconButton
import androidx.compose.material.LocalTextStyle import androidx.compose.material.LocalTextStyle
import androidx.compose.material.MaterialTheme import androidx.compose.material.MaterialTheme
import androidx.compose.material.Surface import androidx.compose.material.Surface
import androidx.compose.material.Text import androidx.compose.material.Text
import androidx.compose.material.icons.Icons
import androidx.compose.material.icons.filled.Share
import androidx.compose.runtime.Composable import androidx.compose.runtime.Composable
import androidx.compose.runtime.DisposableEffect import androidx.compose.runtime.DisposableEffect
import androidx.compose.runtime.Immutable import androidx.compose.runtime.Immutable
@ -46,10 +53,12 @@ import androidx.compose.runtime.rememberCoroutineScope
import androidx.compose.runtime.setValue import androidx.compose.runtime.setValue
import androidx.compose.ui.Alignment import androidx.compose.ui.Alignment
import androidx.compose.ui.Modifier import androidx.compose.ui.Modifier
import androidx.compose.ui.graphics.Color
import androidx.compose.ui.layout.ContentScale import androidx.compose.ui.layout.ContentScale
import androidx.compose.ui.platform.LocalClipboardManager import androidx.compose.ui.platform.LocalClipboardManager
import androidx.compose.ui.platform.LocalContext import androidx.compose.ui.platform.LocalContext
import androidx.compose.ui.platform.LocalView import androidx.compose.ui.platform.LocalView
import androidx.compose.ui.res.stringResource
import androidx.compose.ui.text.AnnotatedString import androidx.compose.ui.text.AnnotatedString
import androidx.compose.ui.text.Placeholder import androidx.compose.ui.text.Placeholder
import androidx.compose.ui.text.PlaceholderVerticalAlign import androidx.compose.ui.text.PlaceholderVerticalAlign
@ -77,11 +86,15 @@ import com.vitorpamplona.amethyst.ui.note.DownloadForOfflineIcon
import com.vitorpamplona.amethyst.ui.note.HashCheckFailedIcon import com.vitorpamplona.amethyst.ui.note.HashCheckFailedIcon
import com.vitorpamplona.amethyst.ui.note.HashCheckIcon import com.vitorpamplona.amethyst.ui.note.HashCheckIcon
import com.vitorpamplona.amethyst.ui.screen.loggedIn.AccountViewModel import com.vitorpamplona.amethyst.ui.screen.loggedIn.AccountViewModel
import com.vitorpamplona.amethyst.ui.theme.ButtonBorder
import com.vitorpamplona.amethyst.ui.theme.Font17SP import com.vitorpamplona.amethyst.ui.theme.Font17SP
import com.vitorpamplona.amethyst.ui.theme.Size20Modifier
import com.vitorpamplona.amethyst.ui.theme.Size20dp import com.vitorpamplona.amethyst.ui.theme.Size20dp
import com.vitorpamplona.amethyst.ui.theme.Size24dp import com.vitorpamplona.amethyst.ui.theme.Size24dp
import com.vitorpamplona.amethyst.ui.theme.Size30dp import com.vitorpamplona.amethyst.ui.theme.Size30dp
import com.vitorpamplona.amethyst.ui.theme.Size5dp
import com.vitorpamplona.amethyst.ui.theme.imageModifier import com.vitorpamplona.amethyst.ui.theme.imageModifier
import com.vitorpamplona.amethyst.ui.theme.placeholderText
import com.vitorpamplona.quartz.crypto.CryptoUtils import com.vitorpamplona.quartz.crypto.CryptoUtils
import com.vitorpamplona.quartz.encoders.toHexKey import com.vitorpamplona.quartz.encoders.toHexKey
import kotlinx.collections.immutable.ImmutableList import kotlinx.collections.immutable.ImmutableList
@ -184,13 +197,20 @@ fun ZoomableContentView(
roundedCorner: Boolean, roundedCorner: Boolean,
accountViewModel: AccountViewModel accountViewModel: AccountViewModel
) { ) {
val clipboardManager = LocalClipboardManager.current
// store the dialog open or close state // store the dialog open or close state
var dialogOpen by remember { var dialogOpen by remember {
mutableStateOf(false) mutableStateOf(false)
} }
// store the dialog open or close state
val shareOpen = remember {
mutableStateOf(false)
}
if (shareOpen.value) {
ShareImageAction(shareOpen, content) { shareOpen.value = false }
}
var mainImageModifier = if (roundedCorner) { var mainImageModifier = if (roundedCorner) {
MaterialTheme.colors.imageModifier MaterialTheme.colors.imageModifier
} else { } else {
@ -200,12 +220,12 @@ fun ZoomableContentView(
if (content is ZoomableUrlContent) { if (content is ZoomableUrlContent) {
mainImageModifier = mainImageModifier.combinedClickable( mainImageModifier = mainImageModifier.combinedClickable(
onClick = { dialogOpen = true }, onClick = { dialogOpen = true },
onLongClick = { clipboardManager.setText(AnnotatedString(content.uri ?: content.url)) } onLongClick = { shareOpen.value = true }
) )
} else if (content is ZoomablePreloadedContent) { } else if (content is ZoomablePreloadedContent) {
mainImageModifier = mainImageModifier.combinedClickable( mainImageModifier = mainImageModifier.combinedClickable(
onClick = { dialogOpen = true }, onClick = { dialogOpen = true },
onLongClick = { clipboardManager.setText(AnnotatedString(content.uri)) } onLongClick = { shareOpen.value = true }
) )
} else { } else {
mainImageModifier = mainImageModifier.clickable { mainImageModifier = mainImageModifier.clickable {
@ -649,7 +669,10 @@ fun ZoomableImageDialog(
val myContent = allImages[pagerState.currentPage] val myContent = allImages[pagerState.currentPage]
if (myContent is ZoomableUrlContent) { if (myContent is ZoomableUrlContent) {
SaveToGallery(url = myContent.url) Row() {
CopyToClipboard(content = myContent)
SaveToGallery(url = myContent.url)
}
} else if (myContent is ZoomableLocalImage && myContent.localFile != null) { } else if (myContent is ZoomableLocalImage && myContent.localFile != null) {
SaveToGallery( SaveToGallery(
localFile = myContent.localFile, localFile = myContent.localFile,
@ -662,6 +685,64 @@ fun ZoomableImageDialog(
} }
} }
@Composable
private fun CopyToClipboard(
content: ZoomableContent
) {
val popupExpanded = remember { mutableStateOf(false) }
Button(
modifier = Modifier.padding(horizontal = Size5dp),
onClick = { popupExpanded.value = true },
shape = ButtonBorder,
colors = ButtonDefaults
.buttonColors(
backgroundColor = MaterialTheme.colors.placeholderText
)
) {
Icon(
tint = Color.White,
imageVector = Icons.Default.Share,
modifier = Size20Modifier,
contentDescription = stringResource(R.string.copy_url_to_clipboard)
)
ShareImageAction(popupExpanded, content) { popupExpanded.value = false }
}
}
@Composable
private fun ShareImageAction(
popupExpanded:
MutableState<Boolean>,
content: ZoomableContent,
onDismiss: () -> Unit
) {
DropdownMenu(
expanded = popupExpanded.value,
onDismissRequest = onDismiss
) {
val clipboardManager = LocalClipboardManager.current
if (content is ZoomableUrlContent) {
DropdownMenuItem(onClick = { clipboardManager.setText(AnnotatedString(content.url)); onDismiss() }) {
Text(stringResource(R.string.copy_url_to_clipboard))
}
if (content.uri != null) {
DropdownMenuItem(onClick = { clipboardManager.setText(AnnotatedString(content.uri)); onDismiss() }) {
Text(stringResource(R.string.copy_the_note_id_to_the_clipboard))
}
}
}
if (content is ZoomablePreloadedContent) {
DropdownMenuItem(onClick = { clipboardManager.setText(AnnotatedString(content.uri)); onDismiss() }) {
Text(stringResource(R.string.copy_the_note_id_to_the_clipboard))
}
}
}
}
@Composable @Composable
private fun RenderImageOrVideo(content: ZoomableContent, roundedCorner: Boolean, accountViewModel: AccountViewModel) { private fun RenderImageOrVideo(content: ZoomableContent, roundedCorner: Boolean, accountViewModel: AccountViewModel) {
val mainModifier = Modifier val mainModifier = Modifier

View File

@ -685,9 +685,6 @@ private fun ProfileHeader(
) { ) {
MessageButton(baseUser, accountViewModel, nav) MessageButton(baseUser, accountViewModel, nav)
// No need for this button anymore
// NPubCopyButton(baseUser)
ProfileActions(baseUser, accountViewModel) ProfileActions(baseUser, accountViewModel)
} }
} }

View File

@ -103,7 +103,7 @@
<string name="uploading">Uploading…</string> <string name="uploading">Uploading…</string>
<string name="user_does_not_have_a_lightning_address_setup_to_receive_sats">User does not have a lightning address setup to receive sats</string> <string name="user_does_not_have_a_lightning_address_setup_to_receive_sats">User does not have a lightning address setup to receive sats</string>
<string name="reply_here">"reply here.. "</string> <string name="reply_here">"reply here.. "</string>
<string name="copies_the_note_id_to_the_clipboard_for_sharing">Copies the Note ID to the clipboard for sharing</string> <string name="copies_the_note_id_to_the_clipboard_for_sharing">Copies the Note ID to the clipboard for sharing in Nostr</string>
<string name="copy_channel_id_note_to_the_clipboard">Copy Channel ID (Note) to the Clipboard</string> <string name="copy_channel_id_note_to_the_clipboard">Copy Channel ID (Note) to the Clipboard</string>
<string name="edits_the_channel_metadata">Edits the Channel Metadata</string> <string name="edits_the_channel_metadata">Edits the Channel Metadata</string>
<string name="join">Join</string> <string name="join">Join</string>
@ -544,4 +544,6 @@
<string name="automatically_show_url_preview_description">Show URL previews</string> <string name="automatically_show_url_preview_description">Show URL previews</string>
<string name="load_image_description">When to load images</string> <string name="load_image_description">When to load images</string>
<string name="copy_url_to_clipboard">Copy URL to clipboard</string>
<string name="copy_the_note_id_to_the_clipboard">Copy Note ID to clipboard</string>
</resources> </resources>