|
|
|
@ -10,11 +10,14 @@ import android.view.TextureView |
|
|
|
import androidx.activity.compose.rememberLauncherForActivityResult |
|
|
|
import androidx.activity.compose.rememberLauncherForActivityResult |
|
|
|
import androidx.activity.result.contract.ActivityResultContracts |
|
|
|
import androidx.activity.result.contract.ActivityResultContracts |
|
|
|
import androidx.compose.foundation.layout.* |
|
|
|
import androidx.compose.foundation.layout.* |
|
|
|
|
|
|
|
import androidx.compose.foundation.rememberScrollState |
|
|
|
|
|
|
|
import androidx.compose.foundation.verticalScroll |
|
|
|
import androidx.compose.material.icons.Icons |
|
|
|
import androidx.compose.material.icons.Icons |
|
|
|
import androidx.compose.material.icons.automirrored.filled.ArrowBack |
|
|
|
import androidx.compose.material.icons.automirrored.filled.ArrowBack |
|
|
|
import androidx.compose.material3.* |
|
|
|
import androidx.compose.material3.* |
|
|
|
import androidx.compose.runtime.* |
|
|
|
import androidx.compose.runtime.* |
|
|
|
import androidx.compose.ui.Modifier |
|
|
|
import androidx.compose.ui.Modifier |
|
|
|
|
|
|
|
import androidx.compose.ui.Alignment |
|
|
|
import androidx.compose.ui.platform.LocalContext |
|
|
|
import androidx.compose.ui.platform.LocalContext |
|
|
|
import androidx.compose.ui.res.stringResource |
|
|
|
import androidx.compose.ui.res.stringResource |
|
|
|
import androidx.compose.ui.unit.dp |
|
|
|
import androidx.compose.ui.unit.dp |
|
|
|
@ -111,11 +114,15 @@ fun StreamScreen(channelId: String, channelName: String, onBack: () -> Unit) { |
|
|
|
} |
|
|
|
} |
|
|
|
local?.error?.let { Text(stringResource(it), color = MaterialTheme.colorScheme.error) } |
|
|
|
local?.error?.let { Text(stringResource(it), color = MaterialTheme.colorScheme.error) } |
|
|
|
if (sources.isEmpty() && local?.ongoing != true) Text(stringResource(R.string.stream_none)) |
|
|
|
if (sources.isEmpty() && local?.ongoing != true) Text(stringResource(R.string.stream_none)) |
|
|
|
sources.forEach { source -> |
|
|
|
Column(Modifier.fillMaxWidth().heightIn(max = 160.dp).verticalScroll(rememberScrollState())) { |
|
|
|
TextButton(onClick = { selected = source }) { Text(stringResource(R.string.stream_watch, source.name.ifEmpty { source.id.toULong().toString() })) } |
|
|
|
sources.forEach { source -> |
|
|
|
|
|
|
|
TextButton(onClick = { selected = source }) { Text(stringResource(R.string.stream_watch, source.name.ifEmpty { source.id.toULong().toString() })) } |
|
|
|
|
|
|
|
} |
|
|
|
} |
|
|
|
} |
|
|
|
selected?.let { source -> |
|
|
|
selected?.let { source -> |
|
|
|
key(group, source.id, source.epoch) { LiveStreamView(group, source.id, source.self) } |
|
|
|
Box(Modifier.weight(1f).fillMaxWidth()) { |
|
|
|
|
|
|
|
key(group, source.id, source.epoch) { LiveStreamView(group, source.id, source.self) } |
|
|
|
|
|
|
|
} |
|
|
|
TextButton(onClick = { selected = null }) { Text(stringResource(R.string.stream_close_view)) } |
|
|
|
TextButton(onClick = { selected = null }) { Text(stringResource(R.string.stream_close_view)) } |
|
|
|
} |
|
|
|
} |
|
|
|
} |
|
|
|
} |
|
|
|
@ -129,8 +136,10 @@ private fun LiveStreamView(group: Long, source: Long, localPreview: Boolean) { |
|
|
|
val status by engine.status.collectAsState() |
|
|
|
val status by engine.status.collectAsState() |
|
|
|
var surface by remember { mutableStateOf<Surface?>(null) } |
|
|
|
var surface by remember { mutableStateOf<Surface?>(null) } |
|
|
|
DisposableEffect(engine) { onDispose { engine.stop() } } |
|
|
|
DisposableEffect(engine) { onDispose { engine.stop() } } |
|
|
|
Text(stringResource(status)) |
|
|
|
Column(Modifier.fillMaxSize()) { |
|
|
|
AndroidView(factory = { context -> |
|
|
|
Text(stringResource(status)) |
|
|
|
|
|
|
|
Box(Modifier.weight(1f).fillMaxWidth(), contentAlignment = Alignment.Center) { |
|
|
|
|
|
|
|
AndroidView(factory = { context -> |
|
|
|
TextureView(context).apply { |
|
|
|
TextureView(context).apply { |
|
|
|
surfaceTextureListener = object : TextureView.SurfaceTextureListener { |
|
|
|
surfaceTextureListener = object : TextureView.SurfaceTextureListener { |
|
|
|
override fun onSurfaceTextureAvailable(texture: SurfaceTexture, width: Int, height: Int) { |
|
|
|
override fun onSurfaceTextureAvailable(texture: SurfaceTexture, width: Int, height: Int) { |
|
|
|
@ -143,7 +152,9 @@ private fun LiveStreamView(group: Long, source: Long, localPreview: Boolean) { |
|
|
|
override fun onSurfaceTextureUpdated(texture: SurfaceTexture) {} |
|
|
|
override fun onSurfaceTextureUpdated(texture: SurfaceTexture) {} |
|
|
|
} |
|
|
|
} |
|
|
|
} |
|
|
|
} |
|
|
|
}, modifier = Modifier.fillMaxWidth().aspectRatio(aspect), onRelease = { view -> |
|
|
|
}, modifier = Modifier.aspectRatio(aspect, matchHeightConstraintsFirst = true), onRelease = { view -> |
|
|
|
engine.stop(); view.surfaceTextureListener = null; surface?.release(); surface = null |
|
|
|
engine.stop(); view.surfaceTextureListener = null; surface?.release(); surface = null |
|
|
|
}) |
|
|
|
}) |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
} |
|
|
|
} |
|
|
|
} |
|
|
|
|