From 27f22a8b345a5a0e6b4b7e90dccbd8bc8103fdcc Mon Sep 17 00:00:00 2001 From: T8RIN Date: Sun, 31 Dec 2023 18:19:01 +0300 Subject: [PATCH] OverwriteFiles setting introduced by #578 --- .../imageresizershrinker/data/keys/Keys.kt | 1 + .../data/repository/SettingsRepositoryImpl.kt | 15 +- .../data/saving/FileControllerImpl.kt | 176 +++++++++++------- .../domain/model/SettingsState.kt | 6 +- .../domain/repository/SettingsRepository.kt | 2 + .../domain/saving/model/FileParams.kt | 3 +- .../ToggleOverwriteFilesUseCase.kt | 10 + .../settings/OverwriteFilesSettingItem.kt | 45 +++++ .../components/settings/Setting.kt | 5 + .../components/settings/SettingItem.kt | 6 + .../components/settings/SettingsGroup.kt | 1 + .../main_screen/viewModel/MainViewModel.kt | 10 +- .../root/model/UiSettingsState.kt | 6 +- .../root/widget/other/ToastHost.kt | 5 +- app/src/main/res/values/strings.xml | 3 + 15 files changed, 219 insertions(+), 75 deletions(-) create mode 100644 app/src/main/java/ru/tech/imageresizershrinker/domain/use_case/edit_settings/ToggleOverwriteFilesUseCase.kt create mode 100644 app/src/main/java/ru/tech/imageresizershrinker/presentation/main_screen/components/settings/OverwriteFilesSettingItem.kt diff --git a/app/src/main/java/ru/tech/imageresizershrinker/data/keys/Keys.kt b/app/src/main/java/ru/tech/imageresizershrinker/data/keys/Keys.kt index 485763701..32571a0e5 100644 --- a/app/src/main/java/ru/tech/imageresizershrinker/data/keys/Keys.kt +++ b/app/src/main/java/ru/tech/imageresizershrinker/data/keys/Keys.kt @@ -48,4 +48,5 @@ object Keys { val DRAW_APPBAR_SHADOWS = booleanPreferencesKey("DRAW_APPBAR_SHADOWS") val COPY_TO_CLIPBOARD = booleanPreferencesKey("COPY_TO_CLIPBOARD") val VIBRATION_STRENGTH = intPreferencesKey("VIBRATION_STRENGTH") + val OVERWRITE_FILE = booleanPreferencesKey("OVERWRITE_FILE") } \ No newline at end of file diff --git a/app/src/main/java/ru/tech/imageresizershrinker/data/repository/SettingsRepositoryImpl.kt b/app/src/main/java/ru/tech/imageresizershrinker/data/repository/SettingsRepositoryImpl.kt index ab5f33020..42d57f5a4 100644 --- a/app/src/main/java/ru/tech/imageresizershrinker/data/repository/SettingsRepositoryImpl.kt +++ b/app/src/main/java/ru/tech/imageresizershrinker/data/repository/SettingsRepositoryImpl.kt @@ -44,6 +44,7 @@ import ru.tech.imageresizershrinker.data.keys.Keys.IMAGE_PICKER_MODE import ru.tech.imageresizershrinker.data.keys.Keys.INVERT_THEME import ru.tech.imageresizershrinker.data.keys.Keys.LOCK_DRAW_ORIENTATION import ru.tech.imageresizershrinker.data.keys.Keys.NIGHT_MODE +import ru.tech.imageresizershrinker.data.keys.Keys.OVERWRITE_FILE import ru.tech.imageresizershrinker.data.keys.Keys.PRESETS import ru.tech.imageresizershrinker.data.keys.Keys.RANDOMIZE_FILENAME import ru.tech.imageresizershrinker.data.keys.Keys.SAVE_FOLDER_URI @@ -131,7 +132,8 @@ class SettingsRepositoryImpl @Inject constructor( isInvertThemeColors = prefs[INVERT_THEME] ?: default.isInvertThemeColors, screensSearchEnabled = prefs[SCREEN_SEARCH_ENABLED] ?: default.screensSearchEnabled, autoCopyToClipBoard = prefs[COPY_TO_CLIPBOARD] ?: default.autoCopyToClipBoard, - hapticsStrength = prefs[VIBRATION_STRENGTH] ?: default.hapticsStrength + hapticsStrength = prefs[VIBRATION_STRENGTH] ?: default.hapticsStrength, + overwriteFiles = prefs[OVERWRITE_FILE] ?: default.overwriteFiles ) } @@ -456,7 +458,7 @@ class SettingsRepositoryImpl @Inject constructor( override suspend fun toggleAutoPinClipboard() { dataStore.edit { - val v = it[COPY_TO_CLIPBOARD] ?: true + val v = it[COPY_TO_CLIPBOARD] ?: false it[COPY_TO_CLIPBOARD] = !v } } @@ -467,6 +469,15 @@ class SettingsRepositoryImpl @Inject constructor( } } + override suspend fun toggleOverwriteFiles() { + dataStore.edit { + val v = it[OVERWRITE_FILE] ?: false + it[OVERWRITE_FILE] = !v + + it[IMAGE_PICKER_MODE] = 2 + } + } + private fun InputStream.toByteArray(): ByteArray { val bytes = ByteArray(this.available()) val dis = DataInputStream(this) diff --git a/app/src/main/java/ru/tech/imageresizershrinker/data/saving/FileControllerImpl.kt b/app/src/main/java/ru/tech/imageresizershrinker/data/saving/FileControllerImpl.kt index 751c0350d..04a701992 100644 --- a/app/src/main/java/ru/tech/imageresizershrinker/data/saving/FileControllerImpl.kt +++ b/app/src/main/java/ru/tech/imageresizershrinker/data/saving/FileControllerImpl.kt @@ -31,6 +31,8 @@ import ru.tech.imageresizershrinker.data.keys.Keys.ADD_SEQ_NUM_TO_FILENAME import ru.tech.imageresizershrinker.data.keys.Keys.ADD_SIZE_TO_FILENAME import ru.tech.imageresizershrinker.data.keys.Keys.COPY_TO_CLIPBOARD import ru.tech.imageresizershrinker.data.keys.Keys.FILENAME_PREFIX +import ru.tech.imageresizershrinker.data.keys.Keys.IMAGE_PICKER_MODE +import ru.tech.imageresizershrinker.data.keys.Keys.OVERWRITE_FILE import ru.tech.imageresizershrinker.data.keys.Keys.RANDOMIZE_FILENAME import ru.tech.imageresizershrinker.data.keys.Keys.SAVE_FOLDER_URI import ru.tech.imageresizershrinker.domain.image.Metadata @@ -63,7 +65,8 @@ class FileControllerImpl @Inject constructor( addOriginalFilename = false, addSequenceNumber = false, randomizeFilename = false, - copyToClipBoard = false + copyToClipBoard = false, + overwriteFile = false ) init { @@ -77,6 +80,7 @@ class FileControllerImpl @Inject constructor( addSequenceNumber = preferences[ADD_SEQ_NUM_TO_FILENAME] ?: true, randomizeFilename = preferences[RANDOMIZE_FILENAME] ?: false, copyToClipBoard = preferences[COPY_TO_CLIPBOARD] ?: false, + overwriteFile = preferences[OVERWRITE_FILE] ?: false ) } } @@ -139,49 +143,15 @@ class FileControllerImpl @Inject constructor( return SaveResult.Error.MissingPermissions } - fileParams.treeUri.takeIf { - it != null - }?.let { treeUri -> - val hasDir: Boolean = treeUri.toUri().let { - DocumentFile.fromTreeUri(context, it) - }?.exists() == true - - if (!hasDir) { - dataStore.edit { - it[SAVE_FOLDER_URI] = "" - } - return SaveResult.Error.Exception( - Exception( - context.getString( - R.string.no_such_directory, - treeUri.toUri().toUiPath(context, defaultPrefix()) - ) - ) - ) - } - } - var filename = "" kotlin.runCatching { - var initialExif: ExifInterface? = null - - val newSaveTarget = if (saveTarget is ImageSaveTarget<*>) { - initialExif = saveTarget.metadata as ExifInterface? - - saveTarget.copy( - filename = constructImageFilename(saveTarget) + if (fileParams.copyToClipBoard) { + val clipboardManager = ContextCompat.getSystemService( + context, + ClipboardManager::class.java ) - } else saveTarget - filename = newSaveTarget.filename ?: "" - - val clipboardManager = ContextCompat.getSystemService( - context, - ClipboardManager::class.java - ) - - if (fileParams.copyToClipBoard) { cacheImage(saveTarget)?.toUri()?.let { uri -> clipboardManager?.setPrimaryClip( ClipData.newUri( @@ -193,35 +163,85 @@ class FileControllerImpl @Inject constructor( } } + if (fileParams.overwriteFile) { + val originalUri = saveTarget.originalUri.toUri() + runCatching { + context.contentResolver.openFileDescriptor(originalUri, "w") + }.onFailure { + dataStore.edit { + it[IMAGE_PICKER_MODE] = 2 + } + return SaveResult.Error.Exception( + Exception( + context.getString( + R.string.overwrite_file_requirements + ) + ) + ) + }.getOrNull()?.use { parcel -> + filename = DocumentFile.fromSingleUri(context, originalUri)?.name.toString() + FileOutputStream(parcel.fileDescriptor).use { out -> + out.write(saveTarget.data) + copyMetadata( + initialExif = (saveTarget as? ImageSaveTarget<*>)?.metadata as ExifInterface?, + fileUri = originalUri, + keepMetadata = keepMetadata, + originalUri = originalUri + ) + } + } + } else { + fileParams.treeUri.takeIf { + it != null + }?.let { treeUri -> + val hasDir: Boolean = treeUri.toUri().let { + DocumentFile.fromTreeUri(context, it) + }?.exists() == true + + if (!hasDir) { + dataStore.edit { + it[SAVE_FOLDER_URI] = "" + } + return SaveResult.Error.Exception( + Exception( + context.getString( + R.string.no_such_directory, + treeUri.toUri().toUiPath(context, defaultPrefix()) + ) + ) + ) + } + } + + var initialExif: ExifInterface? = null - val savingFolder = context.getSavingFolder( - treeUri = fileParams.treeUri?.takeIf { it.isNotEmpty() }?.toUri(), - saveTarget = newSaveTarget - ) + val newSaveTarget = if (saveTarget is ImageSaveTarget<*>) { + initialExif = saveTarget.metadata as ExifInterface? - savingFolder.outputStream?.use { - it.write(saveTarget.data) - } + saveTarget.copy( + filename = constructImageFilename(saveTarget) + ) + } else saveTarget - kotlin.runCatching { - if (initialExif != null) { - getFileDescriptorFor(savingFolder.fileUri)?.use { - val ex = ExifInterface(it.fileDescriptor) - initialExif.copyTo(ex) - ex.saveAttributes() - } - } else if (keepMetadata) { - val exif = context - .contentResolver - .openFileDescriptor(saveTarget.originalUri.toUri(), "r") - ?.use { ExifInterface(it.fileDescriptor) } - - getFileDescriptorFor(savingFolder.fileUri)?.use { - val ex = ExifInterface(it.fileDescriptor) - exif?.copyTo(ex) - ex.saveAttributes() - } - } else Unit + filename = newSaveTarget.filename ?: "" + + val savingFolder = context.getSavingFolder( + treeUri = fileParams.treeUri?.takeIf { it.isNotEmpty() }?.toUri(), + saveTarget = newSaveTarget + ) + + savingFolder.outputStream?.use { + it.write(saveTarget.data) + } + + kotlin.runCatching { + copyMetadata( + initialExif = initialExif, + fileUri = savingFolder.fileUri, + keepMetadata = keepMetadata, + originalUri = saveTarget.originalUri.toUri() + ) + } } }.let { result -> if (result.isFailure) { @@ -232,6 +252,32 @@ class FileControllerImpl @Inject constructor( } } + private fun copyMetadata( + initialExif: ExifInterface?, + fileUri: Uri?, + keepMetadata: Boolean, + originalUri: Uri + ) { + if (initialExif != null) { + getFileDescriptorFor(fileUri)?.use { + val ex = ExifInterface(it.fileDescriptor) + initialExif.copyTo(ex) + ex.saveAttributes() + } + } else if (keepMetadata) { + val exif = context + .contentResolver + .openFileDescriptor(originalUri, "r") + ?.use { ExifInterface(it.fileDescriptor) } + + getFileDescriptorFor(fileUri)?.use { + val ex = ExifInterface(it.fileDescriptor) + exif?.copyTo(ex) + ex.saveAttributes() + } + } else Unit + } + private suspend fun cacheImage( saveTarget: SaveTarget ): String? = withContext(Dispatchers.IO) { diff --git a/app/src/main/java/ru/tech/imageresizershrinker/domain/model/SettingsState.kt b/app/src/main/java/ru/tech/imageresizershrinker/domain/model/SettingsState.kt index c1e5f334d..5aaa5e11d 100644 --- a/app/src/main/java/ru/tech/imageresizershrinker/domain/model/SettingsState.kt +++ b/app/src/main/java/ru/tech/imageresizershrinker/domain/model/SettingsState.kt @@ -44,7 +44,8 @@ data class SettingsState( val isInvertThemeColors: Boolean, val screensSearchEnabled: Boolean, val autoCopyToClipBoard: Boolean, - val hapticsStrength: Int + val hapticsStrength: Int, + val overwriteFiles: Boolean ) : Domain { companion object { @@ -90,7 +91,8 @@ data class SettingsState( isInvertThemeColors = false, screensSearchEnabled = false, autoCopyToClipBoard = false, - hapticsStrength = 1 + hapticsStrength = 1, + overwriteFiles = false ) } } \ No newline at end of file diff --git a/app/src/main/java/ru/tech/imageresizershrinker/domain/repository/SettingsRepository.kt b/app/src/main/java/ru/tech/imageresizershrinker/domain/repository/SettingsRepository.kt index bafdd3e3c..babd830b3 100644 --- a/app/src/main/java/ru/tech/imageresizershrinker/domain/repository/SettingsRepository.kt +++ b/app/src/main/java/ru/tech/imageresizershrinker/domain/repository/SettingsRepository.kt @@ -104,4 +104,6 @@ interface SettingsRepository { suspend fun toggleAutoPinClipboard() suspend fun setVibrationStrength(strength: Int) + + suspend fun toggleOverwriteFiles() } \ No newline at end of file diff --git a/app/src/main/java/ru/tech/imageresizershrinker/domain/saving/model/FileParams.kt b/app/src/main/java/ru/tech/imageresizershrinker/domain/saving/model/FileParams.kt index add7f189c..3216ab2a7 100644 --- a/app/src/main/java/ru/tech/imageresizershrinker/domain/saving/model/FileParams.kt +++ b/app/src/main/java/ru/tech/imageresizershrinker/domain/saving/model/FileParams.kt @@ -7,5 +7,6 @@ data class FileParams( val addOriginalFilename: Boolean, val addSequenceNumber: Boolean, val randomizeFilename: Boolean, - val copyToClipBoard: Boolean + val copyToClipBoard: Boolean, + val overwriteFile: Boolean ) \ No newline at end of file diff --git a/app/src/main/java/ru/tech/imageresizershrinker/domain/use_case/edit_settings/ToggleOverwriteFilesUseCase.kt b/app/src/main/java/ru/tech/imageresizershrinker/domain/use_case/edit_settings/ToggleOverwriteFilesUseCase.kt new file mode 100644 index 000000000..2c59ffcc7 --- /dev/null +++ b/app/src/main/java/ru/tech/imageresizershrinker/domain/use_case/edit_settings/ToggleOverwriteFilesUseCase.kt @@ -0,0 +1,10 @@ +package ru.tech.imageresizershrinker.domain.use_case.edit_settings + +import ru.tech.imageresizershrinker.domain.repository.SettingsRepository +import javax.inject.Inject + +class ToggleOverwriteFilesUseCase @Inject constructor( + private val settingsRepository: SettingsRepository +) { + suspend operator fun invoke() = settingsRepository.toggleAddOriginalFilename() +} \ No newline at end of file diff --git a/app/src/main/java/ru/tech/imageresizershrinker/presentation/main_screen/components/settings/OverwriteFilesSettingItem.kt b/app/src/main/java/ru/tech/imageresizershrinker/presentation/main_screen/components/settings/OverwriteFilesSettingItem.kt new file mode 100644 index 000000000..3764892ee --- /dev/null +++ b/app/src/main/java/ru/tech/imageresizershrinker/presentation/main_screen/components/settings/OverwriteFilesSettingItem.kt @@ -0,0 +1,45 @@ +package ru.tech.imageresizershrinker.presentation.main_screen.components.settings + +import androidx.compose.foundation.layout.padding +import androidx.compose.material.icons.Icons +import androidx.compose.material.icons.outlined.Architecture +import androidx.compose.material3.Icon +import androidx.compose.runtime.Composable +import androidx.compose.ui.Modifier +import androidx.compose.ui.graphics.Shape +import androidx.compose.ui.res.stringResource +import androidx.compose.ui.unit.dp +import ru.tech.imageresizershrinker.R +import ru.tech.imageresizershrinker.presentation.root.widget.modifier.ContainerShapeDefaults +import ru.tech.imageresizershrinker.presentation.root.widget.preferences.PreferenceRowSwitch +import ru.tech.imageresizershrinker.presentation.root.widget.utils.LocalSettingsState + +@Composable +fun OverwriteFilesSettingItem( + onClick: (Boolean) -> Unit, + shape: Shape = ContainerShapeDefaults.centerShape, + modifier: Modifier = Modifier.padding(start = 8.dp, end = 8.dp) +) { + val settingsState = LocalSettingsState.current + PreferenceRowSwitch( + shape = shape, + modifier = modifier, + applyHorPadding = false, + onClick = onClick, + enabled = !settingsState.randomizeFilename, + title = stringResource(R.string.overwrite_files), + subtitle = stringResource(R.string.overwrite_files_sub), + checked = settingsState.addSequenceNumber, + resultModifier = Modifier.padding( + horizontal = 16.dp, + vertical = 8.dp + ), + startContent = { + Icon( + imageVector = Icons.Outlined.Architecture, + contentDescription = null, + modifier = Modifier.padding(end = 16.dp) + ) + } + ) +} \ No newline at end of file diff --git a/app/src/main/java/ru/tech/imageresizershrinker/presentation/main_screen/components/settings/Setting.kt b/app/src/main/java/ru/tech/imageresizershrinker/presentation/main_screen/components/settings/Setting.kt index 5ad43b7ea..2c0d1a86c 100644 --- a/app/src/main/java/ru/tech/imageresizershrinker/presentation/main_screen/components/settings/Setting.kt +++ b/app/src/main/java/ru/tech/imageresizershrinker/presentation/main_screen/components/settings/Setting.kt @@ -250,4 +250,9 @@ sealed class Setting( title = R.string.vibration_strength, subtitle = null ) + + data object OverwriteFiles : Setting( + title = R.string.overwrite_files, + subtitle = R.string.overwrite_files_sub + ) } \ No newline at end of file diff --git a/app/src/main/java/ru/tech/imageresizershrinker/presentation/main_screen/components/settings/SettingItem.kt b/app/src/main/java/ru/tech/imageresizershrinker/presentation/main_screen/components/settings/SettingItem.kt index 9e08e65af..e450da513 100644 --- a/app/src/main/java/ru/tech/imageresizershrinker/presentation/main_screen/components/settings/SettingItem.kt +++ b/app/src/main/java/ru/tech/imageresizershrinker/presentation/main_screen/components/settings/SettingItem.kt @@ -270,6 +270,12 @@ fun SettingItem( ) } + Setting.OverwriteFiles -> { + OverwriteFilesSettingItem( + onClick = { viewModel.toggleOverwriteFiles() } + ) + } + Setting.Reset -> { ResetSettingsSettingItem( onReset = viewModel::resetSettings diff --git a/app/src/main/java/ru/tech/imageresizershrinker/presentation/main_screen/components/settings/SettingsGroup.kt b/app/src/main/java/ru/tech/imageresizershrinker/presentation/main_screen/components/settings/SettingsGroup.kt index 6399ddcda..3282258ae 100644 --- a/app/src/main/java/ru/tech/imageresizershrinker/presentation/main_screen/components/settings/SettingsGroup.kt +++ b/app/src/main/java/ru/tech/imageresizershrinker/presentation/main_screen/components/settings/SettingsGroup.kt @@ -143,6 +143,7 @@ sealed class SettingsGroup( Setting.AddFileSize, Setting.AddOriginalFilename, Setting.ReplaceSequenceNumber, + Setting.OverwriteFiles, Setting.RandomizeFilename ), initialState = false diff --git a/app/src/main/java/ru/tech/imageresizershrinker/presentation/main_screen/viewModel/MainViewModel.kt b/app/src/main/java/ru/tech/imageresizershrinker/presentation/main_screen/viewModel/MainViewModel.kt index d38506b3d..ff3b267f8 100644 --- a/app/src/main/java/ru/tech/imageresizershrinker/presentation/main_screen/viewModel/MainViewModel.kt +++ b/app/src/main/java/ru/tech/imageresizershrinker/presentation/main_screen/viewModel/MainViewModel.kt @@ -63,6 +63,7 @@ import ru.tech.imageresizershrinker.domain.use_case.edit_settings.ToggleDynamicC import ru.tech.imageresizershrinker.domain.use_case.edit_settings.ToggleGroupOptionsByTypesUseCase import ru.tech.imageresizershrinker.domain.use_case.edit_settings.ToggleInvertColorsUseCase import ru.tech.imageresizershrinker.domain.use_case.edit_settings.ToggleLockDrawOrientationUseCase +import ru.tech.imageresizershrinker.domain.use_case.edit_settings.ToggleOverwriteFilesUseCase import ru.tech.imageresizershrinker.domain.use_case.edit_settings.ToggleRandomizeFilenameUseCase import ru.tech.imageresizershrinker.domain.use_case.edit_settings.ToggleScreensSearchEnabledUseCase import ru.tech.imageresizershrinker.domain.use_case.edit_settings.ToggleShowDialogUseCase @@ -137,7 +138,8 @@ class MainViewModel @Inject constructor( private val toggleScreensSearchEnabledUseCase: ToggleScreensSearchEnabledUseCase, private val toggleDrawAppBarShadowsUseCase: ToggleDrawAppBarShadowsUseCase, private val toggleAutoPinClipboardUseCase: ToggleAutoPinClipboardUseCase, - private val setVibrationStrengthUseCase: SetVibrationStrengthUseCase + private val setVibrationStrengthUseCase: SetVibrationStrengthUseCase, + private val toggleOverwriteFilesUseCase: ToggleOverwriteFilesUseCase ) : ViewModel() { private val _settingsState = mutableStateOf(SettingsState.Default()) @@ -630,4 +632,10 @@ class MainViewModel @Inject constructor( } } + fun toggleOverwriteFiles() { + viewModelScope.launch { + toggleOverwriteFilesUseCase() + } + } + } \ No newline at end of file diff --git a/app/src/main/java/ru/tech/imageresizershrinker/presentation/root/model/UiSettingsState.kt b/app/src/main/java/ru/tech/imageresizershrinker/presentation/root/model/UiSettingsState.kt index 4d3e073e6..5c8849f8f 100644 --- a/app/src/main/java/ru/tech/imageresizershrinker/presentation/root/model/UiSettingsState.kt +++ b/app/src/main/java/ru/tech/imageresizershrinker/presentation/root/model/UiSettingsState.kt @@ -65,7 +65,8 @@ data class UiSettingsState( val isInvertThemeColors: Boolean, val screensSearchEnabled: Boolean, val autoCopyToClipBoard: Boolean, - val hapticsStrength: Int + val hapticsStrength: Int, + val overwriteFiles: Boolean ) fun UiSettingsState.isFirstLaunch( @@ -144,7 +145,8 @@ fun SettingsState.toUiState(): UiSettingsState { isInvertThemeColors = isInvertThemeColors, screensSearchEnabled = screensSearchEnabled, autoCopyToClipBoard = autoCopyToClipBoard, - hapticsStrength = hapticsStrength + hapticsStrength = hapticsStrength, + overwriteFiles = overwriteFiles ) } diff --git a/app/src/main/java/ru/tech/imageresizershrinker/presentation/root/widget/other/ToastHost.kt b/app/src/main/java/ru/tech/imageresizershrinker/presentation/root/widget/other/ToastHost.kt index 51b6c0eed..749c17510 100644 --- a/app/src/main/java/ru/tech/imageresizershrinker/presentation/root/widget/other/ToastHost.kt +++ b/app/src/main/java/ru/tech/imageresizershrinker/presentation/root/widget/other/ToastHost.kt @@ -291,9 +291,10 @@ suspend fun ToastHostState.showError( context: Context, error: Throwable ) = showToast( - context.getString( + message = context.getString( R.string.smth_went_wrong, error.localizedMessage ?: "" ), - Icons.Rounded.ErrorOutline + icon = Icons.Rounded.ErrorOutline, + duration = ToastDuration.Long ) \ No newline at end of file diff --git a/app/src/main/res/values/strings.xml b/app/src/main/res/values/strings.xml index 7b7359dee..5133b0a11 100644 --- a/app/src/main/res/values/strings.xml +++ b/app/src/main/res/values/strings.xml @@ -524,4 +524,7 @@ Automatically adds saved image to clipboard if enabled Vibration Vibration Strength + In order to overwrite files you need to use \"Explorer\" image source, try repick images, we've changed image source to the needed one + Overwrite Files + Original file will be replaced with new one instead of saving in selected folder, this option need to image source be \"Explorer\" or GetContent, when toggling this, it will be set automatically \ No newline at end of file