feat: placeholder media channel overlay
Signed-off-by: Infi <infi@infi.sh>
This commit is contained in:
parent
4784bb3f3f
commit
67881fefb7
|
|
@ -17,6 +17,19 @@ sealed class LabsAccessControlVariates {
|
||||||
data class Restricted(val predicate: () -> Boolean) : LabsAccessControlVariates()
|
data class Restricted(val predicate: () -> Boolean) : LabsAccessControlVariates()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@FeatureFlag("MediaConversations")
|
||||||
|
sealed class MediaConversationsVariates {
|
||||||
|
@Treatment(
|
||||||
|
"Enable voice, video and screen conversations for all users"
|
||||||
|
)
|
||||||
|
object Enabled : MediaConversationsVariates()
|
||||||
|
|
||||||
|
@Treatment(
|
||||||
|
"Enable voice, video and screen conversations for users that meet certain or all criteria (implementation-specific)"
|
||||||
|
)
|
||||||
|
data class Restricted(val predicate: () -> Boolean) : MediaConversationsVariates()
|
||||||
|
}
|
||||||
|
|
||||||
object FeatureFlags {
|
object FeatureFlags {
|
||||||
@FeatureFlag("LabsAccessControl")
|
@FeatureFlag("LabsAccessControl")
|
||||||
var labsAccessControl by mutableStateOf<LabsAccessControlVariates>(
|
var labsAccessControl by mutableStateOf<LabsAccessControlVariates>(
|
||||||
|
|
@ -24,4 +37,22 @@ object FeatureFlags {
|
||||||
RevoltAPI.selfId == SpecialUsers.JENNIFER
|
RevoltAPI.selfId == SpecialUsers.JENNIFER
|
||||||
}
|
}
|
||||||
)
|
)
|
||||||
|
|
||||||
|
val labsAccessControlGranted: Boolean
|
||||||
|
get() = when (labsAccessControl) {
|
||||||
|
is LabsAccessControlVariates.Restricted -> (labsAccessControl as LabsAccessControlVariates.Restricted).predicate()
|
||||||
|
}
|
||||||
|
|
||||||
|
@FeatureFlag("MediaConversations")
|
||||||
|
var mediaConversations by mutableStateOf<MediaConversationsVariates>(
|
||||||
|
MediaConversationsVariates.Restricted {
|
||||||
|
RevoltAPI.selfId == SpecialUsers.JENNIFER
|
||||||
|
}
|
||||||
|
)
|
||||||
|
|
||||||
|
val mediaConversationsGranted: Boolean
|
||||||
|
get() = when (mediaConversations) {
|
||||||
|
is MediaConversationsVariates.Enabled -> true
|
||||||
|
is MediaConversationsVariates.Restricted -> (mediaConversations as MediaConversationsVariates.Restricted).predicate()
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -10,6 +10,7 @@ sealed class Action {
|
||||||
data class MessageReactionInfo(val messageId: String, val emoji: String) : Action()
|
data class MessageReactionInfo(val messageId: String, val emoji: String) : Action()
|
||||||
data class TopNavigate(val route: String) : Action()
|
data class TopNavigate(val route: String) : Action()
|
||||||
data class ChatNavigate(val route: String) : Action()
|
data class ChatNavigate(val route: String) : Action()
|
||||||
|
data class OpenVoiceChannelOverlay(val channelId: String) : Action()
|
||||||
}
|
}
|
||||||
|
|
||||||
val ActionChannel = Channel<Action>(
|
val ActionChannel = Channel<Action>(
|
||||||
|
|
|
||||||
|
|
@ -0,0 +1,64 @@
|
||||||
|
package chat.revolt.components.screens.voice
|
||||||
|
|
||||||
|
import android.content.Context
|
||||||
|
import android.util.DisplayMetrics
|
||||||
|
import android.view.WindowManager
|
||||||
|
import androidx.compose.foundation.background
|
||||||
|
import androidx.compose.foundation.layout.Arrangement
|
||||||
|
import androidx.compose.foundation.layout.Column
|
||||||
|
import androidx.compose.foundation.layout.requiredSize
|
||||||
|
import androidx.compose.material3.Button
|
||||||
|
import androidx.compose.material3.MaterialTheme
|
||||||
|
import androidx.compose.material3.Text
|
||||||
|
import androidx.compose.runtime.Composable
|
||||||
|
import androidx.compose.runtime.remember
|
||||||
|
import androidx.compose.ui.Alignment
|
||||||
|
import androidx.compose.ui.Modifier
|
||||||
|
import androidx.compose.ui.platform.LocalContext
|
||||||
|
import androidx.compose.ui.platform.LocalDensity
|
||||||
|
import androidx.compose.ui.text.style.TextAlign
|
||||||
|
import androidx.compose.ui.unit.dp
|
||||||
|
import androidx.compose.ui.window.Dialog
|
||||||
|
import androidx.compose.ui.window.DialogProperties
|
||||||
|
|
||||||
|
@Composable
|
||||||
|
fun VoiceChannelOverlay(channelId: String, onCollapse: () -> Unit) {
|
||||||
|
val context = LocalContext.current
|
||||||
|
val windowManager =
|
||||||
|
remember { context.getSystemService(Context.WINDOW_SERVICE) as WindowManager }
|
||||||
|
|
||||||
|
val metrics = DisplayMetrics().apply {
|
||||||
|
@Suppress("DEPRECATION") // We *need* the real metrics here, not the window metrics
|
||||||
|
windowManager.defaultDisplay.getRealMetrics(this)
|
||||||
|
}
|
||||||
|
val (width, height) = with(LocalDensity.current) {
|
||||||
|
Pair(metrics.widthPixels.toDp(), metrics.heightPixels.toDp())
|
||||||
|
}
|
||||||
|
|
||||||
|
Dialog(
|
||||||
|
onDismissRequest = {
|
||||||
|
onCollapse()
|
||||||
|
},
|
||||||
|
properties = DialogProperties(
|
||||||
|
usePlatformDefaultWidth = false,
|
||||||
|
decorFitsSystemWindows = true,
|
||||||
|
dismissOnClickOutside = false,
|
||||||
|
dismissOnBackPress = true
|
||||||
|
)
|
||||||
|
) {
|
||||||
|
Column(
|
||||||
|
Modifier
|
||||||
|
.requiredSize(width, height)
|
||||||
|
.background(MaterialTheme.colorScheme.background),
|
||||||
|
horizontalAlignment = Alignment.CenterHorizontally,
|
||||||
|
verticalArrangement = Arrangement.spacedBy(8.dp, Alignment.CenterVertically)
|
||||||
|
) {
|
||||||
|
Text(text = "Voice channel overlay for $channelId", textAlign = TextAlign.Center)
|
||||||
|
Button(onClick = {
|
||||||
|
onCollapse()
|
||||||
|
}) {
|
||||||
|
Text("Close")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -87,6 +87,7 @@ import chat.revolt.components.screens.chat.drawer.channel.ChannelList
|
||||||
import chat.revolt.components.screens.chat.drawer.server.DrawerServer
|
import chat.revolt.components.screens.chat.drawer.server.DrawerServer
|
||||||
import chat.revolt.components.screens.chat.drawer.server.DrawerServerlikeIcon
|
import chat.revolt.components.screens.chat.drawer.server.DrawerServerlikeIcon
|
||||||
import chat.revolt.components.screens.chat.drawer.server.ServerDrawerSeparator
|
import chat.revolt.components.screens.chat.drawer.server.ServerDrawerSeparator
|
||||||
|
import chat.revolt.components.screens.voice.VoiceChannelOverlay
|
||||||
import chat.revolt.internals.Changelogs
|
import chat.revolt.internals.Changelogs
|
||||||
import chat.revolt.persistence.KVStorage
|
import chat.revolt.persistence.KVStorage
|
||||||
import chat.revolt.screens.chat.dialogs.safety.ReportMessageDialog
|
import chat.revolt.screens.chat.dialogs.safety.ReportMessageDialog
|
||||||
|
|
@ -290,6 +291,9 @@ fun ChatRouterScreen(
|
||||||
|
|
||||||
var useTabletAwareUI by remember { mutableStateOf(false) }
|
var useTabletAwareUI by remember { mutableStateOf(false) }
|
||||||
|
|
||||||
|
var voiceChannelOverlay by remember { mutableStateOf(false) }
|
||||||
|
var voiceChannelOverlayChannelId by remember { mutableStateOf("") }
|
||||||
|
|
||||||
val toggleDrawerLambda = remember {
|
val toggleDrawerLambda = remember {
|
||||||
{
|
{
|
||||||
scope.launch {
|
scope.launch {
|
||||||
|
|
@ -410,6 +414,11 @@ fun ChatRouterScreen(
|
||||||
is Action.ChatNavigate -> {
|
is Action.ChatNavigate -> {
|
||||||
navController.navigate(action.route)
|
navController.navigate(action.route)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
is Action.OpenVoiceChannelOverlay -> {
|
||||||
|
voiceChannelOverlayChannelId = action.channelId
|
||||||
|
voiceChannelOverlay = true
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -671,6 +680,12 @@ fun ChatRouterScreen(
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (voiceChannelOverlay) {
|
||||||
|
VoiceChannelOverlay(voiceChannelOverlayChannelId) {
|
||||||
|
voiceChannelOverlay = false
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
Column(
|
Column(
|
||||||
modifier = Modifier
|
modifier = Modifier
|
||||||
.fillMaxWidth()
|
.fillMaxWidth()
|
||||||
|
|
|
||||||
|
|
@ -31,6 +31,7 @@ import androidx.compose.foundation.layout.windowInsetsPadding
|
||||||
import androidx.compose.foundation.lazy.LazyColumn
|
import androidx.compose.foundation.lazy.LazyColumn
|
||||||
import androidx.compose.foundation.lazy.items
|
import androidx.compose.foundation.lazy.items
|
||||||
import androidx.compose.foundation.lazy.rememberLazyListState
|
import androidx.compose.foundation.lazy.rememberLazyListState
|
||||||
|
import androidx.compose.material3.Button
|
||||||
import androidx.compose.material3.CircularProgressIndicator
|
import androidx.compose.material3.CircularProgressIndicator
|
||||||
import androidx.compose.material3.ExperimentalMaterial3Api
|
import androidx.compose.material3.ExperimentalMaterial3Api
|
||||||
import androidx.compose.material3.Icon
|
import androidx.compose.material3.Icon
|
||||||
|
|
@ -72,6 +73,9 @@ import chat.revolt.api.routes.channel.react
|
||||||
import chat.revolt.api.routes.microservices.autumn.FileArgs
|
import chat.revolt.api.routes.microservices.autumn.FileArgs
|
||||||
import chat.revolt.api.schemas.Channel
|
import chat.revolt.api.schemas.Channel
|
||||||
import chat.revolt.api.schemas.ChannelType
|
import chat.revolt.api.schemas.ChannelType
|
||||||
|
import chat.revolt.api.settings.FeatureFlags
|
||||||
|
import chat.revolt.callbacks.Action
|
||||||
|
import chat.revolt.callbacks.ActionChannel
|
||||||
import chat.revolt.components.chat.Message
|
import chat.revolt.components.chat.Message
|
||||||
import chat.revolt.components.chat.NativeMessageField
|
import chat.revolt.components.chat.NativeMessageField
|
||||||
import chat.revolt.components.chat.SystemMessage
|
import chat.revolt.components.chat.SystemMessage
|
||||||
|
|
@ -267,6 +271,20 @@ fun ChannelScreen(
|
||||||
useDrawer = useDrawer
|
useDrawer = useDrawer
|
||||||
)
|
)
|
||||||
|
|
||||||
|
if (FeatureFlags.mediaConversationsGranted && channel?.channelType == ChannelType.VoiceChannel) {
|
||||||
|
Button(onClick = {
|
||||||
|
coroutineScope.launch {
|
||||||
|
ActionChannel.send(
|
||||||
|
Action.OpenVoiceChannelOverlay(
|
||||||
|
channelId
|
||||||
|
)
|
||||||
|
)
|
||||||
|
}
|
||||||
|
}) {
|
||||||
|
Text("Open voice channel overlay")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
val isScrolledToBottom = remember(lazyListState) {
|
val isScrolledToBottom = remember(lazyListState) {
|
||||||
derivedStateOf {
|
derivedStateOf {
|
||||||
lazyListState.firstVisibleItemIndex <= 6
|
lazyListState.firstVisibleItemIndex <= 6
|
||||||
|
|
|
||||||
|
|
@ -12,16 +12,13 @@ import androidx.navigation.compose.NavHost
|
||||||
import androidx.navigation.compose.composable
|
import androidx.navigation.compose.composable
|
||||||
import androidx.navigation.compose.rememberNavController
|
import androidx.navigation.compose.rememberNavController
|
||||||
import chat.revolt.api.settings.FeatureFlags
|
import chat.revolt.api.settings.FeatureFlags
|
||||||
import chat.revolt.api.settings.LabsAccessControlVariates
|
|
||||||
import chat.revolt.screens.labs.ui.mockups.CallScreenMockup
|
import chat.revolt.screens.labs.ui.mockups.CallScreenMockup
|
||||||
|
|
||||||
annotation class LabsFeature
|
annotation class LabsFeature
|
||||||
|
|
||||||
@Composable
|
@Composable
|
||||||
fun LabsGuard(onTurnBack: () -> Unit = {}, content: @Composable () -> Unit) {
|
fun LabsGuard(onTurnBack: () -> Unit = {}, content: @Composable () -> Unit) {
|
||||||
if (FeatureFlags.labsAccessControl is LabsAccessControlVariates.Restricted &&
|
if (!FeatureFlags.labsAccessControlGranted) {
|
||||||
(FeatureFlags.labsAccessControl as LabsAccessControlVariates.Restricted).predicate().not()
|
|
||||||
) {
|
|
||||||
AlertDialog(
|
AlertDialog(
|
||||||
onDismissRequest = { onTurnBack() },
|
onDismissRequest = { onTurnBack() },
|
||||||
confirmButton = {
|
confirmButton = {
|
||||||
|
|
|
||||||
|
|
@ -45,7 +45,6 @@ import chat.revolt.activities.InviteActivity
|
||||||
import chat.revolt.api.RevoltAPI
|
import chat.revolt.api.RevoltAPI
|
||||||
import chat.revolt.api.settings.FeatureFlags
|
import chat.revolt.api.settings.FeatureFlags
|
||||||
import chat.revolt.api.settings.GlobalState
|
import chat.revolt.api.settings.GlobalState
|
||||||
import chat.revolt.api.settings.LabsAccessControlVariates
|
|
||||||
import chat.revolt.components.generic.ListHeader
|
import chat.revolt.components.generic.ListHeader
|
||||||
import chat.revolt.components.screens.settings.SelfUserOverview
|
import chat.revolt.components.screens.settings.SelfUserOverview
|
||||||
import chat.revolt.persistence.KVStorage
|
import chat.revolt.persistence.KVStorage
|
||||||
|
|
@ -241,9 +240,7 @@ fun SettingsScreen(
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
if (FeatureFlags.labsAccessControl is LabsAccessControlVariates.Restricted &&
|
if (FeatureFlags.labsAccessControlGranted) {
|
||||||
(FeatureFlags.labsAccessControl as LabsAccessControlVariates.Restricted).predicate()
|
|
||||||
) {
|
|
||||||
ListItem(
|
ListItem(
|
||||||
headlineContent = {
|
headlineContent = {
|
||||||
Text(
|
Text(
|
||||||
|
|
|
||||||
|
|
@ -47,7 +47,6 @@ import chat.revolt.api.internals.hasPermission
|
||||||
import chat.revolt.api.routes.channel.leaveDeleteOrCloseChannel
|
import chat.revolt.api.routes.channel.leaveDeleteOrCloseChannel
|
||||||
import chat.revolt.api.schemas.ChannelType
|
import chat.revolt.api.schemas.ChannelType
|
||||||
import chat.revolt.api.settings.FeatureFlags
|
import chat.revolt.api.settings.FeatureFlags
|
||||||
import chat.revolt.api.settings.LabsAccessControlVariates
|
|
||||||
import chat.revolt.internals.extensions.rememberChannelPermissions
|
import chat.revolt.internals.extensions.rememberChannelPermissions
|
||||||
import kotlinx.coroutines.launch
|
import kotlinx.coroutines.launch
|
||||||
|
|
||||||
|
|
@ -151,7 +150,7 @@ fun ChannelSettingsHome(navController: NavController, channelId: String) {
|
||||||
}
|
}
|
||||||
|
|
||||||
// TODO Implement permissions UI and remove the predicate check
|
// TODO Implement permissions UI and remove the predicate check
|
||||||
if (permissions.hasPermission(PermissionBit.ManageRole) && (FeatureFlags.labsAccessControl is LabsAccessControlVariates.Restricted && (FeatureFlags.labsAccessControl as LabsAccessControlVariates.Restricted).predicate())) {
|
if (permissions.hasPermission(PermissionBit.ManageRole) && FeatureFlags.labsAccessControlGranted) {
|
||||||
ListItem(
|
ListItem(
|
||||||
headlineContent = {
|
headlineContent = {
|
||||||
Text(
|
Text(
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue