feat: add conversation settings activity

pull/1403/head
0x330a 3 years ago
parent 35902e5047
commit 00ed94a930

@ -0,0 +1,32 @@
package org.thoughtcrime.securesms.conversation.settings
import android.content.Context
import android.content.Intent
import android.os.Bundle
import androidx.activity.viewModels
import dagger.hilt.android.AndroidEntryPoint
import network.loki.messenger.databinding.ActivityConversationSettingsBinding
import org.thoughtcrime.securesms.PassphraseRequiredActionBarActivity
import org.thoughtcrime.securesms.conversation.v2.utilities.BaseDialog
import org.thoughtcrime.securesms.util.ActivityDispatcher
@AndroidEntryPoint
class ConversationSettingsActivity: PassphraseRequiredActionBarActivity(), ActivityDispatcher {
lateinit var binding: ActivityConversationSettingsBinding
val viewModel: ConversationSettingsViewModel by viewModels()
override fun dispatchIntent(body: (Context) -> Intent?) {
TODO()
}
override fun showDialog(baseDialog: BaseDialog, tag: String?) {
TODO()
}
override fun onCreate(savedInstanceState: Bundle?, ready: Boolean) {
super.onCreate(savedInstanceState, ready)
binding = ActivityConversationSettingsBinding.inflate(layoutInflater)
}
}

@ -0,0 +1,9 @@
package org.thoughtcrime.securesms.conversation.settings
import androidx.lifecycle.ViewModel
class ConversationSettingsViewModel: ViewModel() {
}

@ -0,0 +1,21 @@
<?xml version="1.0" encoding="utf-8"?>
<ScrollView xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent"
xmlns:app="http://schemas.android.com/apk/res-auto">
<androidx.constraintlayout.widget.ConstraintLayout
android:layout_width="match_parent"
android:layout_height="wrap_content">
<include
android:id="@+id/profilePictureView"
layout="@layout/view_profile_picture"
android:layout_height="120dp"
android:layout_width="120dp"
app:layout_constraintTop_toTopOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintEnd_toEndOf="parent"
android:layout_marginTop="@dimen/small_profile_picture_size"
/>
</androidx.constraintlayout.widget.ConstraintLayout>
</ScrollView>

@ -1,11 +1,14 @@
package org.session.libsession.utilities.bencode package org.session.libsession.utilities.bencode
import org.session.libsession.utilities.bencode.Bencode.Decoder.Companion.DICT_INDICATOR
import org.session.libsession.utilities.bencode.Bencode.Decoder.Companion.END_INDICATOR
import org.session.libsession.utilities.bencode.Bencode.Decoder.Companion.LIST_INDICATOR
import java.util.LinkedList import java.util.LinkedList
object Bencode { object Bencode {
class Decoder(source: CharArray) { class Decoder(source: ByteArray) {
private val iterator = LinkedList<Char>().apply { private val iterator = LinkedList<Byte>().apply {
addAll(source.asIterable()) addAll(source.asIterable())
} }
@ -29,14 +32,14 @@ object Bencode {
* Decode a string element from iterator assumed to have structure `{length}:{data}` * Decode a string element from iterator assumed to have structure `{length}:{data}`
*/ */
private fun decodeString(): BencodeString? { private fun decodeString(): BencodeString? {
val lengthStrings = buildString { val lengthStrings = buildList<Byte> {
while (iterator.isNotEmpty() && iterator.peek() != SEPARATOR) { while (iterator.isNotEmpty() && iterator.peek() != SEPARATOR) {
append(iterator.pop()) add(iterator.pop())
} }
}.toCharArray() }.toByteArray()
iterator.pop() // drop `:` iterator.pop() // drop `:`
val length = String(lengthStrings).toIntOrNull(10) ?: return null val length = lengthStrings.decodeToString().toIntOrNull(10) ?: return null
val remaining = (0 until length).map { iterator.pop() }.toCharArray() val remaining = (0 until length).map { iterator.pop() }.toByteArray()
return BencodeString(String(remaining)) return BencodeString(String(remaining))
} }
@ -45,12 +48,12 @@ object Bencode {
*/ */
private fun decodeInt(): BencodeElement? { private fun decodeInt(): BencodeElement? {
iterator.pop() // drop `i` iterator.pop() // drop `i`
val intString = buildString { val intString = buildList<Byte> {
while (iterator.isNotEmpty() && iterator.peek() != END_INDICATOR) { while (iterator.isNotEmpty() && iterator.peek() != END_INDICATOR) {
append(iterator.pop()) add(iterator.pop())
} }
} }.toByteArray()
val asInt = intString.toIntOrNull(10) ?: return null val asInt = intString.decodeToString().toIntOrNull(10) ?: return null
iterator.pop() // drop `e` iterator.pop() // drop `e`
return BencodeInteger(asInt) return BencodeInteger(asInt)
} }
@ -86,12 +89,12 @@ object Bencode {
} }
companion object { companion object {
private val NUMBERS = arrayOf('0', '1', '2', '3', '4', '5', '6', '7', '8', '9') val NUMBERS = arrayOf('0', '1', '2', '3', '4', '5', '6', '7', '8', '9').map { it.code.toByte() }
private const val INT_INDICATOR = 'i' const val INT_INDICATOR = 'i'.code.toByte()
private const val LIST_INDICATOR = 'l' const val LIST_INDICATOR = 'l'.code.toByte()
private const val DICT_INDICATOR = 'd' const val DICT_INDICATOR = 'd'.code.toByte()
private const val END_INDICATOR = 'e' const val END_INDICATOR = 'e'.code.toByte()
private const val SEPARATOR = ':' const val SEPARATOR = ':'.code.toByte()
} }
} }
@ -99,48 +102,50 @@ object Bencode {
} }
sealed class BencodeElement { sealed class BencodeElement {
abstract fun encode(): CharArray abstract fun encode(): ByteArray
} }
fun String.bencode() = BencodeString(this) fun String.bencode() = BencodeString(this)
fun Int.bencode() = BencodeInteger(this) fun Int.bencode() = BencodeInteger(this)
data class BencodeString(val value: String): BencodeElement() { data class BencodeString(val value: String): BencodeElement() {
override fun encode(): CharArray = buildString { override fun encode(): ByteArray = buildString {
append(value.length.toString()) append(value.length.toString())
append(':') append(':')
append(value) append(value)
}.toCharArray() }.toByteArray()
} }
data class BencodeInteger(val value: Int): BencodeElement() { data class BencodeInteger(val value: Int): BencodeElement() {
override fun encode(): CharArray = buildString { override fun encode(): ByteArray = buildString {
append('i') append('i')
append(value) append(value)
append('e') append('e')
}.toCharArray() }.toByteArray()
} }
data class BencodeList(val values: List<BencodeElement>): BencodeElement() { data class BencodeList(val values: List<BencodeElement>): BencodeElement() {
constructor(vararg values: BencodeElement) : this(values.toList()) constructor(vararg values: BencodeElement) : this(values.toList())
override fun encode(): CharArray = buildString { override fun encode(): ByteArray = buildList {
append('l') add(LIST_INDICATOR)
for (value in values) { for (value in values) {
append(value.encode()) addAll(value.encode().toTypedArray())
} }
append('e') add(END_INDICATOR)
}.toCharArray() }.toByteArray()
} }
data class BencodeDict(val values: Map<String, BencodeElement>): BencodeElement() { data class BencodeDict(val values: Map<String, BencodeElement>): BencodeElement() {
constructor(vararg values: Pair<String, BencodeElement>) : this(values.toMap()) constructor(vararg values: Pair<String, BencodeElement>) : this(values.toMap())
override fun encode(): CharArray = buildString { override fun encode(): ByteArray = buildList {
append('d') add(DICT_INDICATOR)
for ((key, value) in values) { for ((key, value) in values) {
append(BencodeString(key).encode()) addAll(BencodeString(key).encode().toTypedArray())
append(value.encode()) addAll(value.encode().toTypedArray())
} }
append('e') add(END_INDICATOR)
}.toCharArray() }.toByteArray()
} }

@ -13,7 +13,7 @@ class BencoderTest {
@Test @Test
fun `it should decode a basic string`() { fun `it should decode a basic string`() {
val basicString = "5:howdy".toCharArray() val basicString = "5:howdy".toByteArray()
val bencoder = Bencode.Decoder(basicString) val bencoder = Bencode.Decoder(basicString)
val result = bencoder.decode() val result = bencoder.decode()
assertEquals("howdy".bencode(), result) assertEquals("howdy".bencode(), result)
@ -21,7 +21,7 @@ class BencoderTest {
@Test @Test
fun `it should decode a basic integer`() { fun `it should decode a basic integer`() {
val basicInteger = "i3e".toCharArray() val basicInteger = "i3e".toByteArray()
val bencoder = Bencode.Decoder(basicInteger) val bencoder = Bencode.Decoder(basicInteger)
val result = bencoder.decode() val result = bencoder.decode()
assertEquals(BencodeInteger(3), result) assertEquals(BencodeInteger(3), result)
@ -29,7 +29,7 @@ class BencoderTest {
@Test @Test
fun `it should decode a list of integers`() { fun `it should decode a list of integers`() {
val basicIntList = "li1ei2ee".toCharArray() val basicIntList = "li1ei2ee".toByteArray()
val bencoder = Bencode.Decoder(basicIntList) val bencoder = Bencode.Decoder(basicIntList)
val result = bencoder.decode() val result = bencoder.decode()
assertEquals( assertEquals(
@ -43,7 +43,7 @@ class BencoderTest {
@Test @Test
fun `it should decode a basic dict`() { fun `it should decode a basic dict`() {
val basicDict = "d4:spaml1:a1:bee".toCharArray() val basicDict = "d4:spaml1:a1:bee".toByteArray()
val bencoder = Bencode.Decoder(basicDict) val bencoder = Bencode.Decoder(basicDict)
val result = bencoder.decode() val result = bencoder.decode()
assertEquals( assertEquals(
@ -59,28 +59,28 @@ class BencoderTest {
@Test @Test
fun `it should encode a basic string`() { fun `it should encode a basic string`() {
val basicString = "5:howdy".toCharArray() val basicString = "5:howdy".toByteArray()
val element = "howdy".bencode() val element = "howdy".bencode()
assertArrayEquals(basicString, element.encode()) assertArrayEquals(basicString, element.encode())
} }
@Test @Test
fun `it should encode a basic int`() { fun `it should encode a basic int`() {
val basicInt = "i3e".toCharArray() val basicInt = "i3e".toByteArray()
val element = 3.bencode() val element = 3.bencode()
assertArrayEquals(basicInt, element.encode()) assertArrayEquals(basicInt, element.encode())
} }
@Test @Test
fun `it should encode a basic list`() { fun `it should encode a basic list`() {
val basicList = "li1ei2ee".toCharArray() val basicList = "li1ei2ee".toByteArray()
val element = BencodeList(1.bencode(),2.bencode()) val element = BencodeList(1.bencode(),2.bencode())
assertArrayEquals(basicList, element.encode()) assertArrayEquals(basicList, element.encode())
} }
@Test @Test
fun `it should encode a basic dict`() { fun `it should encode a basic dict`() {
val basicDict = "d4:spaml1:a1:bee".toCharArray() val basicDict = "d4:spaml1:a1:bee".toByteArray()
val element = BencodeDict( val element = BencodeDict(
"spam" to BencodeList( "spam" to BencodeList(
"a".bencode(), "a".bencode(),
@ -92,7 +92,7 @@ class BencoderTest {
@Test @Test
fun `it should encode a more complex real world case`() { fun `it should encode a more complex real world case`() {
val source = "d15:lastReadMessaged66:031122334455667788990011223344556677889900112233445566778899001122i1234568790e66:051122334455667788990011223344556677889900112233445566778899001122i1234568790ee5:seqNoi1ee".toCharArray() val source = "d15:lastReadMessaged66:031122334455667788990011223344556677889900112233445566778899001122i1234568790e66:051122334455667788990011223344556677889900112233445566778899001122i1234568790ee5:seqNoi1ee".toByteArray()
val result = Bencode.Decoder(source).decode() val result = Bencode.Decoder(source).decode()
val expected = BencodeDict( val expected = BencodeDict(
"lastReadMessage" to BencodeDict( "lastReadMessage" to BencodeDict(

Loading…
Cancel
Save