feat: routine housekeeping
Signed-off-by: Infi <infi@infi.sh>
This commit is contained in:
parent
b68267c1e7
commit
9e003897a5
|
|
@ -33,6 +33,7 @@ import chat.revolt.screens.about.AboutScreen
|
||||||
import chat.revolt.screens.about.AttributionScreen
|
import chat.revolt.screens.about.AttributionScreen
|
||||||
import chat.revolt.screens.chat.ChatRouterScreen
|
import chat.revolt.screens.chat.ChatRouterScreen
|
||||||
import chat.revolt.screens.chat.dialogs.FeedbackDialog
|
import chat.revolt.screens.chat.dialogs.FeedbackDialog
|
||||||
|
import chat.revolt.screens.labs.LabsRootScreen
|
||||||
import chat.revolt.screens.login.LoginGreetingScreen
|
import chat.revolt.screens.login.LoginGreetingScreen
|
||||||
import chat.revolt.screens.login.LoginScreen
|
import chat.revolt.screens.login.LoginScreen
|
||||||
import chat.revolt.screens.login.MfaScreen
|
import chat.revolt.screens.login.MfaScreen
|
||||||
|
|
@ -159,6 +160,8 @@ fun AppEntrypoint(windowSizeClass: WindowSizeClass) {
|
||||||
|
|
||||||
composable("about") { AboutScreen(navController) }
|
composable("about") { AboutScreen(navController) }
|
||||||
composable("about/oss") { AttributionScreen(navController) }
|
composable("about/oss") { AttributionScreen(navController) }
|
||||||
|
|
||||||
|
composable("labs") { LabsRootScreen(navController) }
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -4,12 +4,14 @@ import android.content.Context
|
||||||
import android.graphics.RuntimeShader
|
import android.graphics.RuntimeShader
|
||||||
import android.os.Build
|
import android.os.Build
|
||||||
import androidx.compose.ui.geometry.Offset
|
import androidx.compose.ui.geometry.Offset
|
||||||
import androidx.compose.ui.graphics.Brush as AndroidBrush
|
|
||||||
import androidx.compose.ui.graphics.Color
|
import androidx.compose.ui.graphics.Color
|
||||||
import androidx.compose.ui.graphics.ShaderBrush
|
import androidx.compose.ui.graphics.ShaderBrush
|
||||||
import org.intellij.lang.annotations.Language
|
import org.intellij.lang.annotations.Language
|
||||||
|
import androidx.compose.ui.graphics.Brush as AndroidBrush
|
||||||
|
|
||||||
object SpecialUsers {
|
object SpecialUsers {
|
||||||
|
val JENNIFER = "01F1WKM5TK2V6KCZWR6DGBJDTZ"
|
||||||
|
|
||||||
val PLATFORM_MODERATION_USER = "01FC17E1WTM2BGE4F3ARN3FDAF"
|
val PLATFORM_MODERATION_USER = "01FC17E1WTM2BGE4F3ARN3FDAF"
|
||||||
|
|
||||||
val TRUSTED_MODERATION_BOTS = listOf(
|
val TRUSTED_MODERATION_BOTS = listOf(
|
||||||
|
|
|
||||||
|
|
@ -4,6 +4,7 @@ import androidx.compose.runtime.getValue
|
||||||
import androidx.compose.runtime.mutableStateOf
|
import androidx.compose.runtime.mutableStateOf
|
||||||
import androidx.compose.runtime.setValue
|
import androidx.compose.runtime.setValue
|
||||||
import chat.revolt.api.RevoltAPI
|
import chat.revolt.api.RevoltAPI
|
||||||
|
import chat.revolt.api.internals.SpecialUsers
|
||||||
|
|
||||||
annotation class FeatureFlag(val name: String)
|
annotation class FeatureFlag(val name: String)
|
||||||
annotation class Treatment(val description: String)
|
annotation class Treatment(val description: String)
|
||||||
|
|
@ -19,6 +20,14 @@ sealed class ClosedBetaAccessControlVariates {
|
||||||
data object Unrestricted : ClosedBetaAccessControlVariates()
|
data object Unrestricted : ClosedBetaAccessControlVariates()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@FeatureFlag("LabsAccessControl")
|
||||||
|
sealed class LabsAccessControlVariates {
|
||||||
|
@Treatment(
|
||||||
|
"Restrict access to Labs to users that meet certain or all criteria (implementation-specific)"
|
||||||
|
)
|
||||||
|
data class Restricted(val predicate: () -> Boolean) : LabsAccessControlVariates()
|
||||||
|
}
|
||||||
|
|
||||||
object FeatureFlags {
|
object FeatureFlags {
|
||||||
@FeatureFlag("ClosedBetaAccessControl")
|
@FeatureFlag("ClosedBetaAccessControl")
|
||||||
var closedBetaAccessControl by mutableStateOf<ClosedBetaAccessControlVariates>(
|
var closedBetaAccessControl by mutableStateOf<ClosedBetaAccessControlVariates>(
|
||||||
|
|
@ -26,4 +35,11 @@ object FeatureFlags {
|
||||||
RevoltAPI.channelCache.containsKey("01H7X2KRB0CA4QDSMB4N7WGERF")
|
RevoltAPI.channelCache.containsKey("01H7X2KRB0CA4QDSMB4N7WGERF")
|
||||||
}
|
}
|
||||||
)
|
)
|
||||||
|
|
||||||
|
@FeatureFlag("LabsAccessControl")
|
||||||
|
var labsAccessControl by mutableStateOf<LabsAccessControlVariates>(
|
||||||
|
LabsAccessControlVariates.Restricted {
|
||||||
|
RevoltAPI.selfId == SpecialUsers.JENNIFER
|
||||||
|
}
|
||||||
|
)
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -0,0 +1,134 @@
|
||||||
|
package chat.revolt.screens.labs
|
||||||
|
|
||||||
|
import androidx.compose.foundation.clickable
|
||||||
|
import androidx.compose.foundation.layout.Arrangement
|
||||||
|
import androidx.compose.foundation.layout.Box
|
||||||
|
import androidx.compose.foundation.layout.Column
|
||||||
|
import androidx.compose.foundation.layout.Spacer
|
||||||
|
import androidx.compose.foundation.layout.fillMaxSize
|
||||||
|
import androidx.compose.foundation.layout.height
|
||||||
|
import androidx.compose.foundation.layout.padding
|
||||||
|
import androidx.compose.foundation.rememberScrollState
|
||||||
|
import androidx.compose.foundation.verticalScroll
|
||||||
|
import androidx.compose.material.icons.Icons
|
||||||
|
import androidx.compose.material.icons.filled.Home
|
||||||
|
import androidx.compose.material.icons.filled.Menu
|
||||||
|
import androidx.compose.material3.Divider
|
||||||
|
import androidx.compose.material3.ExperimentalMaterial3Api
|
||||||
|
import androidx.compose.material3.Icon
|
||||||
|
import androidx.compose.material3.ListItem
|
||||||
|
import androidx.compose.material3.MaterialTheme
|
||||||
|
import androidx.compose.material3.NavigationBar
|
||||||
|
import androidx.compose.material3.NavigationBarItem
|
||||||
|
import androidx.compose.material3.Scaffold
|
||||||
|
import androidx.compose.material3.Text
|
||||||
|
import androidx.compose.material3.TopAppBar
|
||||||
|
import androidx.compose.material3.TopAppBarDefaults
|
||||||
|
import androidx.compose.runtime.Composable
|
||||||
|
import androidx.compose.runtime.mutableStateOf
|
||||||
|
import androidx.compose.runtime.saveable.rememberSaveable
|
||||||
|
import androidx.compose.ui.Alignment
|
||||||
|
import androidx.compose.ui.Modifier
|
||||||
|
import androidx.compose.ui.text.style.TextAlign
|
||||||
|
import androidx.compose.ui.unit.dp
|
||||||
|
import androidx.navigation.NavController
|
||||||
|
|
||||||
|
enum class LabsHomeScreenTab {
|
||||||
|
Home,
|
||||||
|
Mockups,
|
||||||
|
}
|
||||||
|
|
||||||
|
@OptIn(ExperimentalMaterial3Api::class)
|
||||||
|
@Composable
|
||||||
|
fun LabsHomeScreen(navController: NavController) {
|
||||||
|
val currentTab = rememberSaveable { mutableStateOf(LabsHomeScreenTab.Home) }
|
||||||
|
|
||||||
|
Scaffold(
|
||||||
|
topBar = {
|
||||||
|
TopAppBar(
|
||||||
|
scrollBehavior = TopAppBarDefaults.exitUntilCollapsedScrollBehavior(),
|
||||||
|
title = {
|
||||||
|
Text("Labs")
|
||||||
|
}
|
||||||
|
)
|
||||||
|
},
|
||||||
|
bottomBar = {
|
||||||
|
NavigationBar {
|
||||||
|
NavigationBarItem(
|
||||||
|
selected = currentTab.value == LabsHomeScreenTab.Home,
|
||||||
|
onClick = { currentTab.value = LabsHomeScreenTab.Home },
|
||||||
|
icon = {
|
||||||
|
Icon(
|
||||||
|
imageVector = Icons.Default.Home,
|
||||||
|
contentDescription = null,
|
||||||
|
)
|
||||||
|
},
|
||||||
|
label = {
|
||||||
|
Text("Home")
|
||||||
|
}
|
||||||
|
)
|
||||||
|
NavigationBarItem(
|
||||||
|
selected = currentTab.value == LabsHomeScreenTab.Mockups,
|
||||||
|
onClick = { currentTab.value = LabsHomeScreenTab.Mockups },
|
||||||
|
icon = {
|
||||||
|
Icon(
|
||||||
|
imageVector = Icons.Default.Menu,
|
||||||
|
contentDescription = null,
|
||||||
|
)
|
||||||
|
},
|
||||||
|
label = {
|
||||||
|
Text("UI Mockups")
|
||||||
|
}
|
||||||
|
)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
) {
|
||||||
|
Box(Modifier.padding(it)) {
|
||||||
|
when (currentTab.value) {
|
||||||
|
LabsHomeScreenTab.Home -> {
|
||||||
|
Column(
|
||||||
|
modifier = Modifier
|
||||||
|
.fillMaxSize()
|
||||||
|
.padding(16.dp),
|
||||||
|
horizontalAlignment = Alignment.CenterHorizontally,
|
||||||
|
verticalArrangement = Arrangement.Center
|
||||||
|
) {
|
||||||
|
Text(
|
||||||
|
"Hey, this is kinda secret 🤫",
|
||||||
|
style = MaterialTheme.typography.headlineMedium,
|
||||||
|
textAlign = TextAlign.Center
|
||||||
|
)
|
||||||
|
Spacer(Modifier.height(8.dp))
|
||||||
|
Text(
|
||||||
|
"Remember, everything you see here can be broken and is not guaranteed to work.",
|
||||||
|
style = MaterialTheme.typography.bodyMedium,
|
||||||
|
textAlign = TextAlign.Center
|
||||||
|
)
|
||||||
|
Spacer(Modifier.height(8.dp))
|
||||||
|
Text(
|
||||||
|
"Don't tell anyone about anything either, okay?",
|
||||||
|
style = MaterialTheme.typography.bodyMedium,
|
||||||
|
textAlign = TextAlign.Center
|
||||||
|
)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
LabsHomeScreenTab.Mockups -> {
|
||||||
|
Column(
|
||||||
|
modifier = Modifier.verticalScroll(rememberScrollState())
|
||||||
|
) {
|
||||||
|
ListItem(
|
||||||
|
headlineContent = {
|
||||||
|
Text("Call Screen")
|
||||||
|
},
|
||||||
|
modifier = Modifier.clickable {
|
||||||
|
navController.navigate("mockups/call")
|
||||||
|
}
|
||||||
|
)
|
||||||
|
Divider()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,71 @@
|
||||||
|
package chat.revolt.screens.labs
|
||||||
|
|
||||||
|
import androidx.compose.foundation.layout.Column
|
||||||
|
import androidx.compose.foundation.layout.fillMaxSize
|
||||||
|
import androidx.compose.material3.AlertDialog
|
||||||
|
import androidx.compose.material3.Text
|
||||||
|
import androidx.compose.material3.TextButton
|
||||||
|
import androidx.compose.runtime.Composable
|
||||||
|
import androidx.compose.ui.Modifier
|
||||||
|
import androidx.navigation.NavController
|
||||||
|
import androidx.navigation.compose.NavHost
|
||||||
|
import androidx.navigation.compose.composable
|
||||||
|
import androidx.navigation.compose.rememberNavController
|
||||||
|
import chat.revolt.api.settings.FeatureFlags
|
||||||
|
import chat.revolt.api.settings.LabsAccessControlVariates
|
||||||
|
import chat.revolt.screens.labs.ui.mockups.CallScreenMockup
|
||||||
|
|
||||||
|
annotation class LabsFeature
|
||||||
|
|
||||||
|
@Composable
|
||||||
|
fun LabsGuard(onTurnBack: () -> Unit = {}, content: @Composable () -> Unit) {
|
||||||
|
if (FeatureFlags.labsAccessControl is LabsAccessControlVariates.Restricted &&
|
||||||
|
(FeatureFlags.labsAccessControl as LabsAccessControlVariates.Restricted).predicate().not()
|
||||||
|
) {
|
||||||
|
AlertDialog(
|
||||||
|
onDismissRequest = { onTurnBack() },
|
||||||
|
confirmButton = {
|
||||||
|
TextButton(onClick = { onTurnBack() }) {
|
||||||
|
Text("Turn back")
|
||||||
|
}
|
||||||
|
},
|
||||||
|
title = {
|
||||||
|
Text("You don't have access to Labs.")
|
||||||
|
},
|
||||||
|
text = {
|
||||||
|
Text("Labs is where we test new features. However, these features may be unstable and may not work as expected. Hence, access to Labs is restricted.")
|
||||||
|
}
|
||||||
|
)
|
||||||
|
} else {
|
||||||
|
content()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Composable
|
||||||
|
fun LabsRootScreen(topNav: NavController) {
|
||||||
|
val labsNav = rememberNavController()
|
||||||
|
|
||||||
|
Column(
|
||||||
|
modifier = Modifier
|
||||||
|
.fillMaxSize()
|
||||||
|
) {
|
||||||
|
LabsGuard(
|
||||||
|
onTurnBack = {
|
||||||
|
topNav.popBackStack()
|
||||||
|
}
|
||||||
|
) {
|
||||||
|
NavHost(
|
||||||
|
navController = labsNav,
|
||||||
|
startDestination = "home",
|
||||||
|
) {
|
||||||
|
composable("home") {
|
||||||
|
LabsHomeScreen(labsNav)
|
||||||
|
}
|
||||||
|
|
||||||
|
composable("mockups/call") {
|
||||||
|
CallScreenMockup()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,262 @@
|
||||||
|
package chat.revolt.screens.labs.ui.mockups
|
||||||
|
|
||||||
|
import androidx.compose.animation.animateColorAsState
|
||||||
|
import androidx.compose.animation.core.EaseInOutExpo
|
||||||
|
import androidx.compose.animation.core.tween
|
||||||
|
import androidx.compose.foundation.background
|
||||||
|
import androidx.compose.foundation.interaction.MutableInteractionSource
|
||||||
|
import androidx.compose.foundation.interaction.collectIsPressedAsState
|
||||||
|
import androidx.compose.foundation.layout.Arrangement
|
||||||
|
import androidx.compose.foundation.layout.BoxWithConstraints
|
||||||
|
import androidx.compose.foundation.layout.Column
|
||||||
|
import androidx.compose.foundation.layout.Row
|
||||||
|
import androidx.compose.foundation.layout.Spacer
|
||||||
|
import androidx.compose.foundation.layout.fillMaxSize
|
||||||
|
import androidx.compose.foundation.layout.height
|
||||||
|
import androidx.compose.foundation.layout.heightIn
|
||||||
|
import androidx.compose.foundation.layout.padding
|
||||||
|
import androidx.compose.foundation.layout.safeDrawingPadding
|
||||||
|
import androidx.compose.foundation.layout.size
|
||||||
|
import androidx.compose.foundation.layout.width
|
||||||
|
import androidx.compose.material.icons.Icons
|
||||||
|
import androidx.compose.material.icons.filled.KeyboardArrowDown
|
||||||
|
import androidx.compose.material.icons.filled.KeyboardArrowRight
|
||||||
|
import androidx.compose.material3.Button
|
||||||
|
import androidx.compose.material3.ButtonDefaults
|
||||||
|
import androidx.compose.material3.Checkbox
|
||||||
|
import androidx.compose.material3.Icon
|
||||||
|
import androidx.compose.material3.IconButton
|
||||||
|
import androidx.compose.material3.MaterialTheme
|
||||||
|
import androidx.compose.material3.Text
|
||||||
|
import androidx.compose.material3.TextButton
|
||||||
|
import androidx.compose.runtime.Composable
|
||||||
|
import androidx.compose.runtime.getValue
|
||||||
|
import androidx.compose.runtime.mutableStateOf
|
||||||
|
import androidx.compose.runtime.remember
|
||||||
|
import androidx.compose.runtime.setValue
|
||||||
|
import androidx.compose.ui.Alignment
|
||||||
|
import androidx.compose.ui.Modifier
|
||||||
|
import androidx.compose.ui.draw.alpha
|
||||||
|
import androidx.compose.ui.draw.clip
|
||||||
|
import androidx.compose.ui.res.painterResource
|
||||||
|
import androidx.compose.ui.res.stringResource
|
||||||
|
import androidx.compose.ui.text.font.FontWeight
|
||||||
|
import androidx.compose.ui.text.style.TextOverflow
|
||||||
|
import androidx.compose.ui.unit.dp
|
||||||
|
import androidx.compose.ui.window.Dialog
|
||||||
|
import chat.revolt.R
|
||||||
|
import chat.revolt.api.schemas.ChannelType
|
||||||
|
import chat.revolt.components.screens.chat.ChannelIcon
|
||||||
|
import chat.revolt.screens.labs.LabsFeature
|
||||||
|
|
||||||
|
@LabsFeature
|
||||||
|
@Composable
|
||||||
|
fun CallScreenMockup() {
|
||||||
|
var showOptions by remember { mutableStateOf(false) }
|
||||||
|
var pushToTalk by remember { mutableStateOf(false) }
|
||||||
|
|
||||||
|
val interactionSource = remember { MutableInteractionSource() }
|
||||||
|
val pushToTalkIsHeld by interactionSource.collectIsPressedAsState()
|
||||||
|
|
||||||
|
val pttBackground by animateColorAsState(
|
||||||
|
targetValue = if (pushToTalkIsHeld) {
|
||||||
|
MaterialTheme.colorScheme.primaryContainer
|
||||||
|
} else {
|
||||||
|
MaterialTheme.colorScheme.secondaryContainer
|
||||||
|
},
|
||||||
|
animationSpec = tween(200, easing = EaseInOutExpo),
|
||||||
|
label = "pttBackground"
|
||||||
|
)
|
||||||
|
val pttText by animateColorAsState(
|
||||||
|
targetValue = if (pushToTalkIsHeld) {
|
||||||
|
MaterialTheme.colorScheme.onPrimaryContainer
|
||||||
|
} else {
|
||||||
|
MaterialTheme.colorScheme.onSecondaryContainer
|
||||||
|
},
|
||||||
|
animationSpec = tween(200, easing = EaseInOutExpo),
|
||||||
|
label = "pttText"
|
||||||
|
)
|
||||||
|
|
||||||
|
if (showOptions) {
|
||||||
|
Dialog(
|
||||||
|
onDismissRequest = { showOptions = false }
|
||||||
|
) {
|
||||||
|
BoxWithConstraints {
|
||||||
|
Column(
|
||||||
|
modifier = Modifier
|
||||||
|
.clip(MaterialTheme.shapes.large)
|
||||||
|
.background(MaterialTheme.colorScheme.surface)
|
||||||
|
.padding(24.dp)
|
||||||
|
.width(maxWidth * 0.85f)
|
||||||
|
.heightIn(max = maxHeight * 0.85f)
|
||||||
|
) {
|
||||||
|
Row {
|
||||||
|
Checkbox(
|
||||||
|
checked = pushToTalk,
|
||||||
|
onCheckedChange = { pushToTalk = it },
|
||||||
|
modifier = Modifier
|
||||||
|
.padding(16.dp)
|
||||||
|
)
|
||||||
|
Text(
|
||||||
|
text = "Push to talk",
|
||||||
|
modifier = Modifier
|
||||||
|
.padding(16.dp)
|
||||||
|
)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
Column(
|
||||||
|
modifier = Modifier
|
||||||
|
.fillMaxSize()
|
||||||
|
.safeDrawingPadding()
|
||||||
|
) {
|
||||||
|
Row(
|
||||||
|
verticalAlignment = Alignment.CenterVertically
|
||||||
|
) {
|
||||||
|
Row(
|
||||||
|
modifier = Modifier
|
||||||
|
.weight(1f)
|
||||||
|
.padding(vertical = 4.dp, horizontal = 4.dp),
|
||||||
|
verticalAlignment = Alignment.CenterVertically
|
||||||
|
) {
|
||||||
|
Spacer(
|
||||||
|
modifier = Modifier
|
||||||
|
.height(48.dp)
|
||||||
|
.width(12.dp)
|
||||||
|
)
|
||||||
|
|
||||||
|
ChannelIcon(
|
||||||
|
channelType = ChannelType.VoiceChannel,
|
||||||
|
modifier = Modifier.alpha(0.6f)
|
||||||
|
)
|
||||||
|
|
||||||
|
Spacer(modifier = Modifier.width(8.dp))
|
||||||
|
|
||||||
|
Row(
|
||||||
|
modifier = Modifier.weight(1f),
|
||||||
|
verticalAlignment = Alignment.CenterVertically
|
||||||
|
) {
|
||||||
|
Text(
|
||||||
|
text = "Voice Channel",
|
||||||
|
fontWeight = FontWeight.Medium,
|
||||||
|
maxLines = 1,
|
||||||
|
overflow = TextOverflow.Ellipsis
|
||||||
|
)
|
||||||
|
|
||||||
|
Spacer(modifier = Modifier.width(4.dp))
|
||||||
|
|
||||||
|
Icon(
|
||||||
|
imageVector = Icons.Default.KeyboardArrowRight,
|
||||||
|
contentDescription = stringResource(R.string.menu),
|
||||||
|
modifier = Modifier
|
||||||
|
.size(18.dp)
|
||||||
|
.alpha(0.4f)
|
||||||
|
)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
IconButton(onClick = {
|
||||||
|
showOptions = true
|
||||||
|
}) {
|
||||||
|
Icon(
|
||||||
|
imageVector = Icons.Default.KeyboardArrowDown,
|
||||||
|
contentDescription = null
|
||||||
|
)
|
||||||
|
}
|
||||||
|
Spacer(modifier = Modifier.width(4.dp))
|
||||||
|
}
|
||||||
|
Column(
|
||||||
|
modifier = Modifier
|
||||||
|
.weight(1f)
|
||||||
|
) {
|
||||||
|
}
|
||||||
|
if (pushToTalk) {
|
||||||
|
Row(
|
||||||
|
modifier = Modifier
|
||||||
|
.padding(16.dp),
|
||||||
|
horizontalArrangement = Arrangement.spacedBy(16.dp)
|
||||||
|
) {
|
||||||
|
TextButton(
|
||||||
|
onClick = {},
|
||||||
|
) {
|
||||||
|
Icon(
|
||||||
|
painter = painterResource(R.drawable.ic_headphones_24dp),
|
||||||
|
contentDescription = null
|
||||||
|
)
|
||||||
|
Spacer(modifier = Modifier.width(8.dp))
|
||||||
|
Text(
|
||||||
|
text = "Galaxy Buds Live",
|
||||||
|
)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
Row(
|
||||||
|
modifier = Modifier
|
||||||
|
.padding(horizontal = 16.dp),
|
||||||
|
horizontalArrangement = Arrangement.spacedBy(16.dp)
|
||||||
|
) {
|
||||||
|
Button(
|
||||||
|
onClick = {},
|
||||||
|
colors = ButtonDefaults.buttonColors(
|
||||||
|
containerColor = pttBackground,
|
||||||
|
contentColor = pttText
|
||||||
|
),
|
||||||
|
interactionSource = interactionSource,
|
||||||
|
modifier = Modifier
|
||||||
|
.weight(1f)
|
||||||
|
) {
|
||||||
|
Icon(
|
||||||
|
painter = painterResource(R.drawable.ic_gesture_tap_button_24dp),
|
||||||
|
contentDescription = null
|
||||||
|
)
|
||||||
|
Spacer(modifier = Modifier.width(8.dp))
|
||||||
|
Text(
|
||||||
|
text = "Hold to talk",
|
||||||
|
)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
Row(
|
||||||
|
modifier = Modifier
|
||||||
|
.padding(16.dp),
|
||||||
|
horizontalArrangement = Arrangement.spacedBy(16.dp)
|
||||||
|
) {
|
||||||
|
if (!pushToTalk) {
|
||||||
|
Button(
|
||||||
|
onClick = {}
|
||||||
|
) {
|
||||||
|
Icon(
|
||||||
|
painter = painterResource(R.drawable.ic_microphone_off_24dp),
|
||||||
|
contentDescription = null
|
||||||
|
)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
Button(
|
||||||
|
onClick = {},
|
||||||
|
colors = ButtonDefaults.buttonColors(
|
||||||
|
containerColor = MaterialTheme.colorScheme.errorContainer,
|
||||||
|
contentColor = MaterialTheme.colorScheme.onErrorContainer
|
||||||
|
),
|
||||||
|
modifier = Modifier
|
||||||
|
.weight(1f)
|
||||||
|
) {
|
||||||
|
Text(
|
||||||
|
text = "Leave call",
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!pushToTalk) {
|
||||||
|
Button(
|
||||||
|
onClick = {}
|
||||||
|
) {
|
||||||
|
Icon(
|
||||||
|
painter = painterResource(R.drawable.ic_headphones_24dp),
|
||||||
|
contentDescription = null
|
||||||
|
)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -7,6 +7,7 @@ import androidx.compose.foundation.layout.safeDrawingPadding
|
||||||
import androidx.compose.foundation.rememberScrollState
|
import androidx.compose.foundation.rememberScrollState
|
||||||
import androidx.compose.foundation.verticalScroll
|
import androidx.compose.foundation.verticalScroll
|
||||||
import androidx.compose.material.icons.Icons
|
import androidx.compose.material.icons.Icons
|
||||||
|
import androidx.compose.material.icons.filled.ArrowForward
|
||||||
import androidx.compose.material.icons.filled.Build
|
import androidx.compose.material.icons.filled.Build
|
||||||
import androidx.compose.material.icons.filled.Close
|
import androidx.compose.material.icons.filled.Close
|
||||||
import androidx.compose.material.icons.filled.DateRange
|
import androidx.compose.material.icons.filled.DateRange
|
||||||
|
|
@ -27,7 +28,9 @@ import androidx.navigation.NavController
|
||||||
import chat.revolt.BuildConfig
|
import chat.revolt.BuildConfig
|
||||||
import chat.revolt.R
|
import chat.revolt.R
|
||||||
import chat.revolt.api.RevoltAPI
|
import chat.revolt.api.RevoltAPI
|
||||||
|
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.PageHeader
|
import chat.revolt.components.generic.PageHeader
|
||||||
import chat.revolt.components.generic.SheetClickable
|
import chat.revolt.components.generic.SheetClickable
|
||||||
import chat.revolt.components.screens.settings.SelfUserOverview
|
import chat.revolt.components.screens.settings.SelfUserOverview
|
||||||
|
|
@ -189,6 +192,25 @@ fun SettingsScreen(
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (FeatureFlags.labsAccessControl is LabsAccessControlVariates.Restricted &&
|
||||||
|
(FeatureFlags.labsAccessControl as LabsAccessControlVariates.Restricted).predicate()
|
||||||
|
) {
|
||||||
|
SheetClickable(
|
||||||
|
icon = { modifier ->
|
||||||
|
Icon(
|
||||||
|
imageVector = Icons.Default.ArrowForward,
|
||||||
|
contentDescription = null,
|
||||||
|
modifier = modifier
|
||||||
|
)
|
||||||
|
},
|
||||||
|
label = { textStyle ->
|
||||||
|
Text(text = "Labs", style = textStyle)
|
||||||
|
},
|
||||||
|
) {
|
||||||
|
navController.navigate("labs")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
SheetClickable(
|
SheetClickable(
|
||||||
icon = { modifier ->
|
icon = { modifier ->
|
||||||
Icon(
|
Icon(
|
||||||
|
|
|
||||||
|
|
@ -0,0 +1,9 @@
|
||||||
|
<vector xmlns:android="http://schemas.android.com/apk/res/android"
|
||||||
|
android:height="24dp"
|
||||||
|
android:width="24dp"
|
||||||
|
android:viewportWidth="24"
|
||||||
|
android:viewportHeight="24">
|
||||||
|
<path
|
||||||
|
android:fillColor="#ffffff"
|
||||||
|
android:pathData="M13 5C15.21 5 17 6.79 17 9C17 10.5 16.2 11.77 15 12.46V11.24C15.61 10.69 16 9.89 16 9C16 7.34 14.66 6 13 6S10 7.34 10 9C10 9.89 10.39 10.69 11 11.24V12.46C9.8 11.77 9 10.5 9 9C9 6.79 10.79 5 13 5M20 20.5C19.97 21.32 19.32 21.97 18.5 22H13C12.62 22 12.26 21.85 12 21.57L8 17.37L8.74 16.6C8.93 16.39 9.2 16.28 9.5 16.28H9.7L12 18V9C12 8.45 12.45 8 13 8S14 8.45 14 9V13.47L15.21 13.6L19.15 15.79C19.68 16.03 20 16.56 20 17.14V20.5M20 2H4C2.9 2 2 2.9 2 4V12C2 13.11 2.9 14 4 14H8V12L4 12L4 4H20L20 12H18V14H20V13.96L20.04 14C21.13 14 22 13.09 22 12V4C22 2.9 21.11 2 20 2Z" />
|
||||||
|
</vector>
|
||||||
|
|
@ -0,0 +1,9 @@
|
||||||
|
<vector xmlns:android="http://schemas.android.com/apk/res/android"
|
||||||
|
android:height="24dp"
|
||||||
|
android:width="24dp"
|
||||||
|
android:viewportWidth="24"
|
||||||
|
android:viewportHeight="24">
|
||||||
|
<path
|
||||||
|
android:fillColor="#ffffff"
|
||||||
|
android:pathData="M12,1C7,1 3,5 3,10V17A3,3 0 0,0 6,20H9V12H5V10A7,7 0 0,1 12,3A7,7 0 0,1 19,10V12H15V20H18A3,3 0 0,0 21,17V10C21,5 16.97,1 12,1Z" />
|
||||||
|
</vector>
|
||||||
|
|
@ -0,0 +1,9 @@
|
||||||
|
<vector xmlns:android="http://schemas.android.com/apk/res/android"
|
||||||
|
android:height="24dp"
|
||||||
|
android:width="24dp"
|
||||||
|
android:viewportWidth="24"
|
||||||
|
android:viewportHeight="24">
|
||||||
|
<path
|
||||||
|
android:fillColor="#ffffff"
|
||||||
|
android:pathData="M12,1A9,9 0 0,1 21,10V17C21,17.62 20.81,18.19 20.5,18.67L15,13.18V12H19V10A7,7 0 0,0 12,3C10,3 8.23,3.82 6.96,5.14L5.55,3.72C7.18,2.04 9.47,1 12,1M2.78,3.5L20.5,21.22L19.23,22.5L16.73,20H15V18.27L9,12.27V20H6A3,3 0 0,1 3,17V10C3,8.89 3.2,7.82 3.57,6.84L1.5,4.77L2.78,3.5M5.17,8.44C5.06,8.94 5,9.46 5,10V12H8.73L5.17,8.44Z" />
|
||||||
|
</vector>
|
||||||
|
|
@ -0,0 +1,9 @@
|
||||||
|
<vector xmlns:android="http://schemas.android.com/apk/res/android"
|
||||||
|
android:height="24dp"
|
||||||
|
android:width="24dp"
|
||||||
|
android:viewportWidth="24"
|
||||||
|
android:viewportHeight="24">
|
||||||
|
<path
|
||||||
|
android:fillColor="#ffffff"
|
||||||
|
android:pathData="M12,2A3,3 0 0,1 15,5V11A3,3 0 0,1 12,14A3,3 0 0,1 9,11V5A3,3 0 0,1 12,2M19,11C19,14.53 16.39,17.44 13,17.93V21H11V17.93C7.61,17.44 5,14.53 5,11H7A5,5 0 0,0 12,16A5,5 0 0,0 17,11H19Z" />
|
||||||
|
</vector>
|
||||||
|
|
@ -0,0 +1,9 @@
|
||||||
|
<vector xmlns:android="http://schemas.android.com/apk/res/android"
|
||||||
|
android:height="24dp"
|
||||||
|
android:width="24dp"
|
||||||
|
android:viewportWidth="24"
|
||||||
|
android:viewportHeight="24">
|
||||||
|
<path
|
||||||
|
android:fillColor="#ffffff"
|
||||||
|
android:pathData="M19,11C19,12.19 18.66,13.3 18.1,14.28L16.87,13.05C17.14,12.43 17.3,11.74 17.3,11H19M15,11.16L9,5.18V5A3,3 0 0,1 12,2A3,3 0 0,1 15,5V11L15,11.16M4.27,3L21,19.73L19.73,21L15.54,16.81C14.77,17.27 13.91,17.58 13,17.72V21H11V17.72C7.72,17.23 5,14.41 5,11H6.7C6.7,14 9.24,16.1 12,16.1C12.81,16.1 13.6,15.91 14.31,15.58L12.65,13.92L12,14A3,3 0 0,1 9,11V10.28L3,4.27L4.27,3Z" />
|
||||||
|
</vector>
|
||||||
|
|
@ -0,0 +1,9 @@
|
||||||
|
<vector xmlns:android="http://schemas.android.com/apk/res/android"
|
||||||
|
android:height="24dp"
|
||||||
|
android:width="24dp"
|
||||||
|
android:viewportWidth="24"
|
||||||
|
android:viewportHeight="24">
|
||||||
|
<path
|
||||||
|
android:fillColor="#ffffff"
|
||||||
|
android:pathData="M12,9C10.4,9 8.85,9.25 7.4,9.72V12.82C7.4,13.22 7.17,13.56 6.84,13.72C5.86,14.21 4.97,14.84 4.17,15.57C4,15.75 3.75,15.86 3.5,15.86C3.2,15.86 2.95,15.74 2.77,15.56L0.29,13.08C0.11,12.9 0,12.65 0,12.38C0,12.1 0.11,11.85 0.29,11.67C3.34,8.77 7.46,7 12,7C16.54,7 20.66,8.77 23.71,11.67C23.89,11.85 24,12.1 24,12.38C24,12.65 23.89,12.9 23.71,13.08L21.23,15.56C21.05,15.74 20.8,15.86 20.5,15.86C20.25,15.86 20,15.75 19.82,15.57C19.03,14.84 18.14,14.21 17.16,13.72C16.83,13.56 16.6,13.22 16.6,12.82V9.72C15.15,9.25 13.6,9 12,9Z" />
|
||||||
|
</vector>
|
||||||
Loading…
Reference in New Issue