Let element enterprise be able to configure id for mapTiler. (#4446)
* Let element enterprise configure the ids for maptiler service. * Disable location sharing and location viewer is the service is not available. * Fix compilation issue on connected test * Do not allow to reload the map if the mapId is not available. * Update screenshots * Rename file. * Better to inject a string provider here, so we can unit test DefaultLocationService. --------- Co-authored-by: ElementBot <android@element.io>
This commit is contained in:
parent
da0a2144bd
commit
f0a6a0037c
24 changed files with 198 additions and 36 deletions
|
|
@ -5,6 +5,7 @@
|
||||||
* Please see LICENSE files in the repository root for full details.
|
* Please see LICENSE files in the repository root for full details.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
import config.BuildTimeConfig
|
||||||
import extension.readLocalProperty
|
import extension.readLocalProperty
|
||||||
|
|
||||||
plugins {
|
plugins {
|
||||||
|
|
@ -19,24 +20,36 @@ android {
|
||||||
resValue(
|
resValue(
|
||||||
type = "string",
|
type = "string",
|
||||||
name = "maptiler_api_key",
|
name = "maptiler_api_key",
|
||||||
value = System.getenv("ELEMENT_ANDROID_MAPTILER_API_KEY")
|
value = if (isEnterpriseBuild) {
|
||||||
?: readLocalProperty("services.maptiler.apikey")
|
BuildTimeConfig.SERVICES_MAPTILER_APIKEY
|
||||||
|
} else {
|
||||||
|
System.getenv("ELEMENT_ANDROID_MAPTILER_API_KEY")
|
||||||
|
?: readLocalProperty("services.maptiler.apikey")
|
||||||
|
}
|
||||||
?: ""
|
?: ""
|
||||||
)
|
)
|
||||||
resValue(
|
resValue(
|
||||||
type = "string",
|
type = "string",
|
||||||
name = "maptiler_light_map_id",
|
name = "maptiler_light_map_id",
|
||||||
value = System.getenv("ELEMENT_ANDROID_MAPTILER_LIGHT_MAP_ID")
|
value = if (isEnterpriseBuild) {
|
||||||
?: readLocalProperty("services.maptiler.lightMapId")
|
BuildTimeConfig.SERVICES_MAPTILER_LIGHT_MAPID
|
||||||
// fall back to maptiler's default light map.
|
} else {
|
||||||
|
System.getenv("ELEMENT_ANDROID_MAPTILER_LIGHT_MAP_ID")
|
||||||
|
?: readLocalProperty("services.maptiler.lightMapId")
|
||||||
|
}
|
||||||
|
// fall back to maptiler's default light map.
|
||||||
?: "basic-v2"
|
?: "basic-v2"
|
||||||
)
|
)
|
||||||
resValue(
|
resValue(
|
||||||
type = "string",
|
type = "string",
|
||||||
name = "maptiler_dark_map_id",
|
name = "maptiler_dark_map_id",
|
||||||
value = System.getenv("ELEMENT_ANDROID_MAPTILER_DARK_MAP_ID")
|
value = if (isEnterpriseBuild) {
|
||||||
?: readLocalProperty("services.maptiler.darkMapId")
|
BuildTimeConfig.SERVICES_MAPTILER_DARK_MAPID
|
||||||
// fall back to maptiler's default dark map.
|
} else {
|
||||||
|
System.getenv("ELEMENT_ANDROID_MAPTILER_DARK_MAP_ID")
|
||||||
|
?: readLocalProperty("services.maptiler.darkMapId")
|
||||||
|
}
|
||||||
|
// fall back to maptiler's default dark map.
|
||||||
?: "basic-v2-dark"
|
?: "basic-v2-dark"
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -0,0 +1,12 @@
|
||||||
|
/*
|
||||||
|
* Copyright 2025 New Vector 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.features.location.api
|
||||||
|
|
||||||
|
interface LocationService {
|
||||||
|
fun isServiceAvailable(): Boolean
|
||||||
|
}
|
||||||
|
|
@ -103,6 +103,7 @@ fun StaticMapView(
|
||||||
} else {
|
} else {
|
||||||
StaticMapPlaceholder(
|
StaticMapPlaceholder(
|
||||||
showProgress = collectedState.value.isLoading(),
|
showProgress = collectedState.value.isLoading(),
|
||||||
|
canReload = builder.isServiceAvailable(),
|
||||||
contentDescription = contentDescription,
|
contentDescription = contentDescription,
|
||||||
width = maxWidth,
|
width = maxWidth,
|
||||||
height = maxHeight,
|
height = maxHeight,
|
||||||
|
|
|
||||||
|
|
@ -57,6 +57,8 @@ internal class MapTilerStaticMapUrlBuilder(
|
||||||
// to keep the perceived content size constant at the expense of sharpness.
|
// to keep the perceived content size constant at the expense of sharpness.
|
||||||
return "$MAPTILER_BASE_URL/$mapId/static/$lon,$lat,$finalZoom/${finalWidth}x${finalHeight}$scale.webp?key=$apiKey&attribution=bottomleft"
|
return "$MAPTILER_BASE_URL/$mapId/static/$lon,$lat,$finalZoom/${finalWidth}x${finalHeight}$scale.webp?key=$apiKey&attribution=bottomleft"
|
||||||
}
|
}
|
||||||
|
|
||||||
|
override fun isServiceAvailable() = apiKey.isNotEmpty()
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun coerceWidthAndHeight(width: Int, height: Int, is2x: Boolean): Pair<Int, Int> {
|
private fun coerceWidthAndHeight(width: Int, height: Int, is2x: Boolean): Pair<Int, Int> {
|
||||||
|
|
|
||||||
|
|
@ -9,8 +9,10 @@ package io.element.android.features.location.api.internal
|
||||||
|
|
||||||
import androidx.compose.foundation.Image
|
import androidx.compose.foundation.Image
|
||||||
import androidx.compose.foundation.clickable
|
import androidx.compose.foundation.clickable
|
||||||
|
import androidx.compose.foundation.layout.Arrangement
|
||||||
import androidx.compose.foundation.layout.Box
|
import androidx.compose.foundation.layout.Box
|
||||||
import androidx.compose.foundation.layout.Column
|
import androidx.compose.foundation.layout.Column
|
||||||
|
import androidx.compose.foundation.layout.padding
|
||||||
import androidx.compose.foundation.layout.size
|
import androidx.compose.foundation.layout.size
|
||||||
import androidx.compose.runtime.Composable
|
import androidx.compose.runtime.Composable
|
||||||
import androidx.compose.ui.Alignment
|
import androidx.compose.ui.Alignment
|
||||||
|
|
@ -18,7 +20,6 @@ import androidx.compose.ui.Modifier
|
||||||
import androidx.compose.ui.layout.ContentScale
|
import androidx.compose.ui.layout.ContentScale
|
||||||
import androidx.compose.ui.res.painterResource
|
import androidx.compose.ui.res.painterResource
|
||||||
import androidx.compose.ui.res.stringResource
|
import androidx.compose.ui.res.stringResource
|
||||||
import androidx.compose.ui.tooling.preview.PreviewParameter
|
|
||||||
import androidx.compose.ui.unit.Dp
|
import androidx.compose.ui.unit.Dp
|
||||||
import androidx.compose.ui.unit.dp
|
import androidx.compose.ui.unit.dp
|
||||||
import io.element.android.compound.tokens.generated.CompoundIcons
|
import io.element.android.compound.tokens.generated.CompoundIcons
|
||||||
|
|
@ -28,12 +29,12 @@ import io.element.android.libraries.designsystem.preview.PreviewsDayNight
|
||||||
import io.element.android.libraries.designsystem.theme.components.CircularProgressIndicator
|
import io.element.android.libraries.designsystem.theme.components.CircularProgressIndicator
|
||||||
import io.element.android.libraries.designsystem.theme.components.Icon
|
import io.element.android.libraries.designsystem.theme.components.Icon
|
||||||
import io.element.android.libraries.designsystem.theme.components.Text
|
import io.element.android.libraries.designsystem.theme.components.Text
|
||||||
import io.element.android.libraries.designsystem.utils.BooleanProvider
|
|
||||||
import io.element.android.libraries.ui.strings.CommonStrings
|
import io.element.android.libraries.ui.strings.CommonStrings
|
||||||
|
|
||||||
@Composable
|
@Composable
|
||||||
internal fun StaticMapPlaceholder(
|
internal fun StaticMapPlaceholder(
|
||||||
showProgress: Boolean,
|
showProgress: Boolean,
|
||||||
|
canReload: Boolean,
|
||||||
contentDescription: String?,
|
contentDescription: String?,
|
||||||
width: Dp,
|
width: Dp,
|
||||||
height: Dp,
|
height: Dp,
|
||||||
|
|
@ -54,7 +55,7 @@ internal fun StaticMapPlaceholder(
|
||||||
)
|
)
|
||||||
if (showProgress) {
|
if (showProgress) {
|
||||||
CircularProgressIndicator()
|
CircularProgressIndicator()
|
||||||
} else {
|
} else if (canReload) {
|
||||||
Column(
|
Column(
|
||||||
horizontalAlignment = Alignment.CenterHorizontally,
|
horizontalAlignment = Alignment.CenterHorizontally,
|
||||||
) {
|
) {
|
||||||
|
|
@ -70,14 +71,24 @@ internal fun StaticMapPlaceholder(
|
||||||
|
|
||||||
@PreviewsDayNight
|
@PreviewsDayNight
|
||||||
@Composable
|
@Composable
|
||||||
internal fun StaticMapPlaceholderPreview(
|
internal fun StaticMapPlaceholderPreview() = ElementPreview {
|
||||||
@PreviewParameter(BooleanProvider::class) values: Boolean
|
Column(
|
||||||
) = ElementPreview {
|
modifier = Modifier.padding(8.dp),
|
||||||
StaticMapPlaceholder(
|
verticalArrangement = Arrangement.spacedBy(8.dp)
|
||||||
showProgress = values,
|
) {
|
||||||
contentDescription = null,
|
listOf(
|
||||||
width = 400.dp,
|
true to false,
|
||||||
height = 400.dp,
|
false to true,
|
||||||
onLoadMapClick = {},
|
false to false,
|
||||||
)
|
).forEach { (showProgress, canReload) ->
|
||||||
|
StaticMapPlaceholder(
|
||||||
|
showProgress = showProgress,
|
||||||
|
canReload = canReload,
|
||||||
|
contentDescription = null,
|
||||||
|
width = 400.dp,
|
||||||
|
height = 200.dp,
|
||||||
|
onLoadMapClick = {},
|
||||||
|
)
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -22,6 +22,8 @@ interface StaticMapUrlBuilder {
|
||||||
height: Int,
|
height: Int,
|
||||||
density: Float,
|
density: Float,
|
||||||
): String
|
): String
|
||||||
|
|
||||||
|
fun isServiceAvailable(): Boolean
|
||||||
}
|
}
|
||||||
|
|
||||||
fun StaticMapUrlBuilder(context: Context): StaticMapUrlBuilder = MapTilerStaticMapUrlBuilder(context = context)
|
fun StaticMapUrlBuilder(context: Context): StaticMapUrlBuilder = MapTilerStaticMapUrlBuilder(context = context)
|
||||||
|
|
|
||||||
|
|
@ -17,6 +17,21 @@ class MapTilerStaticMapUrlBuilderTest {
|
||||||
darkMapId = "aDarkMapId",
|
darkMapId = "aDarkMapId",
|
||||||
)
|
)
|
||||||
|
|
||||||
|
@Test
|
||||||
|
fun `isServiceAvailable returns true if api key is not empty`() {
|
||||||
|
assertThat(builder.isServiceAvailable()).isTrue()
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
fun `isServiceAvailable returns false if api key is empty`() {
|
||||||
|
val builderWithoutKey = MapTilerStaticMapUrlBuilder(
|
||||||
|
apiKey = "",
|
||||||
|
lightMapId = "aLightMapId",
|
||||||
|
darkMapId = "aDarkMapId",
|
||||||
|
)
|
||||||
|
assertThat(builderWithoutKey.isServiceAvailable()).isFalse()
|
||||||
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
fun `static map 1x density`() {
|
fun `static map 1x density`() {
|
||||||
assertThat(
|
assertThat(
|
||||||
|
|
|
||||||
|
|
@ -49,6 +49,7 @@ dependencies {
|
||||||
testImplementation(projects.libraries.testtags)
|
testImplementation(projects.libraries.testtags)
|
||||||
testImplementation(projects.services.analytics.test)
|
testImplementation(projects.services.analytics.test)
|
||||||
testImplementation(projects.features.messages.test)
|
testImplementation(projects.features.messages.test)
|
||||||
|
testImplementation(projects.services.toolbox.test)
|
||||||
testImplementation(projects.tests.testutils)
|
testImplementation(projects.tests.testutils)
|
||||||
testImplementation(libs.androidx.compose.ui.test.junit)
|
testImplementation(libs.androidx.compose.ui.test.junit)
|
||||||
testReleaseImplementation(libs.androidx.compose.ui.test.manifest)
|
testReleaseImplementation(libs.androidx.compose.ui.test.manifest)
|
||||||
|
|
|
||||||
|
|
@ -0,0 +1,24 @@
|
||||||
|
/*
|
||||||
|
* Copyright 2025 New Vector 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.features.location.impl
|
||||||
|
|
||||||
|
import com.squareup.anvil.annotations.ContributesBinding
|
||||||
|
import io.element.android.features.location.api.LocationService
|
||||||
|
import io.element.android.features.location.api.R
|
||||||
|
import io.element.android.libraries.di.AppScope
|
||||||
|
import io.element.android.services.toolbox.api.strings.StringProvider
|
||||||
|
import javax.inject.Inject
|
||||||
|
|
||||||
|
@ContributesBinding(AppScope::class)
|
||||||
|
class DefaultLocationService @Inject constructor(
|
||||||
|
private val stringProvider: StringProvider,
|
||||||
|
) : LocationService {
|
||||||
|
override fun isServiceAvailable(): Boolean {
|
||||||
|
return stringProvider.getString(R.string.maptiler_api_key).isNotEmpty()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,37 @@
|
||||||
|
/*
|
||||||
|
* Copyright 2025 New Vector 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.features.location.impl
|
||||||
|
|
||||||
|
import com.google.common.truth.Truth.assertThat
|
||||||
|
import io.element.android.features.location.api.R
|
||||||
|
import io.element.android.services.toolbox.test.strings.FakeStringProvider
|
||||||
|
import org.junit.Test
|
||||||
|
|
||||||
|
class DefaultLocationServiceTest {
|
||||||
|
@Test
|
||||||
|
fun `if apiKey is empty, isServiceAvailable should return false`() {
|
||||||
|
val fakeStringProvider = FakeStringProvider(
|
||||||
|
defaultResult = ""
|
||||||
|
)
|
||||||
|
val locationService = DefaultLocationService(
|
||||||
|
stringProvider = fakeStringProvider,
|
||||||
|
)
|
||||||
|
assertThat(locationService.isServiceAvailable()).isFalse()
|
||||||
|
assertThat(fakeStringProvider.lastResIdParam).isEqualTo(R.string.maptiler_api_key)
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
fun `if apiKey is not empty, isServiceAvailable should return true`() {
|
||||||
|
val locationService = DefaultLocationService(
|
||||||
|
stringProvider = FakeStringProvider(
|
||||||
|
defaultResult = "aKey"
|
||||||
|
)
|
||||||
|
)
|
||||||
|
assertThat(locationService.isServiceAvailable()).isTrue()
|
||||||
|
}
|
||||||
|
}
|
||||||
18
features/location/test/build.gradle.kts
Normal file
18
features/location/test/build.gradle.kts
Normal file
|
|
@ -0,0 +1,18 @@
|
||||||
|
/*
|
||||||
|
* Copyright 2025 New Vector Ltd.
|
||||||
|
*
|
||||||
|
* SPDX-License-Identifier: AGPL-3.0-only OR LicenseRef-Element-Commercial
|
||||||
|
* Please see LICENSE files in the repository root for full details.
|
||||||
|
*/
|
||||||
|
|
||||||
|
plugins {
|
||||||
|
id("io.element.android-library")
|
||||||
|
}
|
||||||
|
|
||||||
|
android {
|
||||||
|
namespace = "io.element.android.features.location.test"
|
||||||
|
}
|
||||||
|
|
||||||
|
dependencies {
|
||||||
|
implementation(projects.features.location.api)
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,16 @@
|
||||||
|
/*
|
||||||
|
* Copyright 2025 New Vector 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.features.location.test
|
||||||
|
|
||||||
|
import io.element.android.features.location.api.LocationService
|
||||||
|
|
||||||
|
class FakeLocationService(
|
||||||
|
private val isServiceAvailable: Boolean,
|
||||||
|
) : LocationService {
|
||||||
|
override fun isServiceAvailable() = isServiceAvailable
|
||||||
|
}
|
||||||
|
|
@ -75,6 +75,7 @@ dependencies {
|
||||||
testImplementation(libs.test.turbine)
|
testImplementation(libs.test.turbine)
|
||||||
testImplementation(projects.libraries.matrix.test)
|
testImplementation(projects.libraries.matrix.test)
|
||||||
testImplementation(projects.libraries.dateformatter.test)
|
testImplementation(projects.libraries.dateformatter.test)
|
||||||
|
testImplementation(projects.features.location.test)
|
||||||
testImplementation(projects.features.networkmonitor.test)
|
testImplementation(projects.features.networkmonitor.test)
|
||||||
testImplementation(projects.features.messages.test)
|
testImplementation(projects.features.messages.test)
|
||||||
testImplementation(projects.services.analytics.test)
|
testImplementation(projects.services.analytics.test)
|
||||||
|
|
|
||||||
|
|
@ -28,6 +28,7 @@ import io.element.android.features.call.api.CallType
|
||||||
import io.element.android.features.call.api.ElementCallEntryPoint
|
import io.element.android.features.call.api.ElementCallEntryPoint
|
||||||
import io.element.android.features.knockrequests.api.list.KnockRequestsListEntryPoint
|
import io.element.android.features.knockrequests.api.list.KnockRequestsListEntryPoint
|
||||||
import io.element.android.features.location.api.Location
|
import io.element.android.features.location.api.Location
|
||||||
|
import io.element.android.features.location.api.LocationService
|
||||||
import io.element.android.features.location.api.SendLocationEntryPoint
|
import io.element.android.features.location.api.SendLocationEntryPoint
|
||||||
import io.element.android.features.location.api.ShowLocationEntryPoint
|
import io.element.android.features.location.api.ShowLocationEntryPoint
|
||||||
import io.element.android.features.messages.api.MessagesEntryPoint
|
import io.element.android.features.messages.api.MessagesEntryPoint
|
||||||
|
|
@ -96,6 +97,7 @@ class MessagesFlowNode @AssistedInject constructor(
|
||||||
private val elementCallEntryPoint: ElementCallEntryPoint,
|
private val elementCallEntryPoint: ElementCallEntryPoint,
|
||||||
private val mediaViewerEntryPoint: MediaViewerEntryPoint,
|
private val mediaViewerEntryPoint: MediaViewerEntryPoint,
|
||||||
private val analyticsService: AnalyticsService,
|
private val analyticsService: AnalyticsService,
|
||||||
|
private val locationService: LocationService,
|
||||||
private val room: MatrixRoom,
|
private val room: MatrixRoom,
|
||||||
private val roomMemberProfilesCache: RoomMemberProfilesCache,
|
private val roomMemberProfilesCache: RoomMemberProfilesCache,
|
||||||
private val mentionSpanTheme: MentionSpanTheme,
|
private val mentionSpanTheme: MentionSpanTheme,
|
||||||
|
|
@ -409,7 +411,7 @@ class MessagesFlowNode @AssistedInject constructor(
|
||||||
NavTarget.LocationViewer(
|
NavTarget.LocationViewer(
|
||||||
location = event.content.location,
|
location = event.content.location,
|
||||||
description = event.content.description,
|
description = event.content.description,
|
||||||
)
|
).takeIf { locationService.isServiceAvailable() }
|
||||||
}
|
}
|
||||||
else -> null
|
else -> null
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -30,6 +30,7 @@ import dagger.assisted.AssistedFactory
|
||||||
import dagger.assisted.AssistedInject
|
import dagger.assisted.AssistedInject
|
||||||
import im.vector.app.features.analytics.plan.Composer
|
import im.vector.app.features.analytics.plan.Composer
|
||||||
import im.vector.app.features.analytics.plan.Interaction
|
import im.vector.app.features.analytics.plan.Interaction
|
||||||
|
import io.element.android.features.location.api.LocationService
|
||||||
import io.element.android.features.messages.impl.MessagesNavigator
|
import io.element.android.features.messages.impl.MessagesNavigator
|
||||||
import io.element.android.features.messages.impl.attachments.Attachment
|
import io.element.android.features.messages.impl.attachments.Attachment
|
||||||
import io.element.android.features.messages.impl.attachments.preview.error.sendAttachmentError
|
import io.element.android.features.messages.impl.attachments.preview.error.sendAttachmentError
|
||||||
|
|
@ -104,6 +105,7 @@ class MessageComposerPresenter @AssistedInject constructor(
|
||||||
private val mediaSender: MediaSender,
|
private val mediaSender: MediaSender,
|
||||||
private val snackbarDispatcher: SnackbarDispatcher,
|
private val snackbarDispatcher: SnackbarDispatcher,
|
||||||
private val analyticsService: AnalyticsService,
|
private val analyticsService: AnalyticsService,
|
||||||
|
private val locationService: LocationService,
|
||||||
private val messageComposerContext: DefaultMessageComposerContext,
|
private val messageComposerContext: DefaultMessageComposerContext,
|
||||||
private val richTextEditorStateFactory: RichTextEditorStateFactory,
|
private val richTextEditorStateFactory: RichTextEditorStateFactory,
|
||||||
private val roomAliasSuggestionsDataSource: RoomAliasSuggestionsDataSource,
|
private val roomAliasSuggestionsDataSource: RoomAliasSuggestionsDataSource,
|
||||||
|
|
@ -155,7 +157,8 @@ class MessageComposerPresenter @AssistedInject constructor(
|
||||||
|
|
||||||
val canShareLocation = remember { mutableStateOf(false) }
|
val canShareLocation = remember { mutableStateOf(false) }
|
||||||
LaunchedEffect(Unit) {
|
LaunchedEffect(Unit) {
|
||||||
canShareLocation.value = featureFlagService.isFeatureEnabled(FeatureFlags.LocationSharing)
|
canShareLocation.value = featureFlagService.isFeatureEnabled(FeatureFlags.LocationSharing) &&
|
||||||
|
locationService.isServiceAvailable()
|
||||||
}
|
}
|
||||||
|
|
||||||
val canCreatePoll = remember { mutableStateOf(false) }
|
val canCreatePoll = remember { mutableStateOf(false) }
|
||||||
|
|
|
||||||
|
|
@ -18,6 +18,8 @@ import app.cash.turbine.test
|
||||||
import com.google.common.truth.Truth.assertThat
|
import com.google.common.truth.Truth.assertThat
|
||||||
import im.vector.app.features.analytics.plan.Composer
|
import im.vector.app.features.analytics.plan.Composer
|
||||||
import im.vector.app.features.analytics.plan.Interaction
|
import im.vector.app.features.analytics.plan.Interaction
|
||||||
|
import io.element.android.features.location.api.LocationService
|
||||||
|
import io.element.android.features.location.test.FakeLocationService
|
||||||
import io.element.android.features.messages.impl.FakeMessagesNavigator
|
import io.element.android.features.messages.impl.FakeMessagesNavigator
|
||||||
import io.element.android.features.messages.impl.MessagesNavigator
|
import io.element.android.features.messages.impl.MessagesNavigator
|
||||||
import io.element.android.features.messages.impl.attachments.Attachment
|
import io.element.android.features.messages.impl.attachments.Attachment
|
||||||
|
|
@ -1536,6 +1538,7 @@ class MessageComposerPresenterTest {
|
||||||
navigator: MessagesNavigator = FakeMessagesNavigator(),
|
navigator: MessagesNavigator = FakeMessagesNavigator(),
|
||||||
pickerProvider: PickerProvider = this.pickerProvider,
|
pickerProvider: PickerProvider = this.pickerProvider,
|
||||||
featureFlagService: FeatureFlagService = this.featureFlagService,
|
featureFlagService: FeatureFlagService = this.featureFlagService,
|
||||||
|
locationService: LocationService = FakeLocationService(true),
|
||||||
sessionPreferencesStore: SessionPreferencesStore = InMemorySessionPreferencesStore(),
|
sessionPreferencesStore: SessionPreferencesStore = InMemorySessionPreferencesStore(),
|
||||||
mediaPreProcessor: MediaPreProcessor = this.mediaPreProcessor,
|
mediaPreProcessor: MediaPreProcessor = this.mediaPreProcessor,
|
||||||
snackbarDispatcher: SnackbarDispatcher = this.snackbarDispatcher,
|
snackbarDispatcher: SnackbarDispatcher = this.snackbarDispatcher,
|
||||||
|
|
@ -1558,6 +1561,7 @@ class MessageComposerPresenterTest {
|
||||||
mediaSender = MediaSender(mediaPreProcessor, room, InMemorySessionPreferencesStore()),
|
mediaSender = MediaSender(mediaPreProcessor, room, InMemorySessionPreferencesStore()),
|
||||||
snackbarDispatcher = snackbarDispatcher,
|
snackbarDispatcher = snackbarDispatcher,
|
||||||
analyticsService = analyticsService,
|
analyticsService = analyticsService,
|
||||||
|
locationService = locationService,
|
||||||
messageComposerContext = DefaultMessageComposerContext(),
|
messageComposerContext = DefaultMessageComposerContext(),
|
||||||
richTextEditorStateFactory = TestRichTextEditorStateFactory(),
|
richTextEditorStateFactory = TestRichTextEditorStateFactory(),
|
||||||
roomAliasSuggestionsDataSource = FakeRoomAliasSuggestionsDataSource(),
|
roomAliasSuggestionsDataSource = FakeRoomAliasSuggestionsDataSource(),
|
||||||
|
|
|
||||||
|
|
@ -46,5 +46,4 @@ dependencies {
|
||||||
androidTestImplementation(libs.test.junit)
|
androidTestImplementation(libs.test.junit)
|
||||||
androidTestImplementation(libs.test.truth)
|
androidTestImplementation(libs.test.truth)
|
||||||
androidTestImplementation(libs.test.runner)
|
androidTestImplementation(libs.test.runner)
|
||||||
androidTestImplementation(projects.libraries.sessionStorage.test)
|
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -10,7 +10,6 @@ package io.element.android.libraries.pushstore.impl
|
||||||
import androidx.test.platform.app.InstrumentationRegistry
|
import androidx.test.platform.app.InstrumentationRegistry
|
||||||
import io.element.android.libraries.matrix.api.core.SessionId
|
import io.element.android.libraries.matrix.api.core.SessionId
|
||||||
import io.element.android.libraries.pushstore.api.UserPushStore
|
import io.element.android.libraries.pushstore.api.UserPushStore
|
||||||
import io.element.android.libraries.sessionstorage.test.observer.NoOpSessionObserver
|
|
||||||
import kotlinx.coroutines.flow.first
|
import kotlinx.coroutines.flow.first
|
||||||
import kotlinx.coroutines.runBlocking
|
import kotlinx.coroutines.runBlocking
|
||||||
import org.junit.Test
|
import org.junit.Test
|
||||||
|
|
@ -28,7 +27,7 @@ class DefaultUserPushStoreFactoryTest {
|
||||||
fun testParallelCreation() {
|
fun testParallelCreation() {
|
||||||
val context = InstrumentationRegistry.getInstrumentation().targetContext.applicationContext
|
val context = InstrumentationRegistry.getInstrumentation().targetContext.applicationContext
|
||||||
val sessionId = SessionId("@alice:server.org")
|
val sessionId = SessionId("@alice:server.org")
|
||||||
val userPushStoreFactory = DefaultUserPushStoreFactory(context, NoOpSessionObserver())
|
val userPushStoreFactory = DefaultUserPushStoreFactory(context)
|
||||||
var userPushStore1: UserPushStore? = null
|
var userPushStore1: UserPushStore? = null
|
||||||
val thread1 = thread {
|
val thread1 = thread {
|
||||||
userPushStore1 = userPushStoreFactory.getOrCreate(sessionId)
|
userPushStore1 = userPushStoreFactory.getOrCreate(sessionId)
|
||||||
|
|
|
||||||
|
|
@ -13,4 +13,8 @@ object BuildTimeConfig {
|
||||||
const val GOOGLE_APP_ID_RELEASE = "1:912726360885:android:d097de99a4c23d2700427c"
|
const val GOOGLE_APP_ID_RELEASE = "1:912726360885:android:d097de99a4c23d2700427c"
|
||||||
const val GOOGLE_APP_ID_DEBUG = "1:912726360885:android:def0a4e454042e9b00427c"
|
const val GOOGLE_APP_ID_DEBUG = "1:912726360885:android:def0a4e454042e9b00427c"
|
||||||
const val GOOGLE_APP_ID_NIGHTLY = "1:912726360885:android:e17435e0beb0303000427c"
|
const val GOOGLE_APP_ID_NIGHTLY = "1:912726360885:android:e17435e0beb0303000427c"
|
||||||
|
|
||||||
|
val SERVICES_MAPTILER_APIKEY: String? = null
|
||||||
|
val SERVICES_MAPTILER_LIGHT_MAPID: String? = null
|
||||||
|
val SERVICES_MAPTILER_DARK_MAPID: String? = null
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -12,15 +12,19 @@ import io.element.android.services.toolbox.api.strings.StringProvider
|
||||||
class FakeStringProvider(
|
class FakeStringProvider(
|
||||||
private val defaultResult: String = "A string"
|
private val defaultResult: String = "A string"
|
||||||
) : StringProvider {
|
) : StringProvider {
|
||||||
|
var lastResIdParam: Int? = null
|
||||||
override fun getString(resId: Int): String {
|
override fun getString(resId: Int): String {
|
||||||
|
lastResIdParam = resId
|
||||||
return defaultResult
|
return defaultResult
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun getString(resId: Int, vararg formatArgs: Any?): String {
|
override fun getString(resId: Int, vararg formatArgs: Any?): String {
|
||||||
|
lastResIdParam = resId
|
||||||
return defaultResult + formatArgs.joinToString()
|
return defaultResult + formatArgs.joinToString()
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun getQuantityString(resId: Int, quantity: Int, vararg formatArgs: Any?): String {
|
override fun getQuantityString(resId: Int, quantity: Int, vararg formatArgs: Any?): String {
|
||||||
|
lastResIdParam = resId
|
||||||
return defaultResult + " ($quantity) " + formatArgs.joinToString()
|
return defaultResult + " ($quantity) " + formatArgs.joinToString()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -1,3 +1,3 @@
|
||||||
version https://git-lfs.github.com/spec/v1
|
version https://git-lfs.github.com/spec/v1
|
||||||
oid sha256:aad48b326c07ed1eda341817b9a30cc74ef6cc83dd80406dd26aed858112eda8
|
oid sha256:7275edb15579beb09be957ca2fb42ac95fc3131a9349446920db9797d79efca5
|
||||||
size 252914
|
size 439078
|
||||||
|
|
|
||||||
|
|
@ -1,3 +0,0 @@
|
||||||
version https://git-lfs.github.com/spec/v1
|
|
||||||
oid sha256:a1dab0d4f896e496af650cab32f2b1fd8572ab698b6cbfd84166334216117149
|
|
||||||
size 255494
|
|
||||||
|
|
@ -1,3 +1,3 @@
|
||||||
version https://git-lfs.github.com/spec/v1
|
version https://git-lfs.github.com/spec/v1
|
||||||
oid sha256:e63a6eaedca373d7154c66d7f9fc5f52e4999dbfaafe00bb06cf94a86e2fb762
|
oid sha256:50de6c03736fc71fc3029dadf353c212bfc504a643d6216594f5417357daf16c
|
||||||
size 105538
|
size 173445
|
||||||
|
|
|
||||||
|
|
@ -1,3 +0,0 @@
|
||||||
version https://git-lfs.github.com/spec/v1
|
|
||||||
oid sha256:ace6730f6dc2fe45aa2cb095b59453cf449de62a98508587439d277ff3fd23db
|
|
||||||
size 107041
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue