Browse Source

Try some stuff on room list and avatar...

feature/bma/flipper
ganfra 2 years ago
parent
commit
14992cb63a
  1. 2
      app/src/main/java/io/element/android/x/MainActivity.kt
  2. 66
      features/roomlist/src/main/java/io/element/android/x/features/roomlist/RoomListScreen.kt
  3. 2
      gradle/libs.versions.toml
  4. 1
      libraries/avatar/.gitignore
  5. 12
      libraries/avatar/build.gradle.kts
  6. 0
      libraries/avatar/consumer-rules.pro
  7. 21
      libraries/avatar/proguard-rules.pro
  8. 24
      libraries/avatar/src/androidTest/java/io/element/android/x/avatar/ExampleInstrumentedTest.kt
  9. 4
      libraries/avatar/src/main/AndroidManifest.xml
  10. 33
      libraries/avatar/src/main/java/io/element/android/x/avatar/Avatar.kt
  11. 10
      libraries/avatar/src/main/java/io/element/android/x/avatar/AvatarData.kt
  12. 41
      libraries/avatar/src/main/java/io/element/android/x/avatar/AvatarFetcher.kt
  13. 17
      libraries/avatar/src/test/java/io/element/android/x/avatar/ExampleUnitTest.kt
  14. 4
      libraries/designsystem/src/main/java/io/element/android/x/designsystem/Color.kt
  15. 2
      libraries/matrix/src/main/java/io/element/android/x/matrix/room/RoomSummary.kt
  16. 2
      libraries/matrix/src/main/java/io/element/android/x/matrix/room/RoomSummaryDataSource.kt
  17. 1
      settings.gradle.kts

2
app/src/main/java/io/element/android/x/MainActivity.kt

@ -23,7 +23,7 @@ class MainActivity : ComponentActivity() { @@ -23,7 +23,7 @@ class MainActivity : ComponentActivity() {
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContent {
ElementXTheme {
ElementXTheme(darkTheme = false) {
MainScreen(viewModel = viewModel)
}
}

66
features/roomlist/src/main/java/io/element/android/x/features/roomlist/RoomListScreen.kt

@ -1,22 +1,30 @@ @@ -1,22 +1,30 @@
package io.element.android.x.features.roomlist
import android.widget.Space
import androidx.compose.foundation.clickable
import androidx.compose.foundation.interaction.MutableInteractionSource
import androidx.compose.foundation.layout.*
import androidx.compose.foundation.lazy.LazyColumn
import androidx.compose.foundation.lazy.items
import androidx.compose.material.icons.Icons
import androidx.compose.material.icons.filled.ExitToApp
import androidx.compose.material.ripple.rememberRipple
import androidx.compose.material3.*
import androidx.compose.runtime.Composable
import androidx.compose.runtime.getValue
import androidx.compose.runtime.remember
import androidx.compose.ui.Alignment
import androidx.compose.ui.Modifier
import androidx.compose.ui.graphics.Color
import androidx.compose.ui.text.font.FontWeight
import androidx.compose.ui.text.style.TextOverflow
import androidx.compose.ui.unit.dp
import androidx.compose.ui.unit.sp
import com.airbnb.mvrx.Success
import com.airbnb.mvrx.compose.collectAsState
import com.airbnb.mvrx.compose.mavericksViewModel
import io.element.android.x.core.data.LogCompositions
import io.element.android.x.designsystem.LightGrey
import io.element.android.x.designsystem.components.Avatar
import io.element.android.x.features.roomlist.model.MatrixUser
import io.element.android.x.matrix.core.RoomId
@ -107,17 +115,59 @@ private fun RoomItem( @@ -107,17 +115,59 @@ private fun RoomItem(
return
}
val details = room.details
Row(verticalAlignment = Alignment.CenterVertically,
Column(
modifier = modifier
.clickable {
onClick(room.details.roomId)
}
.fillMaxWidth()
.padding(horizontal = 8.dp)
.clickable(
onClick = { onClick(room.details.roomId) },
indication = rememberRipple(),
interactionSource = remember { MutableInteractionSource() }
),
) {
Column(modifier = modifier.padding(8.dp)) {
Text(fontSize = 18.sp, text = details.name.orEmpty())
Text(text = details.lastMessage?.toString().orEmpty(), maxLines = 2)
Row(
modifier = Modifier
.fillMaxWidth()
.padding(horizontal = 16.dp),
) {
Box(modifier = Modifier
.align(Alignment.CenterVertically)
) {
Avatar(data = null)
}
Column(
modifier = Modifier
.padding(12.dp)
.weight(1f)
) {
Text(
fontSize = 16.sp,
fontWeight = FontWeight.Bold,
color = Color.Black,
text = details.name,
maxLines = 1,
overflow = TextOverflow.Ellipsis
)
Text(
text = details.lastMessage?.toString().orEmpty(),
color = LightGrey,
maxLines = 1,
overflow = TextOverflow.Ellipsis
)
}
Column(
Modifier
.padding(horizontal = 8.dp)
.align(Alignment.CenterVertically)
) {
Text(
fontSize = 12.sp,
text = "14:18",
color = LightGrey
)
Spacer(Modifier.size(20.dp))
}
}
}
}

2
gradle/libs.versions.toml

@ -32,6 +32,7 @@ test_orchestrator = "1.4.1" @@ -32,6 +32,7 @@ test_orchestrator = "1.4.1"
#other
mavericks = "3.0.1"
timber = "5.0.1"
coil = "2.2.1"
[libraries]
# Project
@ -69,5 +70,6 @@ test_orchestrator = { module = "androidx.test:orchestrator", version.ref = "test @@ -69,5 +70,6 @@ test_orchestrator = { module = "androidx.test:orchestrator", version.ref = "test
mavericks_compose = { module = "com.airbnb.android:mavericks-compose", version.ref = "mavericks" }
timber = { module = "com.jakewharton.timber:timber", version.ref = "timber" }
coil_compose = { module = "io.coil-kt:coil-compose", version.ref = "coil" }
[bundles]

1
libraries/avatar/.gitignore vendored

@ -0,0 +1 @@ @@ -0,0 +1 @@
/build

12
libraries/avatar/build.gradle.kts

@ -0,0 +1,12 @@ @@ -0,0 +1,12 @@
plugins {
id("io.element.android-compose")
}
android {
namespace = "io.element.android.x.libraries.avatar"
}
dependencies {
implementation(project(":libraries:matrix"))
implementation(libs.coil.compose)
}

0
libraries/avatar/consumer-rules.pro

21
libraries/avatar/proguard-rules.pro vendored

@ -0,0 +1,21 @@ @@ -0,0 +1,21 @@
# Add project specific ProGuard rules here.
# You can control the set of applied configuration files using the
# proguardFiles setting in build.gradle.
#
# For more details, see
# http://developer.android.com/guide/developing/tools/proguard.html
# If your project uses WebView with JS, uncomment the following
# and specify the fully qualified class name to the JavaScript interface
# class:
#-keepclassmembers class fqcn.of.javascript.interface.for.webview {
# public *;
#}
# Uncomment this to preserve the line number information for
# debugging stack traces.
#-keepattributes SourceFile,LineNumberTable
# If you keep the line number information, uncomment this to
# hide the original source file name.
#-renamesourcefileattribute SourceFile

24
libraries/avatar/src/androidTest/java/io/element/android/x/avatar/ExampleInstrumentedTest.kt

@ -0,0 +1,24 @@ @@ -0,0 +1,24 @@
package io.element.android.x.avatar
import androidx.test.platform.app.InstrumentationRegistry
import androidx.test.ext.junit.runners.AndroidJUnit4
import org.junit.Test
import org.junit.runner.RunWith
import org.junit.Assert.*
/**
* Instrumented test, which will execute on an Android device.
*
* See [testing documentation](http://d.android.com/tools/testing).
*/
@RunWith(AndroidJUnit4::class)
class ExampleInstrumentedTest {
@Test
fun useAppContext() {
// Context of the app under test.
val appContext = InstrumentationRegistry.getInstrumentation().targetContext
assertEquals("io.element.android.x.avatar.test", appContext.packageName)
}
}

4
libraries/avatar/src/main/AndroidManifest.xml

@ -0,0 +1,4 @@ @@ -0,0 +1,4 @@
<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android">
</manifest>

33
libraries/avatar/src/main/java/io/element/android/x/avatar/Avatar.kt

@ -0,0 +1,33 @@ @@ -0,0 +1,33 @@
package io.element.android.x.avatar
import android.util.Log
import androidx.compose.foundation.Image
import androidx.compose.foundation.border
import androidx.compose.foundation.layout.size
import androidx.compose.foundation.shape.CircleShape
import androidx.compose.material3.MaterialTheme
import androidx.compose.runtime.Composable
import androidx.compose.ui.Modifier
import androidx.compose.ui.draw.clip
import androidx.compose.ui.unit.dp
import coil.compose.rememberAsyncImagePainter
/**
* TODO fallback Avatar
*/
@Composable
fun Avatar(avatarData: AvatarData) {
Image(
painter = rememberAsyncImagePainter(
model = avatarData.url,
onError = {
Log.e("TAG", "Error $it\n${it.result}", it.result.throwable)
}),
contentDescription = null,
modifier = Modifier
.size(avatarData.size)
.clip(CircleShape)
.border(1.5.dp, MaterialTheme.colorScheme.primary, CircleShape)
)
}

10
libraries/avatar/src/main/java/io/element/android/x/avatar/AvatarData.kt

@ -0,0 +1,10 @@ @@ -0,0 +1,10 @@
package io.element.android.x.avatar
import androidx.compose.ui.unit.Dp
import androidx.compose.ui.unit.dp
data class AvatarData(
val url: String,
val size: Dp = 48.dp
)

41
libraries/avatar/src/main/java/io/element/android/x/avatar/AvatarFetcher.kt

@ -0,0 +1,41 @@ @@ -0,0 +1,41 @@
package io.element.android.x.avatar
import coil.ImageLoader
import coil.fetch.FetchResult
import coil.fetch.Fetcher
import coil.request.Options
import io.element.android.x.matrix.MatrixClient
import org.matrix.rustcomponents.sdk.mediaSourceFromUrl
class AvatarFetcher(
private val matrixClient: MatrixClient,
private val avatarData: AvatarData,
private val options: Options,
private val imageLoader: ImageLoader
) :
Fetcher {
override suspend fun fetch(): FetchResult? {
val mediaSource = mediaSourceFromUrl(avatarData.url)
val mediaContent = matrixClient.loadMediaContentForSource(mediaSource)
return mediaContent.fold(
{ mediaContent ->
val byteArray = mediaContent.toUByteArray().toByteArray()
val fetcher = imageLoader.components.newFetcher(byteArray, options, imageLoader)
fetcher?.first?.fetch()
},
{null}
)
}
class Factory(private val matrixClient: MatrixClient) : Fetcher.Factory<AvatarData> {
override fun create(
data: AvatarData,
options: Options,
imageLoader: ImageLoader
): Fetcher? {
return AvatarFetcher(matrixClient, data, options, imageLoader)
}
}
}

17
libraries/avatar/src/test/java/io/element/android/x/avatar/ExampleUnitTest.kt

@ -0,0 +1,17 @@ @@ -0,0 +1,17 @@
package io.element.android.x.avatar
import org.junit.Test
import org.junit.Assert.*
/**
* Example local unit test, which will execute on the development machine (host).
*
* See [testing documentation](http://d.android.com/tools/testing).
*/
class ExampleUnitTest {
@Test
fun addition_isCorrect() {
assertEquals(4, 2 + 2)
}
}

4
libraries/designsystem/src/main/java/io/element/android/x/designsystem/Color.kt

@ -8,4 +8,6 @@ val Pink80 = Color(0xFFEFB8C8) @@ -8,4 +8,6 @@ val Pink80 = Color(0xFFEFB8C8)
val Purple40 = Color(0xFF6650a4)
val PurpleGrey40 = Color(0xFF625b71)
val Pink40 = Color(0xFF7D5260)
val Pink40 = Color(0xFF7D5260)
val LightGrey = Color(0x993C3C43)

2
libraries/matrix/src/main/java/io/element/android/x/matrix/room/RoomSummary.kt

@ -18,7 +18,7 @@ sealed interface RoomSummary { @@ -18,7 +18,7 @@ sealed interface RoomSummary {
data class RoomSummaryDetails(
val roomId: RoomId,
val name: String?,
val name: String,
val isDirect: Boolean,
val avatarURLString: String?,
val lastMessage: CharSequence?,

2
libraries/matrix/src/main/java/io/element/android/x/matrix/room/RoomSummaryDataSource.kt

@ -123,7 +123,7 @@ internal class RustRoomSummaryDataSource( @@ -123,7 +123,7 @@ internal class RustRoomSummaryDataSource(
return RoomSummary.Filled(
details = RoomSummaryDetails(
roomId = RoomId(identifier),
name = room.name(),
name = room.name() ?: identifier,
isDirect = room.isDm() ?: false,
avatarURLString = room.fullRoom()?.avatarUrl(),
unreadNotificationCount = room.unreadNotifications().notificationCount(),

1
settings.gradle.kts

@ -24,3 +24,4 @@ include(":features:login") @@ -24,3 +24,4 @@ include(":features:login")
include(":features:roomlist")
include(":features:messages")
include(":libraries:designsystem")
include(":libraries:avatar")

Loading…
Cancel
Save