From f7e9778ca430dac6a15e2ae312798b35c7554c33 Mon Sep 17 00:00:00 2001
From: tapframe <85391825+tapframe@users.noreply.github.com>
Date: Tue, 5 May 2026 13:22:47 +0530
Subject: [PATCH] feat: add error message for magnets
fixes #899
---
.../composeResources/values/strings.xml | 1 +
.../app/features/streams/StreamModels.kt | 8 +++++++
.../app/features/streams/StreamsScreen.kt | 21 +++++++++++++++----
3 files changed, 26 insertions(+), 4 deletions(-)
diff --git a/composeApp/src/commonMain/composeResources/values/strings.xml b/composeApp/src/commonMain/composeResources/values/strings.xml
index dfb70a90..43f04cb0 100644
--- a/composeApp/src/commonMain/composeResources/values/strings.xml
+++ b/composeApp/src/commonMain/composeResources/values/strings.xml
@@ -1026,6 +1026,7 @@
Resume from %1$d%
Resume from %1$s
SIZE %1$s
+ Torrent streams are not supported
Close trailer
Unable to play trailer
Failed to load Trakt lists
diff --git a/composeApp/src/commonMain/kotlin/com/nuvio/app/features/streams/StreamModels.kt b/composeApp/src/commonMain/kotlin/com/nuvio/app/features/streams/StreamModels.kt
index 545f71fd..c7db8b2d 100644
--- a/composeApp/src/commonMain/kotlin/com/nuvio/app/features/streams/StreamModels.kt
+++ b/composeApp/src/commonMain/kotlin/com/nuvio/app/features/streams/StreamModels.kt
@@ -25,10 +25,18 @@ data class StreamItem(
val directPlaybackUrl: String?
get() = url ?: externalUrl
+ val isTorrentStream: Boolean
+ get() = !infoHash.isNullOrBlank() ||
+ url.isMagnetLink() ||
+ externalUrl.isMagnetLink()
+
val hasPlayableSource: Boolean
get() = url != null || infoHash != null || externalUrl != null
}
+private fun String?.isMagnetLink(): Boolean =
+ this?.trimStart()?.startsWith("magnet:", ignoreCase = true) == true
+
data class StreamBehaviorHints(
val bingeGroup: String? = null,
val notWebReady: Boolean = false,
diff --git a/composeApp/src/commonMain/kotlin/com/nuvio/app/features/streams/StreamsScreen.kt b/composeApp/src/commonMain/kotlin/com/nuvio/app/features/streams/StreamsScreen.kt
index fdf38d55..a0cadbc0 100644
--- a/composeApp/src/commonMain/kotlin/com/nuvio/app/features/streams/StreamsScreen.kt
+++ b/composeApp/src/commonMain/kotlin/com/nuvio/app/features/streams/StreamsScreen.kt
@@ -129,6 +129,7 @@ fun StreamsScreen(
val clipboardManager = LocalClipboardManager.current
val streamLinkCopiedText = stringResource(Res.string.streams_link_copied)
val noDirectStreamLinkText = stringResource(Res.string.streams_no_direct_link)
+ val torrentUnsupportedText = stringResource(Res.string.streams_torrent_not_supported)
var streamActionsTarget by remember(videoId) { mutableStateOf(null) }
var preferredFilterApplied by remember(videoId) { mutableStateOf(false) }
val storedProgress = if (startFromBeginning) {
@@ -205,7 +206,13 @@ fun StreamsScreen(
uiState = uiState,
resumePositionMs = effectiveResumePositionMs,
resumeProgressFraction = effectiveResumeProgressFraction,
- onStreamSelected = onStreamSelected,
+ onStreamSelected = { stream, positionMs, progressFraction ->
+ if (stream.isTorrentStream) {
+ NuvioToastController.show(torrentUnsupportedText)
+ } else {
+ onStreamSelected(stream, positionMs, progressFraction)
+ }
+ },
onStreamLongPress = { stream -> streamActionsTarget = stream },
)
} else {
@@ -220,7 +227,13 @@ fun StreamsScreen(
uiState = uiState,
resumePositionMs = effectiveResumePositionMs,
resumeProgressFraction = effectiveResumeProgressFraction,
- onStreamSelected = onStreamSelected,
+ onStreamSelected = { stream, positionMs, progressFraction ->
+ if (stream.isTorrentStream) {
+ NuvioToastController.show(torrentUnsupportedText)
+ } else {
+ onStreamSelected(stream, positionMs, progressFraction)
+ }
+ },
onStreamLongPress = { stream -> streamActionsTarget = stream },
)
}
@@ -830,7 +843,7 @@ private fun LazyListScope.streamSection(
StreamCard(
stream = stream,
onClick = {
- if (stream.directPlaybackUrl != null) {
+ if (stream.directPlaybackUrl != null || stream.isTorrentStream) {
onStreamSelected(stream, resumePositionMs, resumeProgressFraction)
}
},
@@ -936,7 +949,7 @@ private fun StreamCard(
onLongClick: (() -> Unit)? = null,
modifier: Modifier = Modifier,
) {
- val isEnabled = stream.directPlaybackUrl != null
+ val isEnabled = stream.directPlaybackUrl != null || stream.isTorrentStream
val cardShape = RoundedCornerShape(12.dp)
Row(
modifier = modifier