Add NoteQuickActionMenu composable cf #71

This commit is contained in:
maxmoney21m
2023-03-08 22:40:32 +08:00
parent 71671865ff
commit 6324dc64d5
4 changed files with 245 additions and 4 deletions

View File

@@ -0,0 +1,57 @@
package com.vitorpamplona.amethyst.ui.components
import androidx.compose.foundation.background
import androidx.compose.foundation.layout.Arrangement
import androidx.compose.foundation.layout.Column
import androidx.compose.foundation.layout.Row
import androidx.compose.foundation.layout.padding
import androidx.compose.foundation.text.selection.SelectionContainer
import androidx.compose.material.Card
import androidx.compose.material.Divider
import androidx.compose.material.Icon
import androidx.compose.material.IconButton
import androidx.compose.material.MaterialTheme
import androidx.compose.material.Text
import androidx.compose.material.icons.Icons
import androidx.compose.material.icons.filled.ArrowBack
import androidx.compose.runtime.Composable
import androidx.compose.ui.Alignment
import androidx.compose.ui.Modifier
import androidx.compose.ui.res.stringResource
import androidx.compose.ui.unit.dp
import androidx.compose.ui.window.Dialog
import com.vitorpamplona.amethyst.R
@Composable
fun SelectTextDialog(text: String, onDismiss: () -> Unit) {
Dialog(
onDismissRequest = onDismiss,
) {
Card {
Column {
Row(
verticalAlignment = Alignment.CenterVertically,
horizontalArrangement = Arrangement.End
) {
IconButton(
onClick = onDismiss,
modifier = Modifier.background(MaterialTheme.colors.background)
) {
Icon(
imageVector = Icons.Default.ArrowBack,
contentDescription = null,
tint = MaterialTheme.colors.primary
)
}
Text(text = stringResource(R.string.select_text))
}
Divider()
Row(modifier = Modifier.padding(16.dp)) {
SelectionContainer {
Text(text)
}
}
}
}
}
}

View File

@@ -0,0 +1,171 @@
package com.vitorpamplona.amethyst.ui.note
import android.content.Intent
import android.widget.Toast
import androidx.compose.foundation.clickable
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.fillMaxHeight
import androidx.compose.foundation.layout.height
import androidx.compose.foundation.layout.size
import androidx.compose.foundation.layout.width
import androidx.compose.foundation.shape.RoundedCornerShape
import androidx.compose.material.Card
import androidx.compose.material.Divider
import androidx.compose.material.Icon
import androidx.compose.material.MaterialTheme
import androidx.compose.material.Text
import androidx.compose.material.icons.Icons
import androidx.compose.material.icons.filled.AlternateEmail
import androidx.compose.material.icons.filled.ContentCopy
import androidx.compose.material.icons.filled.Share
import androidx.compose.runtime.Composable
import androidx.compose.runtime.getValue
import androidx.compose.runtime.mutableStateOf
import androidx.compose.runtime.remember
import androidx.compose.runtime.rememberCoroutineScope
import androidx.compose.runtime.setValue
import androidx.compose.ui.Alignment
import androidx.compose.ui.Modifier
import androidx.compose.ui.draw.shadow
import androidx.compose.ui.graphics.Color
import androidx.compose.ui.graphics.toArgb
import androidx.compose.ui.graphics.vector.ImageVector
import androidx.compose.ui.platform.LocalClipboardManager
import androidx.compose.ui.platform.LocalContext
import androidx.compose.ui.res.stringResource
import androidx.compose.ui.res.vectorResource
import androidx.compose.ui.text.AnnotatedString
import androidx.compose.ui.unit.dp
import androidx.compose.ui.unit.sp
import androidx.compose.ui.window.Popup
import androidx.core.content.ContextCompat
import androidx.core.graphics.ColorUtils
import com.vitorpamplona.amethyst.R
import com.vitorpamplona.amethyst.model.Note
import com.vitorpamplona.amethyst.ui.components.SelectTextDialog
import com.vitorpamplona.amethyst.ui.screen.loggedIn.AccountViewModel
import kotlinx.coroutines.launch
fun lightenColor(color: Color, amount: Float): Color {
var argb = color.toArgb()
val hslOut = floatArrayOf(0f, 0f, 0f)
ColorUtils.colorToHSL(argb, hslOut)
hslOut[2] += amount
argb = ColorUtils.HSLToColor(hslOut)
return Color(argb)
}
val externalLinkForNote = { note: Note -> "https://snort.social/e/${note.idNote()}" }
@Composable
fun VerticalDivider(color: Color) =
Divider(
color = color, modifier = Modifier
.fillMaxHeight()
.width(1.dp)
)
@Composable
fun NoteQuickActionMenu(note: Note, popupExpanded: Boolean, onDismiss: () -> Unit, accountViewModel: AccountViewModel) {
val context = LocalContext.current
val primaryLight = lightenColor(MaterialTheme.colors.primary, 0.2f)
val cardShape = RoundedCornerShape(5.dp)
val clipboardManager = LocalClipboardManager.current
val scope = rememberCoroutineScope()
var showSelectTextDialog by remember { mutableStateOf(false) }
val showToast = { stringResource: Int ->
scope.launch {
Toast.makeText(
context,
context.getString(stringResource),
Toast.LENGTH_SHORT
).show()
}
}
if (popupExpanded) {
Popup(onDismissRequest = onDismiss) {
Card(
modifier = Modifier.shadow(elevation = 6.dp, shape = cardShape),
shape = cardShape,
backgroundColor = MaterialTheme.colors.primary,
) {
Column(modifier = Modifier.width(IntrinsicSize.Min)) {
Row(modifier = Modifier.height(IntrinsicSize.Min)) {
NoteQuickActionItem(
icon = Icons.Default.ContentCopy,
label = stringResource(R.string.quick_action_copy_text)
) {
clipboardManager.setText(
AnnotatedString(
accountViewModel.decrypt(note) ?: ""
)
)
showToast(R.string.copied_note_text_to_clipboard)
onDismiss()
}
VerticalDivider(primaryLight)
NoteQuickActionItem(Icons.Default.AlternateEmail, stringResource(R.string.quick_action_copy_note_id)) {
clipboardManager.setText(AnnotatedString("@${note.idNote()}"))
showToast(R.string.copied_note_id_to_clipboard)
onDismiss()
}
VerticalDivider(primaryLight)
NoteQuickActionItem(
icon = ImageVector.vectorResource(id = R.drawable.text_select_move_forward_character),
label = stringResource(R.string.quick_action_select)
) {
showSelectTextDialog = true
onDismiss()
}
VerticalDivider(primaryLight)
NoteQuickActionItem(icon = Icons.Default.Share, label = stringResource(R.string.quick_action_share)) {
val sendIntent = Intent().apply {
action = Intent.ACTION_SEND
type = "text/plain"
putExtra(
Intent.EXTRA_TEXT,
externalLinkForNote(note)
)
putExtra(Intent.EXTRA_TITLE, context.getString(R.string.quick_action_share_browser_link))
}
val shareIntent = Intent.createChooser(sendIntent, context.getString(R.string.quick_action_share))
ContextCompat.startActivity(context, shareIntent, null)
onDismiss()
}
}
}
}
}
}
if (showSelectTextDialog) {
accountViewModel.decrypt(note)?.let {
SelectTextDialog(it) { showSelectTextDialog = false }
}
}
}
@Composable
fun NoteQuickActionItem(icon: ImageVector, label: String, onClick: () -> Unit) {
Column(
modifier = Modifier
.size(64.dp)
.clickable { onClick() },
verticalArrangement = Arrangement.Center,
horizontalAlignment = Alignment.CenterHorizontally,
) {
Icon(
imageVector = icon,
contentDescription = null,
modifier = Modifier.size(20.dp),
tint = MaterialTheme.colors.onPrimary,
)
Text(text = label, fontSize = 12.sp)
}
}

View File

@@ -0,0 +1,5 @@
<vector android:autoMirrored="true" android:height="48dp"
android:viewportHeight="960" android:viewportWidth="960"
android:width="48dp" xmlns:android="http://schemas.android.com/apk/res/android">
<path android:fillColor="#FF000000" android:pathData="M439,840v-60h83v60h-83ZM439,180v-60h83v60h-83ZM609,840v-60h83v60h-83ZM609,180v-60h83v60h-83ZM780,840v-60h60v60h-60ZM780,180v-60h60v60h-60ZM120,840v-60h86L206,180h-86v-60h231v60h-85v600h85v60L120,840ZM694,626 L652,584 725,510L414,510v-60h311l-73,-74 42,-42 146,146 -146,146Z"/>
</vector>

View File

@@ -1,4 +1,4 @@
<resources>
<resources xmlns:tools="http://schemas.android.com/tools">
<string name="app_name_release" translatable="false">Amethyst</string>
<string name="app_name_debug" translatable="false">Amethyst Debug</string>
<string name="point_to_the_qr_code">Point to the QR Code</string>
@@ -20,7 +20,7 @@
<string name="relay_icon">Relay Icon</string>
<string name="unknown_author">Unknown Author</string>
<string name="copy_text">Copy Text</string>
<string name="copy_user_pubkey">Copy User PubKey</string>
<string name="copy_user_pubkey">Copy Author @npub</string>
<string name="copy_note_id">Copy Note ID</string>
<string name="broadcast">Broadcast</string>
<string name="block_hide_user"><![CDATA[Block & Hide User]]></string>
@@ -177,7 +177,7 @@
<string name="mark_all_known_as_read">Mark all Known as read</string>
<string name="mark_all_new_as_read">Mark all New as read</string>
<string name="mark_all_as_read">Mark all as read</string>
<string name="account_backup_tips_md">
<string name="account_backup_tips_md" tools:ignore="Typos">
## Key Backup and Safety Tips
\n\nYour account is secured by a secret key. The key is long random string starting with **nsec1**. Anyone who has access to your secret key can publish content using your identity.
\n\n- Do **not** put your secret key in any website or software you do not trust.
@@ -192,4 +192,12 @@
<string name="badge_award_image_for">"Badge award image for %1$s"</string>
<string name="new_badge_award_notif">You Received a new Badge Award</string>
<string name="award_granted_to">Badge award granted to</string>
</resources>
<string name="copied_note_text_to_clipboard">Copied note text to clipboard</string>
<string name="copied_note_id_to_clipboard" tools:ignore="Typos">Copied note ID (@note1) to clipboard</string>
<string name="select_text">Select Text</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>
<string name="quick_action_copy_note_id">Copy ID</string>
<string name="quick_action_copy_text">Copy Text</string>
</resources>