Open Android stream controls from own multiview tile
This commit is contained in:
1 parent
ca7e169811
commit
39bca58515
2 files changed
+35
-7
No files matched your search
+9
-5
@@ -50,7 +50,8 @@ private class GridStream(val source: StreamSource) {
|
||||
* Пустой каталог оставляет экран открытым; временный сбой каталога сохраняет действующие readers. */
|
||||
@OptIn(ExperimentalMaterial3Api::class)
|
||||
@Composable
|
||||
internal fun StreamGridScreen(group: Long, title: String, sources: List<StreamSource>, unavailable: Boolean, onClose: () -> Unit) {
|
||||
internal fun StreamGridScreen(group: Long, title: String, sources: List<StreamSource>, unavailable: Boolean,
|
||||
ownPreviewVisible: Boolean, onOwnStream: () -> Unit, onClose: () -> Unit) {
|
||||
val tiles = remember(group) { mutableStateListOf<GridStream>() }
|
||||
var expanded by remember(group) { mutableStateOf<GridStream?>(null) }
|
||||
val focused = expanded?.takeIf { it in tiles }
|
||||
@@ -106,7 +107,7 @@ internal fun StreamGridScreen(group: Long, title: String, sources: List<StreamSo
|
||||
delay(250)
|
||||
}
|
||||
}
|
||||
Scaffold(topBar = {
|
||||
Scaffold(modifier = if (ownPreviewVisible) Modifier else Modifier.clearAndSetSemantics {}, topBar = {
|
||||
if (focused == null)
|
||||
TopAppBar(title = { Text(stringResource(R.string.stream_all_title, title), maxLines = 1, overflow = TextOverflow.Ellipsis) },
|
||||
navigationIcon = { IconButton(onClick = onClose) { Icon(Icons.Filled.Close, stringResource(R.string.stream_close_view)) } })
|
||||
@@ -124,8 +125,10 @@ internal fun StreamGridScreen(group: Long, title: String, sources: List<StreamSo
|
||||
}
|
||||
Layout(content = {
|
||||
for (tile in tiles) key(tile.source.id, tile.source.epoch) {
|
||||
StreamGridTile(group, tile, visible, tile === focused, focused != null && tile !== focused) {
|
||||
expanded = if (tile === focused) null else tile
|
||||
StreamGridTile(group, tile, visible && (!tile.source.self || ownPreviewVisible),
|
||||
tile === focused, focused != null && tile !== focused) {
|
||||
if (tile.source.self) onOwnStream()
|
||||
else expanded = if (tile === focused) null else tile
|
||||
}
|
||||
}
|
||||
}, modifier = Modifier.fillMaxSize()) { children, constraints ->
|
||||
@@ -179,7 +182,8 @@ private fun StreamGridTile(group: Long, tile: GridStream, visible: Boolean, expa
|
||||
}
|
||||
}
|
||||
Box(Modifier.matchParentSize().clickable(interactionSource = remember { MutableInteractionSource() }, indication = null,
|
||||
role = Role.Button, onClickLabel = stringResource(if (expanded) R.string.collapse else R.string.expand), onClick = onClick)
|
||||
role = Role.Button, onClickLabel = stringResource(if (tile.source.self) R.string.stream_manage
|
||||
else if (expanded) R.string.collapse else R.string.expand), onClick = onClick)
|
||||
.semantics { contentDescription = tile.source.displayName })
|
||||
}
|
||||
}
|
||||
|
||||
@@ -11,6 +11,7 @@ import android.os.Handler
|
||||
import android.os.Looper
|
||||
import android.os.SystemClock
|
||||
import android.view.TextureView
|
||||
import androidx.activity.compose.BackHandler
|
||||
import androidx.activity.compose.rememberLauncherForActivityResult
|
||||
import androidx.activity.result.contract.ActivityResultContracts
|
||||
import androidx.compose.foundation.layout.*
|
||||
@@ -27,6 +28,7 @@ import androidx.compose.material.icons.filled.ScreenRotation
|
||||
import androidx.compose.material.icons.filled.Stop
|
||||
import androidx.compose.material3.*
|
||||
import androidx.compose.runtime.*
|
||||
import androidx.compose.runtime.saveable.rememberSaveable
|
||||
import androidx.compose.ui.Modifier
|
||||
import androidx.compose.ui.Alignment
|
||||
import androidx.compose.ui.geometry.CornerRadius
|
||||
@@ -75,10 +77,24 @@ import kotlin.math.roundToInt
|
||||
fun StreamScreen(channelId: String, channelName: String, sources: List<StreamSource>, selected: StreamSource?,
|
||||
sourcesFailed: Boolean, onSelect: (StreamSource?) -> Unit, viewAll: Boolean = false,
|
||||
onBack: () -> Unit) {
|
||||
val context = LocalContext.current
|
||||
val group = remember(channelId) { channelId.toULongOrNull()?.toLong() ?: 0L }
|
||||
if (viewAll) {
|
||||
StreamGridScreen(group, channelName, sources, sourcesFailed) { onSelect(null); onBack() }
|
||||
var manageOwn by rememberSaveable(group) { mutableStateOf(false) }
|
||||
LaunchedEffect(manageOwn) {
|
||||
LogManager.addLog("INFO", "stream", "multiview controls group=$group open=$manageOwn " +
|
||||
"publisher=${StreamController.state.value?.id} readersPreserved=true")
|
||||
}
|
||||
Box(Modifier.fillMaxSize()) {
|
||||
StreamGridScreen(group, channelName, sources, sourcesFailed, ownPreviewVisible = !manageOwn, onOwnStream = {
|
||||
val publisher = StreamController.state.value
|
||||
if (publisher?.ongoing == true && publisher.group == group) manageOwn = true
|
||||
else LogManager.addLog("WARN", "stream", "multiview controls stale group=$group publisher=${publisher?.id} phase=${publisher?.phase}")
|
||||
}, onClose = { onSelect(null); onBack() })
|
||||
if (manageOwn) {
|
||||
BackHandler { manageOwn = false }
|
||||
StreamPublishScreen(group, channelName) { manageOwn = false }
|
||||
}
|
||||
}
|
||||
return
|
||||
}
|
||||
if (selected != null && !selected.self) {
|
||||
@@ -87,6 +103,14 @@ fun StreamScreen(channelId: String, channelName: String, sources: List<StreamSou
|
||||
}
|
||||
return
|
||||
}
|
||||
StreamPublishScreen(group, channelName, onBack)
|
||||
}
|
||||
|
||||
/** Управление публикацией используется отдельно и поверх сетки, не меняя выбор просмотра. */
|
||||
@OptIn(ExperimentalMaterial3Api::class)
|
||||
@Composable
|
||||
private fun StreamPublishScreen(group: Long, channelName: String, onBack: () -> Unit) {
|
||||
val context = LocalContext.current
|
||||
val displayDegrees = StreamDisplayDegrees()
|
||||
val state by StreamController.state.collectAsState()
|
||||
val local = state?.takeIf { it.group == group }
|
||||
|
||||
Reference in new issue
Block a user