Remove deprecated ClipboardManager

This commit is contained in:
T8RIN
2025-01-21 12:52:50 +03:00
parent 3dab466351
commit 06b53be776
45 changed files with 147 additions and 204 deletions

View File

@ -51,7 +51,6 @@ import androidx.compose.material3.MaterialTheme
import androidx.compose.material3.Text import androidx.compose.material3.Text
import androidx.compose.runtime.getValue import androidx.compose.runtime.getValue
import androidx.compose.runtime.remember import androidx.compose.runtime.remember
import androidx.compose.runtime.rememberCoroutineScope
import androidx.compose.ui.Alignment import androidx.compose.ui.Alignment
import androidx.compose.ui.Modifier import androidx.compose.ui.Modifier
import androidx.compose.ui.platform.LocalUriHandler import androidx.compose.ui.platform.LocalUriHandler
@ -64,7 +63,6 @@ import androidx.exifinterface.media.ExifInterface
import com.t8rin.dynamic.theme.ColorTuple import com.t8rin.dynamic.theme.ColorTuple
import com.t8rin.dynamic.theme.extractPrimaryColor import com.t8rin.dynamic.theme.extractPrimaryColor
import dagger.hilt.android.AndroidEntryPoint import dagger.hilt.android.AndroidEntryPoint
import kotlinx.coroutines.launch
import ru.tech.imageresizershrinker.core.crash.components.CrashHandler import ru.tech.imageresizershrinker.core.crash.components.CrashHandler
import ru.tech.imageresizershrinker.core.domain.ISSUE_TRACKER import ru.tech.imageresizershrinker.core.domain.ISSUE_TRACKER
import ru.tech.imageresizershrinker.core.domain.TELEGRAM_GROUP_LINK import ru.tech.imageresizershrinker.core.domain.TELEGRAM_GROUP_LINK
@ -83,14 +81,13 @@ import ru.tech.imageresizershrinker.core.ui.theme.ImageToolboxThemeSurface
import ru.tech.imageresizershrinker.core.ui.theme.White import ru.tech.imageresizershrinker.core.ui.theme.White
import ru.tech.imageresizershrinker.core.ui.theme.outlineVariant import ru.tech.imageresizershrinker.core.ui.theme.outlineVariant
import ru.tech.imageresizershrinker.core.ui.utils.helper.AppActivityClass import ru.tech.imageresizershrinker.core.ui.utils.helper.AppActivityClass
import ru.tech.imageresizershrinker.core.ui.utils.helper.ContextUtils.copyToClipboard
import ru.tech.imageresizershrinker.core.ui.utils.provider.ImageToolboxCompositionLocals import ru.tech.imageresizershrinker.core.ui.utils.provider.ImageToolboxCompositionLocals
import ru.tech.imageresizershrinker.core.ui.utils.provider.LocalScreenSize import ru.tech.imageresizershrinker.core.ui.utils.provider.LocalScreenSize
import ru.tech.imageresizershrinker.core.ui.utils.provider.rememberLocalEssentials
import ru.tech.imageresizershrinker.core.ui.utils.provider.setContentWithWindowSizeClass import ru.tech.imageresizershrinker.core.ui.utils.provider.setContentWithWindowSizeClass
import ru.tech.imageresizershrinker.core.ui.widget.enhanced.EnhancedButton import ru.tech.imageresizershrinker.core.ui.widget.enhanced.EnhancedButton
import ru.tech.imageresizershrinker.core.ui.widget.enhanced.EnhancedFloatingActionButton import ru.tech.imageresizershrinker.core.ui.widget.enhanced.EnhancedFloatingActionButton
import ru.tech.imageresizershrinker.core.ui.widget.other.ExpandableItem import ru.tech.imageresizershrinker.core.ui.widget.other.ExpandableItem
import ru.tech.imageresizershrinker.core.ui.widget.other.LocalToastHostState
import ru.tech.imageresizershrinker.core.ui.widget.other.ToastHost import ru.tech.imageresizershrinker.core.ui.widget.other.ToastHost
import ru.tech.imageresizershrinker.core.ui.widget.text.AutoSizeText import ru.tech.imageresizershrinker.core.ui.widget.text.AutoSizeText
import javax.inject.Inject import javax.inject.Inject
@ -118,20 +115,13 @@ class CrashActivity : CrashHandler() {
onGetEmojiColorTuple = ::getColorTupleFromEmoji onGetEmojiColorTuple = ::getColorTupleFromEmoji
) )
) { ) {
val toastHostState = LocalToastHostState.current val essentials = rememberLocalEssentials()
val scope = rememberCoroutineScope()
val createClip: (String) -> Unit = { val createClip: (String) -> Unit = {
copyToClipboard( essentials.copyToClipboard(it)
label = getString(R.string.exception), essentials.showToast(
value = it icon = Icons.Rounded.ContentCopy,
message = getString(R.string.copied),
) )
scope.launch {
toastHostState.showToast(
icon = Icons.Rounded.ContentCopy,
message = getString(R.string.copied),
)
}
} }
val linkHandler = LocalUriHandler.current val linkHandler = LocalUriHandler.current

View File

@ -24,9 +24,9 @@ inline fun <reified T> T?.notNullAnd(
): Boolean = if (this != null) predicate(this) ): Boolean = if (this != null) predicate(this)
else false else false
fun String.isBase64() = isNotEmpty() && BASE64_PATTERN.matches(this) fun CharSequence.isBase64() = isNotEmpty() && BASE64_PATTERN.matches(this)
fun String.trimToBase64() = filter { !it.isWhitespace() }.substringAfter(",") fun CharSequence.trimToBase64() = toString().filter { !it.isWhitespace() }.substringAfter(",")
private val BASE64_PATTERN = Regex( private val BASE64_PATTERN = Regex(
"^(?=(.{4})*\$)[A-Za-z0-9+/]*={0,2}\$" "^(?=(.{4})*\$)[A-Za-z0-9+/]*={0,2}\$"

View File

@ -225,7 +225,7 @@ internal fun OtherContent(
}, },
onCopy = { manager -> onCopy = { manager ->
component.cacheNeutralLut { uri -> component.cacheNeutralLut { uri ->
manager.setClip( manager.copyToClipboard(
uri.asClip(context) uri.asClip(context)
) )
showConfetti() showConfetti()

View File

@ -145,6 +145,10 @@ fun List<Uri>.toClipData(
} }
} }
fun CharSequence.toClipData(
label: String = "plain text"
): ClipData = ClipData.newPlainText(label, this)
fun Uri.asClip( fun Uri.asClip(
context: Context, context: Context,
label: String = "Image" label: String = "Image"

View File

@ -366,11 +366,10 @@ object ContextUtils {
/** Save a text into the clipboard. */ /** Save a text into the clipboard. */
fun Context.copyToClipboard( fun Context.copyToClipboard(
label: String,
value: String, value: String,
) { ) {
val clipboard = getSystemService(Context.CLIPBOARD_SERVICE) as ClipboardManager val clipboard = getSystemService(Context.CLIPBOARD_SERVICE) as ClipboardManager
val clip = ClipData.newPlainText(label, value) val clip = ClipData.newPlainText("plain text", value)
clipboard.setPrimaryClip(clip) clipboard.setPrimaryClip(clip)
} }

View File

@ -17,6 +17,8 @@
package ru.tech.imageresizershrinker.core.ui.utils.provider package ru.tech.imageresizershrinker.core.ui.utils.provider
import android.content.ClipData
import android.os.Build
import androidx.activity.ComponentActivity import androidx.activity.ComponentActivity
import androidx.compose.material.icons.Icons import androidx.compose.material.icons.Icons
import androidx.compose.material.icons.outlined.FolderOff import androidx.compose.material.icons.outlined.FolderOff
@ -27,6 +29,9 @@ import androidx.compose.runtime.remember
import androidx.compose.runtime.rememberCoroutineScope import androidx.compose.runtime.rememberCoroutineScope
import androidx.compose.ui.graphics.Color import androidx.compose.ui.graphics.Color
import androidx.compose.ui.graphics.vector.ImageVector import androidx.compose.ui.graphics.vector.ImageVector
import androidx.compose.ui.platform.ClipEntry
import androidx.compose.ui.platform.Clipboard
import androidx.compose.ui.platform.LocalClipboard
import kotlinx.coroutines.CoroutineScope import kotlinx.coroutines.CoroutineScope
import kotlinx.coroutines.launch import kotlinx.coroutines.launch
import ru.tech.imageresizershrinker.core.domain.saving.model.SaveResult import ru.tech.imageresizershrinker.core.domain.saving.model.SaveResult
@ -37,6 +42,7 @@ import ru.tech.imageresizershrinker.core.ui.utils.helper.ContextUtils.createScre
import ru.tech.imageresizershrinker.core.ui.utils.helper.parseFileSaveResult import ru.tech.imageresizershrinker.core.ui.utils.helper.parseFileSaveResult
import ru.tech.imageresizershrinker.core.ui.utils.helper.parseSaveResult import ru.tech.imageresizershrinker.core.ui.utils.helper.parseSaveResult
import ru.tech.imageresizershrinker.core.ui.utils.helper.parseSaveResults import ru.tech.imageresizershrinker.core.ui.utils.helper.parseSaveResults
import ru.tech.imageresizershrinker.core.ui.utils.helper.toClipData
import ru.tech.imageresizershrinker.core.ui.utils.navigation.Screen import ru.tech.imageresizershrinker.core.ui.utils.navigation.Screen
import ru.tech.imageresizershrinker.core.ui.widget.other.LocalToastHostState import ru.tech.imageresizershrinker.core.ui.widget.other.LocalToastHostState
import ru.tech.imageresizershrinker.core.ui.widget.other.ToastDuration import ru.tech.imageresizershrinker.core.ui.widget.other.ToastDuration
@ -49,22 +55,26 @@ fun rememberLocalEssentials(): LocalEssentials {
val confettiHostState = LocalConfettiHostState.current val confettiHostState = LocalConfettiHostState.current
val context = LocalComponentActivity.current val context = LocalComponentActivity.current
val coroutineScope = rememberCoroutineScope() val coroutineScope = rememberCoroutineScope()
val clipboard = LocalClipboard.current
return remember( return remember(
toastHostState, toastHostState,
coroutineScope, coroutineScope,
confettiHostState, confettiHostState,
context context,
clipboard
) { ) {
LocalEssentials( LocalEssentials(
toastHostState = toastHostState, toastHostState = toastHostState,
confettiHostState = confettiHostState, confettiHostState = confettiHostState,
coroutineScope = coroutineScope, coroutineScope = coroutineScope,
context = context context = context,
clipboard = clipboard
) )
} }
} }
@ConsistentCopyVisibility
@Stable @Stable
@Immutable @Immutable
data class LocalEssentials internal constructor( data class LocalEssentials internal constructor(
@ -72,6 +82,7 @@ data class LocalEssentials internal constructor(
val confettiHostState: ConfettiHostState, val confettiHostState: ConfettiHostState,
val coroutineScope: CoroutineScope, val coroutineScope: CoroutineScope,
val context: ComponentActivity, val context: ComponentActivity,
val clipboard: Clipboard
) { ) {
fun showToast( fun showToast(
message: String, message: String,
@ -147,4 +158,46 @@ data class LocalEssentials internal constructor(
) )
} }
} }
fun copyToClipboard(clipEntry: ClipEntry?) {
coroutineScope.launch {
clipboard.setClipEntry(clipEntry)
}
}
fun copyToClipboard(text: CharSequence) {
copyToClipboard(ClipEntry(text.toClipData()))
}
fun getTextFromClipboard(
onSuccess: (CharSequence) -> Unit
) {
coroutineScope.launch {
clipboard.getClipEntry()
?.clipData?.let { primaryClip ->
if (primaryClip.itemCount > 0) {
primaryClip.getItemAt(0)?.text
} else {
null
}
}?.takeIf { it.isNotEmpty() }?.let(onSuccess)
}
}
fun clearClipboard() {
val clipboardManager = clipboard.nativeClipboard
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.P) {
runCatching {
clipboardManager.clearPrimaryClip()
}.onFailure {
clipboardManager.setPrimaryClip(
ClipData.newPlainText(null, "")
)
}
} else {
clipboardManager.setPrimaryClip(
ClipData.newPlainText(null, "")
)
}
}
} }

View File

@ -37,12 +37,12 @@ import androidx.compose.runtime.saveable.rememberSaveable
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.platform.ClipboardManager
import androidx.compose.ui.platform.LocalClipboardManager
import androidx.compose.ui.res.stringResource import androidx.compose.ui.res.stringResource
import androidx.compose.ui.unit.dp import androidx.compose.ui.unit.dp
import ru.tech.imageresizershrinker.core.resources.R import ru.tech.imageresizershrinker.core.resources.R
import ru.tech.imageresizershrinker.core.resources.icons.MiniEdit import ru.tech.imageresizershrinker.core.resources.icons.MiniEdit
import ru.tech.imageresizershrinker.core.ui.utils.provider.LocalEssentials
import ru.tech.imageresizershrinker.core.ui.utils.provider.rememberLocalEssentials
import ru.tech.imageresizershrinker.core.ui.widget.enhanced.EnhancedAlertDialog import ru.tech.imageresizershrinker.core.ui.widget.enhanced.EnhancedAlertDialog
import ru.tech.imageresizershrinker.core.ui.widget.enhanced.EnhancedButton import ru.tech.imageresizershrinker.core.ui.widget.enhanced.EnhancedButton
import ru.tech.imageresizershrinker.core.ui.widget.enhanced.EnhancedIconButton import ru.tech.imageresizershrinker.core.ui.widget.enhanced.EnhancedIconButton
@ -56,7 +56,7 @@ fun ShareButton(
enabled: Boolean = true, enabled: Boolean = true,
onShare: () -> Unit, onShare: () -> Unit,
onEdit: (() -> Unit)? = null, onEdit: (() -> Unit)? = null,
onCopy: ((ClipboardManager) -> Unit)? = null onCopy: ((LocalEssentials) -> Unit)? = null
) { ) {
var showSelectionDialog by rememberSaveable { var showSelectionDialog by rememberSaveable {
mutableStateOf(false) mutableStateOf(false)
@ -99,7 +99,7 @@ fun ShareButton(
) )
}, },
text = { text = {
val clipboardManager = LocalClipboardManager.current val essentials = rememberLocalEssentials()
val scrollState = rememberScrollState() val scrollState = rememberScrollState()
Column( Column(
@ -131,7 +131,7 @@ fun ShareButton(
startIcon = Icons.Rounded.ContentCopy, startIcon = Icons.Rounded.ContentCopy,
onClick = { onClick = {
showSelectionDialog = false showSelectionDialog = false
onCopy(clipboardManager) onCopy(essentials)
}, },
titleFontStyle = PreferenceItemDefaults.TitleFontStyleCentered titleFontStyle = PreferenceItemDefaults.TitleFontStyleCentered
) )

View File

@ -98,10 +98,7 @@ fun ColorInfo(
val context = LocalContext.current val context = LocalContext.current
val colorPasteError = rememberSaveable { mutableStateOf<String?>(null) } val colorPasteError = rememberSaveable { mutableStateOf<String?>(null) }
val onCopyCustomColor = { val onCopyCustomColor = {
context.copyToClipboard( context.copyToClipboard(getFormattedColor(color))
label = context.getString(R.string.color),
value = getFormattedColor(color)
)
} }
val onPasteCustomColor = { val onPasteCustomColor = {
context.pasteColorFromClipboard( context.pasteColorFromClipboard(

View File

@ -17,8 +17,6 @@
package ru.tech.imageresizershrinker.core.ui.widget.other package ru.tech.imageresizershrinker.core.ui.widget.other
import android.content.ClipData
import android.content.Intent
import androidx.compose.foundation.background import androidx.compose.foundation.background
import androidx.compose.foundation.layout.Arrangement import androidx.compose.foundation.layout.Arrangement
import androidx.compose.foundation.layout.Column import androidx.compose.foundation.layout.Column
@ -38,7 +36,6 @@ import androidx.compose.runtime.Composable
import androidx.compose.runtime.getValue import androidx.compose.runtime.getValue
import androidx.compose.runtime.mutableStateOf import androidx.compose.runtime.mutableStateOf
import androidx.compose.runtime.remember import androidx.compose.runtime.remember
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
@ -48,20 +45,18 @@ import androidx.compose.ui.graphics.Shape
import androidx.compose.ui.graphics.compositeOver import androidx.compose.ui.graphics.compositeOver
import androidx.compose.ui.layout.ContentScale import androidx.compose.ui.layout.ContentScale
import androidx.compose.ui.layout.onSizeChanged import androidx.compose.ui.layout.onSizeChanged
import androidx.compose.ui.platform.LocalClipboardManager
import androidx.compose.ui.platform.LocalContext
import androidx.compose.ui.platform.LocalDensity import androidx.compose.ui.platform.LocalDensity
import androidx.compose.ui.platform.LocalUriHandler
import androidx.compose.ui.res.stringResource import androidx.compose.ui.res.stringResource
import androidx.compose.ui.text.font.FontWeight import androidx.compose.ui.text.font.FontWeight
import androidx.compose.ui.text.style.TextAlign import androidx.compose.ui.text.style.TextAlign
import androidx.compose.ui.text.style.TextOverflow import androidx.compose.ui.text.style.TextOverflow
import androidx.compose.ui.unit.dp import androidx.compose.ui.unit.dp
import androidx.compose.ui.unit.sp import androidx.compose.ui.unit.sp
import androidx.core.net.toUri
import kotlinx.coroutines.launch
import ru.tech.imageresizershrinker.core.resources.R import ru.tech.imageresizershrinker.core.resources.R
import ru.tech.imageresizershrinker.core.ui.shapes.MaterialStarShape import ru.tech.imageresizershrinker.core.ui.shapes.MaterialStarShape
import ru.tech.imageresizershrinker.core.ui.utils.helper.LinkPreview import ru.tech.imageresizershrinker.core.ui.utils.helper.LinkPreview
import ru.tech.imageresizershrinker.core.ui.utils.provider.rememberLocalEssentials
import ru.tech.imageresizershrinker.core.ui.widget.enhanced.hapticsCombinedClickable import ru.tech.imageresizershrinker.core.ui.widget.enhanced.hapticsCombinedClickable
import ru.tech.imageresizershrinker.core.ui.widget.image.Picture import ru.tech.imageresizershrinker.core.ui.widget.image.Picture
import ru.tech.imageresizershrinker.core.ui.widget.modifier.container import ru.tech.imageresizershrinker.core.ui.widget.modifier.container
@ -71,12 +66,9 @@ fun LinkPreviewCard(
linkPreview: LinkPreview, linkPreview: LinkPreview,
shape: Shape shape: Shape
) { ) {
val clipboardManager = LocalClipboardManager.current.nativeClipboard val essentials = rememberLocalEssentials()
val coroutineScope = rememberCoroutineScope()
val onLinkCopiedText = stringResource(R.string.copied) val onLinkCopiedText = stringResource(R.string.copied)
val linkTextLabel = stringResource(R.string.image_link) val linkHandler = LocalUriHandler.current
val context = LocalContext.current
val toastHostState = LocalToastHostState.current
Row( Row(
modifier = Modifier modifier = Modifier
@ -88,28 +80,14 @@ fun LinkPreviewCard(
) )
.hapticsCombinedClickable( .hapticsCombinedClickable(
onClick = { onClick = {
linkPreview.link?.let { linkPreview.link?.let(linkHandler::openUri)
context.startActivity(
Intent(
Intent.ACTION_VIEW,
it.toUri()
)
)
}
}, },
onLongClick = { onLongClick = {
clipboardManager.setPrimaryClip( linkPreview.link?.let(essentials::copyToClipboard)
ClipData.newPlainText( essentials.showToast(
linkTextLabel, message = onLinkCopiedText,
linkPreview.link icon = Icons.Default.Link
)
) )
coroutineScope.launch {
toastHostState.showToast(
message = onLinkCopiedText,
icon = Icons.Default.Link
)
}
}, },
), ),
verticalAlignment = Alignment.CenterVertically verticalAlignment = Alignment.CenterVertically

View File

@ -128,7 +128,7 @@ fun Base64ToolsContent(
}, },
onCopy = { manager -> onCopy = { manager ->
component.cacheCurrentImage { uri -> component.cacheCurrentImage { uri ->
manager.setClip(uri.asClip(context)) manager.copyToClipboard(uri.asClip(context))
showConfetti() showConfetti()
} }
}, },

View File

@ -51,7 +51,6 @@ import androidx.compose.ui.Alignment
import androidx.compose.ui.Modifier import androidx.compose.ui.Modifier
import androidx.compose.ui.graphics.Shape import androidx.compose.ui.graphics.Shape
import androidx.compose.ui.graphics.vector.ImageVector import androidx.compose.ui.graphics.vector.ImageVector
import androidx.compose.ui.platform.LocalClipboardManager
import androidx.compose.ui.platform.LocalContext import androidx.compose.ui.platform.LocalContext
import androidx.compose.ui.res.stringResource import androidx.compose.ui.res.stringResource
import androidx.compose.ui.text.buildAnnotatedString import androidx.compose.ui.text.buildAnnotatedString
@ -72,19 +71,21 @@ import ru.tech.imageresizershrinker.feature.base64_tools.presentation.screenLogi
internal fun Base64ToolsTiles(component: Base64ToolsComponent) { internal fun Base64ToolsTiles(component: Base64ToolsComponent) {
val essentials = rememberLocalEssentials() val essentials = rememberLocalEssentials()
val context = LocalContext.current val context = LocalContext.current
val clipboardManager = LocalClipboardManager.current
val pasteTile: @Composable RowScope.(shape: Shape) -> Unit = { shape -> val pasteTile: @Composable RowScope.(shape: Shape) -> Unit = { shape ->
Tile( Tile(
onClick = { onClick = {
val text = clipboardManager.getText()?.text?.trimToBase64() ?: "" essentials.getTextFromClipboard { text ->
if (text.isBase64()) { val text = text.trimToBase64()
component.setBase64(text)
} else { if (text.isBase64()) {
essentials.showToast( component.setBase64(text)
message = context.getString(R.string.not_a_valid_base_64), } else {
icon = Icons.Rounded.Base64 essentials.showToast(
) message = context.getString(R.string.not_a_valid_base_64),
icon = Icons.Rounded.Base64
)
}
} }
}, },
shape = shape, shape = shape,
@ -181,7 +182,7 @@ internal fun Base64ToolsTiles(component: Base64ToolsComponent) {
append(component.base64String) append(component.base64String)
} }
if (component.base64String.isBase64()) { if (component.base64String.isBase64()) {
clipboardManager.setText(text) essentials.copyToClipboard(text)
essentials.showToast( essentials.showToast(
message = context.getString(R.string.copied), message = context.getString(R.string.copied),
icon = Icons.Rounded.CopyAll icon = Icons.Rounded.CopyAll

View File

@ -73,11 +73,9 @@ import androidx.compose.ui.draw.drawWithContent
import androidx.compose.ui.geometry.Offset import androidx.compose.ui.geometry.Offset
import androidx.compose.ui.graphics.Color import androidx.compose.ui.graphics.Color
import androidx.compose.ui.hapticfeedback.HapticFeedbackType import androidx.compose.ui.hapticfeedback.HapticFeedbackType
import androidx.compose.ui.platform.LocalClipboardManager
import androidx.compose.ui.platform.LocalHapticFeedback import androidx.compose.ui.platform.LocalHapticFeedback
import androidx.compose.ui.platform.LocalLayoutDirection import androidx.compose.ui.platform.LocalLayoutDirection
import androidx.compose.ui.res.stringResource import androidx.compose.ui.res.stringResource
import androidx.compose.ui.text.buildAnnotatedString
import androidx.compose.ui.text.input.KeyboardType import androidx.compose.ui.text.input.KeyboardType
import androidx.compose.ui.unit.dp import androidx.compose.ui.unit.dp
import kotlinx.coroutines.launch import kotlinx.coroutines.launch
@ -297,14 +295,8 @@ fun ChecksumToolsContent(
0.5f 0.5f
) )
) )
val clipboardManager = LocalClipboardManager.current
val onCopyText: (String) -> Unit = { text -> val onCopyText: (String) -> Unit = essentials::copyToClipboard
clipboardManager.setText(
buildAnnotatedString {
append(text)
}
)
}
when (pageIndex) { when (pageIndex) {
ChecksumPage.CalculateFromUri.INDEX -> { ChecksumPage.CalculateFromUri.INDEX -> {

View File

@ -212,7 +212,7 @@ fun CollageMakerContent(
}, },
onCopy = { manager -> onCopy = { manager ->
component.cacheImage { uri -> component.cacheImage { uri ->
manager.setClip(uri.asClip(context)) manager.copyToClipboard(uri.asClip(context))
showConfetti() showConfetti()
} }
}, },

View File

@ -149,10 +149,7 @@ internal fun ColorHarmonies(
.transparencyChecker() .transparencyChecker()
.background(boxColor) .background(boxColor)
.hapticsClickable { .hapticsClickable {
context.copyToClipboard( context.copyToClipboard(getFormattedColor(color))
label = context.getString(R.string.color),
value = getFormattedColor(color)
)
scope.launch { scope.launch {
toastHostState.showToast( toastHostState.showToast(
icon = Icons.Rounded.ContentPaste, icon = Icons.Rounded.ContentPaste,

View File

@ -105,10 +105,7 @@ internal fun ColorInfo(
.transparencyChecker() .transparencyChecker()
.background(boxColor) .background(boxColor)
.hapticsClickable { .hapticsClickable {
context.copyToClipboard( context.copyToClipboard(getFormattedColor(selectedColor))
label = context.getString(R.string.color),
value = getFormattedColor(selectedColor)
)
scope.launch { scope.launch {
toastHostState.showToast( toastHostState.showToast(
icon = Icons.Rounded.ContentPaste, icon = Icons.Rounded.ContentPaste,
@ -179,10 +176,7 @@ internal fun ColorInfo(
onColorChange(it ?: selectedColor) onColorChange(it ?: selectedColor)
}, },
onCopy = { onCopy = {
context.copyToClipboard( context.copyToClipboard(it)
label = context.getString(R.string.color),
value = it
)
scope.launch { scope.launch {
toastHostState.showToast( toastHostState.showToast(
icon = Icons.Rounded.ContentPaste, icon = Icons.Rounded.ContentPaste,

View File

@ -166,10 +166,7 @@ internal fun ColorMixing(
.transparencyChecker() .transparencyChecker()
.background(boxColor) .background(boxColor)
.hapticsClickable { .hapticsClickable {
context.copyToClipboard( context.copyToClipboard(getFormattedColor(color))
label = context.getString(R.string.color),
value = getFormattedColor(color)
)
scope.launch { scope.launch {
toastHostState.showToast( toastHostState.showToast(
icon = Icons.Rounded.ContentPaste, icon = Icons.Rounded.ContentPaste,

View File

@ -168,10 +168,7 @@ internal fun ColorShading(
.transparencyChecker() .transparencyChecker()
.background(boxColor) .background(boxColor)
.hapticsClickable { .hapticsClickable {
context.copyToClipboard( context.copyToClipboard(getFormattedColor(color))
label = context.getString(R.string.color),
value = getFormattedColor(color)
)
scope.launch { scope.launch {
toastHostState.showToast( toastHostState.showToast(
icon = Icons.Rounded.ContentPaste, icon = Icons.Rounded.ContentPaste,

View File

@ -238,7 +238,7 @@ fun CompareContent(
percent = compareProgress, percent = compareProgress,
imageFormat = imageFormat imageFormat = imageFormat
) { uri -> ) { uri ->
manager.setClip(uri.asClip(context)) manager.copyToClipboard(uri.asClip(context))
showConfetti() showConfetti()
} }
}, },

View File

@ -43,12 +43,12 @@ 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.RectangleShape import androidx.compose.ui.graphics.RectangleShape
import androidx.compose.ui.platform.ClipboardManager
import androidx.compose.ui.platform.LocalClipboardManager
import androidx.compose.ui.res.stringResource import androidx.compose.ui.res.stringResource
import androidx.compose.ui.unit.dp import androidx.compose.ui.unit.dp
import ru.tech.imageresizershrinker.core.domain.image.model.ImageFormat import ru.tech.imageresizershrinker.core.domain.image.model.ImageFormat
import ru.tech.imageresizershrinker.core.resources.R import ru.tech.imageresizershrinker.core.resources.R
import ru.tech.imageresizershrinker.core.ui.utils.provider.LocalEssentials
import ru.tech.imageresizershrinker.core.ui.utils.provider.rememberLocalEssentials
import ru.tech.imageresizershrinker.core.ui.widget.controls.selection.ImageFormatSelector import ru.tech.imageresizershrinker.core.ui.widget.controls.selection.ImageFormatSelector
import ru.tech.imageresizershrinker.core.ui.widget.dialogs.OneTimeSaveLocationSelectionDialog import ru.tech.imageresizershrinker.core.ui.widget.dialogs.OneTimeSaveLocationSelectionDialog
import ru.tech.imageresizershrinker.core.ui.widget.enhanced.EnhancedButton import ru.tech.imageresizershrinker.core.ui.widget.enhanced.EnhancedButton
@ -69,10 +69,10 @@ internal fun CompareShareSheet(
onVisibleChange: (Boolean) -> Unit, onVisibleChange: (Boolean) -> Unit,
onSaveBitmap: (ImageFormat, String?) -> Unit, onSaveBitmap: (ImageFormat, String?) -> Unit,
onShare: (ImageFormat) -> Unit, onShare: (ImageFormat) -> Unit,
onCopy: (ImageFormat, ClipboardManager) -> Unit, onCopy: (ImageFormat, LocalEssentials) -> Unit,
previewBitmap: Bitmap? previewBitmap: Bitmap?
) { ) {
val clipboardManager = LocalClipboardManager.current val essentials = rememberLocalEssentials()
EnhancedModalBottomSheet( EnhancedModalBottomSheet(
sheetContent = { sheetContent = {
@ -147,7 +147,7 @@ internal fun CompareShareSheet(
.padding(horizontal = 16.dp), .padding(horizontal = 16.dp),
shape = centerShape, shape = centerShape,
onClick = { onClick = {
onCopy(imageFormat, clipboardManager) onCopy(imageFormat, essentials)
}, },
color = MaterialTheme.colorScheme.secondaryContainer, color = MaterialTheme.colorScheme.secondaryContainer,
endIcon = Icons.Rounded.ContentCopy endIcon = Icons.Rounded.ContentCopy

View File

@ -215,7 +215,7 @@ fun CropContent(
}, },
onCopy = { manager -> onCopy = { manager ->
component.cacheCurrentImage { uri -> component.cacheCurrentImage { uri ->
manager.setClip(uri.asClip(context)) manager.copyToClipboard(uri.asClip(context))
showConfetti() showConfetti()
} }
} }

View File

@ -142,7 +142,7 @@ fun DeleteExifContent(
}, },
onCopy = { manager -> onCopy = { manager ->
component.cacheCurrentImage { uri -> component.cacheCurrentImage { uri ->
manager.setClip(uri.asClip(context)) manager.copyToClipboard(uri.asClip(context))
showConfetti() showConfetti()
} }
}, },

View File

@ -243,7 +243,7 @@ fun DrawContent(
}, },
onCopy = { manager -> onCopy = { manager ->
component.cacheCurrentImage { uri -> component.cacheCurrentImage { uri ->
manager.setClip(uri.asClip(context)) manager.copyToClipboard(uri.asClip(context))
showConfetti() showConfetti()
} }
}, },

View File

@ -151,7 +151,7 @@ fun EditExifContent(
}, },
onCopy = { manager -> onCopy = { manager ->
component.cacheCurrentImage { uri -> component.cacheCurrentImage { uri ->
manager.setClip(uri.asClip(context)) manager.copyToClipboard(uri.asClip(context))
showConfetti() showConfetti()
} }
}, },

View File

@ -264,7 +264,7 @@ fun EraseBackgroundContent(
}, },
onCopy = { manager -> onCopy = { manager ->
component.cacheCurrentImage { uri -> component.cacheCurrentImage { uri ->
manager.setClip(uri.asClip(context)) manager.copyToClipboard(uri.asClip(context))
showConfetti() showConfetti()
} }
}, },

View File

@ -117,7 +117,7 @@ fun FiltersContent(
}, },
onCopy = { manager -> onCopy = { manager ->
component.cacheCurrentImage { uri -> component.cacheCurrentImage { uri ->
manager.setClip(uri.asClip(context)) manager.copyToClipboard(uri.asClip(context))
showConfetti() showConfetti()
} }
}, },

View File

@ -157,7 +157,7 @@ fun FormatConversionContent(
}, },
onCopy = { manager -> onCopy = { manager ->
component.cacheCurrentImage { uri -> component.cacheCurrentImage { uri ->
manager.setClip(uri.asClip(context)) manager.copyToClipboard(uri.asClip(context))
showConfetti() showConfetti()
} }
}, },

View File

@ -360,10 +360,7 @@ internal fun GeneratePaletteScreenControls(
}, },
maximumColorCount = count, maximumColorCount = count,
onColorChange = { onColorChange = {
context.copyToClipboard( context.copyToClipboard(it.color.toHex())
context.getString(R.string.color),
it.color.toHex()
)
scope.launch { scope.launch {
toastHostState.showToast( toastHostState.showToast(
icon = Icons.Rounded.ContentPaste, icon = Icons.Rounded.ContentPaste,

View File

@ -88,10 +88,7 @@ internal fun MaterialYouPalette(
MaterialYouPaletteGroup( MaterialYouPaletteGroup(
colorScheme = colorScheme, colorScheme = colorScheme,
onCopy = { color -> onCopy = { color ->
context.copyToClipboard( context.copyToClipboard(color.toHex())
context.getString(R.string.color),
color.toHex()
)
scope.launch { scope.launch {
toastHostState.showToast( toastHostState.showToast(
icon = Icons.Rounded.ContentPaste, icon = Icons.Rounded.ContentPaste,
@ -125,10 +122,7 @@ internal fun MaterialYouPalette(
isInvertColors = isInvertColors isInvertColors = isInvertColors
).asCodeString(true) ).asCodeString(true)
context.copyToClipboard( context.copyToClipboard(light + "\n\n" + dark)
context.getString(R.string.color_scheme),
light + "\n\n" + dark
)
scope.launch { scope.launch {
toastHostState.showToast( toastHostState.showToast(
icon = Icons.Rounded.ContentPaste, icon = Icons.Rounded.ContentPaste,

View File

@ -208,7 +208,7 @@ fun GradientMakerContent(
}, },
onCopy = { manager -> onCopy = { manager ->
component.cacheCurrentImage { uri -> component.cacheCurrentImage { uri ->
manager.setClip(uri.asClip(context)) manager.copyToClipboard(uri.asClip(context))
showConfetti() showConfetti()
} }
}, },

View File

@ -148,7 +148,7 @@ fun ImageStackingContent(
}, },
onCopy = { manager -> onCopy = { manager ->
component.cacheCurrentImage { uri -> component.cacheCurrentImage { uri ->
manager.setClip(uri.asClip(context)) manager.copyToClipboard(uri.asClip(context))
showConfetti() showConfetti()
} }
}, },

View File

@ -150,7 +150,7 @@ fun ImageStitchingContent(
}, },
onCopy = { manager -> onCopy = { manager ->
component.cacheCurrentImage { uri -> component.cacheCurrentImage { uri ->
manager.setClip(uri.asClip(context)) manager.copyToClipboard(uri.asClip(context))
showConfetti() showConfetti()
} }
}, },

View File

@ -144,7 +144,7 @@ fun LimitsResizeContent(
}, },
onCopy = { manager -> onCopy = { manager ->
component.cacheCurrentImage { uri -> component.cacheCurrentImage { uri ->
manager.setClip(uri.asClip(context)) manager.copyToClipboard(uri.asClip(context))
showConfetti() showConfetti()
} }
}, },

View File

@ -45,7 +45,7 @@ internal fun RowScope.LoadNetImageAdaptiveActions(
}, },
onCopy = { manager -> onCopy = { manager ->
component.cacheCurrentImage { uri -> component.cacheCurrentImage { uri ->
manager.setClip(uri.asClip(context)) manager.copyToClipboard(uri.asClip(context))
essentials.showConfetti() essentials.showConfetti()
} }
} }

View File

@ -82,7 +82,7 @@ internal fun MarkupLayersTopAppBarActions(
}, },
onCopy = { manager -> onCopy = { manager ->
component.cacheCurrentImage { uri -> component.cacheCurrentImage { uri ->
manager.setClip(uri.asClip(context)) manager.copyToClipboard(uri.asClip(context))
showConfetti() showConfetti()
} }
}, },

View File

@ -91,7 +91,7 @@ fun NoiseGenerationContent(
}, },
onCopy = { manager -> onCopy = { manager ->
component.cacheCurrentNoise { uri -> component.cacheCurrentNoise { uri ->
manager.setClip(uri.asClip(context)) manager.copyToClipboard(uri.asClip(context))
showConfetti() showConfetti()
} }
}, },

View File

@ -161,10 +161,7 @@ fun PickColorFromImageSheet(
) )
.clip(RoundedCornerShape(12.dp)) .clip(RoundedCornerShape(12.dp))
.hapticsClickable { .hapticsClickable {
context.copyToClipboard( context.copyToClipboard(color.toHex())
context.getString(R.string.color),
color.toHex()
)
scope.launch { scope.launch {
toastHostState.showToast( toastHostState.showToast(
icon = Icons.Rounded.ContentPaste, icon = Icons.Rounded.ContentPaste,
@ -194,10 +191,7 @@ fun PickColorFromImageSheet(
modifier = Modifier modifier = Modifier
.clip(RoundedCornerShape(8.dp)) .clip(RoundedCornerShape(8.dp))
.hapticsClickable { .hapticsClickable {
context.copyToClipboard( context.copyToClipboard(color.toHex())
context.getString(R.string.color),
color.toHex()
)
scope.launch { scope.launch {
toastHostState.showToast( toastHostState.showToast(
icon = Icons.Rounded.ContentPaste, icon = Icons.Rounded.ContentPaste,

View File

@ -169,10 +169,7 @@ internal fun PickColorFromImageTopAppBar(
.padding(horizontal = 8.dp) .padding(horizontal = 8.dp)
.clip(RoundedCornerShape(8.dp)) .clip(RoundedCornerShape(8.dp))
.hapticsClickable { .hapticsClickable {
context.copyToClipboard( context.copyToClipboard(color.toHex())
context.getString(R.string.color),
color.toHex()
)
essentials.showToast( essentials.showToast(
icon = Icons.Rounded.ContentPaste, icon = Icons.Rounded.ContentPaste,
message = context.getString(R.string.color_copied) message = context.getString(R.string.color_copied)
@ -226,10 +223,7 @@ internal fun PickColorFromImageTopAppBar(
) )
.clip(RoundedCornerShape(12.dp)) .clip(RoundedCornerShape(12.dp))
.hapticsClickable { .hapticsClickable {
context.copyToClipboard( context.copyToClipboard(color.toHex())
context.getString(R.string.color),
color.toHex()
)
essentials.showToast( essentials.showToast(
icon = Icons.Rounded.ContentPaste, icon = Icons.Rounded.ContentPaste,
message = context.getString(R.string.color_copied) message = context.getString(R.string.color_copied)
@ -264,10 +258,7 @@ internal fun PickColorFromImageTopAppBar(
.padding(horizontal = 8.dp) .padding(horizontal = 8.dp)
.clip(RoundedCornerShape(8.dp)) .clip(RoundedCornerShape(8.dp))
.hapticsClickable { .hapticsClickable {
context.copyToClipboard( context.copyToClipboard(color.toHex())
context.getString(R.string.color),
color.toHex()
)
essentials.showToast( essentials.showToast(
icon = Icons.Rounded.ContentPaste, icon = Icons.Rounded.ContentPaste,
message = context.getString(R.string.color_copied) message = context.getString(R.string.color_copied)
@ -313,10 +304,7 @@ internal fun PickColorFromImageTopAppBar(
) )
.clip(RoundedCornerShape(12.dp)) .clip(RoundedCornerShape(12.dp))
.hapticsClickable { .hapticsClickable {
context.copyToClipboard( context.copyToClipboard(color.toHex())
context.getString(R.string.color),
color.toHex()
)
essentials.showToast( essentials.showToast(
icon = Icons.Rounded.ContentPaste, icon = Icons.Rounded.ContentPaste,
message = context.getString(R.string.color_copied) message = context.getString(R.string.color_copied)

View File

@ -190,10 +190,7 @@ fun RecognizeTextContent(
val copyText: () -> Unit = { val copyText: () -> Unit = {
editedText?.let { editedText?.let {
context.copyToClipboard( context.copyToClipboard(it)
label = context.getString(R.string.recognize_text),
value = it
)
essentials.showToast( essentials.showToast(
icon = Icons.Rounded.ContentCopy, icon = Icons.Rounded.ContentCopy,
message = context.getString(R.string.copied), message = context.getString(R.string.copied),

View File

@ -177,7 +177,7 @@ fun ResizeAndConvertContent(
}, },
onCopy = { manager -> onCopy = { manager ->
component.cacheCurrentImage { uri -> component.cacheCurrentImage { uri ->
manager.setClip(uri.asClip(context)) manager.copyToClipboard(uri.asClip(context))
showConfetti() showConfetti()
} }
}, },

View File

@ -17,13 +17,11 @@
package ru.tech.imageresizershrinker.feature.root.presentation.components package ru.tech.imageresizershrinker.feature.root.presentation.components
import android.content.ClipData
import android.os.Build
import androidx.compose.runtime.Composable import androidx.compose.runtime.Composable
import androidx.compose.ui.platform.LocalClipboardManager
import ru.tech.imageresizershrinker.core.settings.presentation.provider.LocalEditPresetsController import ru.tech.imageresizershrinker.core.settings.presentation.provider.LocalEditPresetsController
import ru.tech.imageresizershrinker.core.ui.utils.helper.ReviewHandler import ru.tech.imageresizershrinker.core.ui.utils.helper.ReviewHandler
import ru.tech.imageresizershrinker.core.ui.utils.provider.LocalComponentActivity import ru.tech.imageresizershrinker.core.ui.utils.provider.LocalComponentActivity
import ru.tech.imageresizershrinker.core.ui.utils.provider.rememberLocalEssentials
import ru.tech.imageresizershrinker.core.ui.widget.UpdateSheet import ru.tech.imageresizershrinker.core.ui.widget.UpdateSheet
import ru.tech.imageresizershrinker.core.ui.widget.sheets.ProcessImagesPreferenceSheet import ru.tech.imageresizershrinker.core.ui.widget.sheets.ProcessImagesPreferenceSheet
import ru.tech.imageresizershrinker.feature.root.presentation.components.dialogs.EditPresetsSheet import ru.tech.imageresizershrinker.feature.root.presentation.components.dialogs.EditPresetsSheet
@ -45,7 +43,7 @@ internal fun RootDialogs(component: RootComponent) {
onUpdatePresets = component::setPresets onUpdatePresets = component::setPresets
) )
val clipboardManager = LocalClipboardManager.current.nativeClipboard val essentials = rememberLocalEssentials()
ProcessImagesPreferenceSheet( ProcessImagesPreferenceSheet(
uris = component.uris ?: emptyList(), uris = component.uris ?: emptyList(),
extraImageType = component.extraImageType, extraImageType = component.extraImageType,
@ -53,19 +51,7 @@ internal fun RootDialogs(component: RootComponent) {
onDismiss = component::hideSelectDialog, onDismiss = component::hideSelectDialog,
onNavigate = { screen -> onNavigate = { screen ->
component.navigateTo(screen) component.navigateTo(screen)
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.P) { essentials.clearClipboard()
runCatching {
clipboardManager.clearPrimaryClip()
}.onFailure {
clipboardManager.setPrimaryClip(
ClipData.newPlainText(null, "")
)
}
} else {
clipboardManager.setPrimaryClip(
ClipData.newPlainText(null, "")
)
}
} }
) )

View File

@ -172,7 +172,7 @@ fun ScanQrCodeContent(
scope.launch { scope.launch {
val bitmap = captureController.captureAsync().await().asAndroidBitmap() val bitmap = captureController.captureAsync().await().asAndroidBitmap()
component.cacheImage(bitmap) { uri -> component.cacheImage(bitmap) { uri ->
manager.setClip(uri.asClip(context)) manager.copyToClipboard(uri.asClip(context))
showConfetti() showConfetti()
} }
} }

View File

@ -97,10 +97,7 @@ fun DonateContainerContent(
shape = ContainerShapeDefaults.topShape, shape = ContainerShapeDefaults.topShape,
onClick = { onClick = {
context.apply { context.apply {
copyToClipboard( copyToClipboard(TONSpaceWallet)
label = getString(R.string.ton_space),
value = TONSpaceWallet
)
scope.launch { scope.launch {
toastHostState.showToast( toastHostState.showToast(
icon = Icons.Rounded.ContentCopy, icon = Icons.Rounded.ContentCopy,
@ -125,10 +122,7 @@ fun DonateContainerContent(
shape = ContainerShapeDefaults.centerShape, shape = ContainerShapeDefaults.centerShape,
onClick = { onClick = {
context.apply { context.apply {
copyToClipboard( copyToClipboard(TONWallet)
label = getString(R.string.ton),
value = TONWallet
)
scope.launch { scope.launch {
toastHostState.showToast( toastHostState.showToast(
icon = Icons.Rounded.ContentCopy, icon = Icons.Rounded.ContentCopy,
@ -153,10 +147,7 @@ fun DonateContainerContent(
shape = ContainerShapeDefaults.centerShape, shape = ContainerShapeDefaults.centerShape,
onClick = { onClick = {
context.apply { context.apply {
copyToClipboard( copyToClipboard(BitcoinWallet)
label = getString(R.string.bitcoin),
value = BitcoinWallet
)
scope.launch { scope.launch {
toastHostState.showToast( toastHostState.showToast(
icon = Icons.Rounded.ContentCopy, icon = Icons.Rounded.ContentCopy,
@ -181,10 +172,7 @@ fun DonateContainerContent(
shape = ContainerShapeDefaults.bottomShape, shape = ContainerShapeDefaults.bottomShape,
onClick = { onClick = {
context.apply { context.apply {
copyToClipboard( copyToClipboard(USDTWallet)
label = getString(R.string.usdt),
value = USDTWallet
)
scope.launch { scope.launch {
toastHostState.showToast( toastHostState.showToast(
icon = Icons.Rounded.ContentCopy, icon = Icons.Rounded.ContentCopy,

View File

@ -185,7 +185,7 @@ fun SingleEditContent(
}, },
onCopy = { manager -> onCopy = { manager ->
component.cacheCurrentImage { uri -> component.cacheCurrentImage { uri ->
manager.setClip(uri.asClip(context)) manager.copyToClipboard(uri.asClip(context))
showConfetti() showConfetti()
} }
}, },

View File

@ -154,7 +154,7 @@ fun WatermarkingContent(
}, },
onCopy = { manager -> onCopy = { manager ->
component.cacheCurrentImage { uri -> component.cacheCurrentImage { uri ->
manager.setClip(uri.asClip(context)) manager.copyToClipboard(uri.asClip(context))
showConfetti() showConfetti()
} }
}, },

View File

@ -166,7 +166,7 @@ fun WeightResizeContent(
}, },
onCopy = { manager -> onCopy = { manager ->
component.cacheCurrentImage { uri -> component.cacheCurrentImage { uri ->
manager.setClip(uri.asClip(context)) manager.copyToClipboard(uri.asClip(context))
showConfetti() showConfetti()
} }
}, },