Refine DownloadsScreen (#392)
* Fix downloads reorder and delete * Fix download label edit and delete * Fix changing download label
This commit is contained in:
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)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Reference in new issue
Block a user