mirror of
https://github.com/T8RIN/ImageToolbox.git
synced 2025-05-17 05:26:02 +08:00
Proposal of Audio cover export by #1742
This commit is contained in:
@ -1,5 +1,3 @@
|
|||||||
import dev.iurysouza.modulegraph.Theme
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* ImageToolbox is an image editor for android
|
* ImageToolbox is an image editor for android
|
||||||
* Copyright (c) 2024 T8RIN (Malik Mukhametzyanov)
|
* Copyright (c) 2024 T8RIN (Malik Mukhametzyanov)
|
||||||
@ -17,10 +15,36 @@ import dev.iurysouza.modulegraph.Theme
|
|||||||
* along with this program. If not, see <http://www.apache.org/licenses/LICENSE-2.0>.
|
* along with this program. If not, see <http://www.apache.org/licenses/LICENSE-2.0>.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
/** Added if needed to regenerate module graph
|
||||||
|
|
||||||
|
import dev.iurysouza.modulegraph.Theme
|
||||||
|
|
||||||
plugins {
|
plugins {
|
||||||
alias(libs.plugins.dev.iurysouza.modulegraph) apply true
|
alias(libs.plugins.dev.iurysouza.modulegraph) apply true
|
||||||
}
|
}
|
||||||
|
|
||||||
|
moduleGraphConfig {
|
||||||
|
readmePath.set("./ARCHITECTURE.md")
|
||||||
|
heading = "# 📐 Modules Graph"
|
||||||
|
theme.set(
|
||||||
|
Theme.BASE(
|
||||||
|
mapOf(
|
||||||
|
"primaryColor" to "#00381a",
|
||||||
|
"primaryTextColor" to "#d4fcb1",
|
||||||
|
"primaryBorderColor" to "#14b800",
|
||||||
|
"lineColor" to "#15c400",
|
||||||
|
"secondaryColor" to "#283b26",
|
||||||
|
"tertiaryColor" to "#355238",
|
||||||
|
"nodeTextColor" to "#e0ffd6",
|
||||||
|
"edgeLabelBackground" to "#1a1a1a",
|
||||||
|
"fontSize" to "28px"
|
||||||
|
)
|
||||||
|
)
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
**/
|
||||||
|
|
||||||
buildscript {
|
buildscript {
|
||||||
repositories {
|
repositories {
|
||||||
gradlePluginPortal()
|
gradlePluginPortal()
|
||||||
@ -46,24 +70,4 @@ buildscript {
|
|||||||
|
|
||||||
tasks.register("clean", Delete::class) {
|
tasks.register("clean", Delete::class) {
|
||||||
delete(rootProject.layout.buildDirectory)
|
delete(rootProject.layout.buildDirectory)
|
||||||
}
|
|
||||||
|
|
||||||
moduleGraphConfig {
|
|
||||||
readmePath.set("./ARCHITECTURE.md")
|
|
||||||
heading = "# 📐 Modules Graph"
|
|
||||||
theme.set(
|
|
||||||
Theme.BASE(
|
|
||||||
mapOf(
|
|
||||||
"primaryColor" to "#00381a",
|
|
||||||
"primaryTextColor" to "#d4fcb1",
|
|
||||||
"primaryBorderColor" to "#14b800",
|
|
||||||
"lineColor" to "#15c400",
|
|
||||||
"secondaryColor" to "#283b26",
|
|
||||||
"tertiaryColor" to "#355238",
|
|
||||||
"nodeTextColor" to "#e0ffd6",
|
|
||||||
"edgeLabelBackground" to "#1a1a1a",
|
|
||||||
"fontSize" to "28px"
|
|
||||||
)
|
|
||||||
)
|
|
||||||
)
|
|
||||||
}
|
}
|
@ -1602,4 +1602,6 @@
|
|||||||
<string name="barcodes_sub">Scan any Barcode (QR, EAN, AZTEC, …) and get it\'s content or paste your text to generate new one</string>
|
<string name="barcodes_sub">Scan any Barcode (QR, EAN, AZTEC, …) and get it\'s content or paste your text to generate new one</string>
|
||||||
<string name="no_barcode_found">No Barcode Found</string>
|
<string name="no_barcode_found">No Barcode Found</string>
|
||||||
<string name="generated_barcode_will_be_here">Generated Barcode Will Be Here</string>
|
<string name="generated_barcode_will_be_here">Generated Barcode Will Be Here</string>
|
||||||
|
<string name="audio_cover_extractor">Audio Cover Extractor</string>
|
||||||
|
<string name="audio_cover_extractor_sub">Extract album cover images from audio files, most common formats are supported</string>
|
||||||
</resources>
|
</resources>
|
@ -199,7 +199,7 @@ object ContextUtils {
|
|||||||
onShowToast: (message: String, icon: ImageVector) -> Unit,
|
onShowToast: (message: String, icon: ImageVector) -> Unit,
|
||||||
onNavigate: (Screen) -> Unit,
|
onNavigate: (Screen) -> Unit,
|
||||||
onGetUris: (List<Uri>) -> Unit,
|
onGetUris: (List<Uri>) -> Unit,
|
||||||
onHasExtraImageType: (String) -> Unit,
|
onHasExtraImageType: (String) -> Unit, //TODO: Add normal sealed class instead of string
|
||||||
isHasUris: Boolean,
|
isHasUris: Boolean,
|
||||||
onWantGithubReview: () -> Unit,
|
onWantGithubReview: () -> Unit,
|
||||||
isOpenEditInsteadOfPreview: Boolean,
|
isOpenEditInsteadOfPreview: Boolean,
|
||||||
@ -294,10 +294,17 @@ object ContextUtils {
|
|||||||
onHasExtraImageType(text)
|
onHasExtraImageType(text)
|
||||||
onGetUris(listOf())
|
onGetUris(listOf())
|
||||||
} else {
|
} else {
|
||||||
|
val isAudio = intent.type?.startsWith("audio/") == true
|
||||||
|
|
||||||
when (intent.action) {
|
when (intent.action) {
|
||||||
Intent.ACTION_SEND_MULTIPLE -> {
|
Intent.ACTION_SEND_MULTIPLE -> {
|
||||||
intent.parcelableArrayList<Uri>(Intent.EXTRA_STREAM)?.let {
|
intent.parcelableArrayList<Uri>(Intent.EXTRA_STREAM)?.let {
|
||||||
onNavigate(Screen.Zip(it))
|
if (isAudio) {
|
||||||
|
onHasExtraImageType("audio")
|
||||||
|
onGetUris(it)
|
||||||
|
} else {
|
||||||
|
onNavigate(Screen.Zip(it))
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -307,7 +314,12 @@ object ContextUtils {
|
|||||||
onHasExtraImageType("$BackupFileExtension $it")
|
onHasExtraImageType("$BackupFileExtension $it")
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
onHasExtraImageType("file")
|
if (isAudio) {
|
||||||
|
onHasExtraImageType("audio")
|
||||||
|
} else {
|
||||||
|
onHasExtraImageType("file")
|
||||||
|
}
|
||||||
|
|
||||||
onGetUris(listOf(it))
|
onGetUris(listOf(it))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -326,10 +338,20 @@ object ContextUtils {
|
|||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
onHasExtraImageType("file")
|
if (isAudio) {
|
||||||
|
onHasExtraImageType("audio")
|
||||||
|
} else {
|
||||||
|
onHasExtraImageType("file")
|
||||||
|
}
|
||||||
|
|
||||||
onGetUris(uris)
|
onGetUris(uris)
|
||||||
} else if (uris.isNotEmpty()) {
|
} else if (uris.isNotEmpty()) {
|
||||||
onNavigate(Screen.Zip(uris))
|
if (isAudio) {
|
||||||
|
onHasExtraImageType("audio")
|
||||||
|
onGetUris(uris)
|
||||||
|
} else {
|
||||||
|
onNavigate(Screen.Zip(uris))
|
||||||
|
}
|
||||||
} else {
|
} else {
|
||||||
Unit
|
Unit
|
||||||
}
|
}
|
||||||
|
@ -726,6 +726,15 @@ sealed class Screen(
|
|||||||
subtitle = R.string.image_cutting_sub
|
subtitle = R.string.image_cutting_sub
|
||||||
)
|
)
|
||||||
|
|
||||||
|
@Serializable
|
||||||
|
data class AudioCoverExtractor(
|
||||||
|
val uris: List<Uri>? = null
|
||||||
|
) : Screen(
|
||||||
|
id = 39,
|
||||||
|
title = R.string.audio_cover_extractor,
|
||||||
|
subtitle = R.string.audio_cover_extractor_sub
|
||||||
|
)
|
||||||
|
|
||||||
companion object : ScreenConstants by ScreenConstantsImpl
|
companion object : ScreenConstants by ScreenConstantsImpl
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -34,6 +34,7 @@ import androidx.compose.material.icons.outlined.Grain
|
|||||||
import androidx.compose.material.icons.outlined.Photo
|
import androidx.compose.material.icons.outlined.Photo
|
||||||
import androidx.compose.material.icons.outlined.PictureAsPdf
|
import androidx.compose.material.icons.outlined.PictureAsPdf
|
||||||
import androidx.compose.material.icons.outlined.QrCode
|
import androidx.compose.material.icons.outlined.QrCode
|
||||||
|
import androidx.compose.material.icons.rounded.Album
|
||||||
import androidx.compose.material.icons.rounded.Compare
|
import androidx.compose.material.icons.rounded.Compare
|
||||||
import androidx.compose.material.icons.rounded.ContentCut
|
import androidx.compose.material.icons.rounded.ContentCut
|
||||||
import androidx.compose.material.icons.rounded.Tag
|
import androidx.compose.material.icons.rounded.Tag
|
||||||
@ -71,7 +72,51 @@ import ru.tech.imageresizershrinker.core.resources.icons.Stack
|
|||||||
import ru.tech.imageresizershrinker.core.resources.icons.Toolbox
|
import ru.tech.imageresizershrinker.core.resources.icons.Toolbox
|
||||||
import ru.tech.imageresizershrinker.core.resources.icons.VectorPolyline
|
import ru.tech.imageresizershrinker.core.resources.icons.VectorPolyline
|
||||||
import ru.tech.imageresizershrinker.core.resources.icons.WebpBox
|
import ru.tech.imageresizershrinker.core.resources.icons.WebpBox
|
||||||
import ru.tech.imageresizershrinker.core.ui.utils.navigation.Screen.*
|
import ru.tech.imageresizershrinker.core.ui.utils.navigation.Screen.ApngTools
|
||||||
|
import ru.tech.imageresizershrinker.core.ui.utils.navigation.Screen.AudioCoverExtractor
|
||||||
|
import ru.tech.imageresizershrinker.core.ui.utils.navigation.Screen.Base64Tools
|
||||||
|
import ru.tech.imageresizershrinker.core.ui.utils.navigation.Screen.ChecksumTools
|
||||||
|
import ru.tech.imageresizershrinker.core.ui.utils.navigation.Screen.Cipher
|
||||||
|
import ru.tech.imageresizershrinker.core.ui.utils.navigation.Screen.CollageMaker
|
||||||
|
import ru.tech.imageresizershrinker.core.ui.utils.navigation.Screen.ColorTools
|
||||||
|
import ru.tech.imageresizershrinker.core.ui.utils.navigation.Screen.Compare
|
||||||
|
import ru.tech.imageresizershrinker.core.ui.utils.navigation.Screen.Crop
|
||||||
|
import ru.tech.imageresizershrinker.core.ui.utils.navigation.Screen.DeleteExif
|
||||||
|
import ru.tech.imageresizershrinker.core.ui.utils.navigation.Screen.DocumentScanner
|
||||||
|
import ru.tech.imageresizershrinker.core.ui.utils.navigation.Screen.Draw
|
||||||
|
import ru.tech.imageresizershrinker.core.ui.utils.navigation.Screen.EasterEgg
|
||||||
|
import ru.tech.imageresizershrinker.core.ui.utils.navigation.Screen.EditExif
|
||||||
|
import ru.tech.imageresizershrinker.core.ui.utils.navigation.Screen.EraseBackground
|
||||||
|
import ru.tech.imageresizershrinker.core.ui.utils.navigation.Screen.Filter
|
||||||
|
import ru.tech.imageresizershrinker.core.ui.utils.navigation.Screen.FormatConversion
|
||||||
|
import ru.tech.imageresizershrinker.core.ui.utils.navigation.Screen.GeneratePalette
|
||||||
|
import ru.tech.imageresizershrinker.core.ui.utils.navigation.Screen.GifTools
|
||||||
|
import ru.tech.imageresizershrinker.core.ui.utils.navigation.Screen.GradientMaker
|
||||||
|
import ru.tech.imageresizershrinker.core.ui.utils.navigation.Screen.ImageCutter
|
||||||
|
import ru.tech.imageresizershrinker.core.ui.utils.navigation.Screen.ImagePreview
|
||||||
|
import ru.tech.imageresizershrinker.core.ui.utils.navigation.Screen.ImageSplitting
|
||||||
|
import ru.tech.imageresizershrinker.core.ui.utils.navigation.Screen.ImageStacking
|
||||||
|
import ru.tech.imageresizershrinker.core.ui.utils.navigation.Screen.ImageStitching
|
||||||
|
import ru.tech.imageresizershrinker.core.ui.utils.navigation.Screen.JxlTools
|
||||||
|
import ru.tech.imageresizershrinker.core.ui.utils.navigation.Screen.LibrariesInfo
|
||||||
|
import ru.tech.imageresizershrinker.core.ui.utils.navigation.Screen.LimitResize
|
||||||
|
import ru.tech.imageresizershrinker.core.ui.utils.navigation.Screen.LoadNetImage
|
||||||
|
import ru.tech.imageresizershrinker.core.ui.utils.navigation.Screen.Main
|
||||||
|
import ru.tech.imageresizershrinker.core.ui.utils.navigation.Screen.MarkupLayers
|
||||||
|
import ru.tech.imageresizershrinker.core.ui.utils.navigation.Screen.MeshGradients
|
||||||
|
import ru.tech.imageresizershrinker.core.ui.utils.navigation.Screen.NoiseGeneration
|
||||||
|
import ru.tech.imageresizershrinker.core.ui.utils.navigation.Screen.PdfTools
|
||||||
|
import ru.tech.imageresizershrinker.core.ui.utils.navigation.Screen.PickColorFromImage
|
||||||
|
import ru.tech.imageresizershrinker.core.ui.utils.navigation.Screen.RecognizeText
|
||||||
|
import ru.tech.imageresizershrinker.core.ui.utils.navigation.Screen.ResizeAndConvert
|
||||||
|
import ru.tech.imageresizershrinker.core.ui.utils.navigation.Screen.ScanQrCode
|
||||||
|
import ru.tech.imageresizershrinker.core.ui.utils.navigation.Screen.Settings
|
||||||
|
import ru.tech.imageresizershrinker.core.ui.utils.navigation.Screen.SingleEdit
|
||||||
|
import ru.tech.imageresizershrinker.core.ui.utils.navigation.Screen.SvgMaker
|
||||||
|
import ru.tech.imageresizershrinker.core.ui.utils.navigation.Screen.Watermarking
|
||||||
|
import ru.tech.imageresizershrinker.core.ui.utils.navigation.Screen.WebpTools
|
||||||
|
import ru.tech.imageresizershrinker.core.ui.utils.navigation.Screen.WeightResize
|
||||||
|
import ru.tech.imageresizershrinker.core.ui.utils.navigation.Screen.Zip
|
||||||
import android.net.Uri as AndroidUri
|
import android.net.Uri as AndroidUri
|
||||||
|
|
||||||
internal fun Screen.isBetaFeature(): Boolean = when (this) {
|
internal fun Screen.isBetaFeature(): Boolean = when (this) {
|
||||||
@ -82,7 +127,7 @@ internal fun Screen.isBetaFeature(): Boolean = when (this) {
|
|||||||
internal fun Screen.simpleName(): String? = when (this) {
|
internal fun Screen.simpleName(): String? = when (this) {
|
||||||
is ApngTools -> "APNG_Tools"
|
is ApngTools -> "APNG_Tools"
|
||||||
is Cipher -> "Cipher"
|
is Cipher -> "Cipher"
|
||||||
is Screen.Compare -> "Compare"
|
is Compare -> "Compare"
|
||||||
is Crop -> "Crop"
|
is Crop -> "Crop"
|
||||||
is DeleteExif -> "Delete_Exif"
|
is DeleteExif -> "Delete_Exif"
|
||||||
is Draw -> "Draw"
|
is Draw -> "Draw"
|
||||||
@ -109,7 +154,7 @@ internal fun Screen.simpleName(): String? = when (this) {
|
|||||||
is Zip -> "Zip"
|
is Zip -> "Zip"
|
||||||
is SvgMaker -> "Svg"
|
is SvgMaker -> "Svg"
|
||||||
is FormatConversion -> "Convert"
|
is FormatConversion -> "Convert"
|
||||||
is Screen.DocumentScanner -> "Document_Scanner"
|
is DocumentScanner -> "Document_Scanner"
|
||||||
is ScanQrCode -> "QR_Code"
|
is ScanQrCode -> "QR_Code"
|
||||||
is ImageStacking -> "Image_Stacking"
|
is ImageStacking -> "Image_Stacking"
|
||||||
is ImageSplitting -> "Image_Splitting"
|
is ImageSplitting -> "Image_Splitting"
|
||||||
@ -124,6 +169,7 @@ internal fun Screen.simpleName(): String? = when (this) {
|
|||||||
is MeshGradients -> "Mesh_Gradients"
|
is MeshGradients -> "Mesh_Gradients"
|
||||||
is EditExif -> "Edit_EXIF"
|
is EditExif -> "Edit_EXIF"
|
||||||
is ImageCutter -> "Image_Cutting"
|
is ImageCutter -> "Image_Cutting"
|
||||||
|
is AudioCoverExtractor -> "Audio_Cover_Extractor"
|
||||||
}
|
}
|
||||||
|
|
||||||
internal fun Screen.icon(): ImageVector? = when (this) {
|
internal fun Screen.icon(): ImageVector? = when (this) {
|
||||||
@ -136,7 +182,7 @@ internal fun Screen.icon(): ImageVector? = when (this) {
|
|||||||
is SingleEdit -> Icons.Outlined.ImageEdit
|
is SingleEdit -> Icons.Outlined.ImageEdit
|
||||||
is ApngTools -> Icons.Rounded.ApngBox
|
is ApngTools -> Icons.Rounded.ApngBox
|
||||||
is Cipher -> Icons.Outlined.Encrypted
|
is Cipher -> Icons.Outlined.Encrypted
|
||||||
is Screen.Compare -> Icons.Rounded.Compare
|
is Compare -> Icons.Rounded.Compare
|
||||||
is Crop -> Icons.Rounded.CropSmall
|
is Crop -> Icons.Rounded.CropSmall
|
||||||
is DeleteExif -> Icons.Outlined.Exif
|
is DeleteExif -> Icons.Outlined.Exif
|
||||||
is Draw -> Icons.Outlined.Draw
|
is Draw -> Icons.Outlined.Draw
|
||||||
@ -159,7 +205,7 @@ internal fun Screen.icon(): ImageVector? = when (this) {
|
|||||||
is Zip -> Icons.Outlined.FolderZip
|
is Zip -> Icons.Outlined.FolderZip
|
||||||
is SvgMaker -> Icons.Outlined.VectorPolyline
|
is SvgMaker -> Icons.Outlined.VectorPolyline
|
||||||
is FormatConversion -> Icons.Outlined.ImageConvert
|
is FormatConversion -> Icons.Outlined.ImageConvert
|
||||||
is Screen.DocumentScanner -> Icons.Outlined.DocumentScanner
|
is DocumentScanner -> Icons.Outlined.DocumentScanner
|
||||||
is ScanQrCode -> Icons.Outlined.QrCode
|
is ScanQrCode -> Icons.Outlined.QrCode
|
||||||
is ImageStacking -> Icons.Outlined.ImageOverlay
|
is ImageStacking -> Icons.Outlined.ImageOverlay
|
||||||
is ImageSplitting -> Icons.Outlined.SplitAlt
|
is ImageSplitting -> Icons.Outlined.SplitAlt
|
||||||
@ -172,6 +218,7 @@ internal fun Screen.icon(): ImageVector? = when (this) {
|
|||||||
is ChecksumTools -> Icons.Rounded.Tag
|
is ChecksumTools -> Icons.Rounded.Tag
|
||||||
is EditExif -> Icons.Outlined.ExifEdit
|
is EditExif -> Icons.Outlined.ExifEdit
|
||||||
is ImageCutter -> Icons.Rounded.ContentCut
|
is ImageCutter -> Icons.Rounded.ContentCut
|
||||||
|
is AudioCoverExtractor -> Icons.Rounded.Album
|
||||||
}
|
}
|
||||||
|
|
||||||
internal object UriSerializer : KSerializer<AndroidUri> {
|
internal object UriSerializer : KSerializer<AndroidUri> {
|
||||||
@ -261,7 +308,8 @@ internal object ScreenConstantsImpl : ScreenConstants {
|
|||||||
Zip(),
|
Zip(),
|
||||||
JxlTools(),
|
JxlTools(),
|
||||||
ApngTools(),
|
ApngTools(),
|
||||||
WebpTools()
|
WebpTools(),
|
||||||
|
AudioCoverExtractor()
|
||||||
),
|
),
|
||||||
title = R.string.tools,
|
title = R.string.tools,
|
||||||
selectedIcon = Icons.Rounded.Toolbox,
|
selectedIcon = Icons.Rounded.Toolbox,
|
||||||
@ -274,5 +322,5 @@ internal object ScreenConstantsImpl : ScreenConstants {
|
|||||||
typedEntries.flatMap { it.entries }.sortedBy { it.id }
|
typedEntries.flatMap { it.entries }.sortedBy { it.id }
|
||||||
}
|
}
|
||||||
|
|
||||||
override val FEATURES_COUNT = 66
|
override val FEATURES_COUNT = 67
|
||||||
}
|
}
|
@ -35,7 +35,7 @@ import java.util.Locale
|
|||||||
|
|
||||||
@Composable
|
@Composable
|
||||||
internal fun List<Uri>.screenList(
|
internal fun List<Uri>.screenList(
|
||||||
extraImageType: String?
|
extraImageType: String? //TODO: Add normal sealed class instead of string
|
||||||
): State<List<Screen>> {
|
): State<List<Screen>> {
|
||||||
val uris = this
|
val uris = this
|
||||||
val context = LocalContext.current
|
val context = LocalContext.current
|
||||||
@ -59,6 +59,17 @@ internal fun List<Uri>.screenList(
|
|||||||
)
|
)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
val audioAvailableScreens by remember(uris) {
|
||||||
|
derivedStateOf {
|
||||||
|
listOf(
|
||||||
|
Screen.AudioCoverExtractor(uris)
|
||||||
|
) + if (uris.size > 1) {
|
||||||
|
filesAvailableScreens
|
||||||
|
} else {
|
||||||
|
listOf(Screen.Zip(uris))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
val gifAvailableScreens by remember(uris) {
|
val gifAvailableScreens by remember(uris) {
|
||||||
derivedStateOf {
|
derivedStateOf {
|
||||||
listOf(
|
listOf(
|
||||||
@ -272,6 +283,7 @@ internal fun List<Uri>.screenList(
|
|||||||
) {
|
) {
|
||||||
derivedStateOf {
|
derivedStateOf {
|
||||||
when {
|
when {
|
||||||
|
extraImageType == "audio" -> audioAvailableScreens
|
||||||
extraImageType == "pdf" -> pdfAvailableScreens
|
extraImageType == "pdf" -> pdfAvailableScreens
|
||||||
extraImageType == "gif" -> gifAvailableScreens
|
extraImageType == "gif" -> gifAvailableScreens
|
||||||
extraImageType == "file" -> filesAvailableScreens
|
extraImageType == "file" -> filesAvailableScreens
|
||||||
|
1
feature/audio-cover-extractor/.gitignore
vendored
Normal file
1
feature/audio-cover-extractor/.gitignore
vendored
Normal file
@ -0,0 +1 @@
|
|||||||
|
/build
|
30
feature/audio-cover-extractor/build.gradle.kts
Normal file
30
feature/audio-cover-extractor/build.gradle.kts
Normal file
@ -0,0 +1,30 @@
|
|||||||
|
/*
|
||||||
|
* ImageToolbox is an image editor for android
|
||||||
|
* Copyright (c) 2024 T8RIN (Malik Mukhametzyanov)
|
||||||
|
*
|
||||||
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
* you may not use this file except in compliance with the License.
|
||||||
|
*
|
||||||
|
* Unless required by applicable law or agreed to in writing, software
|
||||||
|
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
* See the License for the specific language governing permissions and
|
||||||
|
* limitations under the License.
|
||||||
|
*
|
||||||
|
* You should have received a copy of the Apache License
|
||||||
|
* along with this program. If not, see <http://www.apache.org/licenses/LICENSE-2.0>.
|
||||||
|
*/
|
||||||
|
|
||||||
|
plugins {
|
||||||
|
alias(libs.plugins.image.toolbox.library)
|
||||||
|
alias(libs.plugins.image.toolbox.feature)
|
||||||
|
alias(libs.plugins.image.toolbox.hilt)
|
||||||
|
alias(libs.plugins.image.toolbox.compose)
|
||||||
|
}
|
||||||
|
|
||||||
|
android.namespace = "ru.tech.imageresizershrinker.feature.audio_cover_extractor"
|
||||||
|
|
||||||
|
dependencies {
|
||||||
|
implementation(libs.ffmpeg.metadata.retriever.core)
|
||||||
|
implementation(libs.ffmpeg.metadata.retriever.native)
|
||||||
|
}
|
@ -0,0 +1,4 @@
|
|||||||
|
<?xml version="1.0" encoding="utf-8"?>
|
||||||
|
<manifest>
|
||||||
|
|
||||||
|
</manifest>
|
@ -0,0 +1,92 @@
|
|||||||
|
/*
|
||||||
|
* ImageToolbox is an image editor for android
|
||||||
|
* Copyright (c) 2025 T8RIN (Malik Mukhametzyanov)
|
||||||
|
*
|
||||||
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
* you may not use this file except in compliance with the License.
|
||||||
|
*
|
||||||
|
* Unless required by applicable law or agreed to in writing, software
|
||||||
|
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
* See the License for the specific language governing permissions and
|
||||||
|
* limitations under the License.
|
||||||
|
*
|
||||||
|
* You should have received a copy of the Apache License
|
||||||
|
* along with this program. If not, see <http://www.apache.org/licenses/LICENSE-2.0>.
|
||||||
|
*/
|
||||||
|
|
||||||
|
package ru.tech.imageresizershrinker.feature.audio_cover_extractor.data
|
||||||
|
|
||||||
|
import android.content.Context
|
||||||
|
import android.graphics.Bitmap
|
||||||
|
import androidx.core.net.toUri
|
||||||
|
import androidx.exifinterface.media.ExifInterface
|
||||||
|
import dagger.hilt.android.qualifiers.ApplicationContext
|
||||||
|
import ru.tech.imageresizershrinker.core.domain.dispatchers.DispatchersHolder
|
||||||
|
import ru.tech.imageresizershrinker.core.domain.image.ImageCompressor
|
||||||
|
import ru.tech.imageresizershrinker.core.domain.image.ImageGetter
|
||||||
|
import ru.tech.imageresizershrinker.core.domain.image.ShareProvider
|
||||||
|
import ru.tech.imageresizershrinker.core.domain.image.model.ImageFormat
|
||||||
|
import ru.tech.imageresizershrinker.core.domain.image.model.Quality
|
||||||
|
import ru.tech.imageresizershrinker.core.domain.resource.ResourceManager
|
||||||
|
import ru.tech.imageresizershrinker.core.resources.R
|
||||||
|
import ru.tech.imageresizershrinker.feature.audio_cover_extractor.domain.AudioCoverRetriever
|
||||||
|
import wseemann.media.FFmpegMediaMetadataRetriever
|
||||||
|
import javax.inject.Inject
|
||||||
|
|
||||||
|
internal class AndroidAudioCoverRetriever @Inject constructor(
|
||||||
|
@ApplicationContext private val context: Context,
|
||||||
|
private val imageCompressor: ImageCompressor<Bitmap>,
|
||||||
|
private val shareProvider: ShareProvider<Bitmap>,
|
||||||
|
private val imageGetter: ImageGetter<Bitmap, ExifInterface>,
|
||||||
|
dispatchersHolder: DispatchersHolder,
|
||||||
|
resourceManager: ResourceManager
|
||||||
|
) : AudioCoverRetriever,
|
||||||
|
DispatchersHolder by dispatchersHolder,
|
||||||
|
ResourceManager by resourceManager {
|
||||||
|
|
||||||
|
override suspend fun loadCover(
|
||||||
|
audioUri: String
|
||||||
|
): Result<String> {
|
||||||
|
val pictureData = FFmpegMediaMetadataRetriever().apply {
|
||||||
|
setDataSource(
|
||||||
|
context,
|
||||||
|
audioUri.toUri()
|
||||||
|
)
|
||||||
|
}.embeddedPicture
|
||||||
|
|
||||||
|
return imageGetter.getImage(
|
||||||
|
data = pictureData,
|
||||||
|
originalSize = true
|
||||||
|
)?.let { bitmap ->
|
||||||
|
shareProvider.cacheData(
|
||||||
|
writeData = {
|
||||||
|
it.writeBytes(
|
||||||
|
imageCompressor.compress(
|
||||||
|
image = bitmap,
|
||||||
|
imageFormat = ImageFormat.Png.Lossless,
|
||||||
|
quality = Quality.Base()
|
||||||
|
)
|
||||||
|
)
|
||||||
|
},
|
||||||
|
filename = "${audioUri.substringBeforeLast('.')}.png"
|
||||||
|
)?.let(Result.Companion::success)
|
||||||
|
} ?: Result.failure(NullPointerException(getString(R.string.no_image)))
|
||||||
|
}
|
||||||
|
|
||||||
|
override suspend fun loadCover(
|
||||||
|
audioData: ByteArray
|
||||||
|
): Result<String> {
|
||||||
|
return loadCover(
|
||||||
|
shareProvider.cacheData(
|
||||||
|
writeData = {
|
||||||
|
it.writeBytes(audioData)
|
||||||
|
},
|
||||||
|
filename = "Audio_data_${System.currentTimeMillis()}.mp3"
|
||||||
|
)
|
||||||
|
?: return Result.failure(NullPointerException(getString(R.string.filename_is_not_set)))
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
}
|
@ -0,0 +1,38 @@
|
|||||||
|
/*
|
||||||
|
* ImageToolbox is an image editor for android
|
||||||
|
* Copyright (c) 2025 T8RIN (Malik Mukhametzyanov)
|
||||||
|
*
|
||||||
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
* you may not use this file except in compliance with the License.
|
||||||
|
*
|
||||||
|
* Unless required by applicable law or agreed to in writing, software
|
||||||
|
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
* See the License for the specific language governing permissions and
|
||||||
|
* limitations under the License.
|
||||||
|
*
|
||||||
|
* You should have received a copy of the Apache License
|
||||||
|
* along with this program. If not, see <http://www.apache.org/licenses/LICENSE-2.0>.
|
||||||
|
*/
|
||||||
|
|
||||||
|
package ru.tech.imageresizershrinker.feature.audio_cover_extractor.di
|
||||||
|
|
||||||
|
import dagger.Binds
|
||||||
|
import dagger.Module
|
||||||
|
import dagger.hilt.InstallIn
|
||||||
|
import dagger.hilt.components.SingletonComponent
|
||||||
|
import ru.tech.imageresizershrinker.feature.audio_cover_extractor.data.AndroidAudioCoverRetriever
|
||||||
|
import ru.tech.imageresizershrinker.feature.audio_cover_extractor.domain.AudioCoverRetriever
|
||||||
|
import javax.inject.Singleton
|
||||||
|
|
||||||
|
@Module
|
||||||
|
@InstallIn(SingletonComponent::class)
|
||||||
|
internal interface AudioCoverExtractorModule {
|
||||||
|
|
||||||
|
@Binds
|
||||||
|
@Singleton
|
||||||
|
fun extractor(
|
||||||
|
impl: AndroidAudioCoverRetriever
|
||||||
|
): AudioCoverRetriever
|
||||||
|
|
||||||
|
}
|
@ -0,0 +1,30 @@
|
|||||||
|
/*
|
||||||
|
* ImageToolbox is an image editor for android
|
||||||
|
* Copyright (c) 2025 T8RIN (Malik Mukhametzyanov)
|
||||||
|
*
|
||||||
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
* you may not use this file except in compliance with the License.
|
||||||
|
*
|
||||||
|
* Unless required by applicable law or agreed to in writing, software
|
||||||
|
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
* See the License for the specific language governing permissions and
|
||||||
|
* limitations under the License.
|
||||||
|
*
|
||||||
|
* You should have received a copy of the Apache License
|
||||||
|
* along with this program. If not, see <http://www.apache.org/licenses/LICENSE-2.0>.
|
||||||
|
*/
|
||||||
|
|
||||||
|
package ru.tech.imageresizershrinker.feature.audio_cover_extractor.domain
|
||||||
|
|
||||||
|
interface AudioCoverRetriever {
|
||||||
|
|
||||||
|
suspend fun loadCover(
|
||||||
|
audioUri: String
|
||||||
|
): Result<String>
|
||||||
|
|
||||||
|
suspend fun loadCover(
|
||||||
|
audioData: ByteArray
|
||||||
|
): Result<String>
|
||||||
|
|
||||||
|
}
|
@ -0,0 +1,28 @@
|
|||||||
|
/*
|
||||||
|
* ImageToolbox is an image editor for android
|
||||||
|
* Copyright (c) 2025 T8RIN (Malik Mukhametzyanov)
|
||||||
|
*
|
||||||
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
* you may not use this file except in compliance with the License.
|
||||||
|
*
|
||||||
|
* Unless required by applicable law or agreed to in writing, software
|
||||||
|
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
* See the License for the specific language governing permissions and
|
||||||
|
* limitations under the License.
|
||||||
|
*
|
||||||
|
* You should have received a copy of the Apache License
|
||||||
|
* along with this program. If not, see <http://www.apache.org/licenses/LICENSE-2.0>.
|
||||||
|
*/
|
||||||
|
|
||||||
|
package ru.tech.imageresizershrinker.feature.audio_cover_extractor.ui
|
||||||
|
|
||||||
|
import androidx.compose.runtime.Composable
|
||||||
|
import ru.tech.imageresizershrinker.feature.audio_cover_extractor.ui.screenLogic.AudioCoverExtractorComponent
|
||||||
|
|
||||||
|
@Composable
|
||||||
|
fun AudioCoverExtractorContent(
|
||||||
|
component: AudioCoverExtractorComponent
|
||||||
|
) {
|
||||||
|
|
||||||
|
}
|
@ -0,0 +1,26 @@
|
|||||||
|
/*
|
||||||
|
* ImageToolbox is an image editor for android
|
||||||
|
* Copyright (c) 2025 T8RIN (Malik Mukhametzyanov)
|
||||||
|
*
|
||||||
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
* you may not use this file except in compliance with the License.
|
||||||
|
*
|
||||||
|
* Unless required by applicable law or agreed to in writing, software
|
||||||
|
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
* See the License for the specific language governing permissions and
|
||||||
|
* limitations under the License.
|
||||||
|
*
|
||||||
|
* You should have received a copy of the Apache License
|
||||||
|
* along with this program. If not, see <http://www.apache.org/licenses/LICENSE-2.0>.
|
||||||
|
*/
|
||||||
|
|
||||||
|
package ru.tech.imageresizershrinker.feature.audio_cover_extractor.ui.components
|
||||||
|
|
||||||
|
import android.net.Uri
|
||||||
|
|
||||||
|
data class AudioWithCover(
|
||||||
|
val audioUri: Uri,
|
||||||
|
val imageCoverUri: Uri?,
|
||||||
|
val isLoading: Boolean
|
||||||
|
)
|
@ -0,0 +1,109 @@
|
|||||||
|
/*
|
||||||
|
* ImageToolbox is an image editor for android
|
||||||
|
* Copyright (c) 2025 T8RIN (Malik Mukhametzyanov)
|
||||||
|
*
|
||||||
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
* you may not use this file except in compliance with the License.
|
||||||
|
*
|
||||||
|
* Unless required by applicable law or agreed to in writing, software
|
||||||
|
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
* See the License for the specific language governing permissions and
|
||||||
|
* limitations under the License.
|
||||||
|
*
|
||||||
|
* You should have received a copy of the Apache License
|
||||||
|
* along with this program. If not, see <http://www.apache.org/licenses/LICENSE-2.0>.
|
||||||
|
*/
|
||||||
|
|
||||||
|
package ru.tech.imageresizershrinker.feature.audio_cover_extractor.ui.screenLogic
|
||||||
|
|
||||||
|
import android.net.Uri
|
||||||
|
import androidx.core.net.toUri
|
||||||
|
import com.arkivanov.decompose.ComponentContext
|
||||||
|
import dagger.assisted.Assisted
|
||||||
|
import dagger.assisted.AssistedFactory
|
||||||
|
import dagger.assisted.AssistedInject
|
||||||
|
import kotlinx.coroutines.async
|
||||||
|
import kotlinx.coroutines.awaitAll
|
||||||
|
import kotlinx.coroutines.flow.MutableStateFlow
|
||||||
|
import kotlinx.coroutines.flow.StateFlow
|
||||||
|
import kotlinx.coroutines.flow.asStateFlow
|
||||||
|
import kotlinx.coroutines.flow.update
|
||||||
|
import ru.tech.imageresizershrinker.core.domain.dispatchers.DispatchersHolder
|
||||||
|
import ru.tech.imageresizershrinker.core.ui.utils.BaseComponent
|
||||||
|
import ru.tech.imageresizershrinker.core.ui.utils.navigation.Screen
|
||||||
|
import ru.tech.imageresizershrinker.feature.audio_cover_extractor.domain.AudioCoverRetriever
|
||||||
|
import ru.tech.imageresizershrinker.feature.audio_cover_extractor.ui.components.AudioWithCover
|
||||||
|
|
||||||
|
class AudioCoverExtractorComponent @AssistedInject constructor(
|
||||||
|
@Assisted componentContext: ComponentContext,
|
||||||
|
@Assisted val initialUris: List<Uri>?,
|
||||||
|
@Assisted val onGoBack: () -> Unit,
|
||||||
|
@Assisted val onNavigate: (Screen) -> Unit,
|
||||||
|
private val audioCoverRetriever: AudioCoverRetriever,
|
||||||
|
dispatchersHolder: DispatchersHolder
|
||||||
|
) : BaseComponent(dispatchersHolder, componentContext) {
|
||||||
|
|
||||||
|
init {
|
||||||
|
debounce {
|
||||||
|
initialUris?.let(::updateCovers)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private val _covers: MutableStateFlow<List<AudioWithCover>> = MutableStateFlow(emptyList())
|
||||||
|
val covers: StateFlow<List<AudioWithCover>> = _covers.asStateFlow()
|
||||||
|
|
||||||
|
|
||||||
|
fun updateCovers(uris: List<Uri>) {
|
||||||
|
val audioUris = uris.distinct()
|
||||||
|
|
||||||
|
componentScope.launch {
|
||||||
|
_covers.update {
|
||||||
|
audioUris.map {
|
||||||
|
AudioWithCover(
|
||||||
|
audioUri = it,
|
||||||
|
imageCoverUri = null,
|
||||||
|
isLoading = true
|
||||||
|
)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
val newCovers = audioUris.map { audioUri ->
|
||||||
|
async {
|
||||||
|
val coverUri = audioCoverRetriever.loadCover(audioUri.toString()).getOrNull()
|
||||||
|
|
||||||
|
val newCover = AudioWithCover(
|
||||||
|
audioUri = audioUri,
|
||||||
|
imageCoverUri = coverUri?.toUri(),
|
||||||
|
isLoading = false
|
||||||
|
)
|
||||||
|
|
||||||
|
_covers.update { covers ->
|
||||||
|
covers.toMutableList().apply {
|
||||||
|
val index = indexOfFirst { it.audioUri == audioUri }.takeIf { it >= 0 }
|
||||||
|
?: return@update covers
|
||||||
|
|
||||||
|
set(index, newCover)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
newCover
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
_covers.update {
|
||||||
|
newCovers.awaitAll().filter { it.imageCoverUri != null }
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@AssistedFactory
|
||||||
|
fun interface Factory {
|
||||||
|
operator fun invoke(
|
||||||
|
componentContext: ComponentContext,
|
||||||
|
initialUris: List<Uri>?,
|
||||||
|
onGoBack: () -> Unit,
|
||||||
|
onNavigate: (Screen) -> Unit,
|
||||||
|
): AudioCoverExtractorComponent
|
||||||
|
}
|
||||||
|
}
|
@ -31,9 +31,7 @@ import coil3.request.ImageRequest
|
|||||||
import coil3.size.Size
|
import coil3.size.Size
|
||||||
import coil3.toBitmap
|
import coil3.toBitmap
|
||||||
import dagger.hilt.android.qualifiers.ApplicationContext
|
import dagger.hilt.android.qualifiers.ApplicationContext
|
||||||
import kotlinx.coroutines.CoroutineScope
|
|
||||||
import kotlinx.coroutines.delay
|
import kotlinx.coroutines.delay
|
||||||
import kotlinx.coroutines.launch
|
|
||||||
import kotlinx.coroutines.withContext
|
import kotlinx.coroutines.withContext
|
||||||
import ru.tech.imageresizershrinker.core.data.utils.aspectRatio
|
import ru.tech.imageresizershrinker.core.data.utils.aspectRatio
|
||||||
import ru.tech.imageresizershrinker.core.data.utils.getSuitableConfig
|
import ru.tech.imageresizershrinker.core.data.utils.getSuitableConfig
|
||||||
@ -108,17 +106,16 @@ internal class AndroidPdfManager @Inject constructor(
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun convertPdfToImages(
|
override suspend fun convertPdfToImages(
|
||||||
pdfUri: String,
|
pdfUri: String,
|
||||||
pages: List<Int>?,
|
pages: List<Int>?,
|
||||||
preset: Preset.Percentage,
|
preset: Preset.Percentage,
|
||||||
onGetPagesCount: suspend (Int) -> Unit,
|
onGetPagesCount: suspend (Int) -> Unit,
|
||||||
onProgressChange: suspend (Int, Bitmap) -> Unit,
|
onProgressChange: suspend (Int, Bitmap) -> Unit,
|
||||||
onComplete: suspend () -> Unit
|
onComplete: suspend () -> Unit
|
||||||
) = CoroutineScope(ioDispatcher).launch {
|
): Unit = withContext(ioDispatcher) {
|
||||||
context.contentResolver.openFileDescriptor(
|
context.contentResolver.openFileDescriptor(
|
||||||
pdfUri.toUri(),
|
pdfUri.toUri(), "r"
|
||||||
"r"
|
|
||||||
)?.use { fileDescriptor ->
|
)?.use { fileDescriptor ->
|
||||||
withContext(defaultDispatcher) {
|
withContext(defaultDispatcher) {
|
||||||
val pdfRenderer = PdfRenderer(fileDescriptor)
|
val pdfRenderer = PdfRenderer(fileDescriptor)
|
||||||
|
@ -17,7 +17,6 @@
|
|||||||
|
|
||||||
package ru.tech.imageresizershrinker.feature.pdf_tools.domain
|
package ru.tech.imageresizershrinker.feature.pdf_tools.domain
|
||||||
|
|
||||||
import kotlinx.coroutines.Job
|
|
||||||
import ru.tech.imageresizershrinker.core.domain.image.model.Preset
|
import ru.tech.imageresizershrinker.core.domain.image.model.Preset
|
||||||
import ru.tech.imageresizershrinker.core.domain.model.IntegerSize
|
import ru.tech.imageresizershrinker.core.domain.model.IntegerSize
|
||||||
|
|
||||||
@ -34,13 +33,13 @@ interface PdfManager<I> {
|
|||||||
preset: Preset.Percentage
|
preset: Preset.Percentage
|
||||||
): ByteArray
|
): ByteArray
|
||||||
|
|
||||||
fun convertPdfToImages(
|
suspend fun convertPdfToImages(
|
||||||
pdfUri: String,
|
pdfUri: String,
|
||||||
pages: List<Int>?,
|
pages: List<Int>?,
|
||||||
preset: Preset.Percentage,
|
preset: Preset.Percentage,
|
||||||
onGetPagesCount: suspend (Int) -> Unit,
|
onGetPagesCount: suspend (Int) -> Unit,
|
||||||
onProgressChange: suspend (Int, I) -> Unit,
|
onProgressChange: suspend (Int, I) -> Unit,
|
||||||
onComplete: suspend () -> Unit = {}
|
onComplete: suspend () -> Unit = {}
|
||||||
): Job
|
)
|
||||||
|
|
||||||
}
|
}
|
@ -215,44 +215,46 @@ class PdfToolsComponent @AssistedInject internal constructor(
|
|||||||
_done.value = 0
|
_done.value = 0
|
||||||
_left.value = 1
|
_left.value = 1
|
||||||
val results = mutableListOf<SaveResult>()
|
val results = mutableListOf<SaveResult>()
|
||||||
savingJob = pdfManager.convertPdfToImages(
|
savingJob = componentScope.launch {
|
||||||
pdfUri = _pdfToImageState.value?.uri.toString(),
|
pdfManager.convertPdfToImages(
|
||||||
pages = _pdfToImageState.value?.selectedPages,
|
pdfUri = _pdfToImageState.value?.uri.toString(),
|
||||||
preset = presetSelected,
|
pages = _pdfToImageState.value?.selectedPages,
|
||||||
onProgressChange = { _, bitmap ->
|
preset = presetSelected,
|
||||||
val imageInfo = imageTransformer.applyPresetBy(
|
onProgressChange = { _, bitmap ->
|
||||||
image = bitmap,
|
val imageInfo = imageTransformer.applyPresetBy(
|
||||||
preset = _presetSelected.value,
|
image = bitmap,
|
||||||
currentInfo = imageInfo
|
preset = _presetSelected.value,
|
||||||
)
|
currentInfo = imageInfo
|
||||||
|
|
||||||
results.add(
|
|
||||||
fileController.save(
|
|
||||||
saveTarget = ImageSaveTarget(
|
|
||||||
imageInfo = imageInfo,
|
|
||||||
metadata = null,
|
|
||||||
originalUri = _pdfToImageState.value?.uri.toString(),
|
|
||||||
sequenceNumber = _done.value + 1,
|
|
||||||
data = imageCompressor.compressAndTransform(
|
|
||||||
image = bitmap,
|
|
||||||
imageInfo = imageInfo
|
|
||||||
)
|
|
||||||
),
|
|
||||||
keepOriginalMetadata = false,
|
|
||||||
oneTimeSaveLocationUri = oneTimeSaveLocationUri
|
|
||||||
)
|
)
|
||||||
)
|
|
||||||
_done.value += 1
|
results.add(
|
||||||
},
|
fileController.save(
|
||||||
onGetPagesCount = { size ->
|
saveTarget = ImageSaveTarget(
|
||||||
_left.update { size }
|
imageInfo = imageInfo,
|
||||||
_isSaving.value = true
|
metadata = null,
|
||||||
},
|
originalUri = _pdfToImageState.value?.uri.toString(),
|
||||||
onComplete = {
|
sequenceNumber = _done.value + 1,
|
||||||
_isSaving.value = false
|
data = imageCompressor.compressAndTransform(
|
||||||
onComplete(results.onSuccess(::registerSave))
|
image = bitmap,
|
||||||
}
|
imageInfo = imageInfo
|
||||||
)
|
)
|
||||||
|
),
|
||||||
|
keepOriginalMetadata = false,
|
||||||
|
oneTimeSaveLocationUri = oneTimeSaveLocationUri
|
||||||
|
)
|
||||||
|
)
|
||||||
|
_done.value += 1
|
||||||
|
},
|
||||||
|
onGetPagesCount = { size ->
|
||||||
|
_left.update { size }
|
||||||
|
_isSaving.value = true
|
||||||
|
},
|
||||||
|
onComplete = {
|
||||||
|
_isSaving.value = false
|
||||||
|
onComplete(results.onSuccess(::registerSave))
|
||||||
|
}
|
||||||
|
)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fun convertImagesToPdf(onComplete: () -> Unit) {
|
fun convertImagesToPdf(onComplete: () -> Unit) {
|
||||||
@ -315,39 +317,41 @@ class PdfToolsComponent @AssistedInject internal constructor(
|
|||||||
_left.value = 1
|
_left.value = 1
|
||||||
_isSaving.value = false
|
_isSaving.value = false
|
||||||
val uris: MutableList<String?> = mutableListOf()
|
val uris: MutableList<String?> = mutableListOf()
|
||||||
savingJob = pdfManager.convertPdfToImages(
|
savingJob = componentScope.launch {
|
||||||
pdfUri = _pdfToImageState.value?.uri.toString(),
|
pdfManager.convertPdfToImages(
|
||||||
pages = _pdfToImageState.value?.selectedPages,
|
pdfUri = _pdfToImageState.value?.uri.toString(),
|
||||||
onProgressChange = { _, bitmap ->
|
pages = _pdfToImageState.value?.selectedPages,
|
||||||
imageInfo.copy(
|
onProgressChange = { _, bitmap ->
|
||||||
originalUri = _pdfToImageState.value?.uri?.toString()
|
imageInfo.copy(
|
||||||
).let {
|
originalUri = _pdfToImageState.value?.uri?.toString()
|
||||||
imageTransformer.applyPresetBy(
|
).let {
|
||||||
image = bitmap,
|
imageTransformer.applyPresetBy(
|
||||||
preset = _presetSelected.value,
|
image = bitmap,
|
||||||
currentInfo = it
|
preset = _presetSelected.value,
|
||||||
)
|
currentInfo = it
|
||||||
}.apply {
|
|
||||||
uris.add(
|
|
||||||
shareProvider.cacheImage(
|
|
||||||
imageInfo = this,
|
|
||||||
image = bitmap
|
|
||||||
)
|
)
|
||||||
)
|
}.apply {
|
||||||
|
uris.add(
|
||||||
|
shareProvider.cacheImage(
|
||||||
|
imageInfo = this,
|
||||||
|
image = bitmap
|
||||||
|
)
|
||||||
|
)
|
||||||
|
}
|
||||||
|
_done.value += 1
|
||||||
|
},
|
||||||
|
preset = presetSelected,
|
||||||
|
onGetPagesCount = { size ->
|
||||||
|
_left.update { size }
|
||||||
|
_isSaving.value = true
|
||||||
|
},
|
||||||
|
onComplete = {
|
||||||
|
_isSaving.value = false
|
||||||
|
shareProvider.shareUris(uris.filterNotNull())
|
||||||
|
onComplete()
|
||||||
}
|
}
|
||||||
_done.value += 1
|
)
|
||||||
},
|
}
|
||||||
preset = presetSelected,
|
|
||||||
onGetPagesCount = { size ->
|
|
||||||
_left.update { size }
|
|
||||||
_isSaving.value = true
|
|
||||||
},
|
|
||||||
onComplete = {
|
|
||||||
_isSaving.value = false
|
|
||||||
shareProvider.shareUris(uris.filterNotNull())
|
|
||||||
onComplete()
|
|
||||||
}
|
|
||||||
)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
is Screen.PdfTools.Type.Preview -> {
|
is Screen.PdfTools.Type.Preview -> {
|
||||||
|
@ -69,4 +69,5 @@ dependencies {
|
|||||||
implementation(projects.feature.meshGradients)
|
implementation(projects.feature.meshGradients)
|
||||||
implementation(projects.feature.editExif)
|
implementation(projects.feature.editExif)
|
||||||
implementation(projects.feature.imageCutting)
|
implementation(projects.feature.imageCutting)
|
||||||
|
implementation(projects.feature.audioCoverExtractor)
|
||||||
}
|
}
|
@ -22,6 +22,7 @@ import ru.tech.imageresizershrinker.collage_maker.presentation.screenLogic.Colla
|
|||||||
import ru.tech.imageresizershrinker.color_tools.presentation.screenLogic.ColorToolsComponent
|
import ru.tech.imageresizershrinker.color_tools.presentation.screenLogic.ColorToolsComponent
|
||||||
import ru.tech.imageresizershrinker.core.ui.utils.navigation.Screen
|
import ru.tech.imageresizershrinker.core.ui.utils.navigation.Screen
|
||||||
import ru.tech.imageresizershrinker.feature.apng_tools.presentation.screenLogic.ApngToolsComponent
|
import ru.tech.imageresizershrinker.feature.apng_tools.presentation.screenLogic.ApngToolsComponent
|
||||||
|
import ru.tech.imageresizershrinker.feature.audio_cover_extractor.ui.screenLogic.AudioCoverExtractorComponent
|
||||||
import ru.tech.imageresizershrinker.feature.base64_tools.presentation.screenLogic.Base64ToolsComponent
|
import ru.tech.imageresizershrinker.feature.base64_tools.presentation.screenLogic.Base64ToolsComponent
|
||||||
import ru.tech.imageresizershrinker.feature.checksum_tools.presentation.screenLogic.ChecksumToolsComponent
|
import ru.tech.imageresizershrinker.feature.checksum_tools.presentation.screenLogic.ChecksumToolsComponent
|
||||||
import ru.tech.imageresizershrinker.feature.cipher.presentation.screenLogic.CipherComponent
|
import ru.tech.imageresizershrinker.feature.cipher.presentation.screenLogic.CipherComponent
|
||||||
@ -53,6 +54,7 @@ import ru.tech.imageresizershrinker.feature.pick_color.presentation.screenLogic.
|
|||||||
import ru.tech.imageresizershrinker.feature.recognize.text.presentation.screenLogic.RecognizeTextComponent
|
import ru.tech.imageresizershrinker.feature.recognize.text.presentation.screenLogic.RecognizeTextComponent
|
||||||
import ru.tech.imageresizershrinker.feature.resize_convert.presentation.screenLogic.ResizeAndConvertComponent
|
import ru.tech.imageresizershrinker.feature.resize_convert.presentation.screenLogic.ResizeAndConvertComponent
|
||||||
import ru.tech.imageresizershrinker.feature.root.presentation.components.navigation.NavigationChild.ApngTools
|
import ru.tech.imageresizershrinker.feature.root.presentation.components.navigation.NavigationChild.ApngTools
|
||||||
|
import ru.tech.imageresizershrinker.feature.root.presentation.components.navigation.NavigationChild.AudioCoverExtractor
|
||||||
import ru.tech.imageresizershrinker.feature.root.presentation.components.navigation.NavigationChild.Base64Tools
|
import ru.tech.imageresizershrinker.feature.root.presentation.components.navigation.NavigationChild.Base64Tools
|
||||||
import ru.tech.imageresizershrinker.feature.root.presentation.components.navigation.NavigationChild.ChecksumTools
|
import ru.tech.imageresizershrinker.feature.root.presentation.components.navigation.NavigationChild.ChecksumTools
|
||||||
import ru.tech.imageresizershrinker.feature.root.presentation.components.navigation.NavigationChild.Cipher
|
import ru.tech.imageresizershrinker.feature.root.presentation.components.navigation.NavigationChild.Cipher
|
||||||
@ -154,7 +156,8 @@ internal class ChildProvider @Inject constructor(
|
|||||||
private val checksumToolsComponentFactory: ChecksumToolsComponent.Factory,
|
private val checksumToolsComponentFactory: ChecksumToolsComponent.Factory,
|
||||||
private val meshGradientsComponentFactory: MeshGradientsComponent.Factory,
|
private val meshGradientsComponentFactory: MeshGradientsComponent.Factory,
|
||||||
private val editExifComponentFactory: EditExifComponent.Factory,
|
private val editExifComponentFactory: EditExifComponent.Factory,
|
||||||
private val imageCutterComponentFactory: ImageCutterComponent.Factory
|
private val imageCutterComponentFactory: ImageCutterComponent.Factory,
|
||||||
|
private val audioCoverExtractorComponentFactory: AudioCoverExtractorComponent.Factory
|
||||||
) {
|
) {
|
||||||
fun RootComponent.createChild(
|
fun RootComponent.createChild(
|
||||||
config: Screen,
|
config: Screen,
|
||||||
@ -541,5 +544,14 @@ internal class ChildProvider @Inject constructor(
|
|||||||
onNavigate = ::navigateTo
|
onNavigate = ::navigateTo
|
||||||
)
|
)
|
||||||
)
|
)
|
||||||
|
|
||||||
|
is Screen.AudioCoverExtractor -> AudioCoverExtractor(
|
||||||
|
audioCoverExtractorComponentFactory(
|
||||||
|
componentContext = componentContext,
|
||||||
|
initialUris = config.uris,
|
||||||
|
onGoBack = ::navigateBack,
|
||||||
|
onNavigate = ::navigateTo
|
||||||
|
)
|
||||||
|
)
|
||||||
}
|
}
|
||||||
}
|
}
|
@ -24,6 +24,8 @@ import ru.tech.imageresizershrinker.color_tools.presentation.ColorToolsContent
|
|||||||
import ru.tech.imageresizershrinker.color_tools.presentation.screenLogic.ColorToolsComponent
|
import ru.tech.imageresizershrinker.color_tools.presentation.screenLogic.ColorToolsComponent
|
||||||
import ru.tech.imageresizershrinker.feature.apng_tools.presentation.ApngToolsContent
|
import ru.tech.imageresizershrinker.feature.apng_tools.presentation.ApngToolsContent
|
||||||
import ru.tech.imageresizershrinker.feature.apng_tools.presentation.screenLogic.ApngToolsComponent
|
import ru.tech.imageresizershrinker.feature.apng_tools.presentation.screenLogic.ApngToolsComponent
|
||||||
|
import ru.tech.imageresizershrinker.feature.audio_cover_extractor.ui.AudioCoverExtractorContent
|
||||||
|
import ru.tech.imageresizershrinker.feature.audio_cover_extractor.ui.screenLogic.AudioCoverExtractorComponent
|
||||||
import ru.tech.imageresizershrinker.feature.base64_tools.presentation.Base64ToolsContent
|
import ru.tech.imageresizershrinker.feature.base64_tools.presentation.Base64ToolsContent
|
||||||
import ru.tech.imageresizershrinker.feature.base64_tools.presentation.screenLogic.Base64ToolsComponent
|
import ru.tech.imageresizershrinker.feature.base64_tools.presentation.screenLogic.Base64ToolsComponent
|
||||||
import ru.tech.imageresizershrinker.feature.checksum_tools.presentation.ChecksumToolsContent
|
import ru.tech.imageresizershrinker.feature.checksum_tools.presentation.ChecksumToolsContent
|
||||||
@ -108,230 +110,237 @@ import ru.tech.imageresizershrinker.noise_generation.presentation.NoiseGeneratio
|
|||||||
import ru.tech.imageresizershrinker.noise_generation.presentation.screenLogic.NoiseGenerationComponent
|
import ru.tech.imageresizershrinker.noise_generation.presentation.screenLogic.NoiseGenerationComponent
|
||||||
|
|
||||||
|
|
||||||
internal sealed class NavigationChild {
|
internal sealed interface NavigationChild {
|
||||||
|
|
||||||
@Composable
|
@Composable
|
||||||
abstract fun Content()
|
fun Content()
|
||||||
|
|
||||||
|
|
||||||
class ApngTools(val component: ApngToolsComponent) : NavigationChild() {
|
class ApngTools(private val component: ApngToolsComponent) : NavigationChild {
|
||||||
@Composable
|
@Composable
|
||||||
override fun Content() = ApngToolsContent(component)
|
override fun Content() = ApngToolsContent(component)
|
||||||
}
|
}
|
||||||
|
|
||||||
class Cipher(val component: CipherComponent) : NavigationChild() {
|
class Cipher(private val component: CipherComponent) : NavigationChild {
|
||||||
@Composable
|
@Composable
|
||||||
override fun Content() = CipherContent(component)
|
override fun Content() = CipherContent(component)
|
||||||
}
|
}
|
||||||
|
|
||||||
class CollageMaker(val component: CollageMakerComponent) : NavigationChild() {
|
class CollageMaker(private val component: CollageMakerComponent) : NavigationChild {
|
||||||
@Composable
|
@Composable
|
||||||
override fun Content() = CollageMakerContent(component)
|
override fun Content() = CollageMakerContent(component)
|
||||||
}
|
}
|
||||||
|
|
||||||
class ColorTools(val component: ColorToolsComponent) : NavigationChild() {
|
class ColorTools(private val component: ColorToolsComponent) : NavigationChild {
|
||||||
@Composable
|
@Composable
|
||||||
override fun Content() = ColorToolsContent(component)
|
override fun Content() = ColorToolsContent(component)
|
||||||
}
|
}
|
||||||
|
|
||||||
class Compare(val component: CompareComponent) : NavigationChild() {
|
class Compare(private val component: CompareComponent) : NavigationChild {
|
||||||
@Composable
|
@Composable
|
||||||
override fun Content() = CompareContent(component)
|
override fun Content() = CompareContent(component)
|
||||||
}
|
}
|
||||||
|
|
||||||
class Crop(val component: CropComponent) : NavigationChild() {
|
class Crop(private val component: CropComponent) : NavigationChild {
|
||||||
@Composable
|
@Composable
|
||||||
override fun Content() = CropContent(component)
|
override fun Content() = CropContent(component)
|
||||||
}
|
}
|
||||||
|
|
||||||
class DeleteExif(val component: DeleteExifComponent) : NavigationChild() {
|
class DeleteExif(private val component: DeleteExifComponent) : NavigationChild {
|
||||||
@Composable
|
@Composable
|
||||||
override fun Content() = DeleteExifContent(component)
|
override fun Content() = DeleteExifContent(component)
|
||||||
}
|
}
|
||||||
|
|
||||||
class DocumentScanner(val component: DocumentScannerComponent) : NavigationChild() {
|
class DocumentScanner(private val component: DocumentScannerComponent) : NavigationChild {
|
||||||
@Composable
|
@Composable
|
||||||
override fun Content() = DocumentScannerContent(component)
|
override fun Content() = DocumentScannerContent(component)
|
||||||
}
|
}
|
||||||
|
|
||||||
class Draw(val component: DrawComponent) : NavigationChild() {
|
class Draw(private val component: DrawComponent) : NavigationChild {
|
||||||
@Composable
|
@Composable
|
||||||
override fun Content() = DrawContent(component)
|
override fun Content() = DrawContent(component)
|
||||||
}
|
}
|
||||||
|
|
||||||
class EasterEgg(val component: EasterEggComponent) : NavigationChild() {
|
class EasterEgg(private val component: EasterEggComponent) : NavigationChild {
|
||||||
@Composable
|
@Composable
|
||||||
override fun Content() = EasterEggContent(component)
|
override fun Content() = EasterEggContent(component)
|
||||||
}
|
}
|
||||||
|
|
||||||
class EraseBackground(val component: EraseBackgroundComponent) : NavigationChild() {
|
class EraseBackground(private val component: EraseBackgroundComponent) : NavigationChild {
|
||||||
@Composable
|
@Composable
|
||||||
override fun Content() = EraseBackgroundContent(component)
|
override fun Content() = EraseBackgroundContent(component)
|
||||||
}
|
}
|
||||||
|
|
||||||
class Filter(val component: FiltersComponent) : NavigationChild() {
|
class Filter(private val component: FiltersComponent) : NavigationChild {
|
||||||
@Composable
|
@Composable
|
||||||
override fun Content() = FiltersContent(component)
|
override fun Content() = FiltersContent(component)
|
||||||
}
|
}
|
||||||
|
|
||||||
class FormatConversion(val component: FormatConversionComponent) : NavigationChild() {
|
class FormatConversion(private val component: FormatConversionComponent) : NavigationChild {
|
||||||
@Composable
|
@Composable
|
||||||
override fun Content() = FormatConversionContent(component)
|
override fun Content() = FormatConversionContent(component)
|
||||||
}
|
}
|
||||||
|
|
||||||
class GeneratePalette(val component: GeneratePaletteComponent) : NavigationChild() {
|
class GeneratePalette(private val component: GeneratePaletteComponent) : NavigationChild {
|
||||||
@Composable
|
@Composable
|
||||||
override fun Content() = GeneratePaletteContent(component)
|
override fun Content() = GeneratePaletteContent(component)
|
||||||
}
|
}
|
||||||
|
|
||||||
class GifTools(val component: GifToolsComponent) : NavigationChild() {
|
class GifTools(private val component: GifToolsComponent) : NavigationChild {
|
||||||
@Composable
|
@Composable
|
||||||
override fun Content() = GifToolsContent(component)
|
override fun Content() = GifToolsContent(component)
|
||||||
}
|
}
|
||||||
|
|
||||||
class GradientMaker(val component: GradientMakerComponent) : NavigationChild() {
|
class GradientMaker(private val component: GradientMakerComponent) : NavigationChild {
|
||||||
@Composable
|
@Composable
|
||||||
override fun Content() = GradientMakerContent(component)
|
override fun Content() = GradientMakerContent(component)
|
||||||
}
|
}
|
||||||
|
|
||||||
class ImagePreview(val component: ImagePreviewComponent) : NavigationChild() {
|
class ImagePreview(private val component: ImagePreviewComponent) : NavigationChild {
|
||||||
@Composable
|
@Composable
|
||||||
override fun Content() = ImagePreviewContent(component)
|
override fun Content() = ImagePreviewContent(component)
|
||||||
}
|
}
|
||||||
|
|
||||||
class ImageSplitting(val component: ImageSplitterComponent) : NavigationChild() {
|
class ImageSplitting(private val component: ImageSplitterComponent) : NavigationChild {
|
||||||
@Composable
|
@Composable
|
||||||
override fun Content() = ImageSplitterContent(component)
|
override fun Content() = ImageSplitterContent(component)
|
||||||
}
|
}
|
||||||
|
|
||||||
class ImageStacking(val component: ImageStackingComponent) : NavigationChild() {
|
class ImageStacking(private val component: ImageStackingComponent) : NavigationChild {
|
||||||
@Composable
|
@Composable
|
||||||
override fun Content() = ImageStackingContent(component)
|
override fun Content() = ImageStackingContent(component)
|
||||||
}
|
}
|
||||||
|
|
||||||
class ImageStitching(val component: ImageStitchingComponent) : NavigationChild() {
|
class ImageStitching(private val component: ImageStitchingComponent) : NavigationChild {
|
||||||
@Composable
|
@Composable
|
||||||
override fun Content() = ImageStitchingContent(component)
|
override fun Content() = ImageStitchingContent(component)
|
||||||
}
|
}
|
||||||
|
|
||||||
class JxlTools(val component: JxlToolsComponent) : NavigationChild() {
|
class JxlTools(private val component: JxlToolsComponent) : NavigationChild {
|
||||||
@Composable
|
@Composable
|
||||||
override fun Content() = JxlToolsContent(component)
|
override fun Content() = JxlToolsContent(component)
|
||||||
}
|
}
|
||||||
|
|
||||||
class LimitResize(val component: LimitsResizeComponent) : NavigationChild() {
|
class LimitResize(private val component: LimitsResizeComponent) : NavigationChild {
|
||||||
@Composable
|
@Composable
|
||||||
override fun Content() = LimitsResizeContent(component)
|
override fun Content() = LimitsResizeContent(component)
|
||||||
}
|
}
|
||||||
|
|
||||||
class LoadNetImage(val component: LoadNetImageComponent) : NavigationChild() {
|
class LoadNetImage(private val component: LoadNetImageComponent) : NavigationChild {
|
||||||
@Composable
|
@Composable
|
||||||
override fun Content() = LoadNetImageContent(component)
|
override fun Content() = LoadNetImageContent(component)
|
||||||
}
|
}
|
||||||
|
|
||||||
class Main(val component: MainComponent) : NavigationChild() {
|
class Main(private val component: MainComponent) : NavigationChild {
|
||||||
@Composable
|
@Composable
|
||||||
override fun Content() = MainContent(component)
|
override fun Content() = MainContent(component)
|
||||||
}
|
}
|
||||||
|
|
||||||
class NoiseGeneration(val component: NoiseGenerationComponent) : NavigationChild() {
|
class NoiseGeneration(private val component: NoiseGenerationComponent) : NavigationChild {
|
||||||
@Composable
|
@Composable
|
||||||
override fun Content() = NoiseGenerationContent(component)
|
override fun Content() = NoiseGenerationContent(component)
|
||||||
}
|
}
|
||||||
|
|
||||||
class PdfTools(val component: PdfToolsComponent) : NavigationChild() {
|
class PdfTools(private val component: PdfToolsComponent) : NavigationChild {
|
||||||
@Composable
|
@Composable
|
||||||
override fun Content() = PdfToolsContent(component)
|
override fun Content() = PdfToolsContent(component)
|
||||||
}
|
}
|
||||||
|
|
||||||
class PickColorFromImage(val component: PickColorFromImageComponent) : NavigationChild() {
|
class PickColorFromImage(private val component: PickColorFromImageComponent) : NavigationChild {
|
||||||
@Composable
|
@Composable
|
||||||
override fun Content() = PickColorFromImageContent(component)
|
override fun Content() = PickColorFromImageContent(component)
|
||||||
}
|
}
|
||||||
|
|
||||||
class RecognizeText(val component: RecognizeTextComponent) : NavigationChild() {
|
class RecognizeText(private val component: RecognizeTextComponent) : NavigationChild {
|
||||||
@Composable
|
@Composable
|
||||||
override fun Content() = RecognizeTextContent(component)
|
override fun Content() = RecognizeTextContent(component)
|
||||||
}
|
}
|
||||||
|
|
||||||
class ResizeAndConvert(val component: ResizeAndConvertComponent) : NavigationChild() {
|
class ResizeAndConvert(private val component: ResizeAndConvertComponent) : NavigationChild {
|
||||||
@Composable
|
@Composable
|
||||||
override fun Content() = ResizeAndConvertContent(component)
|
override fun Content() = ResizeAndConvertContent(component)
|
||||||
}
|
}
|
||||||
|
|
||||||
class ScanQrCode(val component: ScanQrCodeComponent) : NavigationChild() {
|
class ScanQrCode(private val component: ScanQrCodeComponent) : NavigationChild {
|
||||||
@Composable
|
@Composable
|
||||||
override fun Content() = ScanQrCodeContent(component)
|
override fun Content() = ScanQrCodeContent(component)
|
||||||
}
|
}
|
||||||
|
|
||||||
class Settings(val component: SettingsComponent) : NavigationChild() {
|
class Settings(private val component: SettingsComponent) : NavigationChild {
|
||||||
@Composable
|
@Composable
|
||||||
override fun Content() = SettingsContent(component)
|
override fun Content() = SettingsContent(component)
|
||||||
}
|
}
|
||||||
|
|
||||||
class SingleEdit(val component: SingleEditComponent) : NavigationChild() {
|
class SingleEdit(private val component: SingleEditComponent) : NavigationChild {
|
||||||
@Composable
|
@Composable
|
||||||
override fun Content() = SingleEditContent(component)
|
override fun Content() = SingleEditContent(component)
|
||||||
}
|
}
|
||||||
|
|
||||||
class SvgMaker(val component: SvgMakerComponent) : NavigationChild() {
|
class SvgMaker(private val component: SvgMakerComponent) : NavigationChild {
|
||||||
@Composable
|
@Composable
|
||||||
override fun Content() = SvgMakerContent(component)
|
override fun Content() = SvgMakerContent(component)
|
||||||
}
|
}
|
||||||
|
|
||||||
class Watermarking(val component: WatermarkingComponent) : NavigationChild() {
|
class Watermarking(private val component: WatermarkingComponent) : NavigationChild {
|
||||||
@Composable
|
@Composable
|
||||||
override fun Content() = WatermarkingContent(component)
|
override fun Content() = WatermarkingContent(component)
|
||||||
}
|
}
|
||||||
|
|
||||||
class WebpTools(val component: WebpToolsComponent) : NavigationChild() {
|
class WebpTools(private val component: WebpToolsComponent) : NavigationChild {
|
||||||
@Composable
|
@Composable
|
||||||
override fun Content() = WebpToolsContent(component)
|
override fun Content() = WebpToolsContent(component)
|
||||||
}
|
}
|
||||||
|
|
||||||
class WeightResize(val component: WeightResizeComponent) : NavigationChild() {
|
class WeightResize(private val component: WeightResizeComponent) : NavigationChild {
|
||||||
@Composable
|
@Composable
|
||||||
override fun Content() = WeightResizeContent(component)
|
override fun Content() = WeightResizeContent(component)
|
||||||
}
|
}
|
||||||
|
|
||||||
class Zip(val component: ZipComponent) : NavigationChild() {
|
class Zip(private val component: ZipComponent) : NavigationChild {
|
||||||
@Composable
|
@Composable
|
||||||
override fun Content() = ZipContent(component)
|
override fun Content() = ZipContent(component)
|
||||||
}
|
}
|
||||||
|
|
||||||
class LibrariesInfo(val component: LibrariesInfoComponent) : NavigationChild() {
|
class LibrariesInfo(private val component: LibrariesInfoComponent) : NavigationChild {
|
||||||
@Composable
|
@Composable
|
||||||
override fun Content() = LibrariesInfoContent(component)
|
override fun Content() = LibrariesInfoContent(component)
|
||||||
}
|
}
|
||||||
|
|
||||||
class MarkupLayers(val component: MarkupLayersComponent) : NavigationChild() {
|
class MarkupLayers(private val component: MarkupLayersComponent) : NavigationChild {
|
||||||
@Composable
|
@Composable
|
||||||
override fun Content() = MarkupLayersContent(component)
|
override fun Content() = MarkupLayersContent(component)
|
||||||
}
|
}
|
||||||
|
|
||||||
class Base64Tools(val component: Base64ToolsComponent) : NavigationChild() {
|
class Base64Tools(private val component: Base64ToolsComponent) : NavigationChild {
|
||||||
@Composable
|
@Composable
|
||||||
override fun Content() = Base64ToolsContent(component)
|
override fun Content() = Base64ToolsContent(component)
|
||||||
}
|
}
|
||||||
|
|
||||||
class ChecksumTools(val component: ChecksumToolsComponent) : NavigationChild() {
|
class ChecksumTools(private val component: ChecksumToolsComponent) : NavigationChild {
|
||||||
@Composable
|
@Composable
|
||||||
override fun Content() = ChecksumToolsContent(component)
|
override fun Content() = ChecksumToolsContent(component)
|
||||||
}
|
}
|
||||||
|
|
||||||
class MeshGradients(val component: MeshGradientsComponent) : NavigationChild() {
|
class MeshGradients(private val component: MeshGradientsComponent) : NavigationChild {
|
||||||
@Composable
|
@Composable
|
||||||
override fun Content() = MeshGradientsContent(component)
|
override fun Content() = MeshGradientsContent(component)
|
||||||
}
|
}
|
||||||
|
|
||||||
class EditExif(val component: EditExifComponent) : NavigationChild() {
|
class EditExif(private val component: EditExifComponent) : NavigationChild {
|
||||||
@Composable
|
@Composable
|
||||||
override fun Content() = EditExifContent(component)
|
override fun Content() = EditExifContent(component)
|
||||||
}
|
}
|
||||||
|
|
||||||
class ImageCutter(val component: ImageCutterComponent) : NavigationChild() {
|
class ImageCutter(private val component: ImageCutterComponent) : NavigationChild {
|
||||||
@Composable
|
@Composable
|
||||||
override fun Content() = ImageCutterContent(component)
|
override fun Content() = ImageCutterContent(component)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
class AudioCoverExtractor(
|
||||||
|
private val component: AudioCoverExtractorComponent
|
||||||
|
) : NavigationChild {
|
||||||
|
@Composable
|
||||||
|
override fun Content() = AudioCoverExtractorContent(component)
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
@ -32,7 +32,6 @@ konfettiCompose = "2.0.5"
|
|||||||
shadowsPlus = "1.0.4"
|
shadowsPlus = "1.0.4"
|
||||||
exifinterface = "1.4.0"
|
exifinterface = "1.4.0"
|
||||||
firebaseAnalyticsKtx = "22.3.0"
|
firebaseAnalyticsKtx = "22.3.0"
|
||||||
firebaseCrashlyticsGradle = "3.0.3"
|
|
||||||
google-segmentationSelfie = "16.0.0-beta6"
|
google-segmentationSelfie = "16.0.0-beta6"
|
||||||
google-subjectSegmentation = "16.0.0-beta1"
|
google-subjectSegmentation = "16.0.0-beta1"
|
||||||
detekt = "1.23.8"
|
detekt = "1.23.8"
|
||||||
@ -75,13 +74,18 @@ zxingAndroidEmbedded = "4.3.0"
|
|||||||
capturable = "3.0.1"
|
capturable = "3.0.1"
|
||||||
moshi = "1.15.2"
|
moshi = "1.15.2"
|
||||||
aboutlibraries = "12.0.0-a02+compose_1_8"
|
aboutlibraries = "12.0.0-a02+compose_1_8"
|
||||||
aboutlibrariesGradle = "12.0.0-a04"
|
|
||||||
junit = "4.13.2"
|
junit = "4.13.2"
|
||||||
bouncycastle = "1.80"
|
bouncycastle = "1.80"
|
||||||
evaluator = "1.0.0"
|
evaluator = "1.0.0"
|
||||||
|
ffmpeg-metadata-retriever = "1.0.19"
|
||||||
|
|
||||||
|
firebaseCrashlyticsGradle = "3.0.3"
|
||||||
|
aboutlibrariesGradle = "12.0.0-a04"
|
||||||
moduleGraphGradle = "0.12.0"
|
moduleGraphGradle = "0.12.0"
|
||||||
|
|
||||||
[libraries]
|
[libraries]
|
||||||
|
ffmpeg-metadata-retriever-core = { module = "com.github.wseemann:FFmpegMediaMetadataRetriever-core", version.ref = "ffmpeg-metadata-retriever" }
|
||||||
|
ffmpeg-metadata-retriever-native = { module = "com.github.wseemann:FFmpegMediaMetadataRetriever-native", version.ref = "ffmpeg-metadata-retriever" }
|
||||||
evaluator = { module = "com.github.T8RIN:KotlinEvaluator", version.ref = "evaluator" }
|
evaluator = { module = "com.github.T8RIN:KotlinEvaluator", version.ref = "evaluator" }
|
||||||
aboutlibraries-m3 = { module = "com.mikepenz:aboutlibraries-compose-m3", version.ref = "aboutlibraries" }
|
aboutlibraries-m3 = { module = "com.mikepenz:aboutlibraries-compose-m3", version.ref = "aboutlibraries" }
|
||||||
moshi = { module = "com.squareup.moshi:moshi-kotlin", version.ref = "moshi" }
|
moshi = { module = "com.squareup.moshi:moshi-kotlin", version.ref = "moshi" }
|
||||||
|
@ -109,6 +109,7 @@ include(":feature:checksum-tools")
|
|||||||
include(":feature:mesh-gradients")
|
include(":feature:mesh-gradients")
|
||||||
include(":feature:edit-exif")
|
include(":feature:edit-exif")
|
||||||
include(":feature:image-cutting")
|
include(":feature:image-cutting")
|
||||||
|
include(":feature:audio-cover-extractor")
|
||||||
|
|
||||||
include(":feature:root")
|
include(":feature:root")
|
||||||
|
|
||||||
|
Reference in New Issue
Block a user