PM-34231: feat: Support renaming attachments during creation (#6742)

This commit is contained in:
David Perez
2026-03-31 13:52:10 -05:00
committed by GitHub
parent 2402e21b4d
commit 9f4ae99c0b
8 changed files with 386 additions and 10 deletions

View File

@@ -0,0 +1,78 @@
package com.bitwarden.ui.platform.components.util
import androidx.compose.runtime.Composable
import androidx.compose.runtime.remember
import androidx.compose.ui.graphics.Color
import androidx.compose.ui.text.AnnotatedString
import androidx.compose.ui.text.SpanStyle
import androidx.compose.ui.text.input.OffsetMapping
import androidx.compose.ui.text.input.TransformedText
import androidx.compose.ui.text.input.VisualTransformation
import androidx.compose.ui.text.withStyle
import com.bitwarden.ui.platform.theme.BitwardenTheme
/**
* Returns the [VisualTransformation] that alters the output of the text in an input field by
* appending a '.' followed by the [fileExtension] to the display text.
*/
@Composable
fun nonEditableExtensionVisualTransformation(
fileExtension: String?,
fileExtensionColor: Color = BitwardenTheme.colorScheme.filledButton.foregroundDisabled,
): VisualTransformation =
remember(fileExtension, fileExtensionColor) {
NonEditableExtensionVisualTransformation(
fileExtension = fileExtension,
fileExtensionColor = fileExtensionColor,
)
}
/**
* Alters the visual output of the text in an input field.
*
* This will append a '.' followed by the [fileExtension] to the display text but not allow users
* to alter that text. If the `fileExtension` is null, then no alteration will occur.
*/
private class NonEditableExtensionVisualTransformation(
private val fileExtension: String?,
private val fileExtensionColor: Color,
) : VisualTransformation {
override fun filter(
text: AnnotatedString,
): TransformedText = TransformedText(
text.buildTransformedAnnotatedString(
fileExtension = fileExtension,
fileExtensionColor = fileExtensionColor,
),
text.getOffsetMapping(),
)
}
private fun AnnotatedString.buildTransformedAnnotatedString(
fileExtension: String?,
fileExtensionColor: Color,
): AnnotatedString {
val extension = fileExtension ?: return this
val builder = AnnotatedString.Builder()
builder.append(this)
builder.withStyle(SpanStyle(color = fileExtensionColor)) { append(".$extension") }
return builder.toAnnotatedString()
}
private fun AnnotatedString.getOffsetMapping(): OffsetMapping =
object : OffsetMapping {
override fun originalToTransformed(offset: Int): Int {
// We always use the regular offset here since the extension is off-limits.
return offset
}
override fun transformedToOriginal(
offset: Int,
): Int = if (offset > this@getOffsetMapping.length) {
// If we are in the extension space, pull us back into the regular text.
this@getOffsetMapping.length
} else {
// We are within the limits, so leave the offset alone.
offset
}
}

View File

@@ -206,6 +206,7 @@ Scanning will happen automatically.</string>
<string name="choose_file">Choose file</string>
<string name="file">File</string>
<string name="no_file_chosen">No file chosen</string>
<string name="file_name">File name</string>
<string name="no_attachments">There are no attachments.</string>
<string name="file_source">File Source</string>
<string name="max_file_size">Maximum file size is 100 MB.</string>