diff --git a/tools/chatgui-android/app/src/main/java/com/utun/chat/data/StreamController.kt b/tools/chatgui-android/app/src/main/java/com/utun/chat/data/StreamController.kt index 7ee4c9f9..b6bf218b 100644 --- a/tools/chatgui-android/app/src/main/java/com/utun/chat/data/StreamController.kt +++ b/tools/chatgui-android/app/src/main/java/com/utun/chat/data/StreamController.kt @@ -76,7 +76,7 @@ object StreamController { fun ended(id: Long, owner: StreamService) { if (service === owner) service = null val st = mutable.value ?: return - if (st.id != id) return + if (st.id != id || !st.ongoing) return capturing = false mutable.value = st.copy(phase = if (st.error != null) StreamPhase.FAILED else StreamPhase.ENDED) LogManager.addLog("INFO", "stream", "publisher released id=$id") diff --git a/tools/chatgui-android/app/src/main/java/com/utun/chat/ui/screens/StreamScreen.kt b/tools/chatgui-android/app/src/main/java/com/utun/chat/ui/screens/StreamScreen.kt index 0ae7010c..2ca3dd10 100644 --- a/tools/chatgui-android/app/src/main/java/com/utun/chat/ui/screens/StreamScreen.kt +++ b/tools/chatgui-android/app/src/main/java/com/utun/chat/ui/screens/StreamScreen.kt @@ -10,11 +10,14 @@ import android.view.TextureView import androidx.activity.compose.rememberLauncherForActivityResult import androidx.activity.result.contract.ActivityResultContracts 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.automirrored.filled.ArrowBack import androidx.compose.material3.* import androidx.compose.runtime.* import androidx.compose.ui.Modifier +import androidx.compose.ui.Alignment import androidx.compose.ui.platform.LocalContext import androidx.compose.ui.res.stringResource 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) } if (sources.isEmpty() && local?.ongoing != true) Text(stringResource(R.string.stream_none)) - sources.forEach { source -> - TextButton(onClick = { selected = source }) { Text(stringResource(R.string.stream_watch, source.name.ifEmpty { source.id.toULong().toString() })) } + Column(Modifier.fillMaxWidth().heightIn(max = 160.dp).verticalScroll(rememberScrollState())) { + sources.forEach { source -> + TextButton(onClick = { selected = source }) { Text(stringResource(R.string.stream_watch, source.name.ifEmpty { source.id.toULong().toString() })) } + } } 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)) } } } @@ -129,8 +136,10 @@ private fun LiveStreamView(group: Long, source: Long, localPreview: Boolean) { val status by engine.status.collectAsState() var surface by remember { mutableStateOf(null) } DisposableEffect(engine) { onDispose { engine.stop() } } - Text(stringResource(status)) - AndroidView(factory = { context -> + Column(Modifier.fillMaxSize()) { + Text(stringResource(status)) + Box(Modifier.weight(1f).fillMaxWidth(), contentAlignment = Alignment.Center) { + AndroidView(factory = { context -> TextureView(context).apply { surfaceTextureListener = object : TextureView.SurfaceTextureListener { 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) {} } } - }, modifier = Modifier.fillMaxWidth().aspectRatio(aspect), onRelease = { view -> + }, modifier = Modifier.aspectRatio(aspect, matchHeightConstraintsFirst = true), onRelease = { view -> engine.stop(); view.surfaceTextureListener = null; surface?.release(); surface = null }) + } + } }