fix(downloads): passing resume position

This commit is contained in:
tapframe 2026-04-11 21:30:44 +05:30
parent 7437f54ab8
commit 7c2cad51b9
6 changed files with 33 additions and 5 deletions

View file

@ -1,20 +1,24 @@
package com.nuvio.app.features.player
import android.content.Context
import androidx.media3.datasource.DataSource
import androidx.media3.datasource.DefaultDataSource
import androidx.media3.datasource.DefaultHttpDataSource
import com.nuvio.app.features.trailer.YoutubeChunkedDataSourceFactory
internal object PlatformPlaybackDataSourceFactory {
fun create(
context: Context,
defaultRequestHeaders: Map<String, String>,
defaultResponseHeaders: Map<String, String>,
useYoutubeChunkedPlayback: Boolean,
): DataSource.Factory {
val baseFactory: DataSource.Factory = if (useYoutubeChunkedPlayback) {
val networkFactory: DataSource.Factory = if (useYoutubeChunkedPlayback) {
YoutubeChunkedDataSourceFactory(defaultRequestHeaders = defaultRequestHeaders)
} else {
DefaultHttpDataSource.Factory().setDefaultRequestProperties(defaultRequestHeaders)
}
val baseFactory: DataSource.Factory = DefaultDataSource.Factory(context, networkFactory)
return if (defaultResponseHeaders.isEmpty()) {
baseFactory
} else {

View file

@ -92,7 +92,8 @@ internal actual object DownloadsPlatformDownloader {
tempFile.delete()
}
onSuccess(destination.toURI().toString(), totalBytes)
val finalSize = destination.length()
onSuccess(destination.toURI().toString(), totalBytes ?: finalSize)
}
} catch (_: CancellationException) {
tempFile.delete()

View file

@ -128,6 +128,7 @@ actual fun PlatformPlayerSurface(
.setTsExtractorTimestampSearchBytes(1500 * TsExtractor.TS_PACKET_SIZE)
val dataSourceFactory = PlatformPlaybackDataSourceFactory.create(
context = context,
defaultRequestHeaders = sanitizedSourceHeaders,
defaultResponseHeaders = sanitizedSourceResponseHeaders,
useYoutubeChunkedPlayback = useYoutubeChunkedPlayback,

View file

@ -1,16 +1,20 @@
package com.nuvio.app.features.player
import android.content.Context
import androidx.media3.datasource.DataSource
import androidx.media3.datasource.DefaultDataSource
import androidx.media3.datasource.DefaultHttpDataSource
internal object PlatformPlaybackDataSourceFactory {
fun create(
context: Context,
defaultRequestHeaders: Map<String, String>,
defaultResponseHeaders: Map<String, String>,
useYoutubeChunkedPlayback: Boolean,
): DataSource.Factory {
val baseFactory = DefaultHttpDataSource.Factory()
val httpFactory = DefaultHttpDataSource.Factory()
.setDefaultRequestProperties(defaultRequestHeaders)
val baseFactory: DataSource.Factory = DefaultDataSource.Factory(context, httpFactory)
return if (defaultResponseHeaders.isEmpty()) {
baseFactory
} else {

View file

@ -1250,6 +1250,11 @@ private fun MainAppContent(
onBack = onBack,
onOpenDownload = { item ->
val sourceUrl = item.localFileUri ?: return@DownloadsScreen
val resumeEntry = item.videoId
.takeIf { it.isNotBlank() }
?.let(WatchProgressRepository::progressForVideo)
?.takeIf { it.isResumable }
val launchId = PlayerLaunchStore.put(
PlayerLaunch(
title = item.title,
@ -1271,7 +1276,8 @@ private fun MainAppContent(
videoId = item.videoId,
parentMetaId = item.parentMetaId,
parentMetaType = item.parentMetaType,
initialPositionMs = 0L,
initialPositionMs = resumeEntry?.lastPositionMs?.takeIf { it > 0L } ?: 0L,
initialProgressFraction = resumeEntry?.progressFraction?.takeIf { it > 0f },
),
)
navController.navigate(PlayerRoute(launchId = launchId))

View file

@ -88,7 +88,8 @@ internal actual object DownloadsPlatformDownloader {
}
val localFileUri = NSURL.fileURLWithPath(destinationPath).absoluteString ?: "file://$destinationPath"
onSuccess(localFileUri, totalBytes)
val finalSize = fileSizeOrNull(destinationPath)
onSuccess(localFileUri, totalBytes ?: finalSize)
} catch (_: CancellationException) {
removePathIfExists(tempPath)
} catch (error: Throwable) {
@ -174,6 +175,17 @@ private suspend fun writeChannelToFile(
}
}
@OptIn(ExperimentalForeignApi::class)
private fun fileSizeOrNull(path: String): Long? {
val attrs = NSFileManager.defaultManager.attributesOfItemAtPath(path, error = null)
val value = attrs?.get("NSFileSize")
return when (value) {
is Long -> value
is Number -> value.toLong()
else -> null
}
}
private fun String.toLocalPath(): String? {
if (startsWith("file://")) {
return removePrefix("file://")