Skip to content

Commit

Permalink
Feat: Download release assets
Browse files Browse the repository at this point in the history
  • Loading branch information
wingio committed Jun 29, 2023
1 parent 2e89ec1 commit bcd9229
Show file tree
Hide file tree
Showing 4 changed files with 121 additions and 2 deletions.
Original file line number Diff line number Diff line change
@@ -1,14 +1,15 @@
package com.materiiapps.gloom.di.modules

import com.materiiapps.gloom.domain.manager.AuthManager
import com.materiiapps.gloom.domain.manager.DownloadManager
import com.materiiapps.gloom.domain.manager.PreferenceManager
import org.koin.core.module.dsl.singleOf
import org.koin.dsl.module

fun managerModule() = module {

singleOf(::PreferenceManager)

singleOf(::AuthManager)
singleOf(::DownloadManager)

}
Original file line number Diff line number Diff line change
@@ -0,0 +1,107 @@
package com.materiiapps.gloom.domain.manager

import android.annotation.SuppressLint
import android.content.BroadcastReceiver
import android.app.DownloadManager as AndroidDownloadManager
import android.content.Context
import android.content.Intent
import android.content.IntentFilter
import android.os.Environment
import android.os.Handler
import android.os.Looper
import androidx.core.content.getSystemService
import androidx.core.net.toUri
import com.materiiapps.gloom.utils.showToast
import io.ktor.http.HttpHeaders
import kotlinx.coroutines.CoroutineScope
import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.launch
import java.io.File
import kotlin.coroutines.resume
import kotlin.coroutines.resumeWithException
import kotlin.coroutines.suspendCoroutine

class DownloadManager(
private val context: Context,
private val authManager: AuthManager
) {
private val downloadManager = context.getSystemService<AndroidDownloadManager>()!!
private val downloadScope = CoroutineScope(Dispatchers.IO)
private val gloomDownloadFolder = File(Environment.getExternalStorageDirectory(), Environment.DIRECTORY_DOWNLOADS).resolve("Gloom")

fun download(url: String) {
val name = url.toUri().lastPathSegment!!
downloadScope.launch {
download(url, File(gloomDownloadFolder, name)).also {
Handler(Looper.getMainLooper()).post {
if(it.exists()) context.showToast("Download complete: $name")
}
}
}
}

@SuppressLint("UnspecifiedRegisterReceiverFlag")
suspend fun download(url: String, out: File): File {
out.parentFile?.mkdirs()

return suspendCoroutine { continuation ->
val receiver = object : BroadcastReceiver() {
var dlId = 0L

@SuppressLint("Range")
override fun onReceive(context: Context, intent: Intent) {
val id = intent.getLongExtra(AndroidDownloadManager.EXTRA_DOWNLOAD_ID, -1)

if(dlId != id) return

val (status, reason) = AndroidDownloadManager.Query().run {
setFilterById(dlId)

val cursor = downloadManager.query(this)
.apply { moveToFirst() }

if (cursor.count == 0) {
-1 to -1
} else {
val status = cursor.run { getInt(getColumnIndex(AndroidDownloadManager.COLUMN_STATUS)) }
val reason = cursor.run { getInt(getColumnIndex(AndroidDownloadManager.COLUMN_REASON)) }

status to reason
}
}

when(status) {
-1 -> {
context.unregisterReceiver(this)
continuation.resumeWithException(Error("Download canceled"))
}

AndroidDownloadManager.STATUS_SUCCESSFUL -> {
context.unregisterReceiver(this)
continuation.resume(out)
}

AndroidDownloadManager.STATUS_FAILED -> {
context.unregisterReceiver(this)
continuation.resumeWithException(
Error("Failed to download $url")
)
}

else -> {}
}
}
}

context.registerReceiver(receiver, IntentFilter(AndroidDownloadManager.ACTION_DOWNLOAD_COMPLETE))

receiver.dlId = AndroidDownloadManager.Request(url.toUri()).run {
setTitle("Gloom: Downloading ${out.name}")
setNotificationVisibility(AndroidDownloadManager.Request.VISIBILITY_VISIBLE)
setDestinationUri(out.toUri())
addRequestHeader(HttpHeaders.Authorization, authManager.authToken)
downloadManager.enqueue(this)
}
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -179,7 +179,7 @@ class ReleaseScreen(
ReleaseAsset(
name = asset.name,
size = asset.size,
onDownloadClick = { /*TODO*/ }
onDownloadClick = { viewModel.downloadAsset(asset.downloadUrl) }
)
}
}
Expand Down
Original file line number Diff line number Diff line change
@@ -1,20 +1,26 @@
package com.materiiapps.gloom.ui.viewmodels.release

import android.content.Context
import androidx.compose.runtime.getValue
import androidx.compose.runtime.mutableStateOf
import androidx.compose.runtime.setValue
import androidx.core.net.toUri
import cafe.adriel.voyager.core.model.coroutineScope
import com.materiiapps.gloom.domain.manager.DownloadManager
import com.materiiapps.gloom.domain.repository.GraphQLRepository
import com.materiiapps.gloom.gql.ReleaseDetailsQuery
import com.materiiapps.gloom.gql.fragment.ReleaseAssetFragment
import com.materiiapps.gloom.gql.fragment.ReleaseDetails
import com.materiiapps.gloom.gql.type.ReactionContent
import com.materiiapps.gloom.rest.utils.getOrNull
import com.materiiapps.gloom.ui.viewmodels.list.base.BaseListViewModel
import com.materiiapps.gloom.utils.showToast
import kotlinx.coroutines.launch

class ReleaseViewModel(
private val repo: GraphQLRepository,
private val downloadManager: DownloadManager,
private val context: Context,
nameAndTag: Triple<String, String, String>
) : BaseListViewModel<ReleaseAssetFragment, ReleaseDetailsQuery.Data?>() {

Expand Down Expand Up @@ -50,4 +56,9 @@ class ReleaseViewModel(
}
}

fun downloadAsset(url: String) {
context.showToast("Downloading ${url.toUri().lastPathSegment}...")
downloadManager.download(url)
}

}

0 comments on commit bcd9229

Please sign in to comment.