Refine DownloadsScreen (#392)

* Fix downloads reorder and delete

* Fix download label edit and delete

* Fix changing download label
This commit is contained in:
FooIbar authored and GitHub committed 2023-11-29 14:15:37 +00:00
1 parent 5bd9fa3a62
commit 07e316d9a9
3 files changed
+46 -42

No files matched your search

@@ -25,6 +25,8 @@ import androidx.compose.runtime.State
import androidx.compose.runtime.collectAsState
import androidx.compose.runtime.mutableStateListOf
import androidx.compose.runtime.remember
import androidx.compose.runtime.snapshots.SnapshotStateList
import androidx.compose.runtime.toMutableStateList
import com.google.android.material.math.MathUtils
import com.hippo.ehviewer.EhDB
import com.hippo.ehviewer.Settings
@@ -46,12 +48,9 @@ import com.hippo.ehviewer.util.runAssertingNotMainThread
import com.hippo.unifile.UniFile
import eu.kanade.tachiyomi.util.lang.launchIO
import eu.kanade.tachiyomi.util.lang.withIOContext
import java.util.LinkedList
import kotlinx.coroutines.coroutineScope
import kotlinx.coroutines.flow.MutableSharedFlow
import kotlinx.coroutines.flow.asSharedFlow
import kotlinx.coroutines.flow.filter
import kotlinx.coroutines.flow.map
import kotlinx.coroutines.flow.transform
import kotlinx.coroutines.launch
import splitties.init.appCtx
@@ -59,24 +58,22 @@ import splitties.preferences.edit
object DownloadManager : OnSpiderListener {
// All download info list
val allInfoList: LinkedList<DownloadInfo> = runAssertingNotMainThread { LinkedList(EhDB.getAllDownloadInfo()) }
val allInfoList = runAssertingNotMainThread { EhDB.getAllDownloadInfo() }.toMutableStateList()
// All download info map
private val mAllInfoMap = allInfoList.associateBy { it.gid } as MutableMap<Long, DownloadInfo>
// label and info list map, without default label info list
private val map: MutableMap<String?, LinkedList<DownloadInfo>>
private val map: MutableMap<String?, SnapshotStateList<DownloadInfo>>
// All labels without default label
val labelList = mutableStateListOf<DownloadLabel>().apply {
addAll(runAssertingNotMainThread { EhDB.getAllDownloadLabelList() })
}
val labelList = runAssertingNotMainThread { EhDB.getAllDownloadLabelList() }.toMutableStateList()
// Store download info with default label
val defaultInfoList: LinkedList<DownloadInfo>
private val defaultInfoList: SnapshotStateList<DownloadInfo>
// Store download info wait to start
private val mWaitList = LinkedList<DownloadInfo>()
private val mWaitList = ArrayDeque<DownloadInfo>()
private val mSpeedReminder = SpeedReminder()
private val mNotifyTaskPool = ConcurrentPool<NotifyTask?>(5)
private var mDownloadListener: DownloadListener? = null
@@ -96,16 +93,16 @@ object DownloadManager : OnSpiderListener {
labelList.add(EhDB.addDownloadLabel(DownloadLabel(label, labelList.size)))
}
}
it.key to LinkedList(it.value)
it.key to it.value.toMutableStateList()
}
} as MutableMap<String?, LinkedList<DownloadInfo>>
defaultInfoList = map.remove(null) ?: LinkedList()
} as MutableMap<String?, SnapshotStateList<DownloadInfo>>
defaultInfoList = map.remove(null) ?: mutableStateListOf()
labelList.forEach { (label) ->
map[label] ?: LinkedList<DownloadInfo>().also { map[label] = it }
map[label] ?: mutableStateListOf<DownloadInfo>().also { map[label] = it }
}
}
private fun getInfoListForLabel(label: String?) = if (label == null) {
fun getInfoListForLabel(label: String?) = if (label == null) {
defaultInfoList
} else {
map[label]
@@ -125,8 +122,6 @@ object DownloadManager : OnSpiderListener {
fun containDownloadInfo(gid: Long) = mAllInfoMap.containsKey(gid)
fun getLabelDownloadInfoList(label: String?) = map[label]
fun getDownloadInfo(gid: Long) = mAllInfoMap[gid]
fun getDownloadState(gid: Long): Int {
@@ -205,10 +200,10 @@ object DownloadManager : OnSpiderListener {
Log.e(TAG, "Can't find download info list with label: $label")
return
}
list.addFirst(info)
list.add(0, info)
// Add to all download list and map
allInfoList.addFirst(info)
allInfoList.add(0, info)
mAllInfoMap[galleryInfo.gid] = info
// Add to wait list
@@ -311,7 +306,7 @@ object DownloadManager : OnSpiderListener {
suspend fun addDownloadLabel(downloadLabelList: List<DownloadLabel>) {
val offset = downloadLabelList.size
downloadLabelList.filterNot { containLabel(it.label) }.forEachIndexed { index, label ->
map[label.label] = LinkedList()
map[label.label] = mutableStateListOf()
label.position = index + offset
labelList.add(EhDB.addDownloadLabel(label))
}
@@ -324,10 +319,10 @@ object DownloadManager : OnSpiderListener {
// Add to default label download list
val list = defaultInfoList
list.addFirst(info)
list.add(0, info)
// Add to all download list and map
allInfoList.addFirst(info)
allInfoList.add(0, info)
mAllInfoMap[galleryInfo.gid] = info
// Save to
@@ -568,7 +563,7 @@ object DownloadManager : OnSpiderListener {
Log.e(TAG, "Not exits label: $label")
return
}
val dstList: MutableList<DownloadInfo>? = getInfoListForLabel(label)
val dstList = getInfoListForLabel(label)
if (dstList == null) {
Log.e(TAG, "Can't find label with label: $label")
return
@@ -577,7 +572,7 @@ object DownloadManager : OnSpiderListener {
if (info.label == label) {
continue
}
val srcList: MutableList<DownloadInfo>? = getInfoListForLabel(info.label)
val srcList = getInfoListForLabel(info.label)
if (srcList == null) {
Log.e(TAG, "Can't find label with label: " + info.label)
continue
@@ -597,7 +592,7 @@ object DownloadManager : OnSpiderListener {
return
}
labelList.add(EhDB.addDownloadLabel(DownloadLabel(label, labelList.size)))
map[label] = LinkedList()
map[label] = mutableStateListOf()
}
suspend fun moveLabel(fromPosition: Int, toPosition: Int) {
@@ -414,12 +414,13 @@ suspend fun DialogState.showMoveDownloadLabel(info: GalleryInfo) {
withUIContext { DownloadManager.changeLabel(listOf(downloadInfo), label) }
}
suspend fun DialogState.showMoveDownloadLabelList(list: Collection<DownloadInfo>) {
suspend fun DialogState.showMoveDownloadLabelList(list: Collection<DownloadInfo>): String? {
val defaultLabel = appCtx.getString(R.string.default_download_label_name)
val labels = DownloadManager.labelList.map { it.label }.toTypedArray()
val selected = showSelectItem(defaultLabel, *labels, title = R.string.download_move_dialog_title)
val label = if (selected == 0) null else labels[selected - 1]
withUIContext { DownloadManager.changeLabel(list, label) }
return label
}
suspend fun DialogState.showDatePicker(): String? {
@@ -46,6 +46,7 @@ import androidx.compose.material3.rememberDismissState
import androidx.compose.runtime.Composable
import androidx.compose.runtime.SideEffect
import androidx.compose.runtime.getValue
import androidx.compose.runtime.mutableStateListOf
import androidx.compose.runtime.mutableStateMapOf
import androidx.compose.runtime.mutableStateOf
import androidx.compose.runtime.remember
@@ -90,6 +91,7 @@ import com.hippo.ehviewer.ui.tools.FastScrollLazyColumn
import com.hippo.ehviewer.ui.tools.LocalDialogState
import com.hippo.ehviewer.ui.tools.SwipeToDismissBox2
import com.hippo.ehviewer.ui.tools.draggingHapticFeedback
import com.hippo.ehviewer.ui.tools.observed
import com.hippo.ehviewer.util.containsIgnoreCase
import com.hippo.ehviewer.util.findActivity
import com.hippo.ehviewer.util.mapToLongArray
@@ -107,7 +109,7 @@ import sh.calvin.reorderable.rememberReorderableLazyColumnState
@Destination
@Composable
fun DownloadsScreen(navigator: DestinationsNavigator) {
var label by rememberSaveable { mutableStateOf<String?>(null) }
var label by Settings::recentDownloadLabel.observed
var keyword by rememberSaveable { mutableStateOf<String?>(null) }
var filterType by rememberSaveable { mutableStateOf(-1) }
var searchBarOffsetY by remember { mutableStateOf(0) }
@@ -125,17 +127,16 @@ fun DownloadsScreen(navigator: DestinationsNavigator) {
val density = LocalDensity.current
val dialogState = LocalDialogState.current
val view = LocalView.current
val title = stringResource(R.string.scene_download_title, label ?: stringResource(R.string.download_all))
val hint = stringResource(R.string.search_bar_hint, title)
val defaultName = stringResource(R.string.default_download_label_name)
val allName = stringResource(R.string.download_all)
val defaultName = stringResource(R.string.default_download_label_name)
val title = stringResource(R.string.scene_download_title, if (label == "") allName else label ?: defaultName)
val hint = stringResource(R.string.search_bar_hint, title)
val list = remember(label, filterType, keyword) {
when (label) {
null -> DownloadManager.allInfoList
defaultName -> DownloadManager.defaultInfoList
else -> DownloadManager.getLabelDownloadInfoList(label) ?: DownloadManager.allInfoList.also { label = null }
}.filter { info ->
(filterType == -1 || info.state == filterType) && keyword?.let { info.title.containsIgnoreCase(it) || info.titleJpn.containsIgnoreCase(it) || info.uploader.containsIgnoreCase(it) } ?: true
val raw = DownloadManager.getInfoListForLabel(label) ?: DownloadManager.allInfoList
raw.filterTo(mutableStateListOf()) { info ->
(filterType == -1 || info.state == filterType) && keyword?.let {
info.title.containsIgnoreCase(it) || info.titleJpn.containsIgnoreCase(it) || info.uploader.containsIgnoreCase(it)
} ?: true
}
}
val labelsList = DownloadManager.labelList
@@ -179,7 +180,7 @@ fun DownloadsScreen(navigator: DestinationsNavigator) {
}
onSelect(defaultName) {
Settings.hasDefaultDownloadLabel = true
Settings.defaultDownloadLabel = defaultName
Settings.defaultDownloadLabel = null
}
DownloadManager.labelList.forEach { (label) ->
onSelect(label) {
@@ -213,7 +214,7 @@ fun DownloadsScreen(navigator: DestinationsNavigator) {
val all = DownloadManager.allInfoList
ListItem(
modifier = Modifier.clickable {
label = null
label = ""
closeSheet()
},
tonalElevation = 1.dp,
@@ -224,10 +225,10 @@ fun DownloadsScreen(navigator: DestinationsNavigator) {
)
}
stickyHeader {
val default = DownloadManager.defaultInfoList
val default = DownloadManager.getInfoListForLabel(null)!!
ListItem(
modifier = Modifier.clickable {
label = defaultName
label = null
closeSheet()
},
tonalElevation = 1.dp,
@@ -243,6 +244,7 @@ fun DownloadsScreen(navigator: DestinationsNavigator) {
if (it == DismissValue.DismissedToStart) {
coroutineScope.launch {
DownloadManager.deleteLabel(item)
label = ""
}
}
true
@@ -262,7 +264,7 @@ fun DownloadsScreen(navigator: DestinationsNavigator) {
},
label = "elevation",
)
val thatList = DownloadManager.getLabelDownloadInfoList(item)
val thatList = DownloadManager.getInfoListForLabel(item)
val text = if (thatList != null) "$item [${thatList.size}]" else item
ListItem(
modifier = Modifier.clickable {
@@ -288,6 +290,7 @@ fun DownloadsScreen(navigator: DestinationsNavigator) {
}
}
DownloadManager.renameLabel(item, new)
label = new
}
},
) {
@@ -402,6 +405,7 @@ fun DownloadsScreen(navigator: DestinationsNavigator) {
coroutineScope.launchIO {
EhDB.updateDownloadInfo(newList)
}
list.add(toIndex, list.removeAt(fromIndex))
view.performHapticFeedback(draggingHapticFeedback)
}
val searchBarConnection = remember {
@@ -513,10 +517,14 @@ fun DownloadsScreen(navigator: DestinationsNavigator) {
onClick(Icons.Default.Delete) {
val infoList = checkedInfoMap.run { toMap().values.also { clear() } }
dialogState.confirmRemoveDownloadRange(infoList)
list.removeAll(infoList)
}
onClick(Icons.AutoMirrored.Default.DriveFileMove) {
val infoList = checkedInfoMap.run { toMap().values.also { clear() } }
dialogState.showMoveDownloadLabelList(infoList)
val toLabel = dialogState.showMoveDownloadLabelList(infoList)
if (label != "" && label != toLabel) {
list.removeAll(infoList)
}
}
}
}