feat: lean, color-coded redesign of the new-conversation chooser

Reworks the "Start a conversation" chooser to be scannable instead of a
wall of text. Each conversation type is now a one-line row — a
color-coded icon tile, the name, a short tagline, and a single chip
naming its deciding axis (1:1–5 rooms / Device-bound / Workspaces /
Unmoderated / Moderated / Live now). Tapping a row expands it in place to
reveal "Best for" and a compact Good / Trade-offs split, then a Create
button that routes to that type's existing flow (accordion: one open at a
time).

Copy now leads with each protocol's real differentiator — Marmot's
device-bound gotcha (chats don't follow an nsec to another app), Concord
as channel-split workspaces, and the relay-aware section grouping Public
Chat + Relay Group by the fact the relay can see and moderate who's there.

Per-type accent colors are lightened in dark theme for legibility; the
solid icon tile keeps the saturated hue in both themes.
This commit is contained in:
Claude
2026-07-15 15:15:38 +00:00
parent ed0df81ccd
commit 5e7fffe08e
2 changed files with 217 additions and 169 deletions
@@ -21,27 +21,39 @@
package com.vitorpamplona.amethyst.ui.screen.loggedIn.chats.rooms
import androidx.annotation.StringRes
import androidx.compose.animation.animateContentSize
import androidx.compose.foundation.isSystemInDarkTheme
import androidx.compose.foundation.layout.Arrangement
import androidx.compose.foundation.layout.Box
import androidx.compose.foundation.layout.Column
import androidx.compose.foundation.layout.PaddingValues
import androidx.compose.foundation.layout.Row
import androidx.compose.foundation.layout.Spacer
import androidx.compose.foundation.layout.fillMaxSize
import androidx.compose.foundation.layout.fillMaxWidth
import androidx.compose.foundation.layout.height
import androidx.compose.foundation.layout.padding
import androidx.compose.foundation.layout.size
import androidx.compose.foundation.layout.width
import androidx.compose.foundation.lazy.LazyColumn
import androidx.compose.foundation.shape.CircleShape
import androidx.compose.foundation.shape.RoundedCornerShape
import androidx.compose.material3.Button
import androidx.compose.material3.ButtonDefaults
import androidx.compose.material3.CardDefaults
import androidx.compose.material3.ElevatedCard
import androidx.compose.material3.HorizontalDivider
import androidx.compose.material3.MaterialTheme
import androidx.compose.material3.Scaffold
import androidx.compose.material3.Surface
import androidx.compose.material3.Text
import androidx.compose.runtime.Composable
import androidx.compose.runtime.getValue
import androidx.compose.runtime.mutableStateOf
import androidx.compose.runtime.saveable.rememberSaveable
import androidx.compose.runtime.setValue
import androidx.compose.ui.Alignment
import androidx.compose.ui.Modifier
import androidx.compose.ui.graphics.Color
import androidx.compose.ui.graphics.lerp
import androidx.compose.ui.text.font.FontWeight
import androidx.compose.ui.tooling.preview.Preview
import androidx.compose.ui.unit.dp
@@ -54,21 +66,34 @@ import com.vitorpamplona.amethyst.ui.navigation.navs.INav
import com.vitorpamplona.amethyst.ui.navigation.routes.Route
import com.vitorpamplona.amethyst.ui.navigation.topbars.TopBarWithBackButton
import com.vitorpamplona.amethyst.ui.stringRes
import com.vitorpamplona.amethyst.ui.theme.DoubleVertSpacer
import com.vitorpamplona.amethyst.ui.theme.StdVertSpacer
import com.vitorpamplona.amethyst.ui.theme.ThemeComparisonColumn
import com.vitorpamplona.amethyst.ui.theme.grayText
// Per-type accent colors. Each protocol gets its own hue so private-vs-public reads at a glance
// instead of via text. Used at full strength for the icon tile (white glyph on top) and, tint-mixed,
// for the type's chip / expanded accents. In dark theme the accent is lightened for legibility on the
// dark ground (see [ConversationRow]); the solid tile keeps the saturated base either way.
private val ColorPrivate = Color(0xFF7C3AED)
private val ColorMarmot = Color(0xFF4F46E5)
private val ColorConcord = Color(0xFF0D9488)
private val ColorPublic = Color(0xFFD97706)
private val ColorRelay = Color(0xFF2563EB)
private val ColorEphemeral = Color(0xFFEA580C)
/**
* One selectable conversation type on the [NewConversationScreen] chooser: an icon, a name, a
* one-line tagline, a "best for" hint, and short pros/cons lists. Tapping the card routes to that
* One selectable conversation type. Collapsed, a row shows only the icon, name, a short tagline, and
* a one-word [chip] naming its deciding axis (scale / device-bound / moderation / live). Tapping the
* row expands it to reveal [bestFor] and the [pros]/[cons] before the [cta] button routes to that
* type's existing creation (or browse) flow.
*/
private class ConversationType(
val icon: MaterialSymbol,
val color: Color,
@StringRes val title: Int,
@StringRes val tagline: Int,
@StringRes val chip: Int,
@StringRes val bestFor: Int,
@StringRes val cta: Int,
val pros: List<Int>,
val cons: List<Int>,
val route: Route,
@@ -79,8 +104,8 @@ private class ConversationSection(
val types: List<ConversationType>,
)
// Grouped by intent so the six protocols read as three simple buckets instead of a flat wall of
// options: talk privately, run an encrypted group, or open something to the public.
// Grouped by intent so the six protocols read as three simple buckets: talk privately, run an
// encrypted group, or use a relay-aware room (where the relay can see/moderate who's there).
private val conversationSections =
listOf(
ConversationSection(
@@ -89,20 +114,14 @@ private val conversationSections =
listOf(
ConversationType(
icon = MaterialSymbols.Mail,
color = ColorPrivate,
title = R.string.new_conversation_dm_title,
tagline = R.string.new_conversation_dm_tagline,
chip = R.string.new_conversation_dm_chip,
bestFor = R.string.new_conversation_dm_best,
pros =
listOf(
R.string.new_conversation_dm_pro_1,
R.string.new_conversation_dm_pro_2,
R.string.new_conversation_dm_pro_3,
),
cons =
listOf(
R.string.new_conversation_dm_con_1,
R.string.new_conversation_dm_con_2,
),
cta = R.string.new_conversation_dm_cta,
pros = listOf(R.string.new_conversation_dm_pro_1, R.string.new_conversation_dm_pro_2),
cons = listOf(R.string.new_conversation_dm_con_1),
route = Route.NewGroupDM(),
),
),
@@ -113,95 +132,68 @@ private val conversationSections =
listOf(
ConversationType(
icon = MaterialSymbols.Lock,
color = ColorMarmot,
title = R.string.new_conversation_marmot_title,
tagline = R.string.new_conversation_marmot_tagline,
chip = R.string.new_conversation_marmot_chip,
bestFor = R.string.new_conversation_marmot_best,
pros =
listOf(
R.string.new_conversation_marmot_pro_1,
R.string.new_conversation_marmot_pro_2,
R.string.new_conversation_marmot_pro_3,
),
cons =
listOf(
R.string.new_conversation_marmot_con_1,
R.string.new_conversation_marmot_con_2,
),
cta = R.string.new_conversation_marmot_cta,
pros = listOf(R.string.new_conversation_marmot_pro_1, R.string.new_conversation_marmot_pro_2),
cons = listOf(R.string.new_conversation_marmot_con_1),
route = Route.CreateMarmotGroup,
),
ConversationType(
icon = MaterialSymbols.Groups,
color = ColorConcord,
title = R.string.new_conversation_concord_title,
tagline = R.string.new_conversation_concord_tagline,
chip = R.string.new_conversation_concord_chip,
bestFor = R.string.new_conversation_concord_best,
pros =
listOf(
R.string.new_conversation_concord_pro_1,
R.string.new_conversation_concord_pro_2,
R.string.new_conversation_concord_pro_3,
),
cons =
listOf(
R.string.new_conversation_concord_con_1,
R.string.new_conversation_concord_con_2,
),
cta = R.string.new_conversation_concord_cta,
pros = listOf(R.string.new_conversation_concord_pro_1, R.string.new_conversation_concord_pro_2),
cons = listOf(R.string.new_conversation_concord_con_1),
route = Route.ConcordCreate,
),
),
),
ConversationSection(
header = R.string.new_conversation_section_public,
header = R.string.new_conversation_section_relay,
types =
listOf(
ConversationType(
icon = MaterialSymbols.Public,
color = ColorPublic,
title = R.string.new_conversation_public_chat_title,
tagline = R.string.new_conversation_public_chat_tagline,
chip = R.string.new_conversation_public_chat_chip,
bestFor = R.string.new_conversation_public_chat_best,
pros =
listOf(
R.string.new_conversation_public_chat_pro_1,
R.string.new_conversation_public_chat_pro_2,
),
cons =
listOf(
R.string.new_conversation_public_chat_con_1,
R.string.new_conversation_public_chat_con_2,
),
cta = R.string.new_conversation_public_chat_cta,
pros = listOf(R.string.new_conversation_public_chat_pro_1, R.string.new_conversation_public_chat_pro_2),
cons = listOf(R.string.new_conversation_public_chat_con_1, R.string.new_conversation_public_chat_con_2),
route = Route.ChannelMetadataEdit(),
),
ConversationType(
icon = MaterialSymbols.Dns,
color = ColorRelay,
title = R.string.new_conversation_relay_group_title,
tagline = R.string.new_conversation_relay_group_tagline,
chip = R.string.new_conversation_relay_group_chip,
bestFor = R.string.new_conversation_relay_group_best,
pros =
listOf(
R.string.new_conversation_relay_group_pro_1,
R.string.new_conversation_relay_group_pro_2,
),
cons =
listOf(
R.string.new_conversation_relay_group_con_1,
R.string.new_conversation_relay_group_con_2,
),
cta = R.string.new_conversation_relay_group_cta,
pros = listOf(R.string.new_conversation_relay_group_pro_1, R.string.new_conversation_relay_group_pro_2),
cons = listOf(R.string.new_conversation_relay_group_con_1),
route = Route.RelayGroupBrowse,
),
ConversationType(
icon = MaterialSymbols.Timer,
color = ColorEphemeral,
title = R.string.new_conversation_ephemeral_title,
tagline = R.string.new_conversation_ephemeral_tagline,
chip = R.string.new_conversation_ephemeral_chip,
bestFor = R.string.new_conversation_ephemeral_best,
pros =
listOf(
R.string.new_conversation_ephemeral_pro_1,
R.string.new_conversation_ephemeral_pro_2,
),
cons =
listOf(
R.string.new_conversation_ephemeral_con_1,
R.string.new_conversation_ephemeral_con_2,
),
cta = R.string.new_conversation_ephemeral_cta,
pros = listOf(R.string.new_conversation_ephemeral_pro_1, R.string.new_conversation_ephemeral_pro_2),
cons = listOf(R.string.new_conversation_ephemeral_con_1, R.string.new_conversation_ephemeral_con_2),
route = Route.NewEphemeralChat,
),
),
@@ -210,13 +202,15 @@ private val conversationSections =
@Composable
fun NewConversationScreen(nav: INav) {
// Accordion: at most one row expanded, keyed by its (unique) title resource id. Survives config
// changes so an opened card stays open on rotation.
var expandedId by rememberSaveable { mutableStateOf(0) }
Scaffold(
topBar = {
TopBarWithBackButton(stringRes(R.string.new_conversation_title), nav)
},
topBar = { TopBarWithBackButton(stringRes(R.string.new_conversation_title), nav) },
) { pad ->
LazyColumn(
modifier = Modifier.fillMaxSize(),
modifier = Modifier.fillMaxWidth(),
contentPadding =
PaddingValues(
start = 12.dp,
@@ -224,31 +218,27 @@ fun NewConversationScreen(nav: INav) {
top = pad.calculateTopPadding() + 4.dp,
bottom = pad.calculateBottomPadding() + 16.dp,
),
verticalArrangement = Arrangement.spacedBy(10.dp),
verticalArrangement = Arrangement.spacedBy(9.dp),
) {
item {
Text(
text = stringRes(R.string.new_conversation_intro),
style = MaterialTheme.typography.bodyMedium,
color = MaterialTheme.colorScheme.grayText,
modifier = Modifier.padding(horizontal = 4.dp, vertical = 4.dp),
)
}
conversationSections.forEach { section ->
item {
item(key = section.header) {
Text(
text = stringRes(section.header),
style = MaterialTheme.typography.titleSmall,
style = MaterialTheme.typography.labelMedium,
fontWeight = FontWeight.Bold,
color = MaterialTheme.colorScheme.primary,
modifier = Modifier.padding(start = 4.dp, top = 6.dp),
color = MaterialTheme.colorScheme.grayText,
modifier = Modifier.padding(start = 6.dp, top = 8.dp),
)
}
section.types.forEach { type ->
item(key = type.title) {
ConversationTypeCard(type) { nav.nav(type.route) }
ConversationRow(
type = type,
expanded = expandedId == type.title,
onToggle = { expandedId = if (expandedId == type.title) 0 else type.title },
onCreate = { nav.nav(type.route) },
)
}
}
}
@@ -257,33 +247,39 @@ fun NewConversationScreen(nav: INav) {
}
@Composable
private fun ConversationTypeCard(
private fun ConversationRow(
type: ConversationType,
onClick: () -> Unit,
expanded: Boolean,
onToggle: () -> Unit,
onCreate: () -> Unit,
) {
// Lighten the accent in dark mode so chip/label/checkmark text stays legible on the dark ground;
// the solid icon tile keeps the saturated base color in both themes.
val accent = if (isSystemInDarkTheme()) lerp(type.color, Color.White, 0.42f) else type.color
ElevatedCard(
onClick = onClick,
onClick = onToggle,
modifier = Modifier.fillMaxWidth(),
elevation = CardDefaults.elevatedCardElevation(defaultElevation = 2.dp),
) {
Column(Modifier.padding(16.dp)) {
Column(Modifier.animateContentSize().padding(13.dp)) {
Row(verticalAlignment = Alignment.CenterVertically) {
Surface(
shape = CircleShape,
color = MaterialTheme.colorScheme.primaryContainer,
shape = RoundedCornerShape(13.dp),
color = type.color,
modifier = Modifier.size(44.dp),
) {
Box(contentAlignment = Alignment.Center) {
Icon(
symbol = type.icon,
contentDescription = null,
tint = MaterialTheme.colorScheme.onPrimaryContainer,
tint = Color.White,
modifier = Modifier.size(24.dp),
)
}
}
Spacer(Modifier.size(14.dp))
Spacer(Modifier.width(13.dp))
Column(Modifier.weight(1f)) {
Text(
@@ -298,54 +294,99 @@ private fun ConversationTypeCard(
)
}
Icon(
symbol = MaterialSymbols.AutoMirrored.KeyboardArrowRight,
contentDescription = null,
tint = MaterialTheme.colorScheme.grayText,
modifier = Modifier.size(22.dp),
)
Spacer(Modifier.width(8.dp))
AxisChip(stringRes(type.chip), accent)
}
Spacer(modifier = DoubleVertSpacer)
if (expanded) {
HorizontalDivider(
modifier = Modifier.padding(top = 13.dp, bottom = 12.dp),
color = accent.copy(alpha = 0.22f),
)
Row {
Text(
text = "${stringRes(R.string.new_conversation_best_for)}: ",
style = MaterialTheme.typography.labelMedium,
fontWeight = FontWeight.Bold,
color = MaterialTheme.colorScheme.primary,
)
Text(
text = stringRes(type.bestFor),
style = MaterialTheme.typography.bodySmall,
color = MaterialTheme.colorScheme.grayText,
)
Column {
ColumnHeader(stringRes(R.string.new_conversation_best_for))
Text(
text = stringRes(type.bestFor),
style = MaterialTheme.typography.bodySmall,
color = MaterialTheme.colorScheme.grayText,
modifier = Modifier.padding(top = 3.dp, bottom = 12.dp),
)
}
Row(horizontalArrangement = Arrangement.spacedBy(14.dp)) {
Column(Modifier.weight(1f)) {
ColumnHeader(stringRes(R.string.new_conversation_pros))
Spacer(Modifier.height(4.dp))
type.pros.forEach { ProConRow(it, accent, isPro = true) }
}
Column(Modifier.weight(1f)) {
ColumnHeader(stringRes(R.string.new_conversation_cons))
Spacer(Modifier.height(4.dp))
type.cons.forEach { ProConRow(it, accent, isPro = false) }
}
}
Button(
onClick = onCreate,
modifier = Modifier.fillMaxWidth().padding(top = 13.dp),
shape = RoundedCornerShape(12.dp),
colors = ButtonDefaults.buttonColors(containerColor = type.color, contentColor = Color.White),
) {
Text(stringRes(type.cta), fontWeight = FontWeight.Bold)
}
}
Spacer(modifier = StdVertSpacer)
type.pros.forEach { ProConRow(it, isPro = true) }
type.cons.forEach { ProConRow(it, isPro = false) }
}
}
}
@Composable
private fun AxisChip(
label: String,
accent: Color,
) {
Surface(
shape = RoundedCornerShape(999.dp),
color = accent.copy(alpha = 0.14f),
) {
Text(
text = label,
style = MaterialTheme.typography.labelSmall,
fontWeight = FontWeight.Bold,
color = accent,
modifier = Modifier.padding(horizontal = 10.dp, vertical = 4.dp),
)
}
}
@Composable
private fun ColumnHeader(text: String) {
Text(
text = text.uppercase(),
style = MaterialTheme.typography.labelSmall,
fontWeight = FontWeight.Bold,
color = MaterialTheme.colorScheme.grayText,
)
}
@Composable
private fun ProConRow(
@StringRes text: Int,
accent: Color,
isPro: Boolean,
) {
Row(
verticalAlignment = Alignment.CenterVertically,
modifier = Modifier.padding(vertical = 1.dp),
verticalAlignment = Alignment.Top,
modifier = Modifier.padding(vertical = 2.dp),
) {
Icon(
symbol = if (isPro) MaterialSymbols.Check else MaterialSymbols.Close,
contentDescription = null,
tint = if (isPro) MaterialTheme.colorScheme.primary else MaterialTheme.colorScheme.grayText,
modifier = Modifier.size(16.dp),
tint = if (isPro) accent else MaterialTheme.colorScheme.grayText,
modifier = Modifier.size(15.dp).padding(top = 1.dp),
)
Spacer(Modifier.size(8.dp))
Spacer(Modifier.width(6.dp))
Text(
text = stringRes(text),
style = MaterialTheme.typography.bodySmall,
+48 -41
View File
@@ -2050,64 +2050,71 @@
<string name="messages_create_group">Group</string>
<string name="messages_create_public_private_chat_description">New Public or Private Group</string>
<!-- New conversation chooser (full-screen picker opened from the Messages FAB) -->
<!-- New conversation chooser (full-screen picker opened from the Messages FAB).
Each row stays lean; the "best for" line and the pros/cons appear only when a row is tapped. -->
<string name="new_conversation_title">Start a conversation</string>
<string name="new_conversation_intro">Pick the kind of conversation that fits what you need. They differ in who can join, how private they are, and where the messages live.</string>
<string name="new_conversation_best_for">Best for</string>
<string name="new_conversation_section_direct">Direct &amp; private</string>
<string name="new_conversation_pros">Good</string>
<string name="new_conversation_cons">Trade-offs</string>
<string name="new_conversation_section_direct">Private</string>
<string name="new_conversation_section_encrypted">Encrypted groups</string>
<string name="new_conversation_section_public">Public &amp; open</string>
<string name="new_conversation_section_relay">Relay-aware</string>
<string name="new_conversation_dm_title">Private Message</string>
<string name="new_conversation_dm_tagline">Encrypted direct messages with one person or a small group.</string>
<string name="new_conversation_dm_best">Talking privately with people you already know.</string>
<string name="new_conversation_dm_pro_1">End-to-end encrypted</string>
<string name="new_conversation_dm_pro_2">Hides who you\'re talking to</string>
<string name="new_conversation_dm_pro_3">Works across all your relays</string>
<string name="new_conversation_dm_con_1">Best for small groups</string>
<string name="new_conversation_dm_con_2">No shared admins or moderation</string>
<string name="new_conversation_dm_tagline">Direct messages, end-to-end encrypted</string>
<string name="new_conversation_dm_chip">1:15 rooms</string>
<string name="new_conversation_dm_best">One-on-one and small group chats with people you know.</string>
<string name="new_conversation_dm_cta">New message</string>
<string name="new_conversation_dm_pro_1">1-on-1 &amp; small groups</string>
<string name="new_conversation_dm_pro_2">End-to-end encrypted</string>
<string name="new_conversation_dm_con_1">Not for big groups</string>
<string name="new_conversation_marmot_title">Marmot Group</string>
<string name="new_conversation_marmot_tagline">Strongly encrypted group chat built on the MLS standard.</string>
<string name="new_conversation_marmot_best">A private team or friend group that needs the strongest encryption.</string>
<string name="new_conversation_marmot_pro_1">Forward-secret group encryption</string>
<string name="new_conversation_marmot_pro_2">Relays can\'t read the messages</string>
<string name="new_conversation_marmot_pro_3">Controlled membership</string>
<string name="new_conversation_marmot_con_1">Newer, still maturing</string>
<string name="new_conversation_marmot_con_2">Everyone needs a Marmot-capable app</string>
<string name="new_conversation_marmot_tagline">Bigger private groups</string>
<string name="new_conversation_marmot_chip">Device-bound</string>
<string name="new_conversation_marmot_best">Larger private groups that outgrow small-group DMs.</string>
<string name="new_conversation_marmot_cta">Create group</string>
<string name="new_conversation_marmot_pro_1">Scales past small DMs</string>
<string name="new_conversation_marmot_pro_2">Encrypted group chat</string>
<string name="new_conversation_marmot_con_1">Device-bound — won\'t appear if you sign in elsewhere</string>
<string name="new_conversation_concord_title">Concord Community</string>
<string name="new_conversation_concord_tagline">An encrypted community with multiple channels, like a private server.</string>
<string name="new_conversation_concord_best">Running a community or team with topic channels and roles.</string>
<string name="new_conversation_concord_pro_1">Many channels and roles</string>
<string name="new_conversation_concord_pro_2">Encrypted, with invite links</string>
<string name="new_conversation_concord_pro_3">Scales to larger groups</string>
<string name="new_conversation_concord_tagline">Communities split by channel</string>
<string name="new_conversation_concord_chip">Workspaces</string>
<string name="new_conversation_concord_best">Massive communities, organized by channels or workstreams.</string>
<string name="new_conversation_concord_cta">Create community</string>
<string name="new_conversation_concord_pro_1">Scales to huge communities</string>
<string name="new_conversation_concord_pro_2">Split by channel / workstream</string>
<string name="new_conversation_concord_con_1">More to set up</string>
<string name="new_conversation_concord_con_2">Members need a Concord-capable app</string>
<string name="new_conversation_public_chat_title">Public Chat</string>
<string name="new_conversation_public_chat_tagline">An open channel anyone can find, read, and join.</string>
<string name="new_conversation_public_chat_best">A public topic room open to everyone.</string>
<string name="new_conversation_public_chat_tagline">Public messages on a relay</string>
<string name="new_conversation_public_chat_chip">Unmoderated</string>
<string name="new_conversation_public_chat_best">Open public rooms where anyone can post.</string>
<string name="new_conversation_public_chat_cta">Create public chat</string>
<string name="new_conversation_public_chat_pro_1">Anyone can join</string>
<string name="new_conversation_public_chat_pro_2">Discoverable and simple</string>
<string name="new_conversation_public_chat_con_1">Not private — messages are public</string>
<string name="new_conversation_public_chat_con_2">Limited moderation</string>
<string name="new_conversation_public_chat_pro_2">Simple &amp; discoverable</string>
<string name="new_conversation_public_chat_con_1">Public only</string>
<string name="new_conversation_public_chat_con_2">No moderation</string>
<string name="new_conversation_relay_group_title">Relay Group</string>
<string name="new_conversation_relay_group_tagline">A group hosted and moderated by a specific relay.</string>
<string name="new_conversation_relay_group_best">A managed group with admins, roles, and moderation.</string>
<string name="new_conversation_relay_group_pro_1">Real moderation and roles</string>
<string name="new_conversation_relay_group_pro_2">Can be open or invite-only</string>
<string name="new_conversation_relay_group_con_1">Lives on a single relay</string>
<string name="new_conversation_relay_group_con_2">That relay can see the group</string>
<string name="new_conversation_relay_group_tagline">Relay-run, public or private</string>
<string name="new_conversation_relay_group_chip">Moderated</string>
<string name="new_conversation_relay_group_best">Groups moderated by the relay that hosts them.</string>
<string name="new_conversation_relay_group_cta">Browse relay groups</string>
<string name="new_conversation_relay_group_pro_1">Moderated by the relay</string>
<string name="new_conversation_relay_group_pro_2">Public or private</string>
<string name="new_conversation_relay_group_con_1">Tied to that one relay</string>
<string name="new_conversation_ephemeral_title">Disappearing Chat</string>
<string name="new_conversation_ephemeral_tagline">A temporary room tied to a relay — messages aren\'t stored.</string>
<string name="new_conversation_ephemeral_best">Quick, in-the-moment chats you don\'t want kept.</string>
<string name="new_conversation_ephemeral_pro_1">Nothing is saved</string>
<string name="new_conversation_ephemeral_pro_2">Lightweight and instant</string>
<string name="new_conversation_ephemeral_con_1">History disappears</string>
<string name="new_conversation_ephemeral_con_2">Only people on that relay see it</string>
<string name="new_conversation_ephemeral_tagline">Whoever\'s online, right now</string>
<string name="new_conversation_ephemeral_chip">Live now</string>
<string name="new_conversation_ephemeral_best">In-the-moment chat with whoever is online right now.</string>
<string name="new_conversation_ephemeral_cta">Start chat</string>
<string name="new_conversation_ephemeral_pro_1">Talk to who\'s online now</string>
<string name="new_conversation_ephemeral_pro_2">Nothing is saved</string>
<string name="new_conversation_ephemeral_con_1">No history</string>
<string name="new_conversation_ephemeral_con_2">Relay-scoped</string>
<string name="relay_groups_title">Relay Groups</string>
<string name="relay_group_view_inline">Inline</string>
<string name="relay_group_view_grouped">By relay</string>