Image Loading Sent to Background for smooth UI

This commit is contained in:
shabinder 2021-04-15 00:06:51 +05:30
parent c25837845e
commit c9696fa4aa
4 changed files with 84 additions and 90 deletions

View File

@ -98,9 +98,6 @@ class MainActivity : ComponentActivity(), PaymentResultListener {
permissionGranted = remember { mutableStateOf(true) } permissionGranted = remember { mutableStateOf(true) }
val view = LocalView.current val view = LocalView.current
LaunchedEffect(view) {
permissionGranted.value = checkPermissions()
}
Box { Box {
root = SpotiFlyerRootContent( root = SpotiFlyerRootContent(
rememberRootComponent(::spotiFlyerRoot), rememberRootComponent(::spotiFlyerRoot),
@ -114,6 +111,9 @@ class MainActivity : ComponentActivity(), PaymentResultListener {
) )
} }
LaunchedEffect(view) {
permissionGranted.value = checkPermissions()
}
NetworkDialog() NetworkDialog()
PermissionDialog() PermissionDialog()
} }

View File

@ -27,10 +27,7 @@ import com.mpatric.mp3agic.Mp3File
import com.shabinder.common.database.appContext import com.shabinder.common.database.appContext
import com.shabinder.common.models.TrackDetails import com.shabinder.common.models.TrackDetails
import com.shabinder.database.Database import com.shabinder.database.Database
import kotlinx.coroutines.CoroutineScope import kotlinx.coroutines.*
import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.GlobalScope
import kotlinx.coroutines.launch
import java.io.File import java.io.File
import java.io.FileOutputStream import java.io.FileOutputStream
import java.io.IOException import java.io.IOException
@ -76,6 +73,7 @@ actual class Dir actual constructor(
} }
actual suspend fun cacheImage(image: Any, path: String) { actual suspend fun cacheImage(image: Any, path: String) {
withContext(Dispatchers.IO){
try { try {
FileOutputStream(path).use { out -> FileOutputStream(path).use { out ->
(image as? Bitmap)?.compress(Bitmap.CompressFormat.JPEG, 100, out) (image as? Bitmap)?.compress(Bitmap.CompressFormat.JPEG, 100, out)
@ -84,12 +82,14 @@ actual class Dir actual constructor(
e.printStackTrace() e.printStackTrace()
} }
} }
}
@Suppress("BlockingMethodInNonBlockingContext") @Suppress("BlockingMethodInNonBlockingContext")
actual suspend fun saveFileWithMetadata( actual suspend fun saveFileWithMetadata(
mp3ByteArray: ByteArray, mp3ByteArray: ByteArray,
trackDetails: TrackDetails trackDetails: TrackDetails
) { ) {
withContext(Dispatchers.IO){
val songFile = File(trackDetails.outputFilePath) val songFile = File(trackDetails.outputFilePath)
/* /*
* Check , if Fetch was Used, File is saved Already, else write byteArray we Received * Check , if Fetch was Used, File is saved Already, else write byteArray we Received
@ -140,6 +140,7 @@ actual class Dir actual constructor(
} }
} }
} }
}
actual fun addToLibrary(path: String) { actual fun addToLibrary(path: String) {
logger.d { "Scanning File" } logger.d { "Scanning File" }
@ -149,9 +150,9 @@ actual class Dir actual constructor(
) )
} }
actual suspend fun loadImage(url: String): Picture { actual suspend fun loadImage(url: String): Picture = withContext(Dispatchers.IO){
val cachePath = imageCacheDir() + getNameURL(url) val cachePath = imageCacheDir() + getNameURL(url)
return Picture(image = (loadCachedImage(cachePath) ?: freshImage(url))?.asImageBitmap()) Picture(image = (loadCachedImage(cachePath) ?: freshImage(url))?.asImageBitmap())
} }
private fun loadCachedImage(cachePath: String): Bitmap? { private fun loadCachedImage(cachePath: String): Bitmap? {
@ -162,8 +163,9 @@ actual class Dir actual constructor(
null null
} }
} }
private suspend fun freshImage(url: String): Bitmap? {
return try { private suspend fun freshImage(url: String): Bitmap? = withContext(Dispatchers.IO) {
try {
val source = URL(url) val source = URL(url)
val connection: HttpURLConnection = source.openConnection() as HttpURLConnection val connection: HttpURLConnection = source.openConnection() as HttpURLConnection
connection.connectTimeout = 5000 connection.connectTimeout = 5000

View File

@ -42,17 +42,15 @@ actual class YoutubeProvider actual constructor(
private val sampleDomain2 = "youtube.com" private val sampleDomain2 = "youtube.com"
private val sampleDomain3 = "youtu.be" private val sampleDomain3 = "youtu.be"
actual suspend fun query(fullLink: String): PlatformQueryResult? { actual suspend fun query(fullLink: String): PlatformQueryResult? = withContext(Dispatchers.IO) {
val link = fullLink.removePrefix("https://").removePrefix("http://") val link = fullLink.removePrefix("https://").removePrefix("http://")
if (link.contains("playlist", true) || link.contains("list", true)) { if (link.contains("playlist", true) || link.contains("list", true)) {
// Given Link is of a Playlist // Given Link is of a Playlist
logger.i { link } logger.i { link }
val playlistId = link.substringAfter("?list=").substringAfter("&list=").substringBefore("&").substringBefore("?") val playlistId = link.substringAfter("?list=").substringAfter("&list=").substringBefore("&").substringBefore("?")
return withContext(Dispatchers.IO) {
getYTPlaylist( getYTPlaylist(
playlistId playlistId
) )
}
} else { // Given Link is of a Video } else { // Given Link is of a Video
var searchId = "error" var searchId = "error"
when { when {
@ -66,12 +64,10 @@ actual class YoutubeProvider actual constructor(
searchId = link.substringAfterLast("/", "error").substringBefore("&") searchId = link.substringAfterLast("/", "error").substringBefore("&")
} }
} }
return if (searchId != "error") { if (searchId != "error") {
withContext(Dispatchers.IO) {
getYTTrack( getYTTrack(
searchId searchId
) )
}
} else { } else {
logger.d { "Your Youtube Link is not of a Video!!" } logger.d { "Your Youtube Link is not of a Video!!" }
null null
@ -81,7 +77,7 @@ actual class YoutubeProvider actual constructor(
private suspend fun getYTPlaylist( private suspend fun getYTPlaylist(
searchId: String searchId: String
): PlatformQueryResult? { ): PlatformQueryResult? = withContext(Dispatchers.IO) {
val result = PlatformQueryResult( val result = PlatformQueryResult(
folderType = "", folderType = "",
subFolder = "", subFolder = "",
@ -133,14 +129,13 @@ actual class YoutubeProvider actual constructor(
logger.d { "An Error Occurred While Processing!" } logger.d { "An Error Occurred While Processing!" }
} }
} }
return if (result.title.isNotBlank()) result if (result.title.isNotBlank()) result else null
else null
} }
@Suppress("DefaultLocale") @Suppress("DefaultLocale")
private suspend fun getYTTrack( private suspend fun getYTTrack(
searchId: String, searchId: String,
): PlatformQueryResult? { ): PlatformQueryResult? = withContext(Dispatchers.IO) {
val result = PlatformQueryResult( val result = PlatformQueryResult(
folderType = "", folderType = "",
subFolder = "", subFolder = "",
@ -188,7 +183,6 @@ actual class YoutubeProvider actual constructor(
logger.e { "An Error Occurred While Processing!,$searchId" } logger.e { "An Error Occurred While Processing!,$searchId" }
} }
} }
return if (result.title.isNotBlank()) result if (result.title.isNotBlank()) result else null
else null
} }
} }

View File

@ -173,7 +173,7 @@ class ForegroundService : Service(), CoroutineScope {
**/ **/
private fun downloadAllTracks(trackList: List<TrackDetails>) { private fun downloadAllTracks(trackList: List<TrackDetails>) {
trackList.forEach { trackList.forEach {
launch { launch(Dispatchers.IO) {
if (!it.videoID.isNullOrBlank()) { // Video ID already known! if (!it.videoID.isNullOrBlank()) { // Video ID already known!
downloadTrack(it.videoID!!, it) downloadTrack(it.videoID!!, it)
} else { } else {
@ -193,8 +193,7 @@ class ForegroundService : Service(), CoroutineScope {
} }
} }
private fun downloadTrack(videoID: String, track: TrackDetails) { private suspend fun downloadTrack(videoID: String, track: TrackDetails) {
launch {
try { try {
val url = fetcher.youtubeMp3.getMp3DownloadLink(videoID) val url = fetcher.youtubeMp3.getMp3DownloadLink(videoID)
if (url == null) { if (url == null) {
@ -208,7 +207,6 @@ class ForegroundService : Service(), CoroutineScope {
allTracksStatus[track.title] = DownloadStatus.Failed allTracksStatus[track.title] = DownloadStatus.Failed
} }
} }
}
private fun enqueueDownload(url: String, track: TrackDetails) { private fun enqueueDownload(url: String, track: TrackDetails) {
val request = Request(url, track.outputFilePath).apply { val request = Request(url, track.outputFilePath).apply {