From 79dca0074d6ff6c470edc78fd5c687acfb931a24 Mon Sep 17 00:00:00 2001 From: Infi Date: Sat, 2 Aug 2025 20:50:30 +0200 Subject: [PATCH] feat(labs): mystery card sandbox Signed-off-by: Infi --- .../revolt/screens/labs/LabsHomeScreen.kt | 11 +- .../revolt/screens/labs/LabsRootScreen.kt | 5 + .../screens/labs/ui/sandbox/NewCardSandbox.kt | 164 ++++++++++++++++++ .../main/res/drawable/tmp_card_asset_tl.xml | 35 ++++ 4 files changed, 213 insertions(+), 2 deletions(-) create mode 100644 app/src/main/java/chat/revolt/screens/labs/ui/sandbox/NewCardSandbox.kt create mode 100644 app/src/main/res/drawable/tmp_card_asset_tl.xml diff --git a/app/src/main/java/chat/revolt/screens/labs/LabsHomeScreen.kt b/app/src/main/java/chat/revolt/screens/labs/LabsHomeScreen.kt index 3f878803..3fe5cd85 100644 --- a/app/src/main/java/chat/revolt/screens/labs/LabsHomeScreen.kt +++ b/app/src/main/java/chat/revolt/screens/labs/LabsHomeScreen.kt @@ -10,8 +10,6 @@ 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.PlayArrow import androidx.compose.material3.ExperimentalMaterial3Api import androidx.compose.material3.HorizontalDivider import androidx.compose.material3.Icon @@ -203,6 +201,15 @@ fun LabsHomeScreen(navController: NavController, topNav: NavController) { } ) HorizontalDivider() + ListItem( + headlineContent = { + Text("New Card") + }, + modifier = Modifier.clickable { + navController.navigate("sandboxes/newcard") + } + ) + HorizontalDivider() } } } diff --git a/app/src/main/java/chat/revolt/screens/labs/LabsRootScreen.kt b/app/src/main/java/chat/revolt/screens/labs/LabsRootScreen.kt index a4f81a9e..2f6288eb 100644 --- a/app/src/main/java/chat/revolt/screens/labs/LabsRootScreen.kt +++ b/app/src/main/java/chat/revolt/screens/labs/LabsRootScreen.kt @@ -16,6 +16,7 @@ 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.NewCardSandboxScreen import chat.revolt.screens.labs.ui.sandbox.SettingsDslSandbox annotation class LabsFeature @@ -79,6 +80,10 @@ fun LabsRootScreen(topNav: NavController) { composable("sandboxes/librevolt") { CoreLibSandbox(labsNav) } + + composable("sandboxes/newcard") { + NewCardSandboxScreen(labsNav) + } } } } diff --git a/app/src/main/java/chat/revolt/screens/labs/ui/sandbox/NewCardSandbox.kt b/app/src/main/java/chat/revolt/screens/labs/ui/sandbox/NewCardSandbox.kt new file mode 100644 index 00000000..30ef52f1 --- /dev/null +++ b/app/src/main/java/chat/revolt/screens/labs/ui/sandbox/NewCardSandbox.kt @@ -0,0 +1,164 @@ +package chat.revolt.screens.labs.ui.sandbox + +import android.widget.Toast +import androidx.compose.foundation.Image +import androidx.compose.foundation.background +import androidx.compose.foundation.layout.aspectRatio +import androidx.compose.foundation.layout.fillMaxWidth +import androidx.compose.foundation.layout.padding +import androidx.compose.foundation.shape.RoundedCornerShape +import androidx.compose.foundation.text.KeyboardActions +import androidx.compose.foundation.text.TextAutoSize +import androidx.compose.material3.ExperimentalMaterial3ExpressiveApi +import androidx.compose.material3.MaterialShapes +import androidx.compose.material3.Text +import androidx.compose.material3.TextField +import androidx.compose.material3.toShape +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.Modifier +import androidx.compose.ui.draw.clip +import androidx.compose.ui.graphics.Color +import androidx.compose.ui.platform.LocalContext +import androidx.compose.ui.res.painterResource +import androidx.compose.ui.text.font.FontWeight +import androidx.compose.ui.text.style.TextOverflow +import androidx.compose.ui.unit.dp +import androidx.compose.ui.unit.sp +import androidx.constraintlayout.compose.ConstraintLayout +import androidx.navigation.NavController +import chat.revolt.R +import chat.revolt.api.RevoltAPI +import chat.revolt.composables.generic.UserAvatar +import chat.revolt.settings.dsl.SettingsPage +import chat.revolt.ui.theme.FragmentMono +import java.text.DateFormat +import java.util.Date +import java.util.Locale + +@OptIn(ExperimentalMaterial3ExpressiveApi::class) +@Composable +fun NewCardSandboxScreen(navController: NavController) { + var uidInput by remember { mutableStateOf(RevoltAPI.selfId ?: "") } + var activeUid by remember { mutableStateOf(RevoltAPI.selfId) } + val activeUser = remember(activeUid) { + RevoltAPI.userCache[activeUid]!! + } + + val context = LocalContext.current + + val date = remember { + DateFormat + .getDateInstance( + DateFormat.MEDIUM, + Locale.getDefault() + ) + .format(Date()) + } + + SettingsPage( + navController, + title = { + Text( + text = "New Card", + maxLines = 1, + overflow = TextOverflow.Ellipsis, + ) + } + ) { + TextField( + value = uidInput, + onValueChange = { uidInput = it }, + label = { Text("User ID") }, + placeholder = { Text("Enter user ID") }, + keyboardActions = KeyboardActions( + onDone = { + if (uidInput.isNotBlank() && RevoltAPI.userCache.containsKey(uidInput)) { + activeUid = uidInput + uidInput = "" + } else if (!RevoltAPI.userCache.containsKey(uidInput)) { + Toast.makeText( + context, + "User id not found in cache", + Toast.LENGTH_SHORT + ).show() + } + } + ), + singleLine = true, + maxLines = 1, + modifier = Modifier.fillMaxWidth() + ) + ConstraintLayout( + modifier = Modifier + .fillMaxWidth() + .aspectRatio(16f / 9f) + .clip(RoundedCornerShape(10)) + .background(Color.Red) + .padding(16.dp) + ) { + val (logoAsset, cardIssuedLabel, cardIssued, tag, avatar) = createRefs() + + Image( + painter = painterResource(R.drawable.tmp_card_asset_tl), + contentDescription = "XY Uppercase Text", + modifier = Modifier + .constrainAs(logoAsset) { + top.linkTo(parent.top) + start.linkTo(parent.start) + } + .fillMaxWidth(1f / 3f) + ) + Text( + text = "Card Issued", + modifier = Modifier.constrainAs(cardIssuedLabel) { + top.linkTo(parent.top) + end.linkTo(parent.end) + }, + fontSize = 16.sp, + fontWeight = FontWeight.ExtraBold, + maxLines = 1, + overflow = TextOverflow.Ellipsis + ) + Text( + text = date, + modifier = Modifier.constrainAs(cardIssued) { + top.linkTo(cardIssuedLabel.bottom) + end.linkTo(parent.end) + }, + fontFamily = FragmentMono, + fontSize = 20.sp, + maxLines = 1, + overflow = TextOverflow.Ellipsis + ) + Text( + text = "${activeUser.username}#${activeUser.discriminator}", + modifier = Modifier + .constrainAs(tag) { + bottom.linkTo(parent.bottom) + start.linkTo(parent.start) + } + .fillMaxWidth(5f / 6f), + fontWeight = FontWeight.ExtraBold, + autoSize = TextAutoSize.StepBased(), + maxLines = 1, + overflow = TextOverflow.Ellipsis, + ) + UserAvatar( + username = activeUser.username ?: "", + userId = activeUser.id ?: "", + avatar = activeUser.avatar, + shape = MaterialShapes.Circle.toShape(), + size = 84.dp, + modifier = Modifier + .constrainAs(avatar) { + bottom.linkTo(tag.top, margin = 8.dp) + start.linkTo(tag.start) + } + ) + } + } +} \ No newline at end of file diff --git a/app/src/main/res/drawable/tmp_card_asset_tl.xml b/app/src/main/res/drawable/tmp_card_asset_tl.xml new file mode 100644 index 00000000..5de87ce4 --- /dev/null +++ b/app/src/main/res/drawable/tmp_card_asset_tl.xml @@ -0,0 +1,35 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +