feat: add error message for magnets

fixes #899
This commit is contained in:
tapframe 2026-05-05 13:22:47 +05:30
parent 1af3cfeded
commit f7e9778ca4
3 changed files with 26 additions and 4 deletions

View file

@ -1026,6 +1026,7 @@
<string name="streams_resume_from_percent">Resume from %1$d%</string> <string name="streams_resume_from_percent">Resume from %1$d%</string>
<string name="streams_resume_from_time">Resume from %1$s</string> <string name="streams_resume_from_time">Resume from %1$s</string>
<string name="streams_size">SIZE %1$s</string> <string name="streams_size">SIZE %1$s</string>
<string name="streams_torrent_not_supported">Torrent streams are not supported</string>
<string name="trailer_close">Close trailer</string> <string name="trailer_close">Close trailer</string>
<string name="trailer_unable_to_play">Unable to play trailer</string> <string name="trailer_unable_to_play">Unable to play trailer</string>
<string name="trakt_lists_load_failed">Failed to load Trakt lists</string> <string name="trakt_lists_load_failed">Failed to load Trakt lists</string>

View file

@ -25,10 +25,18 @@ data class StreamItem(
val directPlaybackUrl: String? val directPlaybackUrl: String?
get() = url ?: externalUrl get() = url ?: externalUrl
val isTorrentStream: Boolean
get() = !infoHash.isNullOrBlank() ||
url.isMagnetLink() ||
externalUrl.isMagnetLink()
val hasPlayableSource: Boolean val hasPlayableSource: Boolean
get() = url != null || infoHash != null || externalUrl != null get() = url != null || infoHash != null || externalUrl != null
} }
private fun String?.isMagnetLink(): Boolean =
this?.trimStart()?.startsWith("magnet:", ignoreCase = true) == true
data class StreamBehaviorHints( data class StreamBehaviorHints(
val bingeGroup: String? = null, val bingeGroup: String? = null,
val notWebReady: Boolean = false, val notWebReady: Boolean = false,

View file

@ -129,6 +129,7 @@ fun StreamsScreen(
val clipboardManager = LocalClipboardManager.current val clipboardManager = LocalClipboardManager.current
val streamLinkCopiedText = stringResource(Res.string.streams_link_copied) val streamLinkCopiedText = stringResource(Res.string.streams_link_copied)
val noDirectStreamLinkText = stringResource(Res.string.streams_no_direct_link) val noDirectStreamLinkText = stringResource(Res.string.streams_no_direct_link)
val torrentUnsupportedText = stringResource(Res.string.streams_torrent_not_supported)
var streamActionsTarget by remember(videoId) { mutableStateOf<StreamItem?>(null) } var streamActionsTarget by remember(videoId) { mutableStateOf<StreamItem?>(null) }
var preferredFilterApplied by remember(videoId) { mutableStateOf(false) } var preferredFilterApplied by remember(videoId) { mutableStateOf(false) }
val storedProgress = if (startFromBeginning) { val storedProgress = if (startFromBeginning) {
@ -205,7 +206,13 @@ fun StreamsScreen(
uiState = uiState, uiState = uiState,
resumePositionMs = effectiveResumePositionMs, resumePositionMs = effectiveResumePositionMs,
resumeProgressFraction = effectiveResumeProgressFraction, resumeProgressFraction = effectiveResumeProgressFraction,
onStreamSelected = onStreamSelected, onStreamSelected = { stream, positionMs, progressFraction ->
if (stream.isTorrentStream) {
NuvioToastController.show(torrentUnsupportedText)
} else {
onStreamSelected(stream, positionMs, progressFraction)
}
},
onStreamLongPress = { stream -> streamActionsTarget = stream }, onStreamLongPress = { stream -> streamActionsTarget = stream },
) )
} else { } else {
@ -220,7 +227,13 @@ fun StreamsScreen(
uiState = uiState, uiState = uiState,
resumePositionMs = effectiveResumePositionMs, resumePositionMs = effectiveResumePositionMs,
resumeProgressFraction = effectiveResumeProgressFraction, resumeProgressFraction = effectiveResumeProgressFraction,
onStreamSelected = onStreamSelected, onStreamSelected = { stream, positionMs, progressFraction ->
if (stream.isTorrentStream) {
NuvioToastController.show(torrentUnsupportedText)
} else {
onStreamSelected(stream, positionMs, progressFraction)
}
},
onStreamLongPress = { stream -> streamActionsTarget = stream }, onStreamLongPress = { stream -> streamActionsTarget = stream },
) )
} }
@ -830,7 +843,7 @@ private fun LazyListScope.streamSection(
StreamCard( StreamCard(
stream = stream, stream = stream,
onClick = { onClick = {
if (stream.directPlaybackUrl != null) { if (stream.directPlaybackUrl != null || stream.isTorrentStream) {
onStreamSelected(stream, resumePositionMs, resumeProgressFraction) onStreamSelected(stream, resumePositionMs, resumeProgressFraction)
} }
}, },
@ -936,7 +949,7 @@ private fun StreamCard(
onLongClick: (() -> Unit)? = null, onLongClick: (() -> Unit)? = null,
modifier: Modifier = Modifier, modifier: Modifier = Modifier,
) { ) {
val isEnabled = stream.directPlaybackUrl != null val isEnabled = stream.directPlaybackUrl != null || stream.isTorrentStream
val cardShape = RoundedCornerShape(12.dp) val cardShape = RoundedCornerShape(12.dp)
Row( Row(
modifier = modifier modifier = modifier