Try some stuff on room list and avatar...

This commit is contained in:
ganfra 2022-10-30 15:43:07 +01:00
parent fcf7e8d7f1
commit 14992cb63a
17 changed files with 230 additions and 12 deletions

1
libraries/avatar/.gitignore vendored Normal file
View file

@ -0,0 +1 @@
/build

View file

@ -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)
}

View file

21
libraries/avatar/proguard-rules.pro vendored Normal file
View file

@ -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

View file

@ -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)
}
}

View file

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

View file

@ -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)
)
}

View file

@ -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
)

View file

@ -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)
}
}
}

View file

@ -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)
}
}

View file

@ -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)

View file

@ -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?,

View file

@ -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(),