mirror of
https://github.com/T8RIN/ImageToolbox.git
synced 2025-05-17 21:45:59 +08:00
Improve performance
This commit is contained in:
@ -29,7 +29,7 @@ import ru.tech.imageresizershrinker.core.data.image.toMetadata
|
||||
import ru.tech.imageresizershrinker.core.domain.image.Metadata
|
||||
import ru.tech.imageresizershrinker.core.domain.image.clearAllAttributes
|
||||
import ru.tech.imageresizershrinker.core.domain.image.copyTo
|
||||
import ru.tech.imageresizershrinker.core.domain.utils.readableByteCount
|
||||
import ru.tech.imageresizershrinker.core.domain.utils.humanFileSize
|
||||
import ru.tech.imageresizershrinker.core.domain.utils.runSuspendCatching
|
||||
import java.io.OutputStream
|
||||
|
||||
@ -103,7 +103,7 @@ internal fun Context.cacheSize(): String = runCatching {
|
||||
externalCacheDirs?.forEach { file ->
|
||||
size += file?.walkTopDown()?.sumOf { if (it.isFile) it.length() else 0 } ?: 0
|
||||
}
|
||||
readableByteCount(size)
|
||||
humanFileSize(size)
|
||||
}.getOrNull() ?: "0 B"
|
||||
|
||||
|
||||
|
@ -22,7 +22,7 @@ import java.text.StringCharacterIterator
|
||||
import java.util.Locale
|
||||
|
||||
|
||||
fun readableByteCount(bytes: Long): String {
|
||||
fun humanFileSize(bytes: Long): String {
|
||||
var tempBytes = bytes
|
||||
if (-1024 < tempBytes && tempBytes < 1024) {
|
||||
return "$tempBytes B"
|
||||
|
@ -37,8 +37,8 @@ import androidx.compose.ui.text.style.TextAlign
|
||||
import androidx.compose.ui.unit.dp
|
||||
import androidx.compose.ui.unit.sp
|
||||
import ru.tech.imageresizershrinker.core.domain.remote.RemoteResourcesDownloadProgress
|
||||
import ru.tech.imageresizershrinker.core.domain.utils.readableByteCount
|
||||
import ru.tech.imageresizershrinker.core.resources.R
|
||||
import ru.tech.imageresizershrinker.core.ui.utils.helper.ImageUtils.rememberHumanFileSize
|
||||
import ru.tech.imageresizershrinker.core.ui.widget.enhanced.BasicEnhancedAlertDialog
|
||||
import ru.tech.imageresizershrinker.core.ui.widget.enhanced.EnhancedAlertDialog
|
||||
import ru.tech.imageresizershrinker.core.ui.widget.enhanced.EnhancedButton
|
||||
@ -114,7 +114,7 @@ internal fun CubeLutDownloadDialog(
|
||||
)
|
||||
Spacer(Modifier.height(2.dp))
|
||||
Text(
|
||||
text = readableByteCount(cubeLutDownloadProgress?.currentTotalSize ?: 0),
|
||||
text = rememberHumanFileSize(cubeLutDownloadProgress?.currentTotalSize ?: 0),
|
||||
maxLines = 1,
|
||||
textAlign = TextAlign.Center,
|
||||
fontSize = 10.sp,
|
||||
|
@ -38,10 +38,14 @@ import androidx.annotation.StringRes
|
||||
import androidx.appcompat.app.AppCompatDelegate
|
||||
import androidx.compose.material.icons.Icons
|
||||
import androidx.compose.material.icons.rounded.ErrorOutline
|
||||
import androidx.compose.runtime.Composable
|
||||
import androidx.compose.runtime.derivedStateOf
|
||||
import androidx.compose.runtime.remember
|
||||
import androidx.compose.ui.graphics.Color
|
||||
import androidx.compose.ui.graphics.asAndroidBitmap
|
||||
import androidx.compose.ui.graphics.takeOrElse
|
||||
import androidx.compose.ui.graphics.vector.ImageVector
|
||||
import androidx.compose.ui.platform.LocalContext
|
||||
import androidx.compose.ui.unit.Density
|
||||
import androidx.core.app.ActivityCompat
|
||||
import androidx.core.app.PendingIntentCompat
|
||||
@ -180,7 +184,7 @@ object ContextUtils {
|
||||
): Boolean = validInstallers.contains(getInstallerPackageName(packageName))
|
||||
|
||||
private fun Context.getInstallerPackageName(packageName: String): String? {
|
||||
kotlin.runCatching {
|
||||
runCatching {
|
||||
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.R)
|
||||
return packageManager.getInstallSourceInfo(packageName).installingPackageName
|
||||
@Suppress("DEPRECATION")
|
||||
@ -197,6 +201,28 @@ object ContextUtils {
|
||||
DocumentFile.fromSingleUri(this, uri)?.name
|
||||
}?.decodeEscaped()
|
||||
|
||||
@Composable
|
||||
fun rememberFilename(uri: Uri): String? {
|
||||
val context = LocalContext.current
|
||||
|
||||
return remember(context, uri) {
|
||||
derivedStateOf {
|
||||
context.getFilename(uri)
|
||||
}
|
||||
}.value
|
||||
}
|
||||
|
||||
@Composable
|
||||
fun rememberFileExtension(uri: Uri): String? {
|
||||
val context = LocalContext.current
|
||||
|
||||
return remember(context, uri) {
|
||||
derivedStateOf {
|
||||
context.getExtension(uri)
|
||||
}
|
||||
}.value
|
||||
}
|
||||
|
||||
fun Activity.parseImageFromIntent(
|
||||
intent: Intent?,
|
||||
onStart: () -> Unit,
|
||||
@ -632,7 +658,7 @@ object ContextUtils {
|
||||
startActivity(shareIntent)
|
||||
}
|
||||
|
||||
private fun Context.getExtension(uri: Uri): String? {
|
||||
fun Context.getExtension(uri: Uri): String? {
|
||||
val filename = getFilename(uri) ?: ""
|
||||
if (filename.endsWith(".qoi")) return "qoi"
|
||||
if (filename.endsWith(".jxl")) return "jxl"
|
||||
|
@ -26,6 +26,7 @@ import android.os.Build.VERSION.SDK_INT
|
||||
import android.provider.OpenableColumns
|
||||
import androidx.annotation.StringRes
|
||||
import androidx.compose.runtime.Composable
|
||||
import androidx.compose.runtime.derivedStateOf
|
||||
import androidx.compose.runtime.remember
|
||||
import androidx.compose.ui.graphics.ImageBitmap
|
||||
import androidx.compose.ui.platform.LocalContext
|
||||
@ -35,6 +36,7 @@ import androidx.core.graphics.scale
|
||||
import androidx.core.text.isDigitsOnly
|
||||
import ru.tech.imageresizershrinker.core.domain.image.model.ImageInfo
|
||||
import ru.tech.imageresizershrinker.core.domain.image.model.MetadataTag
|
||||
import ru.tech.imageresizershrinker.core.domain.utils.humanFileSize
|
||||
import ru.tech.imageresizershrinker.core.resources.R
|
||||
import ru.tech.imageresizershrinker.core.ui.utils.helper.ContextUtils.getStringLocalized
|
||||
import java.util.Locale
|
||||
@ -228,7 +230,7 @@ object ImageUtils {
|
||||
it in possibleConfigs
|
||||
} ?: Bitmap.Config.ARGB_8888
|
||||
|
||||
fun Uri.fileSize(context: Context): Long? {
|
||||
private fun Uri.fileSize(context: Context): Long? {
|
||||
runCatching {
|
||||
context.contentResolver
|
||||
.query(this, null, null, null, null, null)
|
||||
@ -244,6 +246,37 @@ object ImageUtils {
|
||||
return null
|
||||
}
|
||||
|
||||
@Composable
|
||||
fun rememberFileSize(uri: Uri?): Long {
|
||||
val context = LocalContext.current
|
||||
|
||||
return remember(uri, context) {
|
||||
derivedStateOf {
|
||||
uri?.fileSize(context) ?: 0L
|
||||
}
|
||||
}.value
|
||||
}
|
||||
|
||||
@Composable
|
||||
fun rememberHumanFileSize(uri: Uri): String {
|
||||
val size = rememberFileSize(uri)
|
||||
|
||||
return remember(size, uri) {
|
||||
derivedStateOf {
|
||||
humanFileSize(size)
|
||||
}
|
||||
}.value
|
||||
}
|
||||
|
||||
@Composable
|
||||
fun rememberHumanFileSize(byteCount: Long): String {
|
||||
return remember(byteCount) {
|
||||
derivedStateOf {
|
||||
humanFileSize(byteCount)
|
||||
}
|
||||
}.value
|
||||
}
|
||||
|
||||
object Dimens {
|
||||
const val MAX_IMAGE_SIZE = 8388607 * 16
|
||||
}
|
||||
|
@ -214,3 +214,8 @@ fun Uri.isJxl(context: Context): Boolean {
|
||||
return context.getFilename(this).toString().endsWith(".jxl")
|
||||
.or(context.contentResolver.getType(this)?.contains("jxl") == true)
|
||||
}
|
||||
|
||||
fun Uri.isGif(context: Context): Boolean {
|
||||
return context.getFilename(this).toString().endsWith(".gif")
|
||||
.or(context.contentResolver.getType(this)?.contains("gif") == true)
|
||||
}
|
@ -39,7 +39,6 @@ import androidx.compose.ui.graphics.Color
|
||||
import androidx.compose.ui.graphics.Shape
|
||||
import androidx.compose.ui.graphics.compositeOver
|
||||
import androidx.compose.ui.layout.ContentScale
|
||||
import androidx.compose.ui.platform.LocalContext
|
||||
import androidx.compose.ui.res.stringResource
|
||||
import androidx.compose.ui.unit.Dp
|
||||
import androidx.compose.ui.unit.dp
|
||||
@ -50,7 +49,7 @@ import ru.tech.imageresizershrinker.core.resources.shapes.CloverShape
|
||||
import ru.tech.imageresizershrinker.core.ui.utils.content_pickers.Picker
|
||||
import ru.tech.imageresizershrinker.core.ui.utils.content_pickers.rememberFilePicker
|
||||
import ru.tech.imageresizershrinker.core.ui.utils.content_pickers.rememberImagePicker
|
||||
import ru.tech.imageresizershrinker.core.ui.utils.helper.ContextUtils.getFilename
|
||||
import ru.tech.imageresizershrinker.core.ui.utils.helper.ContextUtils.rememberFilename
|
||||
import ru.tech.imageresizershrinker.core.ui.widget.dialogs.OneTimeImagePickingDialog
|
||||
import ru.tech.imageresizershrinker.core.ui.widget.image.Picture
|
||||
import ru.tech.imageresizershrinker.core.ui.widget.preferences.PreferenceItemOverload
|
||||
@ -137,12 +136,10 @@ fun FileSelector(
|
||||
) {
|
||||
val pickFileLauncher = rememberFilePicker(onSuccess = onValueChange)
|
||||
|
||||
val context = LocalContext.current
|
||||
|
||||
PreferenceItemOverload(
|
||||
title = title,
|
||||
subtitle = if (subtitle == null && value != null) {
|
||||
context.getFilename(value.toUri())
|
||||
rememberFilename(value.toUri())
|
||||
} else subtitle,
|
||||
onClick = pickFileLauncher::pickFile,
|
||||
autoShadowElevation = autoShadowElevation,
|
||||
|
@ -65,7 +65,6 @@ import androidx.compose.material3.MaterialTheme
|
||||
import androidx.compose.material3.Text
|
||||
import androidx.compose.runtime.Composable
|
||||
import androidx.compose.runtime.LaunchedEffect
|
||||
import androidx.compose.runtime.derivedStateOf
|
||||
import androidx.compose.runtime.getValue
|
||||
import androidx.compose.runtime.mutableFloatStateOf
|
||||
import androidx.compose.runtime.mutableStateListOf
|
||||
@ -81,7 +80,6 @@ import androidx.compose.ui.graphics.RectangleShape
|
||||
import androidx.compose.ui.graphics.compositeOver
|
||||
import androidx.compose.ui.graphics.graphicsLayer
|
||||
import androidx.compose.ui.layout.ContentScale
|
||||
import androidx.compose.ui.platform.LocalContext
|
||||
import androidx.compose.ui.platform.LocalDensity
|
||||
import androidx.compose.ui.res.stringResource
|
||||
import androidx.compose.ui.unit.IntOffset
|
||||
@ -97,7 +95,7 @@ import ru.tech.imageresizershrinker.core.resources.icons.BrokenImageAlt
|
||||
import ru.tech.imageresizershrinker.core.resources.icons.EditAlt
|
||||
import ru.tech.imageresizershrinker.core.ui.theme.White
|
||||
import ru.tech.imageresizershrinker.core.ui.theme.takeColorFromScheme
|
||||
import ru.tech.imageresizershrinker.core.ui.utils.helper.ContextUtils.getFilename
|
||||
import ru.tech.imageresizershrinker.core.ui.utils.helper.ContextUtils.rememberFilename
|
||||
import ru.tech.imageresizershrinker.core.ui.utils.helper.PredictiveBackObserver
|
||||
import ru.tech.imageresizershrinker.core.ui.utils.navigation.Screen
|
||||
import ru.tech.imageresizershrinker.core.ui.utils.provider.LocalScreenSize
|
||||
@ -373,14 +371,8 @@ fun ImagePager(
|
||||
}
|
||||
)
|
||||
}
|
||||
val context = LocalContext.current
|
||||
val selectedUriFilename by remember(selectedUri) {
|
||||
derivedStateOf {
|
||||
selectedUri?.let {
|
||||
context.getFilename(it)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
val selectedUriFilename = selectedUri?.let { rememberFilename(it) }
|
||||
val showBottomHist = pagerState.currentPage !in imageErrorPages && moreThanOneUri
|
||||
|
||||
AnimatedVisibility(
|
||||
|
@ -69,7 +69,6 @@ import androidx.compose.ui.graphics.RectangleShape
|
||||
import androidx.compose.ui.graphics.compositeOver
|
||||
import androidx.compose.ui.layout.ContentScale
|
||||
import androidx.compose.ui.layout.layout
|
||||
import androidx.compose.ui.platform.LocalContext
|
||||
import androidx.compose.ui.platform.LocalDensity
|
||||
import androidx.compose.ui.platform.LocalHapticFeedback
|
||||
import androidx.compose.ui.text.font.FontWeight
|
||||
@ -83,7 +82,7 @@ import ru.tech.imageresizershrinker.core.domain.image.model.ImageFrames
|
||||
import ru.tech.imageresizershrinker.core.resources.icons.BrokenImageAlt
|
||||
import ru.tech.imageresizershrinker.core.ui.theme.White
|
||||
import ru.tech.imageresizershrinker.core.ui.theme.takeColorFromScheme
|
||||
import ru.tech.imageresizershrinker.core.ui.utils.helper.ContextUtils.getFilename
|
||||
import ru.tech.imageresizershrinker.core.ui.utils.helper.ContextUtils.rememberFileExtension
|
||||
import ru.tech.imageresizershrinker.core.ui.utils.provider.LocalScreenSize
|
||||
import ru.tech.imageresizershrinker.core.ui.widget.modifier.advancedShadow
|
||||
import ru.tech.imageresizershrinker.core.ui.widget.modifier.dragHandler
|
||||
@ -412,14 +411,7 @@ private fun ImageItem(
|
||||
aboveImageContent(index)
|
||||
|
||||
if (showExtension) {
|
||||
val context = LocalContext.current
|
||||
val extension by remember(uri) {
|
||||
derivedStateOf {
|
||||
uri.toUri().let { uri ->
|
||||
context.getFilename(uri)?.takeLastWhile { it != '.' }?.uppercase()
|
||||
}
|
||||
}
|
||||
}
|
||||
val extension = rememberFileExtension(uri.toUri())?.uppercase()
|
||||
|
||||
extension?.let {
|
||||
Row(
|
||||
|
@ -41,7 +41,6 @@ import androidx.compose.material3.LocalTextStyle
|
||||
import androidx.compose.material3.MaterialTheme
|
||||
import androidx.compose.material3.Text
|
||||
import androidx.compose.runtime.Composable
|
||||
import androidx.compose.runtime.derivedStateOf
|
||||
import androidx.compose.runtime.getValue
|
||||
import androidx.compose.runtime.mutableStateOf
|
||||
import androidx.compose.runtime.remember
|
||||
@ -50,7 +49,6 @@ import androidx.compose.ui.Alignment
|
||||
import androidx.compose.ui.Modifier
|
||||
import androidx.compose.ui.draw.clip
|
||||
import androidx.compose.ui.graphics.Color
|
||||
import androidx.compose.ui.platform.LocalContext
|
||||
import androidx.compose.ui.res.stringResource
|
||||
import androidx.compose.ui.text.font.FontWeight
|
||||
import androidx.compose.ui.text.style.TextAlign
|
||||
@ -59,7 +57,7 @@ import androidx.compose.ui.unit.dp
|
||||
import androidx.compose.ui.unit.sp
|
||||
import ru.tech.imageresizershrinker.core.resources.R
|
||||
import ru.tech.imageresizershrinker.core.ui.theme.takeColorFromScheme
|
||||
import ru.tech.imageresizershrinker.core.ui.utils.helper.ContextUtils.getFilename
|
||||
import ru.tech.imageresizershrinker.core.ui.utils.helper.ContextUtils.rememberFilename
|
||||
import ru.tech.imageresizershrinker.core.ui.widget.enhanced.hapticsClickable
|
||||
import ru.tech.imageresizershrinker.core.ui.widget.modifier.container
|
||||
import ru.tech.imageresizershrinker.core.ui.widget.text.AutoSizeText
|
||||
@ -94,8 +92,6 @@ fun UrisPreview(
|
||||
showScrimForNonSuccess: Boolean = true,
|
||||
filenameSource: (index: Int) -> Uri = { uris[it] }
|
||||
) {
|
||||
val context = LocalContext.current
|
||||
|
||||
BoxWithConstraints {
|
||||
val size = uris.size + 1f
|
||||
|
||||
@ -192,11 +188,8 @@ fun UrisPreview(
|
||||
),
|
||||
)
|
||||
}
|
||||
val filename by remember(filenameSource, index) {
|
||||
derivedStateOf {
|
||||
context.getFilename(filenameSource(index))
|
||||
}
|
||||
}
|
||||
val filename = rememberFilename(filenameSource(index))
|
||||
|
||||
filename?.let {
|
||||
AutoSizeText(
|
||||
text = it,
|
||||
|
@ -24,15 +24,18 @@ import androidx.compose.animation.togetherWith
|
||||
import androidx.compose.material3.LocalTextStyle
|
||||
import androidx.compose.material3.Text
|
||||
import androidx.compose.runtime.Composable
|
||||
import androidx.compose.runtime.derivedStateOf
|
||||
import androidx.compose.runtime.getValue
|
||||
import androidx.compose.runtime.remember
|
||||
import androidx.compose.ui.Modifier
|
||||
import androidx.compose.ui.res.stringResource
|
||||
import androidx.compose.ui.text.buildAnnotatedString
|
||||
import androidx.compose.ui.text.withStyle
|
||||
import ru.tech.imageresizershrinker.core.domain.utils.readableByteCount
|
||||
import ru.tech.imageresizershrinker.core.resources.R
|
||||
import ru.tech.imageresizershrinker.core.ui.theme.Green
|
||||
import ru.tech.imageresizershrinker.core.ui.theme.blend
|
||||
import ru.tech.imageresizershrinker.core.ui.theme.takeColorFromScheme
|
||||
import ru.tech.imageresizershrinker.core.ui.utils.helper.ImageUtils.rememberHumanFileSize
|
||||
|
||||
@Composable
|
||||
fun <T : Any> TopAppBarTitle(
|
||||
@ -64,12 +67,12 @@ fun <T : Any> TopAppBarTitle(
|
||||
} else {
|
||||
AnimatedContent(originalSize) { originalSize ->
|
||||
val readableOriginal = if ((originalSize ?: 0) > 0) {
|
||||
readableByteCount(originalSize ?: 0)
|
||||
rememberHumanFileSize(originalSize ?: 0)
|
||||
} else {
|
||||
"? B"
|
||||
}
|
||||
val readableCompressed = if (size > 0) {
|
||||
readableByteCount(size)
|
||||
rememberHumanFileSize(size)
|
||||
} else {
|
||||
"(...)"
|
||||
}
|
||||
@ -83,21 +86,36 @@ fun <T : Any> TopAppBarTitle(
|
||||
else -> Green
|
||||
}
|
||||
}
|
||||
Text(
|
||||
text = buildAnnotatedString {
|
||||
|
||||
val textStyle = LocalTextStyle.current
|
||||
val sizeString = stringResource(R.string.size, readableCompressed)
|
||||
|
||||
val text by remember(
|
||||
originalSize,
|
||||
isSizesEqual,
|
||||
sizeString,
|
||||
readableOriginal,
|
||||
readableCompressed,
|
||||
textStyle
|
||||
) {
|
||||
derivedStateOf {
|
||||
buildAnnotatedString {
|
||||
append(
|
||||
if (originalSize == null || isSizesEqual) {
|
||||
stringResource(R.string.size, readableCompressed)
|
||||
} else ""
|
||||
if (originalSize == null || isSizesEqual) sizeString else ""
|
||||
)
|
||||
originalSize?.takeIf { !isSizesEqual }?.let {
|
||||
append(readableOriginal)
|
||||
append(" -> ")
|
||||
withStyle(LocalTextStyle.current.toSpanStyle().copy(color)) {
|
||||
withStyle(textStyle.toSpanStyle().copy(color)) {
|
||||
append(readableCompressed)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Text(
|
||||
text = text
|
||||
)
|
||||
}
|
||||
}
|
||||
@ -117,8 +135,8 @@ fun <T : Any> TopAppBarTitle(
|
||||
Text(it)
|
||||
}
|
||||
} else {
|
||||
val readableOriginal = readableByteCount(originalSize ?: 0)
|
||||
val readableCompressed = readableByteCount(size)
|
||||
val readableOriginal = rememberHumanFileSize(originalSize ?: 0)
|
||||
val readableCompressed = rememberHumanFileSize(size)
|
||||
val isSizesEqual =
|
||||
size == originalSize || readableCompressed == readableOriginal
|
||||
val color = takeColorFromScheme {
|
||||
@ -128,21 +146,36 @@ fun <T : Any> TopAppBarTitle(
|
||||
else -> Green
|
||||
}
|
||||
}
|
||||
Text(
|
||||
text = buildAnnotatedString {
|
||||
|
||||
val textStyle = LocalTextStyle.current
|
||||
val sizeString = stringResource(R.string.size, readableCompressed)
|
||||
|
||||
val text by remember(
|
||||
originalSize,
|
||||
isSizesEqual,
|
||||
sizeString,
|
||||
readableOriginal,
|
||||
readableCompressed,
|
||||
textStyle
|
||||
) {
|
||||
derivedStateOf {
|
||||
buildAnnotatedString {
|
||||
append(
|
||||
if (originalSize == null || isSizesEqual) {
|
||||
stringResource(R.string.size, readableCompressed)
|
||||
} else ""
|
||||
if (originalSize == null || isSizesEqual) sizeString else ""
|
||||
)
|
||||
originalSize?.takeIf { !isSizesEqual }?.let {
|
||||
append(readableOriginal)
|
||||
append(" -> ")
|
||||
withStyle(LocalTextStyle.current.toSpanStyle().copy(color)) {
|
||||
withStyle(textStyle.toSpanStyle().copy(color)) {
|
||||
append(readableCompressed)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Text(
|
||||
text = text
|
||||
)
|
||||
}
|
||||
}
|
||||
|
@ -17,22 +17,17 @@
|
||||
|
||||
package ru.tech.imageresizershrinker.core.ui.widget.utils
|
||||
|
||||
import android.content.ContentResolver
|
||||
import android.content.Context
|
||||
import android.net.Uri
|
||||
import android.webkit.MimeTypeMap
|
||||
import androidx.compose.runtime.Composable
|
||||
import androidx.compose.runtime.State
|
||||
import androidx.compose.runtime.derivedStateOf
|
||||
import androidx.compose.runtime.getValue
|
||||
import androidx.compose.runtime.remember
|
||||
import androidx.compose.ui.platform.LocalContext
|
||||
import androidx.core.net.toUri
|
||||
import ru.tech.imageresizershrinker.core.domain.model.ExtraDataType
|
||||
import ru.tech.imageresizershrinker.core.settings.presentation.provider.LocalSettingsState
|
||||
import ru.tech.imageresizershrinker.core.ui.utils.helper.ContextUtils.getFilename
|
||||
import ru.tech.imageresizershrinker.core.ui.utils.helper.ContextUtils.getExtension
|
||||
import ru.tech.imageresizershrinker.core.ui.utils.navigation.Screen
|
||||
import java.util.Locale
|
||||
|
||||
@Composable
|
||||
internal fun List<Uri>.screenList(
|
||||
@ -46,7 +41,7 @@ internal fun List<Uri>.screenList(
|
||||
): Boolean {
|
||||
if (this == null) return false
|
||||
|
||||
val extension = context.getExtension(toString()) ?: return false
|
||||
val extension = context.getExtension(this) ?: return false
|
||||
|
||||
return extensions.any(extension::contains)
|
||||
}
|
||||
@ -307,19 +302,3 @@ internal fun List<Uri>.screenList(
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private fun Context.getExtension(
|
||||
uri: String
|
||||
): String? {
|
||||
val filename = getFilename(uri.toUri()) ?: ""
|
||||
if (filename.endsWith(".qoi")) return "qoi"
|
||||
if (filename.endsWith(".jxl")) return "jxl"
|
||||
return if (ContentResolver.SCHEME_CONTENT == uri.toUri().scheme) {
|
||||
MimeTypeMap.getSingleton()
|
||||
.getExtensionFromMimeType(
|
||||
contentResolver.getType(uri.toUri())
|
||||
)
|
||||
} else {
|
||||
MimeTypeMap.getFileExtensionFromUrl(uri).lowercase(Locale.getDefault())
|
||||
}?.replace(".", "")
|
||||
}
|
@ -28,17 +28,15 @@ import androidx.compose.material.icons.outlined.FilePresent
|
||||
import androidx.compose.material3.Icon
|
||||
import androidx.compose.material3.MaterialTheme
|
||||
import androidx.compose.runtime.Composable
|
||||
import androidx.compose.runtime.remember
|
||||
import androidx.compose.ui.Alignment
|
||||
import androidx.compose.ui.Modifier
|
||||
import androidx.compose.ui.draw.clip
|
||||
import androidx.compose.ui.platform.LocalContext
|
||||
import androidx.compose.ui.res.stringResource
|
||||
import androidx.compose.ui.unit.dp
|
||||
import ru.tech.imageresizershrinker.core.data.utils.fileSize
|
||||
import ru.tech.imageresizershrinker.core.domain.utils.readableByteCount
|
||||
import ru.tech.imageresizershrinker.core.resources.R
|
||||
import ru.tech.imageresizershrinker.core.resources.shapes.CloverShape
|
||||
import ru.tech.imageresizershrinker.core.ui.utils.helper.ContextUtils.getFilename
|
||||
import ru.tech.imageresizershrinker.core.ui.utils.helper.ContextUtils.rememberFilename
|
||||
import ru.tech.imageresizershrinker.core.ui.utils.helper.ImageUtils.rememberHumanFileSize
|
||||
import ru.tech.imageresizershrinker.core.ui.widget.preferences.PreferenceItemOverload
|
||||
|
||||
@Composable
|
||||
@ -48,15 +46,9 @@ internal fun UriWithHashItem(
|
||||
) {
|
||||
val (uri, checksum) = uriWithHash
|
||||
|
||||
val context = LocalContext.current
|
||||
val filename = rememberFilename(uri) ?: stringResource(R.string.filename)
|
||||
|
||||
val filename = remember {
|
||||
context.getFilename(uri)
|
||||
?: context.getString(R.string.filename)
|
||||
}
|
||||
val fileSize = remember {
|
||||
readableByteCount(uri.fileSize(context) ?: 0L)
|
||||
}
|
||||
val fileSize = rememberHumanFileSize(uri)
|
||||
|
||||
Column(
|
||||
modifier = Modifier.fillMaxWidth(),
|
||||
|
@ -53,22 +53,20 @@ import androidx.compose.runtime.setValue
|
||||
import androidx.compose.ui.Alignment
|
||||
import androidx.compose.ui.Modifier
|
||||
import androidx.compose.ui.graphics.Color
|
||||
import androidx.compose.ui.platform.LocalContext
|
||||
import androidx.compose.ui.res.stringResource
|
||||
import androidx.compose.ui.text.font.FontWeight
|
||||
import androidx.compose.ui.text.input.ImeAction
|
||||
import androidx.compose.ui.unit.dp
|
||||
import androidx.compose.ui.unit.sp
|
||||
import ru.tech.imageresizershrinker.core.domain.model.CipherType
|
||||
import ru.tech.imageresizershrinker.core.domain.utils.readableByteCount
|
||||
import ru.tech.imageresizershrinker.core.domain.utils.toInt
|
||||
import ru.tech.imageresizershrinker.core.resources.R
|
||||
import ru.tech.imageresizershrinker.core.settings.presentation.provider.LocalSettingsState
|
||||
import ru.tech.imageresizershrinker.core.ui.theme.Green
|
||||
import ru.tech.imageresizershrinker.core.ui.theme.outlineVariant
|
||||
import ru.tech.imageresizershrinker.core.ui.utils.content_pickers.rememberFileCreator
|
||||
import ru.tech.imageresizershrinker.core.ui.utils.helper.ContextUtils.getFilename
|
||||
import ru.tech.imageresizershrinker.core.ui.utils.helper.ImageUtils.fileSize
|
||||
import ru.tech.imageresizershrinker.core.ui.utils.helper.ContextUtils.rememberFilename
|
||||
import ru.tech.imageresizershrinker.core.ui.utils.helper.ImageUtils.rememberHumanFileSize
|
||||
import ru.tech.imageresizershrinker.core.ui.utils.helper.isPortraitOrientationAsState
|
||||
import ru.tech.imageresizershrinker.core.ui.utils.provider.rememberLocalEssentials
|
||||
import ru.tech.imageresizershrinker.core.ui.widget.buttons.ToggleGroupButton
|
||||
@ -86,7 +84,6 @@ import kotlin.random.Random
|
||||
internal fun CipherControls(component: CipherComponent) {
|
||||
val settingsState = LocalSettingsState.current
|
||||
val isPortrait by isPortraitOrientationAsState()
|
||||
val context = LocalContext.current
|
||||
val essentials = rememberLocalEssentials()
|
||||
val showConfetti: () -> Unit = essentials::showConfetti
|
||||
|
||||
@ -99,6 +96,10 @@ internal fun CipherControls(component: CipherComponent) {
|
||||
}
|
||||
)
|
||||
|
||||
val filename = component.uri?.let {
|
||||
rememberFilename(it)
|
||||
}
|
||||
|
||||
Column(horizontalAlignment = Alignment.CenterHorizontally) {
|
||||
if (isPortrait) Spacer(Modifier.height(20.dp))
|
||||
Row(
|
||||
@ -140,9 +141,7 @@ internal fun CipherControls(component: CipherComponent) {
|
||||
Spacer(Modifier.height(16.dp))
|
||||
PreferenceItem(
|
||||
modifier = Modifier,
|
||||
title = component.uri?.let {
|
||||
context.getFilename(it)
|
||||
} ?: stringResource(R.string.something_went_wrong),
|
||||
title = filename ?: stringResource(R.string.something_went_wrong),
|
||||
onClick = null,
|
||||
titleFontStyle = LocalTextStyle.current.copy(
|
||||
lineHeight = 16.sp,
|
||||
@ -151,9 +150,7 @@ internal fun CipherControls(component: CipherComponent) {
|
||||
subtitle = component.uri?.let {
|
||||
stringResource(
|
||||
id = R.string.size,
|
||||
readableByteCount(
|
||||
it.fileSize(context) ?: 0L
|
||||
)
|
||||
rememberHumanFileSize(it)
|
||||
)
|
||||
},
|
||||
startIcon = Icons.AutoMirrored.Rounded.InsertDriveFile
|
||||
@ -245,15 +242,13 @@ internal fun CipherControls(component: CipherComponent) {
|
||||
lineHeight = 14.sp,
|
||||
modifier = Modifier.padding(vertical = 16.dp)
|
||||
)
|
||||
var name by rememberSaveable(component.byteArray) {
|
||||
var name by rememberSaveable(component.byteArray, filename) {
|
||||
mutableStateOf(
|
||||
if (component.isEncrypt) {
|
||||
"enc-"
|
||||
} else {
|
||||
"dec-"
|
||||
} + (component.uri?.let {
|
||||
context.getFilename(it)
|
||||
} ?: Random.nextInt())
|
||||
} + (filename ?: Random.nextInt())
|
||||
)
|
||||
}
|
||||
RoundedTextField(
|
||||
|
@ -25,16 +25,15 @@ import androidx.compose.foundation.layout.padding
|
||||
import androidx.compose.material3.MaterialTheme
|
||||
import androidx.compose.material3.Text
|
||||
import androidx.compose.runtime.Composable
|
||||
import androidx.compose.runtime.remember
|
||||
import androidx.compose.ui.Alignment
|
||||
import androidx.compose.ui.Modifier
|
||||
import androidx.compose.ui.graphics.Color
|
||||
import androidx.compose.ui.graphics.Shape
|
||||
import androidx.compose.ui.platform.LocalContext
|
||||
import androidx.compose.ui.res.stringResource
|
||||
import androidx.compose.ui.unit.dp
|
||||
import androidx.compose.ui.unit.sp
|
||||
import ru.tech.imageresizershrinker.core.resources.R
|
||||
import ru.tech.imageresizershrinker.core.ui.utils.helper.ContextUtils.getFilename
|
||||
import ru.tech.imageresizershrinker.core.ui.utils.helper.ContextUtils.rememberFilename
|
||||
|
||||
@Composable
|
||||
internal fun BoxScope.CompareLabel(
|
||||
@ -48,12 +47,9 @@ internal fun BoxScope.CompareLabel(
|
||||
visible = enabled && uri != null,
|
||||
modifier = modifier.align(alignment)
|
||||
) {
|
||||
val context = LocalContext.current
|
||||
Text(
|
||||
text = remember(uri) {
|
||||
uri?.let { context.getFilename(it) }
|
||||
?: context.getString(R.string.filename)
|
||||
},
|
||||
text = uri?.let { rememberFilename(it) }
|
||||
?: stringResource(R.string.filename),
|
||||
modifier = Modifier
|
||||
.background(
|
||||
color = MaterialTheme.colorScheme.scrim.copy(0.4f),
|
||||
|
@ -32,7 +32,6 @@ import androidx.compose.runtime.remember
|
||||
import androidx.compose.runtime.saveable.rememberSaveable
|
||||
import androidx.compose.runtime.setValue
|
||||
import androidx.compose.ui.Modifier
|
||||
import androidx.compose.ui.platform.LocalContext
|
||||
import androidx.compose.ui.res.stringResource
|
||||
import androidx.compose.ui.unit.dp
|
||||
import ru.tech.imageresizershrinker.core.resources.R
|
||||
@ -40,8 +39,8 @@ import ru.tech.imageresizershrinker.core.resources.icons.Exif
|
||||
import ru.tech.imageresizershrinker.core.resources.icons.MiniEdit
|
||||
import ru.tech.imageresizershrinker.core.ui.utils.content_pickers.Picker
|
||||
import ru.tech.imageresizershrinker.core.ui.utils.content_pickers.rememberImagePicker
|
||||
import ru.tech.imageresizershrinker.core.ui.utils.helper.ImageUtils.fileSize
|
||||
import ru.tech.imageresizershrinker.core.ui.utils.helper.ImageUtils.localizedName
|
||||
import ru.tech.imageresizershrinker.core.ui.utils.helper.ImageUtils.rememberFileSize
|
||||
import ru.tech.imageresizershrinker.core.ui.utils.helper.asClip
|
||||
import ru.tech.imageresizershrinker.core.ui.utils.helper.isPortraitOrientationAsState
|
||||
import ru.tech.imageresizershrinker.core.ui.utils.provider.LocalComponentActivity
|
||||
@ -124,7 +123,7 @@ fun DeleteExifContent(
|
||||
title = stringResource(R.string.delete_exif),
|
||||
input = component.bitmap,
|
||||
isLoading = component.isImageLoading,
|
||||
size = component.selectedUri?.fileSize(LocalContext.current) ?: 0L
|
||||
size = rememberFileSize(component.selectedUri)
|
||||
)
|
||||
},
|
||||
onGoBack = {
|
||||
|
@ -36,7 +36,6 @@ import androidx.compose.runtime.setValue
|
||||
import androidx.compose.ui.Alignment
|
||||
import androidx.compose.ui.Modifier
|
||||
import androidx.compose.ui.layout.ContentScale
|
||||
import androidx.compose.ui.platform.LocalContext
|
||||
import androidx.compose.ui.res.stringResource
|
||||
import androidx.compose.ui.unit.dp
|
||||
import coil3.toBitmap
|
||||
@ -46,7 +45,7 @@ import ru.tech.imageresizershrinker.core.resources.icons.Exif
|
||||
import ru.tech.imageresizershrinker.core.resources.icons.MiniEdit
|
||||
import ru.tech.imageresizershrinker.core.ui.utils.content_pickers.Picker
|
||||
import ru.tech.imageresizershrinker.core.ui.utils.content_pickers.rememberImagePicker
|
||||
import ru.tech.imageresizershrinker.core.ui.utils.helper.ImageUtils.fileSize
|
||||
import ru.tech.imageresizershrinker.core.ui.utils.helper.ImageUtils.rememberFileSize
|
||||
import ru.tech.imageresizershrinker.core.ui.utils.helper.asClip
|
||||
import ru.tech.imageresizershrinker.core.ui.utils.helper.isPortraitOrientationAsState
|
||||
import ru.tech.imageresizershrinker.core.ui.utils.provider.LocalComponentActivity
|
||||
@ -126,7 +125,7 @@ fun EditExifContent(
|
||||
title = stringResource(R.string.edit_exif_screen),
|
||||
input = component.uri.takeIf { it != Uri.EMPTY },
|
||||
isLoading = component.isImageLoading,
|
||||
size = component.uri.fileSize(LocalContext.current) ?: 0L
|
||||
size = rememberFileSize(component.uri)
|
||||
)
|
||||
},
|
||||
onGoBack = onBack,
|
||||
|
@ -17,7 +17,6 @@
|
||||
|
||||
package ru.tech.imageresizershrinker.feature.gif_tools.presentation
|
||||
|
||||
import android.content.Context
|
||||
import android.net.Uri
|
||||
import androidx.compose.animation.core.animateDpAsState
|
||||
import androidx.compose.foundation.layout.WindowInsets
|
||||
@ -37,7 +36,7 @@ import ru.tech.imageresizershrinker.core.ui.utils.content_pickers.Picker
|
||||
import ru.tech.imageresizershrinker.core.ui.utils.content_pickers.rememberFileCreator
|
||||
import ru.tech.imageresizershrinker.core.ui.utils.content_pickers.rememberFilePicker
|
||||
import ru.tech.imageresizershrinker.core.ui.utils.content_pickers.rememberImagePicker
|
||||
import ru.tech.imageresizershrinker.core.ui.utils.helper.ContextUtils.getFilename
|
||||
import ru.tech.imageresizershrinker.core.ui.utils.helper.isGif
|
||||
import ru.tech.imageresizershrinker.core.ui.utils.helper.isPortraitOrientationAsState
|
||||
import ru.tech.imageresizershrinker.core.ui.utils.navigation.Screen
|
||||
import ru.tech.imageresizershrinker.core.ui.utils.provider.LocalComponentActivity
|
||||
@ -310,11 +309,6 @@ fun GifToolsContent(
|
||||
)
|
||||
}
|
||||
|
||||
private fun Uri.isGif(context: Context): Boolean {
|
||||
return context.getFilename(this).toString().endsWith(".gif")
|
||||
.or(context.contentResolver.getType(this)?.contains("gif") == true)
|
||||
}
|
||||
|
||||
private val GifToolsComponent.canSave: Boolean
|
||||
get() = (gifFrames == ImageFrames.All)
|
||||
.or(type is Screen.GifTools.Type.ImageToGif)
|
||||
|
@ -28,13 +28,12 @@ import androidx.compose.runtime.remember
|
||||
import androidx.compose.runtime.saveable.rememberSaveable
|
||||
import androidx.compose.runtime.setValue
|
||||
import androidx.compose.ui.Modifier
|
||||
import androidx.compose.ui.platform.LocalContext
|
||||
import androidx.compose.ui.res.stringResource
|
||||
import androidx.compose.ui.unit.dp
|
||||
import ru.tech.imageresizershrinker.core.resources.R
|
||||
import ru.tech.imageresizershrinker.core.ui.utils.content_pickers.Picker
|
||||
import ru.tech.imageresizershrinker.core.ui.utils.content_pickers.rememberImagePicker
|
||||
import ru.tech.imageresizershrinker.core.ui.utils.helper.ImageUtils.fileSize
|
||||
import ru.tech.imageresizershrinker.core.ui.utils.helper.ImageUtils.rememberFileSize
|
||||
import ru.tech.imageresizershrinker.core.ui.utils.helper.asClip
|
||||
import ru.tech.imageresizershrinker.core.ui.utils.helper.isPortraitOrientationAsState
|
||||
import ru.tech.imageresizershrinker.core.ui.utils.provider.LocalComponentActivity
|
||||
@ -128,7 +127,7 @@ fun LimitsResizeContent(
|
||||
title = stringResource(R.string.limits_resize),
|
||||
input = component.bitmap,
|
||||
isLoading = component.isImageLoading,
|
||||
size = component.selectedUri?.fileSize(LocalContext.current) ?: 0L
|
||||
size = rememberFileSize(component.selectedUri)
|
||||
)
|
||||
},
|
||||
onGoBack = onBack,
|
||||
|
@ -48,8 +48,8 @@ import androidx.compose.ui.text.font.FontWeight
|
||||
import androidx.compose.ui.text.style.TextAlign
|
||||
import androidx.compose.ui.unit.dp
|
||||
import androidx.compose.ui.unit.sp
|
||||
import ru.tech.imageresizershrinker.core.domain.utils.readableByteCount
|
||||
import ru.tech.imageresizershrinker.core.resources.R
|
||||
import ru.tech.imageresizershrinker.core.ui.utils.helper.ImageUtils.rememberHumanFileSize
|
||||
import ru.tech.imageresizershrinker.core.ui.utils.helper.plus
|
||||
import ru.tech.imageresizershrinker.core.ui.utils.provider.rememberLocalEssentials
|
||||
import ru.tech.imageresizershrinker.core.ui.widget.enhanced.EnhancedIconButton
|
||||
@ -159,9 +159,8 @@ fun MeshGradientsContent(
|
||||
)
|
||||
Spacer(Modifier.height(2.dp))
|
||||
Text(
|
||||
text = readableByteCount(
|
||||
meshGradientDownloadProgress?.currentTotalSize
|
||||
?: 0
|
||||
text = rememberHumanFileSize(
|
||||
meshGradientDownloadProgress?.currentTotalSize ?: 0
|
||||
),
|
||||
maxLines = 1,
|
||||
textAlign = TextAlign.Center,
|
||||
|
@ -72,7 +72,6 @@ import androidx.compose.ui.Alignment
|
||||
import androidx.compose.ui.Modifier
|
||||
import androidx.compose.ui.draw.clipToBounds
|
||||
import androidx.compose.ui.graphics.RectangleShape
|
||||
import androidx.compose.ui.platform.LocalContext
|
||||
import androidx.compose.ui.platform.LocalLayoutDirection
|
||||
import androidx.compose.ui.res.stringResource
|
||||
import androidx.compose.ui.text.font.FontWeight
|
||||
@ -81,7 +80,7 @@ import androidx.compose.ui.unit.dp
|
||||
import androidx.compose.ui.unit.sp
|
||||
import ru.tech.imageresizershrinker.core.resources.R
|
||||
import ru.tech.imageresizershrinker.core.ui.utils.animation.fancySlideTransition
|
||||
import ru.tech.imageresizershrinker.core.ui.utils.helper.ContextUtils.getFilename
|
||||
import ru.tech.imageresizershrinker.core.ui.utils.helper.ContextUtils.rememberFilename
|
||||
import ru.tech.imageresizershrinker.core.ui.utils.navigation.Screen
|
||||
import ru.tech.imageresizershrinker.core.ui.utils.provider.LocalScreenSize
|
||||
import ru.tech.imageresizershrinker.core.ui.widget.enhanced.EnhancedFloatingActionButton
|
||||
@ -112,8 +111,6 @@ internal fun PdfToolsContentImpl(
|
||||
val selectAllToggle = remember { mutableStateOf(false) }
|
||||
val deselectAllToggle = remember { mutableStateOf(false) }
|
||||
|
||||
val context = LocalContext.current
|
||||
|
||||
Column(Modifier.fillMaxSize()) {
|
||||
EnhancedTopAppBar(
|
||||
type = EnhancedTopAppBarType.Large,
|
||||
@ -126,7 +123,7 @@ internal fun PdfToolsContentImpl(
|
||||
) { (pdfType, previewUri) ->
|
||||
Text(
|
||||
text = previewUri?.let {
|
||||
context.getFilename(it)
|
||||
rememberFilename(it)
|
||||
} ?: stringResource(pdfType?.title ?: R.string.pdf_tools),
|
||||
textAlign = TextAlign.Center
|
||||
)
|
||||
|
@ -26,7 +26,7 @@ import androidx.compose.runtime.mutableStateOf
|
||||
import androidx.compose.runtime.saveable.rememberSaveable
|
||||
import androidx.compose.runtime.setValue
|
||||
import androidx.compose.ui.platform.LocalContext
|
||||
import ru.tech.imageresizershrinker.core.domain.utils.readableByteCount
|
||||
import ru.tech.imageresizershrinker.core.domain.utils.humanFileSize
|
||||
import ru.tech.imageresizershrinker.core.resources.R
|
||||
import ru.tech.imageresizershrinker.core.ui.utils.provider.rememberLocalEssentials
|
||||
import ru.tech.imageresizershrinker.core.ui.widget.other.ToastDuration
|
||||
@ -63,7 +63,7 @@ internal fun RecognizeTextDownloadDataDialog(component: RecognizeTextComponent)
|
||||
?: RecognitionType.Standard,
|
||||
languageCode = downloadDialogData.joinToString(separator = "+") { it.languageCode },
|
||||
onProgress = { p, size ->
|
||||
dataRemaining = readableByteCount(size)
|
||||
dataRemaining = humanFileSize(size)
|
||||
progress = p
|
||||
},
|
||||
onComplete = {
|
||||
|
@ -26,6 +26,7 @@ import androidx.compose.runtime.Composable
|
||||
import androidx.compose.runtime.LaunchedEffect
|
||||
import androidx.compose.runtime.getValue
|
||||
import androidx.compose.runtime.mutableIntStateOf
|
||||
import androidx.compose.runtime.remember
|
||||
import androidx.compose.runtime.saveable.rememberSaveable
|
||||
import androidx.compose.runtime.setValue
|
||||
import androidx.compose.ui.graphics.Color
|
||||
@ -153,7 +154,9 @@ internal fun SettingItem(
|
||||
|
||||
Setting.ClearCache -> {
|
||||
ClearCacheSettingItem(
|
||||
value = component.getReadableCacheSize(),
|
||||
value = remember {
|
||||
component.getReadableCacheSize()
|
||||
},
|
||||
onClearCache = component::clearCache
|
||||
)
|
||||
}
|
||||
|
Reference in New Issue
Block a user