diff --git a/app/src/main/java/com/hippo/ehviewer/EhDB.kt b/app/src/main/java/com/hippo/ehviewer/EhDB.kt index 04e54d3cf..2e8f4bee2 100644 --- a/app/src/main/java/com/hippo/ehviewer/EhDB.kt +++ b/app/src/main/java/com/hippo/ehviewer/EhDB.kt @@ -36,23 +36,20 @@ import com.hippo.ehviewer.util.sendTo import splitties.arch.room.roomDb object EhDB { - private val db = roomDb("eh.db") { allowMainThreadQueries() } + private val db = roomDb("eh.db") - // Fix state suspend fun getAllDownloadInfo() = db.downloadsDao().list().onEach { if (it.state == DownloadInfo.STATE_WAIT || it.state == DownloadInfo.STATE_DOWNLOAD) { it.state = DownloadInfo.STATE_NONE } } - @Synchronized - fun updateDownloadInfo(downloadInfos: List) { + suspend fun updateDownloadInfo(downloadInfo: List) { val dao = db.downloadsDao() - dao.update(downloadInfos) + dao.update(downloadInfo) } - @Synchronized - fun putDownloadInfo(downloadInfo: DownloadInfo) { + suspend fun putDownloadInfo(downloadInfo: DownloadInfo) { db.downloadsDao().run { if (load(downloadInfo.gid) != null) { update(downloadInfo) @@ -62,8 +59,7 @@ object EhDB { } } - @Synchronized - fun removeDownloadInfo(downloadInfo: DownloadInfo) { + suspend fun removeDownloadInfo(downloadInfo: DownloadInfo) { db.downloadsDao().delete(downloadInfo) } @@ -111,11 +107,8 @@ object EhDB { dao.update(raw) } - @Synchronized - fun moveDownloadLabel(fromPosition: Int, toPosition: Int) { - if (fromPosition == toPosition) { - return - } + suspend fun moveDownloadLabel(fromPosition: Int, toPosition: Int) { + if (fromPosition == toPosition) return val reverse = fromPosition > toPosition val offset = if (reverse) toPosition else fromPosition val limit = if (reverse) fromPosition - toPosition + 1 else toPosition - fromPosition + 1 @@ -126,7 +119,7 @@ object EhDB { val end = if (reverse) 0 else limit - 1 val toTime = list[end].time var i = end - while (if (reverse) i < start else i > start) { + while (if (reverse) i < start else i > 0) { list[i].time = list[i + step].time i += step } @@ -197,9 +190,7 @@ object EhDB { } suspend fun moveQuickSearch(fromPosition: Int, toPosition: Int) { - if (fromPosition == toPosition) { - return - } + if (fromPosition == toPosition) return val reverse = fromPosition > toPosition val offset = if (reverse) toPosition else fromPosition val limit = if (reverse) fromPosition - toPosition + 1 else toPosition - fromPosition + 1 @@ -210,7 +201,7 @@ object EhDB { val end = if (reverse) 0 else limit - 1 val toTime = list[end].time var i = end - while (if (reverse) i < start else i > start) { + while (if (reverse) i < start else i > 0) { list[i].time = list[i + step].time i += step } diff --git a/app/src/main/java/com/hippo/ehviewer/dao/DownloadLabelDao.kt b/app/src/main/java/com/hippo/ehviewer/dao/DownloadLabelDao.kt index c2b64e807..8cdeb32d0 100644 --- a/app/src/main/java/com/hippo/ehviewer/dao/DownloadLabelDao.kt +++ b/app/src/main/java/com/hippo/ehviewer/dao/DownloadLabelDao.kt @@ -12,10 +12,10 @@ interface DownloadLabelDao { suspend fun list(): List @Query("SELECT * FROM DOWNLOAD_LABELS ORDER BY TIME ASC LIMIT :limit OFFSET :offset") - fun list(offset: Int, limit: Int): List + suspend fun list(offset: Int, limit: Int): List @Update - fun update(downloadLabels: List) + suspend fun update(downloadLabels: List) @Update suspend fun update(downloadLabel: DownloadLabel) diff --git a/app/src/main/java/com/hippo/ehviewer/dao/DownloadsDao.kt b/app/src/main/java/com/hippo/ehviewer/dao/DownloadsDao.kt index 72db1876e..bd7838f7d 100644 --- a/app/src/main/java/com/hippo/ehviewer/dao/DownloadsDao.kt +++ b/app/src/main/java/com/hippo/ehviewer/dao/DownloadsDao.kt @@ -12,20 +12,20 @@ interface DownloadsDao { suspend fun list(): List @Query("SELECT * FROM DOWNLOADS ORDER BY TIME DESC LIMIT :limit OFFSET :offset") - fun list(offset: Int, limit: Int): List + suspend fun list(offset: Int, limit: Int): List @Query("SELECT * FROM DOWNLOADS WHERE GID = :gid") - fun load(gid: Long): DownloadInfo? + suspend fun load(gid: Long): DownloadInfo? @Update - fun update(downloadInfos: List) + suspend fun update(downloadInfo: List) @Update - fun update(downloadInfo: DownloadInfo) + suspend fun update(downloadInfo: DownloadInfo) @Insert - fun insert(t: DownloadInfo): Long + suspend fun insert(t: DownloadInfo): Long @Delete - fun delete(downloadInfo: DownloadInfo) + suspend fun delete(downloadInfo: DownloadInfo) } diff --git a/app/src/main/java/com/hippo/ehviewer/download/DownloadManager.kt b/app/src/main/java/com/hippo/ehviewer/download/DownloadManager.kt index 4817c9ea4..01c9ca27a 100644 --- a/app/src/main/java/com/hippo/ehviewer/download/DownloadManager.kt +++ b/app/src/main/java/com/hippo/ehviewer/download/DownloadManager.kt @@ -137,7 +137,7 @@ object DownloadManager : OnSpiderListener { mDownloadListener = listener } - private fun ensureDownload() { + private suspend fun ensureDownload() { if (mCurrentTask != null) { // Only one download return @@ -175,7 +175,7 @@ object DownloadManager : OnSpiderListener { } } - fun startDownload(galleryInfo: GalleryInfo, label: String?) { + suspend fun startDownload(galleryInfo: GalleryInfo, label: String?) { if (mCurrentTask != null && mCurrentTask!!.gid == galleryInfo.gid) { // It is current task return @@ -240,7 +240,7 @@ object DownloadManager : OnSpiderListener { } } - fun startRangeDownload(gidList: LongList) { + suspend fun startRangeDownload(gidList: LongList) { var update = false for (i in 0 until gidList.size) { val gid = gidList[i] @@ -301,7 +301,7 @@ object DownloadManager : OnSpiderListener { fun stateFlow(gid: Long) = _stateFlow.filter { it.gid == gid } - fun startAllDownload() { + suspend fun startAllDownload() { var update = false // Start all STATE_NONE and STATE_FAILED item for (info in allInfoList) { @@ -418,7 +418,7 @@ object DownloadManager : OnSpiderListener { } } - fun stopDownload(gid: Long) { + suspend fun stopDownload(gid: Long) { val info = stopDownloadInternal(gid) if (info != null) { // Update listener @@ -433,7 +433,7 @@ object DownloadManager : OnSpiderListener { } } - fun stopCurrentDownload() { + suspend fun stopCurrentDownload() { val info = stopCurrentDownloadInternal() if (info != null) { // Update listener @@ -448,7 +448,7 @@ object DownloadManager : OnSpiderListener { } } - fun stopRangeDownload(gidList: LongList) { + suspend fun stopRangeDownload(gidList: LongList) { stopRangeDownloadInternal(gidList) // Update listener @@ -460,7 +460,7 @@ object DownloadManager : OnSpiderListener { ensureDownload() } - fun stopAllDownload() { + suspend fun stopAllDownload() { // Stop all in wait list for (info in mWaitList) { info.state = DownloadInfo.STATE_NONE @@ -478,7 +478,7 @@ object DownloadManager : OnSpiderListener { } } - fun deleteDownload(gid: Long) { + suspend fun deleteDownload(gid: Long) { stopDownloadInternal(gid) val info = mAllInfoMap[gid] if (info != null) { @@ -507,7 +507,7 @@ object DownloadManager : OnSpiderListener { } } - fun deleteRangeDownload(gidList: LongList) { + suspend fun deleteRangeDownload(gidList: LongList) { stopRangeDownloadInternal(gidList) for (i in 0 until gidList.size) { val gid = gidList[i] @@ -538,7 +538,7 @@ object DownloadManager : OnSpiderListener { ensureDownload() } - fun moveDownload(fromPosition: Int, toPosition: Int) { + suspend fun moveDownload(fromPosition: Int, toPosition: Int) { if (fromPosition > toPosition) { val time = allInfoList[toPosition].time for (i in toPosition until fromPosition) { @@ -560,7 +560,7 @@ object DownloadManager : OnSpiderListener { list.sortByDateDescending() } - fun moveDownload(label: String?, fromPosition: Int, toPosition: Int) { + suspend fun moveDownload(label: String?, fromPosition: Int, toPosition: Int) { val list = getInfoListForLabel(label) list?.let { val absFromPosition = allInfoList.indexOf(it[fromPosition]) @@ -593,7 +593,7 @@ object DownloadManager : OnSpiderListener { // Update in DB // Update listener // No ensureDownload - private fun stopDownloadInternal(gid: Long): DownloadInfo? { + private suspend fun stopDownloadInternal(gid: Long): DownloadInfo? { // Check current task if (mCurrentTask != null && mCurrentTask!!.gid == gid) { // Stop current @@ -617,7 +617,7 @@ object DownloadManager : OnSpiderListener { // Update in DB // Update mDownloadListener - private fun stopCurrentDownloadInternal(): DownloadInfo? { + private suspend fun stopCurrentDownloadInternal(): DownloadInfo? { val info = mCurrentTask val spider = mCurrentSpider // Release spider @@ -646,7 +646,7 @@ object DownloadManager : OnSpiderListener { // Update in DB // Update mDownloadListener - private fun stopRangeDownloadInternal(gidList: LongList) { + private suspend fun stopRangeDownloadInternal(gidList: LongList) { // Two way if (gidList.size < mWaitList.size) { for (i in 0 until gidList.size) { @@ -678,7 +678,7 @@ object DownloadManager : OnSpiderListener { /** * @param label Not allow new label */ - fun changeLabel(list: List, label: String?) { + suspend fun changeLabel(list: List, label: String?) { if (null != label && !containLabel(label)) { Log.e(TAG, "Not exits label: $label") return @@ -718,7 +718,7 @@ object DownloadManager : OnSpiderListener { map[label] = LinkedList() } - fun moveLabel(fromPosition: Int, toPosition: Int) { + suspend fun moveLabel(fromPosition: Int, toPosition: Int) { val item = labelList.removeAt(fromPosition) labelList.add(toPosition, item) EhDB.moveDownloadLabel(fromPosition, toPosition) @@ -1077,24 +1077,26 @@ object DownloadManager : OnSpiderListener { } else { info.state = DownloadInfo.STATE_FAILED } - // Update in DB - EhDB.putDownloadInfo(info) - // Notify - if (mDownloadListener != null) { - mDownloadListener!!.onFinish(info) - } - val list: List? = getInfoListForLabel(info.label) - if (list != null) { - for (l in mDownloadInfoListeners) { - l.onUpdate(info, list) + launchIO { + // Update in DB + EhDB.putDownloadInfo(info) + // Notify + if (mDownloadListener != null) { + mDownloadListener!!.onFinish(info) } + val list: List? = getInfoListForLabel(info.label) + if (list != null) { + for (l in mDownloadInfoListeners) { + l.onUpdate(info, list) + } + } + // Start next download + ensureDownload() } - // Start next download - ensureDownload() } } } - mNotifyTaskPool.push(this) + if (mType != TYPE_ON_FINISH) mNotifyTaskPool.push(this) } } diff --git a/app/src/main/java/com/hippo/ehviewer/download/DownloadService.kt b/app/src/main/java/com/hippo/ehviewer/download/DownloadService.kt index 3b746f27d..b1d5428c9 100644 --- a/app/src/main/java/com/hippo/ehviewer/download/DownloadService.kt +++ b/app/src/main/java/com/hippo/ehviewer/download/DownloadService.kt @@ -21,7 +21,6 @@ import android.app.Service import android.content.Intent import android.content.pm.PackageManager import android.os.Bundle -import android.os.IBinder import android.os.SystemClock import android.util.Log import androidx.annotation.IntDef @@ -41,8 +40,13 @@ import com.hippo.ehviewer.util.LongList import com.hippo.ehviewer.util.ReadableTime import com.hippo.ehviewer.util.SimpleHandler import com.hippo.ehviewer.util.getParcelableExtraCompat +import kotlinx.coroutines.CoroutineScope +import kotlinx.coroutines.Dispatchers +import kotlinx.coroutines.SupervisorJob +import kotlinx.coroutines.launch -class DownloadService : Service(), DownloadManager.DownloadListener { +class DownloadService : Service(), DownloadManager.DownloadListener, CoroutineScope { + override val coroutineContext = Dispatchers.IO + SupervisorJob() private var mNotifyManager: NotificationManagerCompat? = null private var mDownloadManager: DownloadManager? = null private var mDownloadingBuilder: NotificationCompat.Builder? = null @@ -88,11 +92,11 @@ class DownloadService : Service(), DownloadManager.DownloadListener { } override fun onStartCommand(intent: Intent?, flags: Int, startId: Int): Int { - handleIntent(intent) + launch { handleIntent(intent) } return START_STICKY } - private fun handleIntent(intent: Intent?) { + private suspend fun handleIntent(intent: Intent?) { when (intent?.action) { ACTION_START -> { val gi = intent.getParcelableExtraCompat(KEY_GALLERY_INFO) @@ -162,9 +166,7 @@ class DownloadService : Service(), DownloadManager.DownloadListener { checkStopSelf() } - override fun onBind(intent: Intent): IBinder? { - throw IllegalStateException("No bindService") - } + override fun onBind(intent: Intent) = error("No bindService") private fun ensureDownloadingBuilder() { if (mDownloadingBuilder != null) { @@ -237,15 +239,17 @@ class DownloadService : Service(), DownloadManager.DownloadListener { } override fun onGet509() { - if (mDownloadManager != null) { - mDownloadManager!!.stopAllDownload() + launch { + if (mDownloadManager != null) { + mDownloadManager!!.stopAllDownload() + } + if (mNotifyManager == null) { + return@launch + } + ensure509Builder() + m509dBuilder!!.setWhen(System.currentTimeMillis()) + m509Delay!!.show() } - if (mNotifyManager == null) { - return - } - ensure509Builder() - m509dBuilder!!.setWhen(System.currentTimeMillis()) - m509Delay!!.show() } override fun onStart(info: DownloadInfo) { diff --git a/app/src/main/java/com/hippo/ehviewer/ui/scene/DownloadsScene.kt b/app/src/main/java/com/hippo/ehviewer/ui/scene/DownloadsScene.kt index fa2540041..4dc296ca1 100644 --- a/app/src/main/java/com/hippo/ehviewer/ui/scene/DownloadsScene.kt +++ b/app/src/main/java/com/hippo/ehviewer/ui/scene/DownloadsScene.kt @@ -370,7 +370,9 @@ class DownloadsScene : } R.id.action_stop_all -> { - DownloadManager.stopAllDownload() + lifecycleScope.launchIO { + DownloadManager.stopAllDownload() + } return true } @@ -564,10 +566,14 @@ class DownloadsScene : } 2 -> { - // Stop - DownloadManager.stopRangeDownload(gidList!!) - // Cancel check mode - binding.recyclerView.outOfCustomChoiceMode() + lifecycleScope.launchIO { + // Stop + DownloadManager.stopRangeDownload(gidList!!) + withUIContext { + // Cancel check mode + binding.recyclerView.outOfCustomChoiceMode() + } + } } 3 -> { @@ -611,10 +617,12 @@ class DownloadsScene : if (mList !== list) { return } - if (mAdapter != null) { - mAdapter!!.notifyItemInserted(position) + lifecycleScope.launchUI { + if (mAdapter != null) { + mAdapter!!.notifyItemInserted(position) + } + updateView() } - updateView() } override fun onUpdate(info: DownloadInfo, list: List) { @@ -622,15 +630,19 @@ class DownloadsScene : return } val index = mList!!.indexOf(info) - if (index >= 0 && mAdapter != null) { - mAdapter!!.notifyItemChanged(index, PAYLOAD_STATE) + lifecycleScope.launchUI { + if (index >= 0 && mAdapter != null) { + mAdapter!!.notifyItemChanged(index, PAYLOAD_STATE) + } } } @SuppressLint("NotifyDataSetChanged") override fun onUpdateAll() { - if (mAdapter != null) { - mAdapter!!.notifyDataSetChanged() + lifecycleScope.launchUI { + if (mAdapter != null) { + mAdapter!!.notifyDataSetChanged() + } } } @@ -648,10 +660,12 @@ class DownloadsScene : if (mList !== list) { return } - if (mAdapter != null) { - mAdapter!!.notifyItemRemoved(position) + lifecycleScope.launchUI { + if (mAdapter != null) { + mAdapter!!.notifyItemRemoved(position) + } + updateView() } - updateView() } private class DownloadLabelHolder(val binding: ItemDrawerListBinding) : @@ -748,14 +762,13 @@ class DownloadsScene : // Cancel check mode binding.recyclerView.outOfCustomChoiceMode() - // Delete - DownloadManager.deleteRangeDownload(mGidList) - // Delete image files val checked = mBuilder.isChecked Settings.removeImageFiles = checked if (checked) { lifecycleScope.launchIO { + // Delete + DownloadManager.deleteRangeDownload(mGidList) val files = arrayOfNulls(mDownloadInfoList.size) for ((i, info) in mDownloadInfoList.withIndex()) { // Put file @@ -784,9 +797,13 @@ class DownloadsScene : } else { mLabels[which] } - downloadManager.changeLabel(mDownloadInfoList, label) - if (mLabelAdapter != null) { - mLabelAdapter!!.notifyDataSetChanged() + lifecycleScope.launchIO { + downloadManager.changeLabel(mDownloadInfoList, label) + withUIContext { + if (mLabelAdapter != null) { + mLabelAdapter!!.notifyDataSetChanged() + } + } } } } @@ -833,7 +850,9 @@ class DownloadsScene : } binding.stop -> { - DownloadManager.stopDownload(list[index].gid) + lifecycleScope.launchIO { + DownloadManager.stopDownload(list[index].gid) + } } } } @@ -1133,7 +1152,9 @@ class DownloadsScene : if (null == context || fromPosition == toPosition || toPosition < LABEL_OFFSET) { return false } - downloadManager.moveLabel(fromPosition - LABEL_OFFSET, toPosition - LABEL_OFFSET) + lifecycleScope.launchIO { + downloadManager.moveLabel(fromPosition - LABEL_OFFSET, toPosition - LABEL_OFFSET) + } val item = mLabels.removeAt(fromPosition) mLabels.add(toPosition, item) mLabelAdapter!!.notifyItemMoved(fromPosition, toPosition) diff --git a/app/src/main/java/com/hippo/ehviewer/ui/scene/GalleryDetailScene.kt b/app/src/main/java/com/hippo/ehviewer/ui/scene/GalleryDetailScene.kt index 4267a0365..1a46eca9d 100755 --- a/app/src/main/java/com/hippo/ehviewer/ui/scene/GalleryDetailScene.kt +++ b/app/src/main/java/com/hippo/ehviewer/ui/scene/GalleryDetailScene.kt @@ -1264,14 +1264,13 @@ class GalleryDetailScene : BaseScene() { return } - // Delete - EhDownloadManager.deleteDownload(mGalleryInfo.gid) - - // Delete image files - val checked = mBuilder.isChecked - Settings.removeImageFiles = checked - if (checked) { - lifecycleScope.launchIO { + lifecycleScope.launchIO { + // Delete + EhDownloadManager.deleteDownload(mGalleryInfo.gid) + // Delete image files + val checked = mBuilder.isChecked + Settings.removeImageFiles = checked + if (checked) { runCatching { val file = getGalleryDownloadDir(mGalleryInfo.gid) EhDB.removeDownloadDirname(mGalleryInfo.gid)