1
Fork 0
mirror of https://github.com/Steffo99/twom.git synced 2024-11-25 17:44:24 +00:00

Load user avatars

This commit is contained in:
Steffo 2023-11-29 03:09:49 +01:00
parent 9f7df9bfa4
commit 43f4b266aa
Signed by: steffo
GPG key ID: 2A24051445686895
5 changed files with 129 additions and 27 deletions

View file

@ -24,32 +24,39 @@ class MainActivity : ComponentActivity() {
super.onCreate(savedInstanceState) super.onCreate(savedInstanceState)
TwoMMatrix.ensureMatrix(applicationContext) TwoMMatrix.ensureMatrix(applicationContext)
TwoMMatrix.ensureDefaultAvatar(applicationContext)
fetchLastSession()
openSession()
loginLauncher = loginLauncher =
registerForActivityResult( registerForActivityResult(
ActivityResultContracts.StartActivityForResult(), ActivityResultContracts.StartActivityForResult(),
this::handleLoginResult this::onLogin
) )
// This calls recompose() by itself resetContent()
openLastSession()
} }
private fun openLastSession() { override fun onDestroy() {
super.onDestroy()
closeSession()
}
private fun fetchLastSession() {
Log.d("Main", "Fetching the last successfully authenticated session...")
session = TwoMMatrix.matrix.authenticationService().getLastAuthenticatedSession() session = TwoMMatrix.matrix.authenticationService().getLastAuthenticatedSession()
session?.open()
recompose()
} }
private fun recompose() { private fun openSession() {
Log.d("Main", "Recomposing...") Log.d("Main", "If possible, opening session: $session")
setContent { session?.open()
MatrixActivityScaffold(
onClickLogin = this::onClickLogin,
onClickLogout = this::onClickLogout,
session = session,
)
} }
private fun closeSession() {
Log.d("Main", "If possible, closing session: $session")
session?.close()
} }
private fun onClickLogin() { private fun onClickLogin() {
@ -57,14 +64,17 @@ class MainActivity : ComponentActivity() {
loginLauncher.launch(Intent(applicationContext, LoginActivity::class.java)) loginLauncher.launch(Intent(applicationContext, LoginActivity::class.java))
} }
private fun handleLoginResult(result: ActivityResult) { private fun onLogin(result: ActivityResult) {
Log.d("Main", "Received result from login activity: $result")
when (result.resultCode) { when (result.resultCode) {
RESULT_OK -> { RESULT_OK -> {
Log.d( Log.d(
"Main", "Main",
"Login activity returned a successful result, trying to get session..." "Login activity returned a successful result, trying to get session..."
) )
openLastSession() fetchLastSession()
session?.open()
resetContent()
} }
else -> { else -> {
@ -79,7 +89,18 @@ class MainActivity : ComponentActivity() {
session!!.signOutService().signOut(true) session!!.signOutService().signOut(true)
session = null session = null
Log.d("Main", "Done logging out, recomposing...") Log.d("Main", "Done logging out, recomposing...")
recompose() resetContent()
}
}
private fun resetContent() {
Log.d("Main", "Recomposing...")
setContent {
MatrixActivityScaffold(
onClickLogin = this::onClickLogin,
onClickLogout = this::onClickLogout,
session = session,
)
} }
} }
} }

View file

@ -18,6 +18,7 @@ import androidx.compose.ui.platform.LocalContext
import androidx.compose.ui.res.stringResource import androidx.compose.ui.res.stringResource
import androidx.compose.ui.tooling.preview.Preview import androidx.compose.ui.tooling.preview.Preview
import eu.steffo.twom.R import eu.steffo.twom.R
import eu.steffo.twom.matrix.Avatar
import org.matrix.android.sdk.api.session.Session import org.matrix.android.sdk.api.session.Session
@Composable @Composable
@ -34,10 +35,18 @@ fun ProfileIconButton(
enabled = (session != null), enabled = (session != null),
onClick = { expanded = true }, onClick = { expanded = true },
) { ) {
if (session == null) {
Icon( Icon(
Icons.Filled.AccountCircle, imageVector = Icons.Filled.AccountCircle,
LocalContext.current.getString(R.string.account_label) contentDescription = LocalContext.current.getString(R.string.account_label),
) )
} else {
Avatar(
session = session,
userId = session.myUserId,
contentDescription = LocalContext.current.getString(R.string.account_label),
)
}
} }
DropdownMenu( DropdownMenu(
expanded = expanded, expanded = expanded,

View file

@ -0,0 +1,47 @@
package eu.steffo.twom.matrix
import android.graphics.BitmapFactory
import android.util.Log
import androidx.compose.foundation.Image
import androidx.compose.runtime.Composable
import androidx.compose.runtime.LaunchedEffect
import androidx.compose.runtime.getValue
import androidx.compose.runtime.mutableStateOf
import androidx.compose.runtime.remember
import androidx.compose.runtime.setValue
import androidx.compose.ui.graphics.ImageBitmap
import androidx.compose.ui.graphics.asImageBitmap
import org.matrix.android.sdk.api.session.Session
@Composable
fun Avatar(
session: Session,
userId: String,
contentDescription: String,
) {
var avatar by remember { mutableStateOf<ImageBitmap?>(null) }
var fetched by remember { mutableStateOf(false) }
LaunchedEffect(session, userId) GetAvatar@{
Log.d("Avatar", "Trying to retrieve the avatar url for $userId...")
val avatarUrl = session.profileService().getAvatarUrl(userId)
Log.d("Avatar", "Avatar URL for $userId is: $avatarUrl")
val avatarFile = session.fileService().downloadFile(
fileName = "avatar",
url = avatarUrl.getOrNull(),
mimeType = null,
elementToDecrypt = null,
)
// TODO: Should I check the MIME type? And the size of the image?
Log.d("Avatar", "Avatar file for $userId is: $avatarFile")
val avatarBitmap = BitmapFactory.decodeFile(avatarFile.absolutePath)
Log.d("Avatar", "Avatar bitmap for $userId is: $avatarBitmap")
avatar = avatarBitmap.asImageBitmap()
fetched = true
}
Image(
bitmap = if (fetched && avatar != null) avatar!! else TwoMMatrix.defaultAvatar,
contentDescription = contentDescription
)
}

View file

@ -1,6 +1,11 @@
package eu.steffo.twom.matrix package eu.steffo.twom.matrix
import android.content.Context import android.content.Context
import android.graphics.BitmapFactory
import android.util.Log
import androidx.compose.ui.graphics.ImageBitmap
import androidx.compose.ui.graphics.asImageBitmap
import eu.steffo.twom.R
import org.matrix.android.sdk.api.Matrix import org.matrix.android.sdk.api.Matrix
import org.matrix.android.sdk.api.MatrixConfiguration import org.matrix.android.sdk.api.MatrixConfiguration
@ -16,17 +21,14 @@ object TwoMMatrix {
*/ */
lateinit var matrix: Matrix lateinit var matrix: Matrix
private fun isMatrixInitialized(): Boolean {
return this::matrix.isInitialized
}
/** /**
* Make sure the [matrix] object is available, constructing it if it isn't initialized. * Make sure the [matrix] object is available, constructing it if it isn't initialized.
* *
* Uses the passed [Context] to access the [application context][Context.getApplicationContext], which is required by the SDK provided by the Matrix Foundation. * Uses the passed [Context] to access the [application context][Context.getApplicationContext], which is required by the SDK provided by the Matrix Foundation.
*/ */
fun ensureMatrix(context: Context): Matrix? { fun ensureMatrix(context: Context): Matrix? {
if (!isMatrixInitialized()) { if (!this::matrix.isInitialized) {
Log.d("Matrix", "Initializing Matrix...")
matrix = Matrix( matrix = Matrix(
context = context.applicationContext, context = context.applicationContext,
matrixConfiguration = MatrixConfiguration( matrixConfiguration = MatrixConfiguration(
@ -38,4 +40,27 @@ object TwoMMatrix {
} }
return null return null
} }
/**
* The avatar to default to when another one is not available.
*
* [Avatar] will expect this to be available.
*/
lateinit var defaultAvatar: ImageBitmap
/**
* Make sure the [matrix] object is available, decoding it if it isn't initialized.
*
* Uses the passed [Context] to access the application resources.
*/
fun ensureDefaultAvatar(context: Context): ImageBitmap? {
if (!this::defaultAvatar.isInitialized) {
Log.d("Matrix", "Initializing default avatar...")
defaultAvatar =
BitmapFactory.decodeResource(context.resources, R.drawable.avatar_default)
.asImageBitmap()
return defaultAvatar
}
return null
}
} }

Binary file not shown.

After

Width:  |  Height:  |  Size: 43 KiB