mirror of
https://github.com/amir1376/ab-download-manager.git
synced 2025-02-20 11:43:24 +08:00
Merge pull request #152 from amir1376/make-category-path-optional
make category path optional
This commit is contained in:
commit
5a0be7e06f
@ -192,13 +192,13 @@ class AddMultiDownloadComponent(
|
||||
url = url,
|
||||
fileName = fleName,
|
||||
)
|
||||
)?.path
|
||||
)?.getDownloadPath()
|
||||
?: defaultFolder
|
||||
}
|
||||
|
||||
is CategorySelectionMode.Fixed -> {
|
||||
downloadSystem.categoryManager
|
||||
.getCategoryById(categorySelectionMode.categoryId)?.path
|
||||
.getCategoryById(categorySelectionMode.categoryId)?.getDownloadPath()
|
||||
?: defaultFolder
|
||||
}
|
||||
|
||||
|
@ -11,7 +11,6 @@ import androidx.compose.runtime.*
|
||||
import com.abdownloadmanager.desktop.utils.mvi.ContainsEffects
|
||||
import com.abdownloadmanager.desktop.utils.mvi.supportEffects
|
||||
import com.abdownloadmanager.resources.Res
|
||||
import com.abdownloadmanager.resources.*
|
||||
import com.abdownloadmanager.utils.extractors.linkextractor.DownloadCredentialFromStringExtractor
|
||||
import com.arkivanov.decompose.ComponentContext
|
||||
import ir.amirab.downloader.connection.DownloaderClient
|
||||
@ -66,20 +65,29 @@ class AddSingleDownloadComponent(
|
||||
|
||||
private val _useCategory = MutableStateFlow(false)
|
||||
val useCategory = _useCategory.asStateFlow()
|
||||
fun setUseCategory(value: Boolean) {
|
||||
_useCategory.update { value }
|
||||
if (value) {
|
||||
useCategoryFolder()
|
||||
fun setUseCategory(useCategory: Boolean) {
|
||||
_useCategory.update { useCategory }
|
||||
if (useCategory) {
|
||||
val usedCategoryFolder = useCategoryFolder(_useCategory.value)
|
||||
if (!usedCategoryFolder) {
|
||||
useDefaultFolder()
|
||||
}
|
||||
} else {
|
||||
useDefaultFolder()
|
||||
}
|
||||
}
|
||||
|
||||
private fun useCategoryFolder() {
|
||||
private fun useCategoryFolder(
|
||||
useCategory: Boolean,
|
||||
): Boolean {
|
||||
val category = selectedCategory.value
|
||||
if (useCategory.value && category != null) {
|
||||
setFolder(category.path)
|
||||
if (useCategory && category != null) {
|
||||
category.getDownloadPath()?.let {
|
||||
setFolder(it)
|
||||
return true
|
||||
}
|
||||
}
|
||||
return false
|
||||
}
|
||||
|
||||
private fun useDefaultFolder() {
|
||||
@ -89,8 +97,12 @@ class AddSingleDownloadComponent(
|
||||
|
||||
fun setSelectedCategory(category: Category) {
|
||||
_selectedCategory.update { category }
|
||||
if (useCategory.value) {
|
||||
useCategoryFolder()
|
||||
val useCategory = useCategory.value
|
||||
if (useCategory) {
|
||||
val used = useCategoryFolder(useCategory)
|
||||
if (!used) {
|
||||
useDefaultFolder()
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@ -145,8 +157,8 @@ class AddSingleDownloadComponent(
|
||||
if (category == null) {
|
||||
setUseCategory(false)
|
||||
} else {
|
||||
setUseCategory(true)
|
||||
setSelectedCategory(category)
|
||||
setUseCategory(true)
|
||||
}
|
||||
}.launchIn(scope)
|
||||
}
|
||||
@ -333,7 +345,7 @@ class AddSingleDownloadComponent(
|
||||
true
|
||||
} else {
|
||||
// only add if category path is not the same as provided path
|
||||
category.path != folder
|
||||
category.getDownloadPath() != folder
|
||||
}
|
||||
if (shouldAdd) {
|
||||
addToLastUsedLocations(folder)
|
||||
|
@ -42,6 +42,7 @@ class CategoryComponent(
|
||||
setUrlPatternsEnabled(category.acceptedUrlPatterns.isNotEmpty())
|
||||
setUrlPatterns(category.acceptedUrlPatterns.joinToString(" "))
|
||||
setPath(category.path)
|
||||
setUsePath(category.usePath)
|
||||
}
|
||||
}
|
||||
|
||||
@ -81,15 +82,22 @@ class CategoryComponent(
|
||||
_path.value = path
|
||||
}
|
||||
|
||||
private val _usePath = MutableStateFlow(false)
|
||||
val usePath = _usePath.asStateFlow()
|
||||
fun setUsePath(usePath: Boolean) {
|
||||
_usePath.value = usePath
|
||||
}
|
||||
|
||||
val canSubmit = combineStateFlows(
|
||||
icon,
|
||||
name,
|
||||
types,
|
||||
path
|
||||
) { icon, name, types, path ->
|
||||
path,
|
||||
usePath,
|
||||
) { icon, name, types, path, usePath ->
|
||||
val iconOk = icon != null
|
||||
val nameOk = name.isNotBlank()
|
||||
val pathOk = FileUtils.canWriteInThisFolder(path)
|
||||
val pathOk = FileUtils.canWriteInThisFolder(path) || !usePath
|
||||
iconOk && nameOk && pathOk
|
||||
}
|
||||
val isEditMode = id >= 0
|
||||
@ -114,6 +122,7 @@ class CategoryComponent(
|
||||
.value!!
|
||||
.uriOrNull()!!,
|
||||
path = path,
|
||||
usePath = usePath.value,
|
||||
acceptedUrlPatterns = urlPatterns.value
|
||||
.split(" ")
|
||||
.filterNot { it.isBlank() }
|
||||
|
@ -82,7 +82,9 @@ fun NewCategory(
|
||||
CategoryDefaultPath(
|
||||
path = categoryComponent.path.collectAsState().value,
|
||||
onPathChanged = categoryComponent::setPath,
|
||||
defaultDownloadLocation = categoryComponent.defaultDownloadLocation.collectAsState().value
|
||||
defaultDownloadLocation = categoryComponent.defaultDownloadLocation.collectAsState().value,
|
||||
checked = categoryComponent.usePath.collectAsState().value,
|
||||
setChecked = categoryComponent::setUsePath
|
||||
)
|
||||
}
|
||||
Spacer(Modifier.height(12.dp))
|
||||
@ -115,6 +117,8 @@ fun CategoryDefaultPath(
|
||||
defaultDownloadLocation: String,
|
||||
path: String,
|
||||
onPathChanged: (String) -> Unit,
|
||||
checked: Boolean,
|
||||
setChecked: (Boolean) -> Unit,
|
||||
) {
|
||||
val initialDirectory = remember(path, defaultDownloadLocation) {
|
||||
path
|
||||
@ -135,14 +139,17 @@ fun CategoryDefaultPath(
|
||||
directory?.path?.let(onPathChanged)
|
||||
}
|
||||
|
||||
WithLabel(
|
||||
OptionalWithLabel(
|
||||
label = myStringResource(Res.string.category_download_location),
|
||||
helpText = myStringResource(Res.string.category_download_location_description)
|
||||
helpText = myStringResource(Res.string.category_download_location_description),
|
||||
enabled = checked,
|
||||
setEnabled = setChecked,
|
||||
) {
|
||||
CategoryPageTextField(
|
||||
text = path,
|
||||
onTextChange = onPathChanged,
|
||||
modifier = Modifier.fillMaxWidth(),
|
||||
enabled = checked,
|
||||
placeholder = "",
|
||||
errorText = null,
|
||||
end = {
|
||||
|
@ -289,6 +289,7 @@ class CategoryActions(
|
||||
private val onRequestAddCategory: () -> Unit,
|
||||
) {
|
||||
private val mainItemExists = MutableStateFlow(categoryItem != null)
|
||||
private val canBeOpened = MutableStateFlow(categoryItem?.usePath ?: false)
|
||||
private inline fun useItem(
|
||||
block: (Category) -> Unit,
|
||||
) {
|
||||
@ -298,7 +299,7 @@ class CategoryActions(
|
||||
val openCategoryFolderAction = simpleAction(
|
||||
title = Res.string.open_folder.asStringSource(),
|
||||
icon = MyIcons.folderOpen,
|
||||
checkEnable = mainItemExists,
|
||||
checkEnable = canBeOpened,
|
||||
onActionPerformed = {
|
||||
scope.launch {
|
||||
useItem {
|
||||
@ -843,7 +844,9 @@ class HomeComponent(
|
||||
categoryItem = categoryItem,
|
||||
openFolder = {
|
||||
runCatching {
|
||||
FileUtils.openFolder(File(it.path))
|
||||
it.getDownloadPath()?.let {
|
||||
FileUtils.openFolder(File(it))
|
||||
}
|
||||
}
|
||||
},
|
||||
onRequestAddCategory = {
|
||||
|
@ -6,6 +6,7 @@ import androidx.compose.runtime.remember
|
||||
import ir.amirab.util.compose.IconSource
|
||||
import ir.amirab.util.compose.fromUri
|
||||
import ir.amirab.util.wildcardMatch
|
||||
import kotlinx.serialization.SerialName
|
||||
import kotlinx.serialization.Serializable
|
||||
|
||||
/**
|
||||
@ -17,13 +18,23 @@ import kotlinx.serialization.Serializable
|
||||
@Immutable
|
||||
@Serializable
|
||||
data class Category(
|
||||
@SerialName("id")
|
||||
val id: Long,
|
||||
@SerialName("name")
|
||||
val name: String,
|
||||
@SerialName("icon")
|
||||
val icon: String,
|
||||
@SerialName("path")
|
||||
// don't directly use this check for usePath first! see [getDownloadPath()]
|
||||
val path: String,
|
||||
@SerialName("usePath")
|
||||
val usePath: Boolean = true,
|
||||
@SerialName("acceptedFileTypes")
|
||||
val acceptedFileTypes: List<String> = emptyList(),
|
||||
// this is optional if nothing provided it means that every url is acceptable
|
||||
@SerialName("acceptedUrlPatterns")
|
||||
val acceptedUrlPatterns: List<String> = emptyList(),
|
||||
@SerialName("items")
|
||||
val items: List<Long> = emptyList(),
|
||||
) {
|
||||
val hasUrlPattern = acceptedUrlPatterns.isNotEmpty()
|
||||
@ -42,7 +53,9 @@ data class Category(
|
||||
items = items.plus(newItems).distinct()
|
||||
)
|
||||
}
|
||||
|
||||
fun getDownloadPath(): String? {
|
||||
return if (usePath) path else null
|
||||
}
|
||||
fun acceptUrl(url: String): Boolean {
|
||||
if (!hasUrlPattern) {
|
||||
return true
|
||||
|
@ -133,8 +133,12 @@ class CategoryManager(
|
||||
|
||||
private fun createDirectoryIfNecessary(category: Category) {
|
||||
kotlin.runCatching {
|
||||
val folder = File(category.path)
|
||||
if (folder.exists()) {
|
||||
val folder = category
|
||||
.getDownloadPath()
|
||||
?.let(::File)
|
||||
?.canonicalFile
|
||||
?: return
|
||||
if (!folder.exists()) {
|
||||
folder.mkdirs()
|
||||
}
|
||||
}
|
||||
@ -201,7 +205,7 @@ class CategoryManager(
|
||||
|
||||
fun isThisPathBelongsToACategory(folder: String): Boolean {
|
||||
return getCategories()
|
||||
.map { it.path }.contains(folder)
|
||||
.mapNotNull { it.getDownloadPath() }.contains(folder)
|
||||
}
|
||||
|
||||
companion object {
|
||||
|
Loading…
x
Reference in New Issue
Block a user