feat(labs): new sandboxes
Signed-off-by: Infi <infi@infi.sh>
This commit is contained in:
parent
32398e8d99
commit
6918f7b9fc
|
|
@ -305,6 +305,9 @@ dependencies {
|
|||
// Square Logcat
|
||||
implementation("com.squareup.logcat:logcat:0.1")
|
||||
|
||||
// Librevolt
|
||||
implementation("librevolt:librevolt-jvm:0.1.0")
|
||||
|
||||
// Testing
|
||||
androidTestImplementation("androidx.test:runner:$androidXTestVersion")
|
||||
androidTestImplementation("androidx.test:rules:$androidXTestVersion")
|
||||
|
|
@ -315,7 +318,16 @@ aboutLibraries {
|
|||
additionalLicenses += listOf("ofl")
|
||||
includePlatform = true
|
||||
strictMode = StrictMode.FAIL
|
||||
allowedLicenses += listOf("Apache-2.0", "OFL", "MIT", "ASDKL", "BSD-2-Clause", "cmark")
|
||||
allowedLicenses += listOf(
|
||||
"Apache-2.0",
|
||||
"OFL",
|
||||
"MIT",
|
||||
"ASDKL",
|
||||
"BSD-2-Clause",
|
||||
"cmark",
|
||||
"EPL-1.0",
|
||||
"BSD-3-Clause"
|
||||
)
|
||||
configPath = "compliance"
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -0,0 +1,57 @@
|
|||
package chat.revolt.components.generic
|
||||
|
||||
import android.annotation.SuppressLint
|
||||
import androidx.compose.foundation.Canvas
|
||||
import androidx.compose.foundation.gestures.detectTapGestures
|
||||
import androidx.compose.foundation.layout.fillMaxWidth
|
||||
import androidx.compose.foundation.layout.padding
|
||||
import androidx.compose.runtime.Composable
|
||||
import androidx.compose.ui.Modifier
|
||||
import androidx.compose.ui.geometry.Offset
|
||||
import androidx.compose.ui.graphics.Brush
|
||||
import androidx.compose.ui.graphics.Color
|
||||
import androidx.compose.ui.input.pointer.pointerInput
|
||||
import androidx.compose.ui.unit.dp
|
||||
import logcat.logcat
|
||||
|
||||
@SuppressLint("UnusedBoxWithConstraintsScope")
|
||||
@Composable
|
||||
fun GradientStopEditor(
|
||||
segments: Int,
|
||||
stops: List<Pair<Float, Color>>,
|
||||
onStopsChanged: (List<Pair<Float, Color>>) -> Unit,
|
||||
_onClickSegment: (Int) -> Unit,
|
||||
modifier: Modifier = Modifier
|
||||
) {
|
||||
// Our gradient stop editor uses zero-width "segments" to represent points where the stops can be placed.
|
||||
// There are two segments, one at the start and one at the end, that are not visible to the user.
|
||||
// They only exist so that the user can place stops at the very beginning and end of the gradient without
|
||||
// having to tap at the edge of the screen.
|
||||
Canvas(
|
||||
modifier
|
||||
.padding(horizontal = 16.dp)
|
||||
.pointerInput(segments) {
|
||||
detectTapGestures { offset ->
|
||||
val segment = (offset.x / size.width * segments).toInt()
|
||||
logcat { "Tapped segment $segment" }
|
||||
}
|
||||
}
|
||||
.fillMaxWidth()
|
||||
) {
|
||||
// Debug code for now
|
||||
val debugStops = mutableListOf(Color.Transparent)
|
||||
for (i in 1 until segments + 1) {
|
||||
if (i % 2 == 0) {
|
||||
debugStops.add(Color(0xff366fd1))
|
||||
} else {
|
||||
debugStops.add(Color(0xff36d1af))
|
||||
}
|
||||
}
|
||||
debugStops.add(Color.Transparent)
|
||||
|
||||
drawRect(
|
||||
brush = Brush.linearGradient(debugStops, Offset(0f, 0f), Offset(size.width, 0f)),
|
||||
size = size,
|
||||
)
|
||||
}
|
||||
}
|
||||
|
|
@ -11,12 +11,14 @@ 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.automirrored.filled.ArrowBack
|
||||
import androidx.compose.material.icons.filled.Home
|
||||
import androidx.compose.material.icons.filled.Menu
|
||||
import androidx.compose.material.icons.filled.PlayArrow
|
||||
import androidx.compose.material3.ExperimentalMaterial3Api
|
||||
import androidx.compose.material3.HorizontalDivider
|
||||
import androidx.compose.material3.Icon
|
||||
import androidx.compose.material3.IconButton
|
||||
import androidx.compose.material3.ListItem
|
||||
import androidx.compose.material3.MaterialTheme
|
||||
import androidx.compose.material3.NavigationBar
|
||||
|
|
@ -30,9 +32,12 @@ 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.SpanStyle
|
||||
import androidx.compose.ui.text.buildAnnotatedString
|
||||
import androidx.compose.ui.text.style.TextAlign
|
||||
import androidx.compose.ui.unit.dp
|
||||
import androidx.navigation.NavController
|
||||
import chat.revolt.ui.theme.FragmentMono
|
||||
|
||||
enum class LabsHomeScreenTab {
|
||||
Home,
|
||||
|
|
@ -42,7 +47,7 @@ enum class LabsHomeScreenTab {
|
|||
|
||||
@OptIn(ExperimentalMaterial3Api::class)
|
||||
@Composable
|
||||
fun LabsHomeScreen(navController: NavController) {
|
||||
fun LabsHomeScreen(navController: NavController, topNav: NavController) {
|
||||
val currentTab = rememberSaveable { mutableStateOf(LabsHomeScreenTab.Home) }
|
||||
|
||||
Scaffold(
|
||||
|
|
@ -51,6 +56,16 @@ fun LabsHomeScreen(navController: NavController) {
|
|||
scrollBehavior = TopAppBarDefaults.exitUntilCollapsedScrollBehavior(),
|
||||
title = {
|
||||
Text("Labs")
|
||||
},
|
||||
navigationIcon = {
|
||||
IconButton(onClick = {
|
||||
topNav.popBackStack()
|
||||
}) {
|
||||
Icon(
|
||||
imageVector = Icons.AutoMirrored.Default.ArrowBack,
|
||||
contentDescription = "Back"
|
||||
)
|
||||
}
|
||||
}
|
||||
)
|
||||
},
|
||||
|
|
@ -175,6 +190,29 @@ fun LabsHomeScreen(navController: NavController) {
|
|||
}
|
||||
)
|
||||
HorizontalDivider()
|
||||
ListItem(
|
||||
headlineContent = {
|
||||
Text("Gradient Editor")
|
||||
},
|
||||
modifier = Modifier.clickable {
|
||||
navController.navigate("sandboxes/gradienteditor")
|
||||
}
|
||||
)
|
||||
HorizontalDivider()
|
||||
ListItem(
|
||||
headlineContent = {
|
||||
Text(buildAnnotatedString {
|
||||
pushStyle(SpanStyle(fontFamily = FragmentMono))
|
||||
append("librevolt")
|
||||
pop()
|
||||
append(" Sample")
|
||||
})
|
||||
},
|
||||
modifier = Modifier.clickable {
|
||||
navController.navigate("sandboxes/librevolt")
|
||||
}
|
||||
)
|
||||
HorizontalDivider()
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -14,6 +14,8 @@ import androidx.navigation.compose.rememberNavController
|
|||
import chat.revolt.api.settings.FeatureFlags
|
||||
import chat.revolt.screens.labs.ui.mockups.CallScreenMockup
|
||||
import chat.revolt.screens.labs.ui.mockups.NewLoginExperienceMockup
|
||||
import chat.revolt.screens.labs.ui.sandbox.CoreLibSandbox
|
||||
import chat.revolt.screens.labs.ui.sandbox.GradientEditorSandbox
|
||||
import chat.revolt.screens.labs.ui.sandbox.JBMSandbox
|
||||
import chat.revolt.screens.labs.ui.sandbox.SettingsDslSandbox
|
||||
|
||||
|
|
@ -59,7 +61,7 @@ fun LabsRootScreen(topNav: NavController) {
|
|||
startDestination = "home",
|
||||
) {
|
||||
composable("home") {
|
||||
LabsHomeScreen(labsNav)
|
||||
LabsHomeScreen(labsNav, topNav)
|
||||
}
|
||||
|
||||
composable("mockups/call") {
|
||||
|
|
@ -75,6 +77,12 @@ fun LabsRootScreen(topNav: NavController) {
|
|||
composable("sandboxes/jbm") {
|
||||
JBMSandbox(labsNav)
|
||||
}
|
||||
composable("sandboxes/gradienteditor") {
|
||||
GradientEditorSandbox(labsNav)
|
||||
}
|
||||
composable("sandboxes/librevolt") {
|
||||
CoreLibSandbox(labsNav)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -0,0 +1,43 @@
|
|||
package chat.revolt.screens.labs.ui.sandbox
|
||||
|
||||
import androidx.compose.material3.Button
|
||||
import androidx.compose.material3.Text
|
||||
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.text.SpanStyle
|
||||
import androidx.compose.ui.text.buildAnnotatedString
|
||||
import androidx.compose.ui.text.style.TextOverflow
|
||||
import androidx.navigation.NavController
|
||||
import chat.revolt.settings.dsl.SettingsPage
|
||||
import chat.revolt.ui.theme.FragmentMono
|
||||
|
||||
@Composable
|
||||
fun CoreLibSandbox(navController: NavController) {
|
||||
var greeting by remember { mutableStateOf("<no greeting>") }
|
||||
|
||||
SettingsPage(
|
||||
navController,
|
||||
title = {
|
||||
Text(
|
||||
text = buildAnnotatedString {
|
||||
pushStyle(SpanStyle(fontFamily = FragmentMono))
|
||||
append("librevolt")
|
||||
pop()
|
||||
append(" Sample")
|
||||
},
|
||||
maxLines = 1,
|
||||
overflow = TextOverflow.Ellipsis,
|
||||
)
|
||||
}
|
||||
) {
|
||||
Button(onClick = {
|
||||
greeting = librevolt.greet()
|
||||
}) {
|
||||
Text("Greet")
|
||||
}
|
||||
Text(greeting)
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,68 @@
|
|||
package chat.revolt.screens.labs.ui.sandbox
|
||||
|
||||
import androidx.compose.foundation.layout.Row
|
||||
import androidx.compose.foundation.layout.height
|
||||
import androidx.compose.material3.Text
|
||||
import androidx.compose.material3.TextButton
|
||||
import androidx.compose.runtime.Composable
|
||||
import androidx.compose.runtime.getValue
|
||||
import androidx.compose.runtime.mutableIntStateOf
|
||||
import androidx.compose.runtime.remember
|
||||
import androidx.compose.runtime.setValue
|
||||
import androidx.compose.ui.Alignment
|
||||
import androidx.compose.ui.Modifier
|
||||
import androidx.compose.ui.text.style.TextAlign
|
||||
import androidx.compose.ui.text.style.TextOverflow
|
||||
import androidx.compose.ui.unit.dp
|
||||
import androidx.navigation.NavController
|
||||
import chat.revolt.components.generic.GradientStopEditor
|
||||
import chat.revolt.settings.dsl.SettingsPage
|
||||
|
||||
@Composable
|
||||
fun GradientEditorSandbox(navController: NavController) {
|
||||
var segmentCount by remember { mutableIntStateOf(10) }
|
||||
|
||||
SettingsPage(
|
||||
navController,
|
||||
title = {
|
||||
Text(
|
||||
text = "Gradient Editor Sandbox",
|
||||
maxLines = 1,
|
||||
overflow = TextOverflow.Ellipsis,
|
||||
)
|
||||
}
|
||||
) {
|
||||
Row(
|
||||
verticalAlignment = Alignment.CenterVertically
|
||||
) {
|
||||
TextButton(
|
||||
onClick = {
|
||||
if (segmentCount >= 2)
|
||||
segmentCount--
|
||||
else showSnackbar("Minimum of 2 segments required.")
|
||||
},
|
||||
modifier = Modifier.weight(1f)
|
||||
) {
|
||||
Text("-")
|
||||
}
|
||||
Text(
|
||||
"$segmentCount segments",
|
||||
modifier = Modifier.weight(1f),
|
||||
textAlign = TextAlign.Center
|
||||
)
|
||||
TextButton(
|
||||
onClick = { segmentCount++ },
|
||||
modifier = Modifier.weight(1f)
|
||||
) {
|
||||
Text("+")
|
||||
}
|
||||
}
|
||||
GradientStopEditor(
|
||||
segments = segmentCount,
|
||||
stops = emptyList(),
|
||||
onStopsChanged = {},
|
||||
_onClickSegment = { showSnackbar("Clicked segment $it") },
|
||||
modifier = Modifier.height(24.dp)
|
||||
)
|
||||
}
|
||||
}
|
||||
|
|
@ -15,9 +15,13 @@ import androidx.compose.material3.Icon
|
|||
import androidx.compose.material3.IconButton
|
||||
import androidx.compose.material3.LargeTopAppBar
|
||||
import androidx.compose.material3.Scaffold
|
||||
import androidx.compose.material3.SnackbarHost
|
||||
import androidx.compose.material3.SnackbarHostState
|
||||
import androidx.compose.material3.Text
|
||||
import androidx.compose.material3.TopAppBarDefaults
|
||||
import androidx.compose.runtime.Composable
|
||||
import androidx.compose.runtime.remember
|
||||
import androidx.compose.runtime.rememberCoroutineScope
|
||||
import androidx.compose.ui.Modifier
|
||||
import androidx.compose.ui.input.nestedscroll.nestedScroll
|
||||
import androidx.compose.ui.res.stringResource
|
||||
|
|
@ -26,11 +30,14 @@ import androidx.navigation.NavController
|
|||
import chat.revolt.R
|
||||
import chat.revolt.components.generic.ListHeader
|
||||
import chat.revolt.components.generic.RadioItem
|
||||
import kotlinx.coroutines.launch
|
||||
import kotlin.enums.EnumEntries
|
||||
|
||||
val SubcategoryContentInsets = PaddingValues(horizontal = 16.dp)
|
||||
|
||||
interface SettingsPageScope {
|
||||
fun showSnackbar(message: String)
|
||||
|
||||
@Composable
|
||||
fun Subcategory(
|
||||
title: @Composable () -> Unit,
|
||||
|
|
@ -84,7 +91,9 @@ fun SettingsPage(
|
|||
title: @Composable () -> Unit,
|
||||
content: @Composable SettingsPageScope.() -> Unit
|
||||
) {
|
||||
val snackbarHostState = remember { SnackbarHostState() }
|
||||
val scrollBehavior = TopAppBarDefaults.exitUntilCollapsedScrollBehavior()
|
||||
val scope = rememberCoroutineScope()
|
||||
|
||||
Scaffold(
|
||||
modifier = Modifier.nestedScroll(scrollBehavior.nestedScrollConnection),
|
||||
|
|
@ -106,6 +115,9 @@ fun SettingsPage(
|
|||
},
|
||||
)
|
||||
},
|
||||
snackbarHost = {
|
||||
SnackbarHost(hostState = snackbarHostState)
|
||||
},
|
||||
) { pv ->
|
||||
Column(
|
||||
Modifier
|
||||
|
|
@ -115,7 +127,13 @@ fun SettingsPage(
|
|||
.verticalScroll(rememberScrollState())
|
||||
) {
|
||||
content(
|
||||
object : SettingsPageScope {}
|
||||
object : SettingsPageScope {
|
||||
override fun showSnackbar(message: String) {
|
||||
scope.launch {
|
||||
snackbarHostState.showSnackbar(message)
|
||||
}
|
||||
}
|
||||
}
|
||||
)
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -21,6 +21,10 @@ dependencyResolutionManagement {
|
|||
name = "compose-dev"
|
||||
url = uri("https://maven.pkg.jetbrains.space/public/p/compose/dev")
|
||||
}
|
||||
maven {
|
||||
name = "revolt"
|
||||
url = uri("https://git.revolt.chat/api/packages/librevolt/maven")
|
||||
}
|
||||
}
|
||||
}
|
||||
rootProject.name = "Revolt"
|
||||
|
|
|
|||
Loading…
Reference in New Issue