Create spaces (#5982)
* Allow creating a space with `CreateRoomParameters` * Add 'Create space' menu item in the spaces home screen. Also, imports new strings related to spaces. * Link the 'Create space' button with the screen to create the space * Unify room access and visibility for `ConfigureRoom`, use the updated design * Fix `EditRoomDetails` avatar size (68dp) * Replace `EditableAvatarView` and `UnsavedAvatar` copmonents with `AvatarPickerView` * `AvatarDataFetcherFactory`: Make sure we use a fallback image fetcher when the URL is not an MXC one (a local one, i.e.). This removes the previous need for a separate `UnsavedAvatarView` * Use `AvatarPickerView` in all the screens where `EditableAvatarView` was used * Improve naming and previews * Update strings, remove unused ones for `RoomAccessItem` * Make `isSpace` part of the `CreateRoomConfig` * Ensure the content fits in the screenshots for `AvatarPickerSizesPreview` * Add `AvatarDataFetcherFactoryTest` * Add new feature flag for creating spaces * Fix ripple being too large for the `Pick` state * Tweak margins and section titles a bit * Add preview for `HomeTopBar` with the spaces case * Update screenshots --------- Co-authored-by: ElementBot <android@element.io>
This commit is contained in:
committed by
GitHub
parent
a234eb3e29
commit
03d14087e6
@@ -11,6 +11,7 @@ package io.element.android.libraries.matrix.ui.media
|
||||
import coil3.ImageLoader
|
||||
import coil3.fetch.Fetcher
|
||||
import coil3.request.Options
|
||||
import coil3.toUri
|
||||
import io.element.android.libraries.designsystem.components.avatar.AvatarData
|
||||
import io.element.android.libraries.matrix.api.media.MatrixMediaLoader
|
||||
|
||||
@@ -21,10 +22,19 @@ internal class AvatarDataFetcherFactory(
|
||||
data: AvatarData,
|
||||
options: Options,
|
||||
imageLoader: ImageLoader
|
||||
): Fetcher {
|
||||
return CoilMediaFetcher(
|
||||
mediaLoader = matrixMediaLoader,
|
||||
mediaData = data.toMediaRequestData(),
|
||||
)
|
||||
): Fetcher? {
|
||||
return when {
|
||||
data.url == null -> null
|
||||
data.url?.startsWith("mxc") == true -> CoilMediaFetcher(
|
||||
mediaLoader = matrixMediaLoader,
|
||||
mediaData = data.toMediaRequestData(),
|
||||
)
|
||||
else -> {
|
||||
// If the URL does not use the mxc scheme, it might be a local one using `content://`, try using a fallback fetcher
|
||||
data.url?.toUri()?.let { uri ->
|
||||
imageLoader.components.newFetcher(uri, options, imageLoader)
|
||||
}?.first
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -0,0 +1,78 @@
|
||||
/*
|
||||
* Copyright (c) 2026 Element Creations Ltd.
|
||||
*
|
||||
* SPDX-License-Identifier: AGPL-3.0-only OR LicenseRef-Element-Commercial.
|
||||
* Please see LICENSE files in the repository root for full details.
|
||||
*/
|
||||
|
||||
package io.element.android.libraries.matrix.ui.media
|
||||
|
||||
import android.graphics.Bitmap
|
||||
import coil3.ComponentRegistry
|
||||
import coil3.ImageLoader
|
||||
import coil3.asImage
|
||||
import coil3.disk.DiskCache
|
||||
import coil3.memory.MemoryCache
|
||||
import coil3.request.Disposable
|
||||
import coil3.request.ImageRequest
|
||||
import coil3.request.ImageResult
|
||||
import coil3.request.Options
|
||||
import coil3.request.SuccessResult
|
||||
import com.google.common.truth.Truth.assertThat
|
||||
import io.element.android.libraries.designsystem.components.avatar.anAvatarData
|
||||
import io.element.android.libraries.matrix.test.media.FakeMatrixMediaLoader
|
||||
import io.mockk.mockk
|
||||
import org.junit.Test
|
||||
|
||||
class AvatarDataFetcherFactoryTest {
|
||||
@Test
|
||||
fun `create - with mxc returns CoilMediaFetcher`() {
|
||||
val factory = AvatarDataFetcherFactory(matrixMediaLoader = FakeMatrixMediaLoader())
|
||||
|
||||
val fetcher = factory.create(anAvatarData(url = "mxc://test"), Options(mockk()), imageLoader = FakeImageLoader())
|
||||
assertThat(fetcher).isInstanceOf(CoilMediaFetcher::class.java)
|
||||
}
|
||||
|
||||
@Test
|
||||
fun `create - with http or https returns null, which means fallback default fetcher will be used`() {
|
||||
val factory = AvatarDataFetcherFactory(matrixMediaLoader = FakeMatrixMediaLoader())
|
||||
|
||||
val fetcherHttp = factory.create(anAvatarData(url = "http://test"), Options(mockk()), imageLoader = FakeImageLoader())
|
||||
assertThat(fetcherHttp).isNull()
|
||||
|
||||
val fetcherHttps = factory.create(anAvatarData(url = "https://test"), Options(mockk()), imageLoader = FakeImageLoader())
|
||||
assertThat(fetcherHttps).isNull()
|
||||
}
|
||||
|
||||
@Test
|
||||
fun `create - with content scheme returns null, which means fallback default fetcher will be used`() {
|
||||
val factory = AvatarDataFetcherFactory(matrixMediaLoader = FakeMatrixMediaLoader())
|
||||
|
||||
val fetcher = factory.create(anAvatarData(url = "content://test"), Options(mockk()), imageLoader = FakeImageLoader())
|
||||
assertThat(fetcher).isNull()
|
||||
}
|
||||
}
|
||||
|
||||
private class FakeImageLoader : ImageLoader {
|
||||
override val defaults: ImageRequest.Defaults = ImageRequest.Defaults.DEFAULT
|
||||
override val components: ComponentRegistry = ComponentRegistry.Builder().build()
|
||||
override val memoryCache: MemoryCache? = null
|
||||
override val diskCache: DiskCache? = null
|
||||
|
||||
override fun enqueue(request: ImageRequest): Disposable {
|
||||
return mockk()
|
||||
}
|
||||
|
||||
override suspend fun execute(request: ImageRequest): ImageResult {
|
||||
return SuccessResult(
|
||||
image = Bitmap.createBitmap(1, 1, Bitmap.Config.ALPHA_8).asImage(),
|
||||
request = request,
|
||||
)
|
||||
}
|
||||
|
||||
override fun shutdown() {}
|
||||
|
||||
override fun newBuilder(): ImageLoader.Builder {
|
||||
return ImageLoader.Builder(mockk())
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user