mirror of
https://github.com/permissionlesstech/bitchat-android.git
synced 2026-08-29 07:16:08 +00:00
fix: address bulletin board review findings
This commit is contained in:
parent
771b063094
commit
ee6d69e111
@ -106,6 +106,18 @@ class BoardStore(
|
||||
return result
|
||||
}
|
||||
|
||||
/**
|
||||
* Ingests a packet received from the mesh and reports whether this exact
|
||||
* arrival may continue through the live relay path.
|
||||
*
|
||||
* A duplicate board payload must not relay again: the payload signature
|
||||
* does not authenticate mutable outer packet fields such as timestamp, so
|
||||
* accepting duplicates for relay would let one captured notice be wrapped
|
||||
* in infinitely many distinct outer packets.
|
||||
*/
|
||||
fun ingestRemoteForRelay(wire: BoardWire, packet: BitchatPacket): Boolean =
|
||||
ingest(wire, packet, BoardIngestSource.REMOTE) == BoardIngestResult.ACCEPTED
|
||||
|
||||
fun posts(forGeohash: String): List<BoardPostPacket> = synchronized(lock) {
|
||||
pruneExpiredLocked(nowMs())
|
||||
posts.asSequence()
|
||||
@ -194,7 +206,11 @@ class BoardStore(
|
||||
now: ULong,
|
||||
retainUntilOverride: ULong?
|
||||
): BoardIngestResult {
|
||||
if (tombstones.any { it.tombstone.postID.contentEquals(tombstone.postID) }) {
|
||||
if (tombstones.any {
|
||||
it.tombstone.postID.contentEquals(tombstone.postID) &&
|
||||
it.tombstone.authorSigningKey.contentEquals(tombstone.authorSigningKey)
|
||||
}
|
||||
) {
|
||||
return BoardIngestResult.DUPLICATE
|
||||
}
|
||||
|
||||
@ -271,8 +287,8 @@ class BoardStore(
|
||||
count: Int
|
||||
) {
|
||||
if (count <= 0) return
|
||||
val victimIDs = candidates.take(count).map { it.tombstone.postID.toHex() }.toSet()
|
||||
tombstones.removeAll { it.tombstone.postID.toHex() in victimIDs }
|
||||
val victims = candidates.take(count)
|
||||
tombstones.removeAll { stored -> victims.any { it === stored } }
|
||||
}
|
||||
|
||||
private fun pruneExpiredLocked(now: ULong): Boolean {
|
||||
|
||||
@ -680,16 +680,7 @@ class BluetoothMeshService(private val context: Context) : TransportBridgeServic
|
||||
override fun handleBoardPost(routed: RoutedPacket): Boolean {
|
||||
val wire = com.bitchat.android.board.BoardWireCodec.decode(routed.packet.payload)
|
||||
?: return false
|
||||
if (!wire.verifySignature()) return false
|
||||
return when (boardStore.ingest(
|
||||
wire,
|
||||
routed.packet,
|
||||
com.bitchat.android.board.BoardIngestSource.REMOTE
|
||||
)) {
|
||||
com.bitchat.android.board.BoardIngestResult.ACCEPTED,
|
||||
com.bitchat.android.board.BoardIngestResult.DUPLICATE -> true
|
||||
com.bitchat.android.board.BoardIngestResult.REJECTED -> false
|
||||
}
|
||||
return boardStore.ingestRemoteForRelay(wire, routed.packet)
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@ -511,16 +511,7 @@ class MeshCore(
|
||||
override fun handleBoardPost(routed: RoutedPacket): Boolean {
|
||||
val wire = com.bitchat.android.board.BoardWireCodec.decode(routed.packet.payload)
|
||||
?: return false
|
||||
if (!wire.verifySignature()) return false
|
||||
return when (boardStore.ingest(
|
||||
wire,
|
||||
routed.packet,
|
||||
com.bitchat.android.board.BoardIngestSource.REMOTE
|
||||
)) {
|
||||
com.bitchat.android.board.BoardIngestResult.ACCEPTED,
|
||||
com.bitchat.android.board.BoardIngestResult.DUPLICATE -> true
|
||||
com.bitchat.android.board.BoardIngestResult.REJECTED -> false
|
||||
}
|
||||
return boardStore.ingestRemoteForRelay(wire, routed.packet)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@ -0,0 +1,11 @@
|
||||
package com.bitchat.android.ui
|
||||
|
||||
internal object NoticeComposerPolicy {
|
||||
private val finiteExpiryDays = listOf(1, 3, 7)
|
||||
|
||||
fun expiryOptions(isGeo: Boolean): List<Int> =
|
||||
if (isGeo) listOf(0) + finiteExpiryDays else finiteExpiryDays
|
||||
|
||||
fun isPermanentRelayOnlyGeo(isGeo: Boolean, expiryDays: Int): Boolean =
|
||||
isGeo && expiryDays == 0
|
||||
}
|
||||
@ -13,8 +13,10 @@ 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.horizontalScroll
|
||||
import androidx.compose.foundation.lazy.LazyColumn
|
||||
import androidx.compose.foundation.lazy.items
|
||||
import androidx.compose.foundation.rememberScrollState
|
||||
import androidx.compose.material.icons.Icons
|
||||
import androidx.compose.material.icons.automirrored.filled.Send
|
||||
import androidx.compose.material.icons.filled.Delete
|
||||
@ -239,7 +241,11 @@ private fun NoticesSheet(
|
||||
enabled = true,
|
||||
sendFailed = sendFailed,
|
||||
onSend = {
|
||||
if (selectedTab == NoticesTab.GEO && expiryDays == 0) {
|
||||
if (NoticeComposerPolicy.isPermanentRelayOnlyGeo(
|
||||
isGeo = selectedTab == NoticesTab.GEO,
|
||||
expiryDays = expiryDays
|
||||
)
|
||||
) {
|
||||
notesManager.send(
|
||||
content = draft,
|
||||
nickname = nickname,
|
||||
@ -470,29 +476,34 @@ private fun Composer(
|
||||
)
|
||||
Switch(checked = urgent, onCheckedChange = onUrgentChange)
|
||||
}
|
||||
Row(
|
||||
horizontalArrangement = Arrangement.spacedBy(8.dp),
|
||||
verticalAlignment = Alignment.CenterVertically
|
||||
) {
|
||||
Text(
|
||||
text = stringResource(R.string.notices_expiry),
|
||||
style = MaterialTheme.typography.labelMedium
|
||||
)
|
||||
listOf(1, 3, 7).forEach { days ->
|
||||
val daysDescription = stringResource(R.string.notices_days, days)
|
||||
FilterChip(
|
||||
selected = expiryDays == days,
|
||||
onClick = { onExpiryChange(days) },
|
||||
label = {
|
||||
Text(
|
||||
text = "${days}d",
|
||||
modifier = Modifier.semantics {
|
||||
contentDescription = daysDescription
|
||||
}
|
||||
)
|
||||
}
|
||||
)
|
||||
}
|
||||
Row(
|
||||
modifier = Modifier
|
||||
.fillMaxWidth()
|
||||
.horizontalScroll(rememberScrollState()),
|
||||
horizontalArrangement = Arrangement.spacedBy(8.dp),
|
||||
verticalAlignment = Alignment.CenterVertically
|
||||
) {
|
||||
Text(
|
||||
text = stringResource(R.string.notices_expiry),
|
||||
style = MaterialTheme.typography.labelMedium
|
||||
)
|
||||
NoticeComposerPolicy.expiryOptions(isGeo).forEach { days ->
|
||||
val optionDescription = if (days == 0) {
|
||||
stringResource(R.string.notices_permanent)
|
||||
} else {
|
||||
stringResource(R.string.notices_days, days)
|
||||
}
|
||||
FilterChip(
|
||||
selected = expiryDays == days,
|
||||
onClick = { onExpiryChange(days) },
|
||||
modifier = Modifier.semantics {
|
||||
contentDescription = optionDescription
|
||||
},
|
||||
label = {
|
||||
Text(if (days == 0) "∞" else "${days}d")
|
||||
}
|
||||
)
|
||||
}
|
||||
}
|
||||
Row(
|
||||
|
||||
@ -406,6 +406,7 @@
|
||||
<string name="notices_tab_geo_count">جغرافي · %1$d</string>
|
||||
<string name="notices_tab_mesh_count">mesh · %1$d</string>
|
||||
<string name="notices_description_mesh">ثبّت إعلانات قصيرة لمن حولك. تنتقل من هاتف إلى هاتف حتى دون اتصال، وتختفي وحدها بعد أيام قليلة.</string>
|
||||
<string name="notices_permanent">دائم</string>
|
||||
<string name="notices_fades">يتلاشى %1$s</string>
|
||||
<string name="notices_source_mesh">mesh</string>
|
||||
<string name="notices_source_network">نت</string>
|
||||
|
||||
@ -393,6 +393,7 @@
|
||||
<string name="notices_tab_geo_count">এলাকা · %1$d</string>
|
||||
<string name="notices_tab_mesh_count">mesh · %1$d</string>
|
||||
<string name="notices_description_mesh">আশেপাশের মানুষের জন্য ছোট নোটিশ পিন করুন। অফলাইনেও ফোন থেকে ফোনে পৌঁছে যায় আর কয়েক দিন পরে নিজে থেকেই মুছে যায়।</string>
|
||||
<string name="notices_permanent">স্থায়ী</string>
|
||||
<string name="notices_fades">%1$s মুছে যাবে</string>
|
||||
<string name="notices_source_mesh">mesh</string>
|
||||
<string name="notices_source_network">নেট</string>
|
||||
|
||||
@ -407,6 +407,7 @@
|
||||
<string name="notices_tab_geo_count">geo · %1$d</string>
|
||||
<string name="notices_tab_mesh_count">mesh · %1$d</string>
|
||||
<string name="notices_description_mesh">hefte kurze hinweise für leute in deiner nähe an. sie springen von handy zu handy, auch offline, und verschwinden nach ein paar tagen von selbst.</string>
|
||||
<string name="notices_permanent">dauerhaft</string>
|
||||
<string name="notices_fades">verblasst %1$s</string>
|
||||
<string name="notices_source_mesh">mesh</string>
|
||||
<string name="notices_source_network">netz</string>
|
||||
|
||||
@ -406,6 +406,7 @@
|
||||
<string name="notices_tab_geo_count">geo · %1$d</string>
|
||||
<string name="notices_tab_mesh_count">mesh · %1$d</string>
|
||||
<string name="notices_description_mesh">fija avisos cortos para la gente cercana. saltan de teléfono a teléfono, incluso sin conexión, y desaparecen solos después de unos días.</string>
|
||||
<string name="notices_permanent">permanente</string>
|
||||
<string name="notices_fades">se desvanece %1$s</string>
|
||||
<string name="notices_source_mesh">mesh</string>
|
||||
<string name="notices_source_network">red</string>
|
||||
|
||||
@ -393,6 +393,7 @@
|
||||
<string name="notices_tab_geo_count">ژئو · %1$d</string>
|
||||
<string name="notices_tab_mesh_count">مش · %1$d</string>
|
||||
<string name="notices_description_mesh">اطلاعیههای کوتاه برای اطرافیانتان سنجاق کنید. گوشی به گوشی جابهجا میشوند، حتی آفلاین، و بعد از چند روز خودبهخود ناپدید میشوند.</string>
|
||||
<string name="notices_permanent">دائمی</string>
|
||||
<string name="notices_fades">%1$s محو میشود</string>
|
||||
<string name="notices_source_mesh">مش</string>
|
||||
<string name="notices_source_network">نت</string>
|
||||
|
||||
@ -406,6 +406,7 @@
|
||||
<string name="notices_tab_geo_count">geo · %1$d</string>
|
||||
<string name="notices_tab_mesh_count">mesh · %1$d</string>
|
||||
<string name="notices_description_mesh">mag-pin ng maiikling paunawa para sa mga taong nasa paligid mo. lumilipat ito mula sa isang telepono patungo sa iba, kahit offline, at kusang nawawala pagkatapos ng ilang araw.</string>
|
||||
<string name="notices_permanent">permanente</string>
|
||||
<string name="notices_fades">maglalaho %1$s</string>
|
||||
<string name="notices_source_mesh">mesh</string>
|
||||
<string name="notices_source_network">net</string>
|
||||
|
||||
@ -420,6 +420,7 @@
|
||||
<string name="notices_tab_geo_count">géo · %1$d</string>
|
||||
<string name="notices_tab_mesh_count">mesh · %1$d</string>
|
||||
<string name="notices_description_mesh">épingle de courtes annonces pour les gens autour de toi. elles passent de téléphone en téléphone, même hors ligne, et disparaissent d\'elles-mêmes après quelques jours.</string>
|
||||
<string name="notices_permanent">permanent</string>
|
||||
<string name="notices_fades">s\'efface %1$s</string>
|
||||
<string name="notices_source_mesh">mesh</string>
|
||||
<string name="notices_source_network">net</string>
|
||||
|
||||
@ -59,6 +59,7 @@
|
||||
<string name="notices_tab_geo_count">אזור · %1$d</string>
|
||||
<string name="notices_tab_mesh_count">mesh · %1$d</string>
|
||||
<string name="notices_description_mesh">הצמד מודעות קצרות לאנשים סביבך. הן עוברות מטלפון לטלפון, גם בלי אינטרנט, ונעלמות מעצמן אחרי כמה ימים.</string>
|
||||
<string name="notices_permanent">קבוע</string>
|
||||
<string name="notices_fades">דוהה %1$s</string>
|
||||
<string name="notices_source_mesh">mesh</string>
|
||||
<string name="notices_source_network">רשת</string>
|
||||
|
||||
@ -406,6 +406,7 @@
|
||||
<string name="notices_tab_geo_count">क्षेत्र · %1$d</string>
|
||||
<string name="notices_tab_mesh_count">mesh · %1$d</string>
|
||||
<string name="notices_description_mesh">आस-पास के लोगों के लिए छोटी सूचनाएँ पिन करें। ये ऑफ़लाइन भी फ़ोन से फ़ोन तक पहुँचती हैं और कुछ दिनों बाद अपने आप मिट जाती हैं।</string>
|
||||
<string name="notices_permanent">स्थायी</string>
|
||||
<string name="notices_fades">%1$s मिट जाएगा</string>
|
||||
<string name="notices_source_mesh">mesh</string>
|
||||
<string name="notices_source_network">नेट</string>
|
||||
|
||||
@ -406,6 +406,7 @@
|
||||
<string name="notices_tab_geo_count">area · %1$d</string>
|
||||
<string name="notices_tab_mesh_count">mesh · %1$d</string>
|
||||
<string name="notices_description_mesh">sematkan pengumuman singkat untuk orang di sekitarmu. berpindah dari ponsel ke ponsel, bahkan saat offline, dan hilang sendiri setelah beberapa hari.</string>
|
||||
<string name="notices_permanent">permanen</string>
|
||||
<string name="notices_fades">memudar %1$s</string>
|
||||
<string name="notices_source_mesh">mesh</string>
|
||||
<string name="notices_source_network">net</string>
|
||||
|
||||
@ -440,6 +440,7 @@
|
||||
<string name="notices_tab_geo_count">geo · %1$d</string>
|
||||
<string name="notices_tab_mesh_count">mesh · %1$d</string>
|
||||
<string name="notices_description_mesh">appunta brevi avvisi per chi ti sta intorno. passano da telefono a telefono, anche offline, e spariscono da soli dopo qualche giorno.</string>
|
||||
<string name="notices_permanent">permanente</string>
|
||||
<string name="notices_fades">svanisce %1$s</string>
|
||||
<string name="notices_source_mesh">mesh</string>
|
||||
<string name="notices_source_network">rete</string>
|
||||
|
||||
@ -406,6 +406,7 @@
|
||||
<string name="notices_tab_geo_count">エリア · %1$d</string>
|
||||
<string name="notices_tab_mesh_count">mesh · %1$d</string>
|
||||
<string name="notices_description_mesh">近くの人に向けて短いお知らせをピン留め。オフラインでもスマホからスマホへ伝わり、数日後に自動的に消えます。</string>
|
||||
<string name="notices_permanent">無期限</string>
|
||||
<string name="notices_fades">%1$sに消えます</string>
|
||||
<string name="notices_source_mesh">mesh</string>
|
||||
<string name="notices_source_network">ネット</string>
|
||||
|
||||
@ -406,6 +406,7 @@
|
||||
<string name="notices_tab_geo_count">지역 · %1$d</string>
|
||||
<string name="notices_tab_mesh_count">mesh · %1$d</string>
|
||||
<string name="notices_description_mesh">주변 사람들을 위해 짧은 공지를 고정하세요. 오프라인에서도 휴대폰에서 휴대폰으로 전달되고 며칠 후 스스로 사라집니다.</string>
|
||||
<string name="notices_permanent">영구</string>
|
||||
<string name="notices_fades">%1$s 사라짐</string>
|
||||
<string name="notices_source_mesh">mesh</string>
|
||||
<string name="notices_source_network">넷</string>
|
||||
|
||||
@ -46,6 +46,7 @@
|
||||
<string name="notices_tab_geo_count">kawasan · %1$d</string>
|
||||
<string name="notices_tab_mesh_count">mesh · %1$d</string>
|
||||
<string name="notices_description_mesh">semat pengumuman ringkas untuk orang di sekeliling anda. ia berpindah dari telefon ke telefon, walaupun di luar talian, dan hilang sendiri selepas beberapa hari.</string>
|
||||
<string name="notices_permanent">kekal</string>
|
||||
<string name="notices_fades">pudar %1$s</string>
|
||||
<string name="notices_source_mesh">mesh</string>
|
||||
<string name="notices_source_network">net</string>
|
||||
|
||||
@ -406,6 +406,7 @@
|
||||
<string name="notices_tab_geo_count">क्षेत्र · %1$d</string>
|
||||
<string name="notices_tab_mesh_count">mesh · %1$d</string>
|
||||
<string name="notices_description_mesh">वरपरका मानिसहरूका लागि छोटा सूचना पिन गर। अफलाइनमा पनि फोनबाट फोनमा पुग्छन् र केही दिनपछि आफैँ हराउँछन्।</string>
|
||||
<string name="notices_permanent">स्थायी</string>
|
||||
<string name="notices_fades">%1$s मेटिन्छ</string>
|
||||
<string name="notices_source_mesh">mesh</string>
|
||||
<string name="notices_source_network">नेट</string>
|
||||
|
||||
@ -438,6 +438,7 @@
|
||||
<string name="notices_tab_geo_count">geo · %1$d</string>
|
||||
<string name="notices_tab_mesh_count">mesh · %1$d</string>
|
||||
<string name="notices_description_mesh">prik korte mededelingen voor mensen om je heen. ze springen van telefoon naar telefoon, ook offline, en verdwijnen vanzelf na een paar dagen.</string>
|
||||
<string name="notices_permanent">permanent</string>
|
||||
<string name="notices_fades">vervaagt %1$s</string>
|
||||
<string name="notices_source_mesh">mesh</string>
|
||||
<string name="notices_source_network">net</string>
|
||||
|
||||
@ -59,6 +59,7 @@
|
||||
<string name="notices_tab_geo_count">geo · %1$d</string>
|
||||
<string name="notices_tab_mesh_count">mesh · %1$d</string>
|
||||
<string name="notices_description_mesh">przypinaj krótkie ogłoszenia dla ludzi w pobliżu. przeskakują z telefonu na telefon, nawet offline, i same znikają po kilku dniach.</string>
|
||||
<string name="notices_permanent">na stałe</string>
|
||||
<string name="notices_fades">zniknie %1$s</string>
|
||||
<string name="notices_source_mesh">mesh</string>
|
||||
<string name="notices_source_network">sieć</string>
|
||||
|
||||
@ -406,6 +406,7 @@
|
||||
<string name="notices_tab_geo_count">geo · %1$d</string>
|
||||
<string name="notices_tab_mesh_count">mesh · %1$d</string>
|
||||
<string name="notices_description_mesh">fixe avisos curtos para as pessoas por perto. eles pulam de celular em celular, mesmo offline, e somem sozinhos depois de alguns dias.</string>
|
||||
<string name="notices_permanent">permanente</string>
|
||||
<string name="notices_fades">desaparece %1$s</string>
|
||||
<string name="notices_source_mesh">mesh</string>
|
||||
<string name="notices_source_network">rede</string>
|
||||
|
||||
@ -406,6 +406,7 @@
|
||||
<string name="notices_tab_geo_count">geo · %1$d</string>
|
||||
<string name="notices_tab_mesh_count">mesh · %1$d</string>
|
||||
<string name="notices_description_mesh">afixa avisos curtos para quem está por perto. saltam de telemóvel em telemóvel, mesmo offline, e desaparecem sozinhos após alguns dias.</string>
|
||||
<string name="notices_permanent">permanente</string>
|
||||
<string name="notices_fades">desvanece %1$s</string>
|
||||
<string name="notices_source_mesh">mesh</string>
|
||||
<string name="notices_source_network">rede</string>
|
||||
|
||||
@ -396,6 +396,7 @@
|
||||
<string name="notices_tab_geo_count">гео · %1$d</string>
|
||||
<string name="notices_tab_mesh_count">mesh · %1$d</string>
|
||||
<string name="notices_description_mesh">закрепляй короткие объявления для людей рядом. они передаются с телефона на телефон, даже офлайн, и сами исчезают через несколько дней.</string>
|
||||
<string name="notices_permanent">навсегда</string>
|
||||
<string name="notices_fades">исчезнет %1$s</string>
|
||||
<string name="notices_source_mesh">mesh</string>
|
||||
<string name="notices_source_network">сеть</string>
|
||||
|
||||
@ -394,6 +394,7 @@
|
||||
<string name="notices_tab_geo_count">geo · %1$d</string>
|
||||
<string name="notices_tab_mesh_count">mesh · %1$d</string>
|
||||
<string name="notices_description_mesh">nåla upp korta anslag för folk i närheten. de hoppar från telefon till telefon, även offline, och försvinner av sig själva efter några dagar.</string>
|
||||
<string name="notices_permanent">permanent</string>
|
||||
<string name="notices_fades">tonar bort %1$s</string>
|
||||
<string name="notices_source_mesh">mesh</string>
|
||||
<string name="notices_source_network">nät</string>
|
||||
|
||||
@ -46,6 +46,7 @@
|
||||
<string name="notices_tab_geo_count">பகுதி · %1$d</string>
|
||||
<string name="notices_tab_mesh_count">mesh · %1$d</string>
|
||||
<string name="notices_description_mesh">அருகிலுள்ளவர்களுக்காக சிறிய அறிவிப்புகளைப் பின் செய்யவும். ஆஃப்லைனிலும் ஃபோனிலிருந்து ஃபோனுக்குப் பரவி, சில நாட்களில் தானாக மறைந்துவிடும்.</string>
|
||||
<string name="notices_permanent">நிரந்தரம்</string>
|
||||
<string name="notices_fades">%1$s மறையும்</string>
|
||||
<string name="notices_source_mesh">mesh</string>
|
||||
<string name="notices_source_network">நெட்</string>
|
||||
|
||||
@ -393,6 +393,7 @@
|
||||
<string name="notices_tab_geo_count">พื้นที่ · %1$d</string>
|
||||
<string name="notices_tab_mesh_count">mesh · %1$d</string>
|
||||
<string name="notices_description_mesh">ปักประกาศสั้น ๆ ให้คนรอบตัว ส่งต่อจากมือถือสู่มือถือได้แม้ออฟไลน์ และหายไปเองหลังผ่านไปสองสามวัน</string>
|
||||
<string name="notices_permanent">ถาวร</string>
|
||||
<string name="notices_fades">เลือนหาย %1$s</string>
|
||||
<string name="notices_source_mesh">mesh</string>
|
||||
<string name="notices_source_network">เน็ต</string>
|
||||
|
||||
@ -394,6 +394,7 @@
|
||||
<string name="notices_tab_geo_count">bölge · %1$d</string>
|
||||
<string name="notices_tab_mesh_count">mesh · %1$d</string>
|
||||
<string name="notices_description_mesh">çevrendekiler için kısa duyurular sabitle. çevrimdışıyken bile telefondan telefona geçer ve birkaç gün sonra kendiliğinden kaybolur.</string>
|
||||
<string name="notices_permanent">kalıcı</string>
|
||||
<string name="notices_fades">%1$s kaybolur</string>
|
||||
<string name="notices_source_mesh">mesh</string>
|
||||
<string name="notices_source_network">ağ</string>
|
||||
|
||||
@ -46,6 +46,7 @@
|
||||
<string name="notices_tab_geo_count">гео · %1$d</string>
|
||||
<string name="notices_tab_mesh_count">mesh · %1$d</string>
|
||||
<string name="notices_description_mesh">закріплюй короткі оголошення для людей поруч. вони передаються з телефона на телефон, навіть офлайн, і самі зникають за кілька днів.</string>
|
||||
<string name="notices_permanent">назавжди</string>
|
||||
<string name="notices_fades">зникне %1$s</string>
|
||||
<string name="notices_source_mesh">mesh</string>
|
||||
<string name="notices_source_network">мережа</string>
|
||||
|
||||
@ -406,6 +406,7 @@
|
||||
<string name="notices_tab_geo_count">علاقہ · %1$d</string>
|
||||
<string name="notices_tab_mesh_count">mesh · %1$d</string>
|
||||
<string name="notices_description_mesh">آس پاس کے لوگوں کیلئے مختصر اعلانات پن کریں۔ یہ آف لائن بھی فون سے فون تک پہنچتے ہیں اور کچھ دنوں بعد خود مٹ جاتے ہیں۔</string>
|
||||
<string name="notices_permanent">مستقل</string>
|
||||
<string name="notices_fades">%1$s مٹ جائے گا</string>
|
||||
<string name="notices_source_mesh">mesh</string>
|
||||
<string name="notices_source_network">نیٹ</string>
|
||||
|
||||
@ -393,6 +393,7 @@
|
||||
<string name="notices_tab_geo_count">khu vực · %1$d</string>
|
||||
<string name="notices_tab_mesh_count">mesh · %1$d</string>
|
||||
<string name="notices_description_mesh">ghim thông báo ngắn cho những người quanh bạn. chúng truyền từ điện thoại này sang điện thoại khác, kể cả khi ngoại tuyến, và tự biến mất sau vài ngày.</string>
|
||||
<string name="notices_permanent">vĩnh viễn</string>
|
||||
<string name="notices_fades">mờ dần %1$s</string>
|
||||
<string name="notices_source_mesh">mesh</string>
|
||||
<string name="notices_source_network">mạng</string>
|
||||
|
||||
@ -59,6 +59,7 @@
|
||||
<string name="notices_tab_geo_count">区域 · %1$d</string>
|
||||
<string name="notices_tab_mesh_count">mesh · %1$d</string>
|
||||
<string name="notices_description_mesh">为周围的人钉上简短公告。即使离线也能在手机间传递,几天后自动消失。</string>
|
||||
<string name="notices_permanent">永久</string>
|
||||
<string name="notices_fades">%1$s消失</string>
|
||||
<string name="notices_source_mesh">mesh</string>
|
||||
<string name="notices_source_network">网络</string>
|
||||
|
||||
@ -59,6 +59,7 @@
|
||||
<string name="notices_tab_geo_count">區域 · %1$d</string>
|
||||
<string name="notices_tab_mesh_count">mesh · %1$d</string>
|
||||
<string name="notices_description_mesh">為周圍的人釘上簡短公告。即使離線也能在手機間傳遞,幾天後自動消失。</string>
|
||||
<string name="notices_permanent">永久</string>
|
||||
<string name="notices_fades">%1$s消失</string>
|
||||
<string name="notices_source_mesh">mesh</string>
|
||||
<string name="notices_source_network">網路</string>
|
||||
|
||||
@ -419,6 +419,7 @@
|
||||
<string name="notices_tab_geo_count">区域 · %1$d</string>
|
||||
<string name="notices_tab_mesh_count">mesh · %1$d</string>
|
||||
<string name="notices_description_mesh">为周围的人钉上简短公告。即使离线也能在手机间传递,几天后自动消失。</string>
|
||||
<string name="notices_permanent">永久</string>
|
||||
<string name="notices_fades">%1$s消失</string>
|
||||
<string name="notices_source_mesh">mesh</string>
|
||||
<string name="notices_source_network">网络</string>
|
||||
|
||||
@ -258,6 +258,7 @@
|
||||
<string name="notices_delete" tools:ignore="MissingTranslation">Delete notice</string>
|
||||
<string name="notices_expiry" tools:ignore="MissingTranslation">expires</string>
|
||||
<string name="notices_days" tools:ignore="MissingTranslation,PluralsCandidate">%1$d days</string>
|
||||
<string name="notices_permanent" tools:ignore="MissingTranslation">permanent</string>
|
||||
<string name="notices_fades" tools:ignore="MissingTranslation">fades %1$s</string>
|
||||
<string name="notices_source_mesh" tools:ignore="MissingTranslation">mesh</string>
|
||||
<string name="notices_source_network" tools:ignore="MissingTranslation">net</string>
|
||||
|
||||
@ -5,6 +5,7 @@ import com.bitchat.android.protocol.MessageType
|
||||
import org.bouncycastle.crypto.params.Ed25519PrivateKeyParameters
|
||||
import org.bouncycastle.crypto.signers.Ed25519Signer
|
||||
import org.junit.Assert.assertEquals
|
||||
import org.junit.Assert.assertFalse
|
||||
import org.junit.Assert.assertTrue
|
||||
import org.junit.Rule
|
||||
import org.junit.Test
|
||||
@ -70,6 +71,48 @@ class BoardStoreTest {
|
||||
assertEquals(1, store.syncCandidates().size)
|
||||
}
|
||||
|
||||
@Test
|
||||
fun `rewrapped duplicate payload is stored but never relayed again`() {
|
||||
val store = BoardStore(nowMs = { now })
|
||||
val wire = BoardWire.Post(signedPost())
|
||||
val firstOuterPacket = packet(wire)
|
||||
|
||||
assertTrue(store.ingestRemoteForRelay(wire, firstOuterPacket))
|
||||
assertFalse(
|
||||
store.ingestRemoteForRelay(
|
||||
wire,
|
||||
firstOuterPacket.copy(timestamp = firstOuterPacket.timestamp + 1uL)
|
||||
)
|
||||
)
|
||||
assertEquals(1, store.posts("").size)
|
||||
}
|
||||
|
||||
@Test
|
||||
fun `attacker orphan tombstone cannot block author deletion`() {
|
||||
val store = BoardStore(nowMs = { now })
|
||||
val post = signedPost()
|
||||
val attackerTombstone = signedTombstone(post, attacker)
|
||||
|
||||
assertEquals(
|
||||
BoardIngestResult.ACCEPTED,
|
||||
store.ingestTombstone(attackerTombstone)
|
||||
)
|
||||
assertEquals(BoardIngestResult.ACCEPTED, store.ingestPost(post))
|
||||
|
||||
val authorTombstone = signedTombstone(post, author, deletedAt = now + 1uL)
|
||||
assertEquals(
|
||||
BoardIngestResult.ACCEPTED,
|
||||
store.ingestTombstone(authorTombstone)
|
||||
)
|
||||
|
||||
assertTrue(store.posts("").isEmpty())
|
||||
assertEquals(2, store.syncCandidates().size)
|
||||
assertEquals(
|
||||
BoardIngestResult.DUPLICATE,
|
||||
store.ingestTombstone(attackerTombstone)
|
||||
)
|
||||
}
|
||||
|
||||
@Test
|
||||
fun `tombstone suppresses a stale copy until original expiry`() {
|
||||
val store = BoardStore(nowMs = { now })
|
||||
|
||||
@ -0,0 +1,40 @@
|
||||
package com.bitchat.android.ui
|
||||
|
||||
import org.junit.Assert.assertEquals
|
||||
import org.junit.Assert.assertFalse
|
||||
import org.junit.Assert.assertTrue
|
||||
import org.junit.Test
|
||||
|
||||
class NoticeComposerPolicyTest {
|
||||
@Test
|
||||
fun `geo offers permanent and finite board lifetimes`() {
|
||||
assertEquals(listOf(0, 1, 3, 7), NoticeComposerPolicy.expiryOptions(isGeo = true))
|
||||
}
|
||||
|
||||
@Test
|
||||
fun `mesh offers only finite board lifetimes`() {
|
||||
assertEquals(listOf(1, 3, 7), NoticeComposerPolicy.expiryOptions(isGeo = false))
|
||||
}
|
||||
|
||||
@Test
|
||||
fun `only permanent geo selection skips the board`() {
|
||||
assertTrue(
|
||||
NoticeComposerPolicy.isPermanentRelayOnlyGeo(
|
||||
isGeo = true,
|
||||
expiryDays = 0
|
||||
)
|
||||
)
|
||||
assertFalse(
|
||||
NoticeComposerPolicy.isPermanentRelayOnlyGeo(
|
||||
isGeo = true,
|
||||
expiryDays = 1
|
||||
)
|
||||
)
|
||||
assertFalse(
|
||||
NoticeComposerPolicy.isPermanentRelayOnlyGeo(
|
||||
isGeo = false,
|
||||
expiryDays = 1
|
||||
)
|
||||
)
|
||||
}
|
||||
}
|
||||
Loading…
x
Reference in New Issue
Block a user