Merge pull request #813 from qutad/fix/766-header-location-control

feat: improve location control accessibility and crowding
This commit is contained in:
callebtc 2026-07-30 19:12:51 +02:00 committed by GitHub
commit 643f329d9d
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
36 changed files with 207 additions and 117 deletions

View File

@ -40,6 +40,7 @@ import androidx.compose.ui.res.painterResource
import androidx.compose.ui.res.stringResource
import androidx.compose.ui.text.font.FontWeight
import androidx.compose.ui.text.input.ImeAction
import androidx.compose.ui.unit.Dp
import androidx.compose.ui.unit.dp
import androidx.compose.ui.unit.sp
import androidx.lifecycle.compose.collectAsStateWithLifecycle
@ -83,6 +84,28 @@ private val HeaderTextSize = 17.sp
/** Minimum tap target for every interactive element in the header. */
private val HeaderTapTarget = 44.dp
internal enum class HeaderCrowdingMode {
Full,
HideJoinedChannelCount,
IconOnlyLocationChannel,
}
internal fun headerCrowdingMode(availableWidth: Dp): HeaderCrowdingMode = when {
availableWidth < 360.dp -> HeaderCrowdingMode.IconOnlyLocationChannel
availableWidth < 400.dp -> HeaderCrowdingMode.HideJoinedChannelCount
else -> HeaderCrowdingMode.Full
}
internal fun locationChannelContentDescription(
actionDescription: String,
channelLabel: String,
showLabel: Boolean,
): String = if (showLabel) {
actionDescription
} else {
"$channelLabel. $actionDescription"
}
/** Corner radius for the header's tappable label+icon clusters. */
private val HeaderClusterShape = RoundedCornerShape(8.dp)
@ -531,6 +554,7 @@ fun NicknameEditor(
}
),
modifier = Modifier
.weight(1f)
.widthIn(max = 150.dp)
.horizontalScroll(scrollState)
)
@ -546,7 +570,8 @@ fun PeerCounter(
selectedLocationChannel: com.bitchat.android.geohash.ChannelID?,
geohashPeople: List<GeoPerson>,
onClick: () -> Unit,
modifier: Modifier = Modifier
modifier: Modifier = Modifier,
showJoinedChannelCount: Boolean = true
) {
val palette = LocalBitchatPalette.current
val colorScheme = MaterialTheme.colorScheme
@ -603,7 +628,7 @@ fun PeerCounter(
fontWeight = FontWeight.Medium
)
if (joinedChannels.isNotEmpty()) {
if (showJoinedChannelCount && joinedChannels.isNotEmpty()) {
AnimatedCount(
count = joinedChannels.size,
prefix = stringResource(R.string.channel_count_prefix),
@ -703,22 +728,17 @@ private fun MainHeader(
val selectedLocationChannel by viewModel.selectedLocationChannel.collectAsStateWithLifecycle()
val geohashPeople by viewModel.geohashPeople.collectAsStateWithLifecycle()
Row(
modifier = Modifier
.fillMaxWidth()
.height(ChatHeaderHeight)
.padding(start = HeaderInsetStart, end = HeaderInsetEnd),
verticalAlignment = Alignment.CenterVertically
) {
// MARK: - Identity cluster.
//
// Weighted so it yields space to the status cluster rather than pushing it off screen.
// Compose measures unweighted children first, so the icons on the right always get the
// width they need and a long nickname simply scrolls within what is left.
BoxWithConstraints(modifier = Modifier.fillMaxWidth()) {
val crowdingMode = headerCrowdingMode(maxWidth)
Row(
modifier = Modifier.weight(1f),
modifier = Modifier
.fillMaxWidth()
.height(ChatHeaderHeight)
.padding(start = HeaderInsetStart, end = HeaderInsetEnd),
verticalAlignment = Alignment.CenterVertically
) {
// Keep the brand and trailing actions fixed. Only the nickname yields under pressure.
BitChatBrandButton(
onClick = onTitleClick,
onTripleClick = onTripleTitleClick,
@ -726,11 +746,13 @@ private fun MainHeader(
modifier = Modifier.size(HeaderTapTarget),
)
// Nudge toward the brand glyph: the 44.dp tap target leaves more optical gap than
// spacing between the mark and the path label.
// Nudge toward the brand glyph: the 44.dp tap target leaves more optical gap than the
// spacing between the mark and path label.
Row(
verticalAlignment = Alignment.CenterVertically,
modifier = Modifier.offset(x = (-6).dp)
modifier = Modifier
.weight(1f)
.offset(x = (-6).dp)
) {
Text(
text = "/",
@ -744,66 +766,58 @@ private fun MainHeader(
NicknameEditor(
value = nickname,
onValueChange = onNicknameChange
onValueChange = onNicknameChange,
modifier = Modifier.weight(1f)
)
}
}
// MARK: - Status cluster.
//
// Order, left to right: unread DMs, notes, channel, people.
// Tor health is read from the location channel / notes icon colour rather than a
// dedicated status dot.
Row(
verticalAlignment = Alignment.CenterVertically,
// Tight, because every child below is its own >=44.dp tap target.
horizontalArrangement = Arrangement.spacedBy(2.dp)
) {
// Unread private messages badge (click to open most recent DM)
if (hasUnreadPrivateMessages.isNotEmpty()) {
HeaderIconButton(
onClick = { viewModel.openLatestUnreadPrivateChat() },
contentDescription = stringResource(R.string.cd_unread_private_messages)
) {
Icon(
painter = painterResource(R.drawable.ic_spec_envelope),
contentDescription = stringResource(R.string.cd_unread_private_messages),
modifier = Modifier.size(HeaderIconSize),
tint = palette.accentOrange
)
}
}
// Location notes + channel badge: one tight unit so the document glyph and the
// bluetooth/globe glyph sit at the same visual pitch as other header pairings.
// Order, left to right: unread DMs, notes, channel, people. This cluster is measured
// before the weighted nickname, so actions cannot be pushed off-screen by identity.
Row(
verticalAlignment = Alignment.CenterVertically,
horizontalArrangement = Arrangement.spacedBy(0.dp)
horizontalArrangement = Arrangement.spacedBy(2.dp)
) {
LocationNotesButton(
viewModel = viewModel,
onClick = onLocationNotesClick
)
if (hasUnreadPrivateMessages.isNotEmpty()) {
HeaderIconButton(
onClick = { viewModel.openLatestUnreadPrivateChat() },
contentDescription = stringResource(R.string.cd_unread_private_messages)
) {
Icon(
painter = painterResource(R.drawable.ic_spec_envelope),
contentDescription = stringResource(R.string.cd_unread_private_messages),
modifier = Modifier.size(HeaderIconSize),
tint = palette.accentOrange
)
}
}
// Bookmarking lives in the Location Channels sheet, one tap away via the channel
// button. Duplicating it here bought a shortcut for a rare action at the cost
// of a slot in the app's most crowded row.
Row(
verticalAlignment = Alignment.CenterVertically,
horizontalArrangement = Arrangement.spacedBy(0.dp)
) {
LocationNotesButton(
viewModel = viewModel,
onClick = onLocationNotesClick
)
LocationChannelsButton(
viewModel = viewModel,
onClick = onLocationChannelsClick
LocationChannelsButton(
viewModel = viewModel,
onClick = onLocationChannelsClick,
showLabel = crowdingMode != HeaderCrowdingMode.IconOnlyLocationChannel
)
}
PeerCounter(
connectedPeers = connectedPeers.filter { it != viewModel.myPeerID },
joinedChannels = joinedChannels,
hasUnreadChannels = hasUnreadChannels,
isConnected = isConnected,
selectedLocationChannel = selectedLocationChannel,
geohashPeople = geohashPeople,
onClick = onSidebarClick,
showJoinedChannelCount = crowdingMode == HeaderCrowdingMode.Full
)
}
PeerCounter(
connectedPeers = connectedPeers.filter { it != viewModel.myPeerID },
joinedChannels = joinedChannels,
hasUnreadChannels = hasUnreadChannels,
isConnected = isConnected,
selectedLocationChannel = selectedLocationChannel,
geohashPeople = geohashPeople,
onClick = onSidebarClick
)
}
}
}
@ -818,7 +832,8 @@ private fun MainHeader(
@Composable
private fun LocationChannelsButton(
viewModel: ChatViewModel,
onClick: () -> Unit
onClick: () -> Unit,
showLabel: Boolean
) {
val colorScheme = MaterialTheme.colorScheme
@ -845,35 +860,44 @@ private fun LocationChannelsButton(
} else {
R.drawable.ic_spec_range
}
val actionDescription = stringResource(R.string.cd_open_location_channels)
val contentDescription = locationChannelContentDescription(
actionDescription = actionDescription,
channelLabel = badgeText,
showLabel = showLabel
)
Row(
verticalAlignment = Alignment.CenterVertically,
horizontalArrangement = Arrangement.spacedBy(6.dp),
horizontalArrangement = if (showLabel) Arrangement.spacedBy(6.dp) else Arrangement.Center,
modifier = Modifier
.clip(HeaderClusterShape)
.pressScaleClickable(
onClick = onClick,
onClickLabel = stringResource(R.string.location_channels_title)
onClickLabel = actionDescription
)
.height(HeaderTapTarget)
// No start padding: the notes icon is paired directly to the left; keep end
// padding so the gap to PeerCounter matches other cluster separations.
.padding(start = 0.dp, end = 6.dp)
.widthIn(min = HeaderTapTarget)
.padding(end = if (showLabel) 6.dp else 0.dp)
) {
TorAwareHeaderIcon(
painter = painterResource(badgeIconRes),
tint = torVisual.tint,
isProgress = torVisual.isProgress,
contentDescription = stringResource(R.string.cd_tor_status)
contentDescription = contentDescription
)
Text(
text = badgeText,
style = MaterialTheme.typography.bodyMedium,
fontSize = HeaderTextSize,
fontWeight = FontWeight.Medium,
color = channelColor,
maxLines = 1
)
if (showLabel) {
Text(
text = badgeText,
style = MaterialTheme.typography.bodyMedium,
fontSize = HeaderTextSize,
fontWeight = FontWeight.Medium,
color = channelColor,
maxLines = 1,
overflow = TextOverflow.Ellipsis,
modifier = Modifier.widthIn(max = 88.dp)
)
}
}
}

View File

@ -74,7 +74,7 @@
<string name="cd_nostr_reachable">يمكن الوصول عبر Nostr</string>
<string name="cd_unread_private_messages">رسائل خاصة غير مقروءة</string>
<string name="cd_teleported">تم الانتقال</string>
<string name="cd_tor_status">حالة Tor</string>
<string name="cd_open_location_channels">فتح إعدادات الموقع والقنوات</string>
<string name="cd_connected_peers">الأقران المتصلون</string>
<string name="cd_geohash_participants">مشاركو geohash</string>
<string name="cd_ready_for_handshake">جاهز للمصافحة</string>

View File

@ -74,7 +74,7 @@
<string name="cd_nostr_reachable">Nostr এর মাধ্যমে পৌঁছানো যায়</string>
<string name="cd_unread_private_messages">অপঠিত ব্যক্তিগত বার্তা</string>
<string name="cd_teleported">টেলিপোর্ট করা হয়েছে</string>
<string name="cd_tor_status">Tor অবস্থা</string>
<string name="cd_open_location_channels">অবস্থান ও চ্যানেল সেটিংস খুলুন</string>
<string name="cd_connected_peers">সংযুক্ত পিয়ার</string>
<string name="cd_geohash_participants">জিওহ্যাশ অংশগ্রহণকারী</string>
<string name="cd_ready_for_handshake">হ্যান্ডশেকের জন্য প্রস্তুত</string>

View File

@ -74,7 +74,7 @@
<string name="cd_nostr_reachable">Über Nostr erreichbar</string>
<string name="cd_unread_private_messages">Ungelesene private Nachrichten</string>
<string name="cd_teleported">Teleportiert</string>
<string name="cd_tor_status">TorStatus</string>
<string name="cd_open_location_channels">Standort- und Kanaleinstellungen öffnen</string>
<string name="cd_connected_peers">Verbundenen Peers</string>
<string name="cd_geohash_participants">GeohashTeilnehmer</string>
<string name="cd_ready_for_handshake">Bereit für Handshake</string>

View File

@ -74,7 +74,7 @@
<string name="cd_nostr_reachable">Accesible vía Nostr</string>
<string name="cd_unread_private_messages">Mensajes privados sin leer</string>
<string name="cd_teleported">Teletransportado</string>
<string name="cd_tor_status">Estado de Tor</string>
<string name="cd_open_location_channels">Abrir ajustes de ubicación y canales</string>
<string name="cd_connected_peers">Pares conectados</string>
<string name="cd_geohash_participants">Participantes geohash</string>
<string name="cd_ready_for_handshake">Listo para handshake</string>

View File

@ -74,7 +74,7 @@
<string name="cd_nostr_reachable">قابل دسترس از طریق Nostr</string>
<string name="cd_unread_private_messages">پیام‌های خصوصی خوانده‌نشده</string>
<string name="cd_teleported">انتقال مکانی</string>
<string name="cd_tor_status">وضعیت Tor</string>
<string name="cd_open_location_channels">باز کردن تنظیمات مکان و کانال‌ها</string>
<string name="cd_connected_peers">همتایان متصل</string>
<string name="cd_geohash_participants">شرکت‌کنندگان geohash</string>
<string name="cd_ready_for_handshake">آمادهٔ دست‌دهی</string>

View File

@ -74,7 +74,7 @@
<string name="cd_nostr_reachable">Maabot sa Nostr</string>
<string name="cd_unread_private_messages">Hindi nabasang pribadong mensahe</string>
<string name="cd_teleported">Naiteleport</string>
<string name="cd_tor_status">Katayuan ng Tor</string>
<string name="cd_open_location_channels">Buksan ang mga setting ng lokasyon at channel</string>
<string name="cd_connected_peers">Nakakonektang peers</string>
<string name="cd_geohash_participants">Mga kalahok sa geohash</string>
<string name="cd_ready_for_handshake">Handa para sa handshake</string>

View File

@ -74,7 +74,7 @@
<string name="cd_nostr_reachable">Joignable via Nostr</string>
<string name="cd_unread_private_messages">Messages privés non lus</string>
<string name="cd_teleported">Téléporté</string>
<string name="cd_tor_status">Statut Tor</string>
<string name="cd_open_location_channels">Ouvrir les réglages de localisation et des canaux</string>
<string name="cd_connected_peers">Pairs connectés</string>
<string name="cd_geohash_participants">Participants geohash</string>
<string name="cd_ready_for_handshake">Prêt pour léchange de clés</string>

View File

@ -122,7 +122,7 @@
<string name="cd_unread_private_messages">הודעות פרטיות שלא נקראו</string>
<string name="cd_location_notes">הערות מיקום</string>
<string name="cd_teleported">טלפורט</string>
<string name="cd_tor_status">סטטוס Tor</string>
<string name="cd_open_location_channels">פתיחת הגדרות מיקום וערוצים</string>
<string name="cd_connected_peers">עמיתים מחוברים</string>
<string name="cd_geohash_participants">משתתפי geohash</string>
<string name="cd_ready_for_handshake">מוכן ללחיצת יד</string>

View File

@ -74,7 +74,7 @@
<string name="cd_nostr_reachable">Nostr के माध्यम से उपलब्ध</string>
<string name="cd_unread_private_messages">अपठित निजी संदेश</string>
<string name="cd_teleported">टेलीपोर्ट हुआ</string>
<string name="cd_tor_status">Tor स्थिति</string>
<string name="cd_open_location_channels">स्थान और चैनल सेटिंग खोलें</string>
<string name="cd_connected_peers">कनेक्टेड पीयर्स</string>
<string name="cd_geohash_participants">geohash प्रतिभागी</string>
<string name="cd_ready_for_handshake">हैंडशेक के लिए तैयार</string>

View File

@ -74,7 +74,7 @@
<string name="cd_nostr_reachable">Dapat dijangkau melalui Nostr</string>
<string name="cd_unread_private_messages">Pesan pribadi yang belum dibaca</string>
<string name="cd_teleported">Diteleportasi</string>
<string name="cd_tor_status">Status Tor</string>
<string name="cd_open_location_channels">Buka pengaturan lokasi dan channel</string>
<string name="cd_connected_peers">Peer yang terhubung</string>
<string name="cd_geohash_participants">Peserta geohash</string>
<string name="cd_ready_for_handshake">Siap untuk handshake</string>

View File

@ -74,7 +74,7 @@
<string name="cd_nostr_reachable">Raggiungibile via Nostr</string>
<string name="cd_unread_private_messages">Messaggi privati non letti</string>
<string name="cd_teleported">Teletrasportato</string>
<string name="cd_tor_status">Stato Tor</string>
<string name="cd_open_location_channels">Apri le impostazioni di posizione e canali</string>
<string name="cd_connected_peers">Peer connessi</string>
<string name="cd_geohash_participants">Partecipanti geohash</string>
<string name="cd_ready_for_handshake">Pronto per l\'handshake</string>

View File

@ -74,7 +74,7 @@
<string name="cd_nostr_reachable">Nostr 経由で到達可能</string>
<string name="cd_unread_private_messages">未読のプライベートメッセージ</string>
<string name="cd_teleported">テレポート済み</string>
<string name="cd_tor_status">Tor ステータス</string>
<string name="cd_open_location_channels">位置情報とチャンネルの設定を開く</string>
<string name="cd_connected_peers">接続中のピア</string>
<string name="cd_geohash_participants">Geohash 参加者</string>
<string name="cd_ready_for_handshake">ハンドシェイク準備完了</string>

View File

@ -74,7 +74,7 @@
<string name="cd_nostr_reachable">მისაწვდომია Nostr-ით</string>
<string name="cd_unread_private_messages">წაუკითხავი პირადი შეტყობინებები</string>
<string name="cd_teleported">ტელეპორტირებული</string>
<string name="cd_tor_status">Tor-ის სტატუსი</string>
<string name="cd_open_location_channels">მდებარეობისა და არხების პარამეტრების გახსნა</string>
<string name="cd_connected_peers">დაკავშირებული პირები</string>
<string name="cd_geohash_participants">geohash მონაწილეები</string>
<string name="cd_ready_for_handshake">მზადაა ხელის ჩამოსართმევად</string>

View File

@ -74,7 +74,7 @@
<string name="cd_nostr_reachable">Nostr로 연결 가능</string>
<string name="cd_unread_private_messages">읽지 않은 개인 메시지</string>
<string name="cd_teleported">텔레포트됨</string>
<string name="cd_tor_status">Tor 상태</string>
<string name="cd_open_location_channels">위치 및 채널 설정 열기</string>
<string name="cd_connected_peers">연결된 피어</string>
<string name="cd_geohash_participants">geohash 참여자</string>
<string name="cd_ready_for_handshake">핸드셰이크 준비됨</string>

View File

@ -74,7 +74,7 @@
<string name="cd_nostr_reachable">Azo tratrarina amin\'ny alalan\'ny Nostr</string>
<string name="cd_unread_private_messages">Hafatra manokana tsy voavaky</string>
<string name="cd_teleported">Nafindra toerana</string>
<string name="cd_tor_status">Toe-javatra Tor</string>
<string name="cd_open_location_channels">Sokafy ny fikirana toerana sy fantsona</string>
<string name="cd_connected_peers">Mpiara-miasa mifandray</string>
<string name="cd_geohash_participants">Mpandray anjara Geohash</string>
<string name="cd_ready_for_handshake">Vonona ho amin\'ny fifampiraharahana</string>

View File

@ -76,7 +76,7 @@
<string name="cd_unread_private_messages">Mesej peribadi belum dibaca</string>
<string name="cd_location_notes">Nota lokasi</string>
<string name="cd_teleported">Diteleport</string>
<string name="cd_tor_status">Status Tor</string>
<string name="cd_open_location_channels">Buka tetapan lokasi dan saluran</string>
<string name="cd_connected_peers">Rakan disambungkan</string>
<string name="cd_geohash_participants">Peserta geohash</string>
<string name="cd_ready_for_handshake">Sedia untuk berjabat tangan</string>

View File

@ -74,7 +74,7 @@
<string name="cd_nostr_reachable">Nostr मार्फत पुग्न सकिने</string>
<string name="cd_unread_private_messages">नपढिएका निजी सन्देश</string>
<string name="cd_teleported">टेलिपोर्ट भयो</string>
<string name="cd_tor_status">Tor स्थिति</string>
<string name="cd_open_location_channels">स्थान र च्यानल सेटिङ खोल्नुहोस्</string>
<string name="cd_connected_peers">जडान भएका साथीहरू</string>
<string name="cd_geohash_participants">Geohash सहभागिहरू</string>
<string name="cd_ready_for_handshake">ह्यान्डशेकका लागि तयार</string>

View File

@ -74,7 +74,7 @@
<string name="cd_nostr_reachable">Bereikbaar via Nostr</string>
<string name="cd_unread_private_messages">Ongelezen privéberichten</string>
<string name="cd_teleported">Geteleporteerd</string>
<string name="cd_tor_status">Tor-status</string>
<string name="cd_open_location_channels">Locatie- en kanaalinstellingen openen</string>
<string name="cd_connected_peers">Verbonden peers</string>
<string name="cd_geohash_participants">Geohash-deelnemers</string>
<string name="cd_ready_for_handshake">Klaar voor handshake</string>

View File

@ -74,7 +74,7 @@
<string name="cd_nostr_reachable">Nostr راہین پہنچ ممکن اے</string>
<string name="cd_unread_private_messages">انہ پڑھیا ذاتی پیغام</string>
<string name="cd_teleported">ٹیلپورٹ کیتا گیا</string>
<string name="cd_tor_status">Tor حالت</string>
<string name="cd_open_location_channels">مقام تے چینل دیاں ترتیباں کھولو</string>
<string name="cd_connected_peers">جُڑے پیئر</string>
<string name="cd_geohash_participants">geohash شریک</string>
<string name="cd_ready_for_handshake">ہینڈشیک لئی تیار</string>

View File

@ -120,7 +120,7 @@
<string name="cd_unread_private_messages">Nieprzeczytane wiadomości prywatne</string>
<string name="cd_location_notes">Notatki lokalizacji</string>
<string name="cd_teleported">Teleportowany</string>
<string name="cd_tor_status">Status Tor</string>
<string name="cd_open_location_channels">Otwórz ustawienia lokalizacji i kanałów</string>
<string name="cd_connected_peers">Połączeni użytkownicy</string>
<string name="cd_geohash_participants">Uczestnicy geohash</string>
<string name="cd_ready_for_handshake">Gotowy do uzgadniania</string>

View File

@ -74,7 +74,7 @@
<string name="cd_nostr_reachable">Acessível via Nostr</string>
<string name="cd_unread_private_messages">Mensagens privadas não lidas</string>
<string name="cd_teleported">Teletransportado</string>
<string name="cd_tor_status">Status do Tor</string>
<string name="cd_open_location_channels">Abrir configurações de localização e canais</string>
<string name="cd_connected_peers">Peers conectados</string>
<string name="cd_geohash_participants">Participantes geohash</string>
<string name="cd_ready_for_handshake">Pronto para handshake</string>

View File

@ -74,7 +74,7 @@
<string name="cd_nostr_reachable">Alcançável via Nostr</string>
<string name="cd_unread_private_messages">Mensagens privadas não lidas</string>
<string name="cd_teleported">Teletransportado</string>
<string name="cd_tor_status">Estado do Tor</string>
<string name="cd_open_location_channels">Abrir definições de localização e canais</string>
<string name="cd_connected_peers">Pares ligados</string>
<string name="cd_geohash_participants">Participantes geohash</string>
<string name="cd_ready_for_handshake">Pronto para handshake</string>

View File

@ -66,7 +66,7 @@
<string name="cd_nostr_reachable">Доступен через Nostr</string>
<string name="cd_unread_private_messages">Непрочитанные личные</string>
<string name="cd_teleported">Телепортировано</string>
<string name="cd_tor_status">Статус Tor</string>
<string name="cd_open_location_channels">Открыть настройки местоположения и каналов</string>
<string name="cd_connected_peers">Подключённые узлы</string>
<string name="cd_geohash_participants">Участники geohash</string>
<string name="cd_ready_for_handshake">Готов к рукопожатию</string>

View File

@ -66,7 +66,7 @@
<string name="cd_nostr_reachable">Nås via Nostr</string>
<string name="cd_unread_private_messages">Olästa privata meddelanden</string>
<string name="cd_teleported">Teleporterad</string>
<string name="cd_tor_status">Torstatus</string>
<string name="cd_open_location_channels">Öppna plats- och kanalinställningar</string>
<string name="cd_connected_peers">Anslutna noder</string>
<string name="cd_geohash_participants">Geohashdeltagare</string>
<string name="cd_ready_for_handshake">Redo för handshake</string>

View File

@ -112,7 +112,7 @@
<string name="cd_unread_private_messages">படிக்காத தனிப்பட்ட செய்திகள்</string>
<string name="cd_location_notes">இருப்பிட குறிப்புகள்</string>
<string name="cd_teleported">டெலிபோர்ட் செய்யப்பட்டது</string>
<string name="cd_tor_status">Tor நிலை</string>
<string name="cd_open_location_channels">இருப்பிடம் மற்றும் சேனல் அமைப்புகளைத் திற</string>
<string name="cd_connected_peers">இணைக்கப்பட்ட பியர்ஸ்</string>
<string name="cd_geohash_participants">ஜியோஹாஷ் பங்கேற்பாளர்கள்</string>
<string name="cd_ready_for_handshake">ஹேண்ட்ஷேக்கிற்கு தயார்</string>

View File

@ -74,7 +74,7 @@
<string name="cd_nostr_reachable">ติดต่อได้ผ่าน Nostr</string>
<string name="cd_unread_private_messages">ข้อความส่วนตัวยังไม่ได้อ่าน</string>
<string name="cd_teleported">เทเลพอร์ตแล้ว</string>
<string name="cd_tor_status">สถานะ Tor</string>
<string name="cd_open_location_channels">เปิดการตั้งค่าตำแหน่งและช่อง</string>
<string name="cd_connected_peers">เพียร์ที่เชื่อมต่อ</string>
<string name="cd_geohash_participants">ผู้เข้าร่วม geohash</string>
<string name="cd_ready_for_handshake">พร้อมสำหรับการจับมือ</string>

View File

@ -66,7 +66,7 @@
<string name="cd_nostr_reachable">Nostr üzerinden ulaşılabilir</string>
<string name="cd_unread_private_messages">Okunmamış özel mesaj</string>
<string name="cd_teleported">Teleport edildi</string>
<string name="cd_tor_status">Tor durumu</string>
<string name="cd_open_location_channels">Konum ve kanal ayarlarını</string>
<string name="cd_connected_peers">Bağlı eşler</string>
<string name="cd_geohash_participants">Geohash katılımcıları</string>
<string name="cd_ready_for_handshake">El sıkışmaya hazır</string>

View File

@ -105,7 +105,7 @@
<string name="cd_unread_private_messages">Непрочитані приватні повідомлення</string>
<string name="cd_location_notes">Нотатки про місце</string>
<string name="cd_teleported">Телепортовано</string>
<string name="cd_tor_status">Статус Tor</string>
<string name="cd_open_location_channels">Відкрити налаштування розташування та каналів</string>
<string name="cd_connected_peers">Підключені піри</string>
<string name="cd_geohash_participants">Учасники геохешу</string>
<string name="cd_ready_for_handshake">Готовий до рукостискання</string>

View File

@ -74,7 +74,7 @@
<string name="cd_nostr_reachable">Nostr کے ذریعے رسائی</string>
<string name="cd_unread_private_messages">غیر پڑھے ہوئے نجی پیغامات</string>
<string name="cd_teleported">ٹیلی پورٹ</string>
<string name="cd_tor_status">Tor کی کیفیت</string>
<string name="cd_open_location_channels">مقام اور چینل کی ترتیبات کھولیں</string>
<string name="cd_connected_peers">منسلک پیئرز</string>
<string name="cd_geohash_participants">geohash شرکاء</string>
<string name="cd_ready_for_handshake">ہینڈ شیک کے لیے تیار</string>

View File

@ -74,7 +74,7 @@
<string name="cd_nostr_reachable">Có thể tiếp cận qua Nostr</string>
<string name="cd_unread_private_messages">Tin nhắn riêng chưa đọc</string>
<string name="cd_teleported">Đã dịch chuyển</string>
<string name="cd_tor_status">Trạng thái Tor</string>
<string name="cd_open_location_channels">Mở cài đặt vị trí và kênh</string>
<string name="cd_connected_peers">Peers đã kết nối</string>
<string name="cd_geohash_participants">Người tham gia geohash</string>
<string name="cd_ready_for_handshake">Sẵn sàng cho handshake</string>

View File

@ -121,7 +121,6 @@
<string name="cd_unread_private_messages">未读私信</string>
<string name="cd_location_notes">位置笔记</string>
<string name="cd_teleported">已传送</string>
<string name="cd_tor_status">Tor 状态</string>
<string name="cd_connected_peers">已连接的节点</string>
<string name="cd_geohash_participants">Geohash 参与者</string>
<string name="cd_ready_for_handshake">准备握手</string>

View File

@ -121,7 +121,6 @@
<string name="cd_unread_private_messages">未讀私訊</string>
<string name="cd_location_notes">位置筆記</string>
<string name="cd_teleported">已傳送</string>
<string name="cd_tor_status">Tor 狀態</string>
<string name="cd_connected_peers">已連線的節點</string>
<string name="cd_geohash_participants">地理雜湊參與者</string>
<string name="cd_ready_for_handshake">準備好進行握手</string>

View File

@ -74,7 +74,7 @@
<string name="cd_nostr_reachable">可通过 Nostr 联系</string>
<string name="cd_unread_private_messages">未读私信</string>
<string name="cd_teleported">已传送</string>
<string name="cd_tor_status">Tor 状态</string>
<string name="cd_open_location_channels">打开位置和频道设置</string>
<string name="cd_connected_peers">已连接节点</string>
<string name="cd_geohash_participants">Geohash 参与者</string>
<string name="cd_ready_for_handshake">准备握手</string>

View File

@ -123,7 +123,7 @@
<string name="you">You</string>
<string name="cd_location_notes">Location notes</string>
<string name="cd_teleported">Teleported</string>
<string name="cd_tor_status">Tor status</string>
<string name="cd_open_location_channels">Open location and channel settings</string>
<string name="cd_connected_peers">Connected peers</string>
<string name="cd_geohash_participants">Geohash participants</string>
<string name="cd_ready_for_handshake">Ready for handshake</string>

View File

@ -0,0 +1,68 @@
package com.bitchat.android.ui
import androidx.compose.ui.unit.dp
import org.junit.Assert.assertEquals
import org.junit.Test
class ChatHeaderCrowdingTest {
@Test
fun `full header is used at four hundred dp and above`() {
assertEquals(HeaderCrowdingMode.Full, headerCrowdingMode(400.dp))
assertEquals(HeaderCrowdingMode.Full, headerCrowdingMode(500.dp))
}
@Test
fun `joined channel count yields before the location label`() {
assertEquals(
HeaderCrowdingMode.HideJoinedChannelCount,
headerCrowdingMode(399.dp)
)
assertEquals(
HeaderCrowdingMode.HideJoinedChannelCount,
headerCrowdingMode(360.dp)
)
}
@Test
fun `location action becomes icon only on narrow headers`() {
assertEquals(
HeaderCrowdingMode.IconOnlyLocationChannel,
headerCrowdingMode(359.dp)
)
assertEquals(
HeaderCrowdingMode.IconOnlyLocationChannel,
headerCrowdingMode(320.dp)
)
}
@Test
fun `icon-only location action includes the selected channel in its description`() {
val action = "Open location and channel settings"
assertEquals(
action,
locationChannelContentDescription(
actionDescription = action,
channelLabel = "mesh",
showLabel = true
)
)
assertEquals(
"mesh. $action",
locationChannelContentDescription(
actionDescription = action,
channelLabel = "mesh",
showLabel = false
)
)
assertEquals(
"#u33d. $action",
locationChannelContentDescription(
actionDescription = action,
channelLabel = "#u33d",
showLabel = false
)
)
}
}