Merge branch 'develop' into renovate/com.posthog-posthog-android-3.x
This commit is contained in:
commit
70223bf350
883 changed files with 1927 additions and 1818 deletions
2
.github/workflows/quality.yml
vendored
2
.github/workflows/quality.yml
vendored
|
|
@ -138,7 +138,7 @@ jobs:
|
|||
- name: Build Fdroid Debug
|
||||
run: ./gradlew :app:compileFdroidDebugKotlin $CI_GRADLE_ARG_PROPERTIES
|
||||
- name: Run lint
|
||||
run: ./gradlew :app:lintGplayDebug :app:lintFdroidDebug $CI_GRADLE_ARG_PROPERTIES
|
||||
run: ./gradlew :app:lintGplayDebug :app:lintFdroidDebug lintDebug $CI_GRADLE_ARG_PROPERTIES --continue
|
||||
- name: Upload reports
|
||||
if: always()
|
||||
uses: actions/upload-artifact@v4
|
||||
|
|
|
|||
|
|
@ -26,6 +26,7 @@ import io.element.android.libraries.core.meta.BuildMeta
|
|||
import io.element.android.libraries.matrix.api.MatrixClient
|
||||
import io.element.android.libraries.matrix.api.encryption.EncryptionService
|
||||
import io.element.android.libraries.matrix.api.encryption.RecoveryState
|
||||
import io.element.android.libraries.matrix.api.oidc.AccountManagementAction
|
||||
import io.element.android.libraries.matrix.api.roomlist.RoomListService
|
||||
import io.element.android.libraries.matrix.api.sync.SlidingSyncVersion
|
||||
import io.element.android.libraries.matrix.api.sync.SyncService
|
||||
|
|
@ -35,6 +36,7 @@ import io.element.android.libraries.matrix.api.verification.SessionVerifiedStatu
|
|||
import io.element.android.libraries.push.api.PushService
|
||||
import io.element.android.libraries.pushproviders.api.RegistrationFailure
|
||||
import io.element.android.services.analytics.api.AnalyticsService
|
||||
import kotlinx.coroutines.CoroutineScope
|
||||
import kotlinx.coroutines.flow.combine
|
||||
import kotlinx.coroutines.flow.launchIn
|
||||
import kotlinx.coroutines.flow.onEach
|
||||
|
|
@ -60,6 +62,7 @@ class LoggedInPresenter @Inject constructor(
|
|||
pushService.ignoreRegistrationError(matrixClient.sessionId)
|
||||
}.collectAsState(initial = false)
|
||||
val pusherRegistrationState = remember<MutableState<AsyncData<Unit>>> { mutableStateOf(AsyncData.Uninitialized) }
|
||||
LaunchedEffect(Unit) { preloadAccountManagementUrl() }
|
||||
LaunchedEffect(Unit) {
|
||||
sessionVerificationService.sessionVerifiedStatus
|
||||
.onEach { sessionVerifiedStatus ->
|
||||
|
|
@ -202,4 +205,9 @@ class LoggedInPresenter @Inject constructor(
|
|||
analyticsService.capture(CryptoSessionStateChange(changeRecoveryState, changeVerificationState))
|
||||
}
|
||||
}
|
||||
|
||||
private fun CoroutineScope.preloadAccountManagementUrl() = launch {
|
||||
matrixClient.getAccountManagementUrl(AccountManagementAction.Profile)
|
||||
matrixClient.getAccountManagementUrl(AccountManagementAction.SessionsList)
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -5,12 +5,11 @@
|
|||
* Please see LICENSE files in the repository root for full details.
|
||||
*/
|
||||
|
||||
@file:OptIn(ExperimentalCoroutinesApi::class)
|
||||
|
||||
package io.element.android.appnav.loggedin
|
||||
|
||||
import app.cash.molecule.RecompositionMode
|
||||
import app.cash.molecule.moleculeFlow
|
||||
import app.cash.turbine.ReceiveTurbine
|
||||
import app.cash.turbine.test
|
||||
import com.google.common.truth.Truth.assertThat
|
||||
import im.vector.app.features.analytics.plan.CryptoSessionStateChange
|
||||
import im.vector.app.features.analytics.plan.UserProperties
|
||||
|
|
@ -19,6 +18,7 @@ import io.element.android.libraries.matrix.api.MatrixClient
|
|||
import io.element.android.libraries.matrix.api.core.SessionId
|
||||
import io.element.android.libraries.matrix.api.encryption.EncryptionService
|
||||
import io.element.android.libraries.matrix.api.encryption.RecoveryState
|
||||
import io.element.android.libraries.matrix.api.oidc.AccountManagementAction
|
||||
import io.element.android.libraries.matrix.api.roomlist.RoomListService
|
||||
import io.element.android.libraries.matrix.api.sync.SlidingSyncVersion
|
||||
import io.element.android.libraries.matrix.api.sync.SyncState
|
||||
|
|
@ -45,8 +45,8 @@ import io.element.android.tests.testutils.lambda.any
|
|||
import io.element.android.tests.testutils.lambda.lambdaError
|
||||
import io.element.android.tests.testutils.lambda.lambdaRecorder
|
||||
import io.element.android.tests.testutils.lambda.value
|
||||
import io.element.android.tests.testutils.test
|
||||
import kotlinx.coroutines.ExperimentalCoroutinesApi
|
||||
import kotlinx.coroutines.test.TestScope
|
||||
import kotlinx.coroutines.test.advanceUntilIdle
|
||||
import kotlinx.coroutines.test.runTest
|
||||
import org.junit.Rule
|
||||
|
|
@ -58,10 +58,7 @@ class LoggedInPresenterTest {
|
|||
|
||||
@Test
|
||||
fun `present - initial state`() = runTest {
|
||||
val presenter = createLoggedInPresenter()
|
||||
moleculeFlow(RecompositionMode.Immediate) {
|
||||
presenter.present()
|
||||
}.test {
|
||||
createLoggedInPresenter().test {
|
||||
val initialState = awaitItem()
|
||||
assertThat(initialState.showSyncSpinner).isFalse()
|
||||
assertThat(initialState.pusherRegistrationState.isUninitialized()).isTrue()
|
||||
|
|
@ -69,13 +66,32 @@ class LoggedInPresenterTest {
|
|||
}
|
||||
}
|
||||
|
||||
@Test
|
||||
fun `present - ensure that account urls are preloaded`() = runTest {
|
||||
val accountManagementUrlResult = lambdaRecorder<AccountManagementAction?, Result<String?>> { Result.success("aUrl") }
|
||||
val matrixClient = FakeMatrixClient(
|
||||
accountManagementUrlResult = accountManagementUrlResult,
|
||||
)
|
||||
createLoggedInPresenter(
|
||||
matrixClient = matrixClient,
|
||||
).test {
|
||||
awaitItem()
|
||||
advanceUntilIdle()
|
||||
accountManagementUrlResult.assertions().isCalledExactly(2)
|
||||
.withSequence(
|
||||
listOf(value(AccountManagementAction.Profile)),
|
||||
listOf(value(AccountManagementAction.SessionsList)),
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
@Test
|
||||
fun `present - show sync spinner`() = runTest {
|
||||
val roomListService = FakeRoomListService()
|
||||
val presenter = createLoggedInPresenter(roomListService, SyncState.Running)
|
||||
moleculeFlow(RecompositionMode.Immediate) {
|
||||
presenter.present()
|
||||
}.test {
|
||||
createLoggedInPresenter(
|
||||
syncState = SyncState.Running,
|
||||
matrixClient = FakeMatrixClient(roomListService = roomListService),
|
||||
).test {
|
||||
val initialState = awaitItem()
|
||||
assertThat(initialState.showSyncSpinner).isFalse()
|
||||
roomListService.postSyncIndicator(RoomListService.SyncIndicator.Show)
|
||||
|
|
@ -92,18 +108,18 @@ class LoggedInPresenterTest {
|
|||
val verificationService = FakeSessionVerificationService()
|
||||
val encryptionService = FakeEncryptionService()
|
||||
val buildMeta = aBuildMeta()
|
||||
val presenter = LoggedInPresenter(
|
||||
matrixClient = FakeMatrixClient(roomListService = roomListService, encryptionService = encryptionService),
|
||||
LoggedInPresenter(
|
||||
matrixClient = FakeMatrixClient(
|
||||
roomListService = roomListService,
|
||||
encryptionService = encryptionService,
|
||||
),
|
||||
syncService = FakeSyncService(initialSyncState = SyncState.Running),
|
||||
pushService = FakePushService(),
|
||||
sessionVerificationService = verificationService,
|
||||
analyticsService = analyticsService,
|
||||
encryptionService = encryptionService,
|
||||
buildMeta = buildMeta,
|
||||
)
|
||||
moleculeFlow(RecompositionMode.Immediate) {
|
||||
presenter.present()
|
||||
}.test {
|
||||
).test {
|
||||
encryptionService.emitRecoveryState(RecoveryState.UNKNOWN)
|
||||
encryptionService.emitRecoveryState(RecoveryState.INCOMPLETE)
|
||||
verificationService.emitVerifiedStatus(SessionVerifiedStatus.Verified)
|
||||
|
|
@ -129,13 +145,10 @@ class LoggedInPresenterTest {
|
|||
val verificationService = FakeSessionVerificationService(
|
||||
initialSessionVerifiedStatus = SessionVerifiedStatus.NotVerified
|
||||
)
|
||||
val presenter = createLoggedInPresenter(
|
||||
createLoggedInPresenter(
|
||||
pushService = pushService,
|
||||
sessionVerificationService = verificationService,
|
||||
)
|
||||
moleculeFlow(RecompositionMode.Immediate) {
|
||||
presenter.present()
|
||||
}.test {
|
||||
).test {
|
||||
val finalState = awaitFirstItem()
|
||||
assertThat(finalState.pusherRegistrationState.errorOrNull())
|
||||
.isInstanceOf(PusherRegistrationFailure.AccountNotVerified::class.java)
|
||||
|
|
@ -155,13 +168,13 @@ class LoggedInPresenterTest {
|
|||
val pushService = createFakePushService(
|
||||
registerWithLambda = lambda,
|
||||
)
|
||||
val presenter = createLoggedInPresenter(
|
||||
createLoggedInPresenter(
|
||||
pushService = pushService,
|
||||
sessionVerificationService = sessionVerificationService,
|
||||
)
|
||||
moleculeFlow(RecompositionMode.Immediate) {
|
||||
presenter.present()
|
||||
}.test {
|
||||
matrixClient = FakeMatrixClient(
|
||||
accountManagementUrlResult = { Result.success(null) },
|
||||
),
|
||||
).test {
|
||||
val finalState = awaitFirstItem()
|
||||
assertThat(finalState.pusherRegistrationState.isSuccess()).isTrue()
|
||||
lambda.assertions()
|
||||
|
|
@ -188,13 +201,13 @@ class LoggedInPresenterTest {
|
|||
val pushService = createFakePushService(
|
||||
registerWithLambda = lambda,
|
||||
)
|
||||
val presenter = createLoggedInPresenter(
|
||||
createLoggedInPresenter(
|
||||
pushService = pushService,
|
||||
sessionVerificationService = sessionVerificationService,
|
||||
)
|
||||
moleculeFlow(RecompositionMode.Immediate) {
|
||||
presenter.present()
|
||||
}.test {
|
||||
matrixClient = FakeMatrixClient(
|
||||
accountManagementUrlResult = { Result.success(null) },
|
||||
),
|
||||
).test {
|
||||
val finalState = awaitFirstItem()
|
||||
assertThat(finalState.pusherRegistrationState.isFailure()).isTrue()
|
||||
lambda.assertions()
|
||||
|
|
@ -233,13 +246,13 @@ class LoggedInPresenterTest {
|
|||
currentPushProvider = { pushProvider },
|
||||
registerWithLambda = lambda,
|
||||
)
|
||||
val presenter = createLoggedInPresenter(
|
||||
createLoggedInPresenter(
|
||||
pushService = pushService,
|
||||
sessionVerificationService = sessionVerificationService,
|
||||
)
|
||||
moleculeFlow(RecompositionMode.Immediate) {
|
||||
presenter.present()
|
||||
}.test {
|
||||
matrixClient = FakeMatrixClient(
|
||||
accountManagementUrlResult = { Result.success(null) },
|
||||
),
|
||||
).test {
|
||||
val finalState = awaitFirstItem()
|
||||
assertThat(finalState.pusherRegistrationState.isSuccess()).isTrue()
|
||||
lambda.assertions()
|
||||
|
|
@ -277,13 +290,13 @@ class LoggedInPresenterTest {
|
|||
currentPushProvider = { pushProvider },
|
||||
registerWithLambda = lambda,
|
||||
)
|
||||
val presenter = createLoggedInPresenter(
|
||||
createLoggedInPresenter(
|
||||
pushService = pushService,
|
||||
sessionVerificationService = sessionVerificationService,
|
||||
)
|
||||
moleculeFlow(RecompositionMode.Immediate) {
|
||||
presenter.present()
|
||||
}.test {
|
||||
matrixClient = FakeMatrixClient(
|
||||
accountManagementUrlResult = { Result.success(null) },
|
||||
),
|
||||
).test {
|
||||
val finalState = awaitFirstItem()
|
||||
assertThat(finalState.pusherRegistrationState.isSuccess()).isTrue()
|
||||
lambda.assertions()
|
||||
|
|
@ -317,13 +330,10 @@ class LoggedInPresenterTest {
|
|||
currentPushProvider = { pushProvider },
|
||||
registerWithLambda = lambda,
|
||||
)
|
||||
val presenter = createLoggedInPresenter(
|
||||
createLoggedInPresenter(
|
||||
pushService = pushService,
|
||||
sessionVerificationService = sessionVerificationService,
|
||||
)
|
||||
moleculeFlow(RecompositionMode.Immediate) {
|
||||
presenter.present()
|
||||
}.test {
|
||||
).test {
|
||||
val finalState = awaitFirstItem()
|
||||
assertThat(finalState.pusherRegistrationState.errorOrNull())
|
||||
.isInstanceOf(PusherRegistrationFailure.NoDistributorsAvailable::class.java)
|
||||
|
|
@ -345,13 +355,10 @@ class LoggedInPresenterTest {
|
|||
registerWithLambda = lambda,
|
||||
setIgnoreRegistrationErrorLambda = setIgnoreRegistrationErrorLambda,
|
||||
)
|
||||
val presenter = createLoggedInPresenter(
|
||||
createLoggedInPresenter(
|
||||
pushService = pushService,
|
||||
sessionVerificationService = sessionVerificationService,
|
||||
)
|
||||
moleculeFlow(RecompositionMode.Immediate) {
|
||||
presenter.present()
|
||||
}.test {
|
||||
).test {
|
||||
val finalState = awaitFirstItem()
|
||||
assertThat(finalState.pusherRegistrationState.errorOrNull())
|
||||
.isInstanceOf(PusherRegistrationFailure.NoProvidersAvailable::class.java)
|
||||
|
|
@ -394,13 +401,10 @@ class LoggedInPresenterTest {
|
|||
registerWithLambda = lambda,
|
||||
selectPushProviderLambda = selectPushProviderLambda,
|
||||
)
|
||||
val presenter = createLoggedInPresenter(
|
||||
createLoggedInPresenter(
|
||||
pushService = pushService,
|
||||
sessionVerificationService = sessionVerificationService,
|
||||
)
|
||||
moleculeFlow(RecompositionMode.Immediate) {
|
||||
presenter.present()
|
||||
}.test {
|
||||
).test {
|
||||
val finalState = awaitFirstItem()
|
||||
assertThat(finalState.pusherRegistrationState.errorOrNull())
|
||||
.isInstanceOf(PusherRegistrationFailure.NoDistributorsAvailable::class.java)
|
||||
|
|
@ -445,13 +449,13 @@ class LoggedInPresenterTest {
|
|||
pushProvider1 = pushProvider1,
|
||||
registerWithLambda = lambda,
|
||||
)
|
||||
val presenter = createLoggedInPresenter(
|
||||
createLoggedInPresenter(
|
||||
pushService = pushService,
|
||||
sessionVerificationService = sessionVerificationService,
|
||||
)
|
||||
moleculeFlow(RecompositionMode.Immediate) {
|
||||
presenter.present()
|
||||
}.test {
|
||||
matrixClient = FakeMatrixClient(
|
||||
accountManagementUrlResult = { Result.success(null) },
|
||||
),
|
||||
).test {
|
||||
val finalState = awaitFirstItem()
|
||||
assertThat(finalState.pusherRegistrationState.isSuccess()).isTrue()
|
||||
lambda.assertions().isCalledOnce()
|
||||
|
|
@ -505,10 +509,9 @@ class LoggedInPresenterTest {
|
|||
currentSlidingSyncVersionLambda = { Result.success(SlidingSyncVersion.Proxy) },
|
||||
availableSlidingSyncVersionsLambda = { Result.success(listOf(SlidingSyncVersion.Native)) },
|
||||
)
|
||||
val presenter = createLoggedInPresenter(matrixClient = matrixClient)
|
||||
moleculeFlow(RecompositionMode.Immediate) {
|
||||
presenter.present()
|
||||
}.test {
|
||||
createLoggedInPresenter(
|
||||
matrixClient = matrixClient,
|
||||
).test {
|
||||
val initialState = awaitItem()
|
||||
assertThat(initialState.forceNativeSlidingSyncMigration).isFalse()
|
||||
|
||||
|
|
@ -525,13 +528,14 @@ class LoggedInPresenterTest {
|
|||
assertThat(userInitiated).isTrue()
|
||||
assertThat(ignoreSdkError).isTrue()
|
||||
}
|
||||
val matrixClient = FakeMatrixClient().apply {
|
||||
val matrixClient = FakeMatrixClient(
|
||||
accountManagementUrlResult = { Result.success(null) },
|
||||
).apply {
|
||||
this.logoutLambda = logoutLambda
|
||||
}
|
||||
val presenter = createLoggedInPresenter(matrixClient = matrixClient)
|
||||
moleculeFlow(RecompositionMode.Immediate) {
|
||||
presenter.present()
|
||||
}.test {
|
||||
createLoggedInPresenter(
|
||||
matrixClient = matrixClient,
|
||||
).test {
|
||||
val initialState = awaitItem()
|
||||
|
||||
initialState.eventSink(LoggedInEvents.LogoutAndMigrateToNativeSlidingSync)
|
||||
|
|
@ -547,14 +551,15 @@ class LoggedInPresenterTest {
|
|||
return awaitItem()
|
||||
}
|
||||
|
||||
private fun TestScope.createLoggedInPresenter(
|
||||
roomListService: RoomListService = FakeRoomListService(),
|
||||
private fun createLoggedInPresenter(
|
||||
syncState: SyncState = SyncState.Running,
|
||||
analyticsService: AnalyticsService = FakeAnalyticsService(),
|
||||
sessionVerificationService: SessionVerificationService = FakeSessionVerificationService(),
|
||||
encryptionService: EncryptionService = FakeEncryptionService(),
|
||||
pushService: PushService = FakePushService(),
|
||||
matrixClient: MatrixClient = FakeMatrixClient(roomListService = roomListService),
|
||||
matrixClient: MatrixClient = FakeMatrixClient(
|
||||
accountManagementUrlResult = { Result.success(null) },
|
||||
),
|
||||
buildMeta: BuildMeta = aBuildMeta(),
|
||||
): LoggedInPresenter {
|
||||
return LoggedInPresenter(
|
||||
|
|
|
|||
|
|
@ -166,14 +166,17 @@ allprojects {
|
|||
// Register quality check tasks.
|
||||
tasks.register("runQualityChecks") {
|
||||
dependsOn(":tests:konsist:testDebugUnitTest")
|
||||
dependsOn(":app:lintGplayDebug")
|
||||
project.subprojects {
|
||||
// For some reason `findByName("lint")` doesn't work
|
||||
tasks.findByPath("$path:lint")?.let { dependsOn(it) }
|
||||
tasks.findByPath("$path:lintDebug")?.let { dependsOn(it) }
|
||||
tasks.findByName("detekt")?.let { dependsOn(it) }
|
||||
tasks.findByName("ktlintCheck")?.let { dependsOn(it) }
|
||||
// tasks.findByName("buildHealth")?.let { dependsOn(it) }
|
||||
}
|
||||
dependsOn(":app:knitCheck")
|
||||
|
||||
// Make sure all checks run even if some fail
|
||||
gradle.startParameter.isContinueOnFailure = true
|
||||
}
|
||||
|
||||
// Make sure to delete old screenshots before recording new ones
|
||||
|
|
|
|||
|
|
@ -100,7 +100,7 @@ internal fun IncomingCallScreen(
|
|||
ActionButton(
|
||||
size = 64.dp,
|
||||
onClick = { onAnswer(notificationData) },
|
||||
icon = CompoundIcons.VoiceCall(),
|
||||
icon = CompoundIcons.VoiceCallSolid(),
|
||||
title = stringResource(CommonStrings.action_accept),
|
||||
backgroundColor = ElementTheme.colors.iconSuccessPrimary,
|
||||
borderColor = ElementTheme.colors.borderSuccessSubtle
|
||||
|
|
|
|||
|
|
@ -136,7 +136,7 @@ private fun ColumnScope.Buttons(
|
|||
verticalAlignment = Alignment.CenterVertically,
|
||||
) {
|
||||
Icon(
|
||||
imageVector = CompoundIcons.Error(),
|
||||
imageVector = CompoundIcons.ErrorSolid(),
|
||||
tint = ElementTheme.colors.iconCriticalPrimary,
|
||||
contentDescription = null,
|
||||
modifier = Modifier.size(24.dp)
|
||||
|
|
|
|||
|
|
@ -391,7 +391,7 @@ private fun VerifiedUserSendFailureView(
|
|||
modifier = modifier
|
||||
.clickable(onClick = onClick)
|
||||
.padding(horizontal = 16.dp, vertical = 8.dp),
|
||||
leadingContent = ListItemContent.Icon(IconSource.Vector(CompoundIcons.Error())),
|
||||
leadingContent = ListItemContent.Icon(IconSource.Vector(CompoundIcons.ErrorSolid())),
|
||||
trailingContent = ListItemContent.Icon(IconSource.Vector(CompoundIcons.ChevronRight())),
|
||||
headlineContent = {
|
||||
Text(
|
||||
|
|
|
|||
|
|
@ -68,7 +68,7 @@ fun TimelineEventTimestampView(
|
|||
val isVerifiedUserSendFailure = event.localSendState is LocalEventSendState.Failed.VerifiedUser
|
||||
Spacer(modifier = Modifier.width(2.dp))
|
||||
Icon(
|
||||
imageVector = CompoundIcons.Error(),
|
||||
imageVector = CompoundIcons.ErrorSolid(),
|
||||
contentDescription = stringResource(id = CommonStrings.common_sending_failed),
|
||||
tint = tint,
|
||||
modifier = Modifier
|
||||
|
|
|
|||
|
|
@ -31,7 +31,7 @@ fun TimelineItemLegacyCallInviteView(
|
|||
modifier = modifier,
|
||||
) {
|
||||
Icon(
|
||||
imageVector = CompoundIcons.VoiceCall(),
|
||||
imageVector = CompoundIcons.VoiceCallSolid(),
|
||||
contentDescription = null,
|
||||
tint = ElementTheme.colors.iconSecondary,
|
||||
)
|
||||
|
|
|
|||
|
|
@ -83,19 +83,19 @@ class NotificationSettingsPresenter @Inject constructor(
|
|||
}
|
||||
}
|
||||
}
|
||||
// List of Distributor names
|
||||
val distributorNames = remember {
|
||||
distributors.map { it.second.name }.toImmutableList()
|
||||
// List of Distributors
|
||||
val availableDistributors = remember {
|
||||
distributors.map { it.second }.toImmutableList()
|
||||
}
|
||||
|
||||
var currentDistributorName by remember { mutableStateOf<AsyncData<String>>(AsyncData.Uninitialized) }
|
||||
var currentDistributor by remember { mutableStateOf<AsyncData<Distributor>>(AsyncData.Uninitialized) }
|
||||
var refreshPushProvider by remember { mutableIntStateOf(0) }
|
||||
|
||||
LaunchedEffect(refreshPushProvider) {
|
||||
val p = pushService.getCurrentPushProvider()
|
||||
val name = p?.getCurrentDistributor(matrixClient.sessionId)?.name
|
||||
currentDistributorName = if (name != null) {
|
||||
AsyncData.Success(name)
|
||||
val distributor = p?.getCurrentDistributor(matrixClient.sessionId)
|
||||
currentDistributor = if (distributor != null) {
|
||||
AsyncData.Success(distributor)
|
||||
} else {
|
||||
AsyncData.Failure(Exception("Failed to get current push provider"))
|
||||
}
|
||||
|
|
@ -108,24 +108,23 @@ class NotificationSettingsPresenter @Inject constructor(
|
|||
) = launch {
|
||||
showChangePushProviderDialog = false
|
||||
data ?: return@launch
|
||||
// No op if the value is the same.
|
||||
if (data.second.name == currentDistributorName.dataOrNull()) return@launch
|
||||
currentDistributorName = AsyncData.Loading(currentDistributorName.dataOrNull())
|
||||
data.let { (pushProvider, distributor) ->
|
||||
pushService.registerWith(
|
||||
matrixClient = matrixClient,
|
||||
pushProvider = pushProvider,
|
||||
distributor = distributor
|
||||
val (pushProvider, distributor) = data
|
||||
// No op if the distributor is the same.
|
||||
if (distributor == currentDistributor.dataOrNull()) return@launch
|
||||
currentDistributor = AsyncData.Loading(currentDistributor.dataOrNull())
|
||||
pushService.registerWith(
|
||||
matrixClient = matrixClient,
|
||||
pushProvider = pushProvider,
|
||||
distributor = distributor
|
||||
)
|
||||
.fold(
|
||||
{
|
||||
refreshPushProvider++
|
||||
},
|
||||
{
|
||||
currentDistributor = AsyncData.Failure(it)
|
||||
}
|
||||
)
|
||||
.fold(
|
||||
{
|
||||
refreshPushProvider++
|
||||
},
|
||||
{
|
||||
currentDistributorName = AsyncData.Failure(it)
|
||||
}
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
fun handleEvents(event: NotificationSettingsEvents) {
|
||||
|
|
@ -162,8 +161,8 @@ class NotificationSettingsPresenter @Inject constructor(
|
|||
appNotificationsEnabled = appNotificationsEnabled.value
|
||||
),
|
||||
changeNotificationSettingAction = changeNotificationSettingAction.value,
|
||||
currentPushDistributor = currentDistributorName,
|
||||
availablePushDistributors = distributorNames,
|
||||
currentPushDistributor = currentDistributor,
|
||||
availablePushDistributors = availableDistributors,
|
||||
showChangePushProviderDialog = showChangePushProviderDialog,
|
||||
fullScreenIntentPermissionsState = key(refreshFullScreenIntentSettings) { fullScreenIntentPermissionsPresenter.present() },
|
||||
eventSink = ::handleEvents
|
||||
|
|
|
|||
|
|
@ -12,6 +12,7 @@ import io.element.android.libraries.architecture.AsyncAction
|
|||
import io.element.android.libraries.architecture.AsyncData
|
||||
import io.element.android.libraries.fullscreenintent.api.FullScreenIntentPermissionsState
|
||||
import io.element.android.libraries.matrix.api.room.RoomNotificationMode
|
||||
import io.element.android.libraries.pushproviders.api.Distributor
|
||||
import kotlinx.collections.immutable.ImmutableList
|
||||
|
||||
@Immutable
|
||||
|
|
@ -19,8 +20,8 @@ data class NotificationSettingsState(
|
|||
val matrixSettings: MatrixSettings,
|
||||
val appSettings: AppSettings,
|
||||
val changeNotificationSettingAction: AsyncAction<Unit>,
|
||||
val currentPushDistributor: AsyncData<String>,
|
||||
val availablePushDistributors: ImmutableList<String>,
|
||||
val currentPushDistributor: AsyncData<Distributor>,
|
||||
val availablePushDistributors: ImmutableList<Distributor>,
|
||||
val showChangePushProviderDialog: Boolean,
|
||||
val fullScreenIntentPermissionsState: FullScreenIntentPermissionsState,
|
||||
val eventSink: (NotificationSettingsEvents) -> Unit,
|
||||
|
|
|
|||
|
|
@ -13,6 +13,7 @@ import io.element.android.libraries.architecture.AsyncData
|
|||
import io.element.android.libraries.fullscreenintent.api.FullScreenIntentPermissionsState
|
||||
import io.element.android.libraries.fullscreenintent.api.aFullScreenIntentPermissionsState
|
||||
import io.element.android.libraries.matrix.api.room.RoomNotificationMode
|
||||
import io.element.android.libraries.pushproviders.api.Distributor
|
||||
import kotlinx.collections.immutable.persistentListOf
|
||||
import kotlinx.collections.immutable.toImmutableList
|
||||
|
||||
|
|
@ -24,11 +25,19 @@ open class NotificationSettingsStateProvider : PreviewParameterProvider<Notifica
|
|||
aValidNotificationSettingsState(changeNotificationSettingAction = AsyncAction.Loading),
|
||||
aValidNotificationSettingsState(changeNotificationSettingAction = AsyncAction.Failure(Throwable("error"))),
|
||||
aValidNotificationSettingsState(
|
||||
availablePushDistributors = listOf("Firebase"),
|
||||
availablePushDistributors = listOf(aDistributor("Firebase")),
|
||||
changeNotificationSettingAction = AsyncAction.Failure(Throwable("error")),
|
||||
),
|
||||
aValidNotificationSettingsState(availablePushDistributors = listOf("Firebase")),
|
||||
aValidNotificationSettingsState(availablePushDistributors = listOf(aDistributor("Firebase"))),
|
||||
aValidNotificationSettingsState(showChangePushProviderDialog = true),
|
||||
aValidNotificationSettingsState(
|
||||
availablePushDistributors = listOf(
|
||||
aDistributor("Firebase"),
|
||||
aDistributor("ntfy", "app.id1"),
|
||||
aDistributor("ntfy", "app.id2"),
|
||||
),
|
||||
showChangePushProviderDialog = true,
|
||||
),
|
||||
aValidNotificationSettingsState(currentPushDistributor = AsyncData.Loading()),
|
||||
aValidNotificationSettingsState(currentPushDistributor = AsyncData.Failure(Exception("Failed to change distributor"))),
|
||||
aInvalidNotificationSettingsState(),
|
||||
|
|
@ -45,8 +54,11 @@ fun aValidNotificationSettingsState(
|
|||
inviteForMeNotificationsEnabled: Boolean = true,
|
||||
systemNotificationsEnabled: Boolean = true,
|
||||
appNotificationEnabled: Boolean = true,
|
||||
currentPushDistributor: AsyncData<String> = AsyncData.Success("Firebase"),
|
||||
availablePushDistributors: List<String> = listOf("Firebase", "ntfy"),
|
||||
currentPushDistributor: AsyncData<Distributor> = AsyncData.Success(aDistributor("Firebase")),
|
||||
availablePushDistributors: List<Distributor> = listOf(
|
||||
aDistributor("Firebase"),
|
||||
aDistributor("ntfy"),
|
||||
),
|
||||
showChangePushProviderDialog: Boolean = false,
|
||||
fullScreenIntentPermissionsState: FullScreenIntentPermissionsState = aFullScreenIntentPermissionsState(),
|
||||
eventSink: (NotificationSettingsEvents) -> Unit = {},
|
||||
|
|
@ -88,3 +100,11 @@ fun aInvalidNotificationSettingsState(
|
|||
fullScreenIntentPermissionsState = aFullScreenIntentPermissionsState(),
|
||||
eventSink = eventSink,
|
||||
)
|
||||
|
||||
fun aDistributor(
|
||||
name: String = "Name",
|
||||
value: String = "$name Value",
|
||||
) = Distributor(
|
||||
value = value,
|
||||
name = name,
|
||||
)
|
||||
|
|
|
|||
|
|
@ -132,7 +132,7 @@ private fun NotificationSettingsContentView(
|
|||
if (!state.fullScreenIntentPermissionsState.permissionGranted) {
|
||||
PreferenceCategory {
|
||||
PreferenceText(
|
||||
icon = CompoundIcons.VoiceCall(),
|
||||
icon = CompoundIcons.VoiceCallSolid(),
|
||||
title = stringResource(id = R.string.full_screen_intent_banner_title),
|
||||
subtitle = stringResource(R.string.full_screen_intent_banner_message),
|
||||
onClick = {
|
||||
|
|
@ -206,7 +206,7 @@ private fun NotificationSettingsContentView(
|
|||
stringResource(id = CommonStrings.common_error)
|
||||
)
|
||||
is AsyncData.Success -> ListItemContent.Text(
|
||||
state.currentPushDistributor.dataOrNull() ?: ""
|
||||
state.currentPushDistributor.dataOrNull()?.name ?: ""
|
||||
)
|
||||
},
|
||||
onClick = {
|
||||
|
|
@ -219,8 +219,14 @@ private fun NotificationSettingsContentView(
|
|||
if (state.showChangePushProviderDialog) {
|
||||
SingleSelectionDialog(
|
||||
title = stringResource(id = R.string.screen_advanced_settings_choose_distributor_dialog_title_android),
|
||||
options = state.availablePushDistributors.map {
|
||||
ListOption(title = it)
|
||||
options = state.availablePushDistributors.map { distributor ->
|
||||
// If there are several distributors with the same name, use the full name
|
||||
val title = if (state.availablePushDistributors.count { it.name == distributor.name } > 1) {
|
||||
distributor.fullName
|
||||
} else {
|
||||
distributor.name
|
||||
}
|
||||
ListOption(title = title)
|
||||
}.toImmutableList(),
|
||||
initialSelection = state.availablePushDistributors.indexOf(state.currentPushDistributor.dataOrNull()),
|
||||
onSelectOption = { index ->
|
||||
|
|
|
|||
|
|
@ -240,8 +240,11 @@ class NotificationSettingsPresenterTest {
|
|||
presenter.present()
|
||||
}.test {
|
||||
val initialState = awaitLastSequentialItem()
|
||||
assertThat(initialState.currentPushDistributor).isEqualTo(AsyncData.Success("aDistributorName0"))
|
||||
assertThat(initialState.availablePushDistributors).containsExactly("aDistributorName0", "aDistributorName1")
|
||||
assertThat(initialState.currentPushDistributor).isEqualTo(AsyncData.Success(Distributor(value = "aDistributorValue0", name = "aDistributorName0")))
|
||||
assertThat(initialState.availablePushDistributors).containsExactly(
|
||||
Distributor(value = "aDistributorValue0", name = "aDistributorName0"),
|
||||
Distributor(value = "aDistributorValue1", name = "aDistributorName1"),
|
||||
)
|
||||
initialState.eventSink.invoke(NotificationSettingsEvents.ChangePushProvider)
|
||||
val withDialog = awaitItem()
|
||||
assertThat(withDialog.showChangePushProviderDialog).isTrue()
|
||||
|
|
@ -257,11 +260,35 @@ class NotificationSettingsPresenterTest {
|
|||
assertThat(withNewProvider.currentPushDistributor).isInstanceOf(AsyncData.Loading::class.java)
|
||||
skipItems(1)
|
||||
val lastItem = awaitItem()
|
||||
assertThat(lastItem.currentPushDistributor).isEqualTo(AsyncData.Success("aDistributorName1"))
|
||||
assertThat(lastItem.currentPushDistributor).isEqualTo(AsyncData.Success(Distributor(value = "aDistributorValue1", name = "aDistributorName1")))
|
||||
cancelAndIgnoreRemainingEvents()
|
||||
}
|
||||
}
|
||||
|
||||
@Test
|
||||
fun `present - change push provider to the same value is no op`() = runTest {
|
||||
val presenter = createNotificationSettingsPresenter(
|
||||
pushService = createFakePushService(),
|
||||
)
|
||||
moleculeFlow(RecompositionMode.Immediate) {
|
||||
presenter.present()
|
||||
}.test {
|
||||
val initialState = awaitLastSequentialItem()
|
||||
assertThat(initialState.currentPushDistributor).isEqualTo(AsyncData.Success(Distributor(value = "aDistributorValue0", name = "aDistributorName0")))
|
||||
assertThat(initialState.availablePushDistributors).containsExactly(
|
||||
Distributor(value = "aDistributorValue0", name = "aDistributorName0"),
|
||||
Distributor(value = "aDistributorValue1", name = "aDistributorName1"),
|
||||
)
|
||||
initialState.eventSink.invoke(NotificationSettingsEvents.ChangePushProvider)
|
||||
assertThat(awaitItem().showChangePushProviderDialog).isTrue()
|
||||
// Choose the same value (index 0)
|
||||
initialState.eventSink(NotificationSettingsEvents.SetPushProvider(0))
|
||||
val withNewProvider = awaitItem()
|
||||
assertThat(withNewProvider.showChangePushProviderDialog).isFalse()
|
||||
expectNoEvents()
|
||||
}
|
||||
}
|
||||
|
||||
@Test
|
||||
fun `present - RefreshSystemNotificationsEnabled also refreshes fullScreenIntentState`() = runTest {
|
||||
var lambdaResult = aFullScreenIntentPermissionsState(permissionGranted = false)
|
||||
|
|
|
|||
|
|
@ -267,7 +267,7 @@ class NotificationSettingsViewTest {
|
|||
state = aValidNotificationSettingsState(
|
||||
eventSink = eventsRecorder,
|
||||
showChangePushProviderDialog = true,
|
||||
availablePushDistributors = listOf("P1", "P2")
|
||||
availablePushDistributors = listOf(aDistributor("P1"), aDistributor("P2"))
|
||||
),
|
||||
)
|
||||
rule.onNodeWithText("P2").performClick()
|
||||
|
|
|
|||
|
|
@ -5,12 +5,11 @@
|
|||
* Please see LICENSE files in the repository root for full details.
|
||||
*/
|
||||
|
||||
@file:OptIn(ExperimentalCoroutinesApi::class)
|
||||
|
||||
package io.element.android.features.preferences.impl.root
|
||||
|
||||
import app.cash.molecule.RecompositionMode
|
||||
import app.cash.molecule.moleculeFlow
|
||||
import app.cash.turbine.ReceiveTurbine
|
||||
import app.cash.turbine.test
|
||||
import com.google.common.truth.Truth.assertThat
|
||||
import io.element.android.features.logout.api.direct.aDirectLogoutState
|
||||
import io.element.android.features.preferences.impl.utils.ShowDeveloperSettingsProvider
|
||||
|
|
@ -18,6 +17,7 @@ import io.element.android.libraries.core.meta.BuildType
|
|||
import io.element.android.libraries.designsystem.utils.snackbar.SnackbarDispatcher
|
||||
import io.element.android.libraries.featureflag.test.FakeFeatureFlagService
|
||||
import io.element.android.libraries.indicator.impl.DefaultIndicatorService
|
||||
import io.element.android.libraries.matrix.api.oidc.AccountManagementAction
|
||||
import io.element.android.libraries.matrix.api.user.MatrixUser
|
||||
import io.element.android.libraries.matrix.test.AN_AVATAR_URL
|
||||
import io.element.android.libraries.matrix.test.A_USER_NAME
|
||||
|
|
@ -27,6 +27,10 @@ import io.element.android.libraries.matrix.test.encryption.FakeEncryptionService
|
|||
import io.element.android.libraries.matrix.test.verification.FakeSessionVerificationService
|
||||
import io.element.android.services.analytics.test.FakeAnalyticsService
|
||||
import io.element.android.tests.testutils.WarmUpRule
|
||||
import io.element.android.tests.testutils.lambda.lambdaRecorder
|
||||
import io.element.android.tests.testutils.lambda.value
|
||||
import io.element.android.tests.testutils.test
|
||||
import kotlinx.coroutines.ExperimentalCoroutinesApi
|
||||
import kotlinx.coroutines.test.runTest
|
||||
import org.junit.Rule
|
||||
import org.junit.Test
|
||||
|
|
@ -37,11 +41,16 @@ class PreferencesRootPresenterTest {
|
|||
|
||||
@Test
|
||||
fun `present - initial state`() = runTest {
|
||||
val matrixClient = FakeMatrixClient(canDeactivateAccountResult = { true })
|
||||
val presenter = createPresenter(matrixClient = matrixClient)
|
||||
moleculeFlow(RecompositionMode.Immediate) {
|
||||
presenter.present()
|
||||
}.test {
|
||||
val accountManagementUrlResult = lambdaRecorder<AccountManagementAction?, Result<String?>> { action ->
|
||||
Result.success("$action url")
|
||||
}
|
||||
val matrixClient = FakeMatrixClient(
|
||||
canDeactivateAccountResult = { true },
|
||||
accountManagementUrlResult = accountManagementUrlResult,
|
||||
)
|
||||
createPresenter(
|
||||
matrixClient = matrixClient,
|
||||
).test {
|
||||
val initialState = awaitItem()
|
||||
assertThat(initialState.myUser).isEqualTo(
|
||||
MatrixUser(
|
||||
|
|
@ -71,19 +80,26 @@ class PreferencesRootPresenterTest {
|
|||
assertThat(loadedState.canDeactivateAccount).isTrue()
|
||||
assertThat(loadedState.directLogoutState).isEqualTo(aDirectLogoutState())
|
||||
assertThat(loadedState.snackbarMessage).isNull()
|
||||
skipItems(1)
|
||||
val finalState = awaitItem()
|
||||
accountManagementUrlResult.assertions().isCalledExactly(2)
|
||||
.withSequence(
|
||||
listOf(value(AccountManagementAction.Profile)),
|
||||
listOf(value(AccountManagementAction.SessionsList)),
|
||||
)
|
||||
assertThat(finalState.accountManagementUrl).isEqualTo("Profile url")
|
||||
assertThat(finalState.devicesManagementUrl).isEqualTo("SessionsList url")
|
||||
}
|
||||
}
|
||||
|
||||
@Test
|
||||
fun `present - can deactivate account is false if the Matrix client say so`() = runTest {
|
||||
val presenter = createPresenter(
|
||||
createPresenter(
|
||||
matrixClient = FakeMatrixClient(
|
||||
canDeactivateAccountResult = { false }
|
||||
)
|
||||
)
|
||||
moleculeFlow(RecompositionMode.Immediate) {
|
||||
presenter.present()
|
||||
}.test {
|
||||
canDeactivateAccountResult = { false },
|
||||
accountManagementUrlResult = { Result.success(null) },
|
||||
),
|
||||
).test {
|
||||
val loadedState = awaitFirstItem()
|
||||
assertThat(loadedState.canDeactivateAccount).isFalse()
|
||||
}
|
||||
|
|
@ -91,12 +107,13 @@ class PreferencesRootPresenterTest {
|
|||
|
||||
@Test
|
||||
fun `present - developer settings is hidden by default in release builds`() = runTest {
|
||||
val presenter = createPresenter(
|
||||
createPresenter(
|
||||
matrixClient = FakeMatrixClient(
|
||||
canDeactivateAccountResult = { true },
|
||||
accountManagementUrlResult = { Result.success(null) },
|
||||
),
|
||||
showDeveloperSettingsProvider = ShowDeveloperSettingsProvider(aBuildMeta(BuildType.RELEASE))
|
||||
)
|
||||
moleculeFlow(RecompositionMode.Immediate) {
|
||||
presenter.present()
|
||||
}.test {
|
||||
).test {
|
||||
val loadedState = awaitFirstItem()
|
||||
assertThat(loadedState.showDeveloperSettings).isFalse()
|
||||
}
|
||||
|
|
@ -104,12 +121,13 @@ class PreferencesRootPresenterTest {
|
|||
|
||||
@Test
|
||||
fun `present - developer settings can be enabled in release builds`() = runTest {
|
||||
val presenter = createPresenter(
|
||||
createPresenter(
|
||||
matrixClient = FakeMatrixClient(
|
||||
canDeactivateAccountResult = { true },
|
||||
accountManagementUrlResult = { Result.success(null) },
|
||||
),
|
||||
showDeveloperSettingsProvider = ShowDeveloperSettingsProvider(aBuildMeta(BuildType.RELEASE))
|
||||
)
|
||||
moleculeFlow(RecompositionMode.Immediate) {
|
||||
presenter.present()
|
||||
}.test {
|
||||
).test {
|
||||
val loadedState = awaitFirstItem()
|
||||
repeat(times = ShowDeveloperSettingsProvider.DEVELOPER_SETTINGS_COUNTER) {
|
||||
assertThat(loadedState.showDeveloperSettings).isFalse()
|
||||
|
|
@ -125,7 +143,7 @@ class PreferencesRootPresenterTest {
|
|||
}
|
||||
|
||||
private fun createPresenter(
|
||||
matrixClient: FakeMatrixClient = FakeMatrixClient(canDeactivateAccountResult = { true }),
|
||||
matrixClient: FakeMatrixClient = FakeMatrixClient(),
|
||||
sessionVerificationService: FakeSessionVerificationService = FakeSessionVerificationService(),
|
||||
showDeveloperSettingsProvider: ShowDeveloperSettingsProvider = ShowDeveloperSettingsProvider(aBuildMeta(BuildType.DEBUG)),
|
||||
) = PreferencesRootPresenter(
|
||||
|
|
|
|||
|
|
@ -17,10 +17,10 @@ core = "1.15.0"
|
|||
# due to the DefaultMigrationStore not behaving as expected.
|
||||
# Stick to 1.0.0 for now, and ensure that this scenario cannot be reproduced when upgrading the version.
|
||||
datastore = "1.0.0"
|
||||
constraintlayout = "2.2.0"
|
||||
constraintlayout_compose = "1.1.0"
|
||||
constraintlayout = "2.2.1"
|
||||
constraintlayout_compose = "1.1.1"
|
||||
lifecycle = "2.8.7"
|
||||
activity = "1.10.0"
|
||||
activity = "1.10.1"
|
||||
media3 = "1.5.1"
|
||||
camera = "1.4.1"
|
||||
|
||||
|
|
@ -88,7 +88,7 @@ androidx_corektx = { module = "androidx.core:core-ktx", version.ref = "core" }
|
|||
androidx_annotationjvm = "androidx.annotation:annotation-jvm:1.9.1"
|
||||
androidx_datastore_preferences = { module = "androidx.datastore:datastore-preferences", version.ref = "datastore" }
|
||||
androidx_datastore_datastore = { module = "androidx.datastore:datastore", version.ref = "datastore" }
|
||||
androidx_exifinterface = "androidx.exifinterface:exifinterface:1.3.7"
|
||||
androidx_exifinterface = "androidx.exifinterface:exifinterface:1.4.0"
|
||||
androidx_constraintlayout = { module = "androidx.constraintlayout:constraintlayout", version.ref = "constraintlayout" }
|
||||
androidx_constraintlayout_compose = { module = "androidx.constraintlayout:constraintlayout-compose", version.ref = "constraintlayout_compose" }
|
||||
androidx_camera_lifecycle = { module = "androidx.camera:camera-lifecycle", version.ref = "camera" }
|
||||
|
|
@ -163,7 +163,7 @@ coil = { module = "io.coil-kt:coil", version.ref = "coil" }
|
|||
coil_compose = { module = "io.coil-kt:coil-compose", version.ref = "coil" }
|
||||
coil_gif = { module = "io.coil-kt:coil-gif", version.ref = "coil" }
|
||||
coil_test = { module = "io.coil-kt:coil-test", version.ref = "coil" }
|
||||
compound = { module = "io.element.android:compound-android", version = "0.2.0" }
|
||||
compound = { module = "io.element.android:compound-android", version = "25.2.26" }
|
||||
datetime = { module = "org.jetbrains.kotlinx:kotlinx-datetime", version.ref = "datetime" }
|
||||
serialization_json = { module = "org.jetbrains.kotlinx:kotlinx-serialization-json", version.ref = "serialization_json" }
|
||||
kotlinx_collections_immutable = "org.jetbrains.kotlinx:kotlinx-collections-immutable:0.3.8"
|
||||
|
|
@ -195,7 +195,7 @@ zxing_cpp = "io.github.zxing-cpp:android:2.3.0"
|
|||
|
||||
# Analytics
|
||||
posthog = "com.posthog:posthog-android:3.11.3"
|
||||
sentry = "io.sentry:sentry-android:8.2.0"
|
||||
sentry = "io.sentry:sentry-android:8.3.0"
|
||||
# main branch can be tested replacing the version with main-SNAPSHOT
|
||||
matrix_analytics_events = "com.github.matrix-org:matrix-analytics-events:0.28.0"
|
||||
|
||||
|
|
|
|||
|
|
@ -93,7 +93,7 @@ internal fun MatrixBadgeAtomNegativePreview() = ElementPreview {
|
|||
MatrixBadgeAtom.View(
|
||||
MatrixBadgeAtom.MatrixBadgeData(
|
||||
text = "Not trusted",
|
||||
icon = CompoundIcons.Error(),
|
||||
icon = CompoundIcons.ErrorSolid(),
|
||||
type = MatrixBadgeAtom.Type.Negative,
|
||||
)
|
||||
)
|
||||
|
|
|
|||
|
|
@ -118,7 +118,7 @@ private fun InformativeAnnouncement(
|
|||
AnnouncementSurface(modifier = modifier) {
|
||||
Row {
|
||||
Icon(
|
||||
imageVector = if (isError) CompoundIcons.Error() else CompoundIcons.Info(),
|
||||
imageVector = if (isError) CompoundIcons.ErrorSolid() else CompoundIcons.Info(),
|
||||
tint = if (isError) ElementTheme.colors.iconCriticalPrimary else ElementTheme.colors.iconPrimary,
|
||||
contentDescription = null,
|
||||
)
|
||||
|
|
|
|||
|
|
@ -105,7 +105,7 @@ object BigIcon {
|
|||
val icon = when (style) {
|
||||
is Style.Default -> style.vectorIcon
|
||||
Style.Alert,
|
||||
Style.AlertSolid -> CompoundIcons.Error()
|
||||
Style.AlertSolid -> CompoundIcons.ErrorSolid()
|
||||
Style.Success,
|
||||
Style.SuccessSolid -> CompoundIcons.CheckCircleSolid()
|
||||
}
|
||||
|
|
|
|||
|
|
@ -259,7 +259,7 @@ private fun SupportingTextLayout(validity: TextFieldValidity?, supportingText: S
|
|||
when (validity) {
|
||||
TextFieldValidity.Invalid -> {
|
||||
Icon(
|
||||
imageVector = CompoundIcons.Error(),
|
||||
imageVector = CompoundIcons.ErrorSolid(),
|
||||
contentDescription = null,
|
||||
modifier = Modifier.size(16.dp),
|
||||
tint = ElementTheme.colors.iconCriticalPrimary
|
||||
|
|
|
|||
|
|
@ -72,11 +72,11 @@ class FakeMatrixClient(
|
|||
private val syncService: FakeSyncService = FakeSyncService(),
|
||||
private val encryptionService: FakeEncryptionService = FakeEncryptionService(),
|
||||
private val roomDirectoryService: RoomDirectoryService = FakeRoomDirectoryService(),
|
||||
private val accountManagementUrlString: Result<String?> = Result.success(null),
|
||||
private val accountManagementUrlResult: (AccountManagementAction?) -> Result<String?> = { lambdaError() },
|
||||
private val resolveRoomAliasResult: (RoomAlias) -> Result<Optional<ResolvedRoomAlias>> = {
|
||||
Result.success(
|
||||
Optional.of(ResolvedRoomAlias(A_ROOM_ID, emptyList()))
|
||||
)
|
||||
Optional.of(ResolvedRoomAlias(A_ROOM_ID, emptyList()))
|
||||
)
|
||||
},
|
||||
private val getRoomPreviewResult: (RoomIdOrAlias, List<String>) -> Result<RoomPreview> = { _, _ -> Result.failure(AN_EXCEPTION) },
|
||||
private val clearCacheLambda: () -> Unit = { lambdaError() },
|
||||
|
|
@ -190,8 +190,8 @@ class FakeMatrixClient(
|
|||
return Result.success(result)
|
||||
}
|
||||
|
||||
override suspend fun getAccountManagementUrl(action: AccountManagementAction?): Result<String?> {
|
||||
return accountManagementUrlString
|
||||
override suspend fun getAccountManagementUrl(action: AccountManagementAction?): Result<String?> = simulateLongTask {
|
||||
accountManagementUrlResult(action)
|
||||
}
|
||||
|
||||
override suspend fun uploadMedia(
|
||||
|
|
|
|||
|
|
@ -68,7 +68,7 @@ fun UnresolvedUserRow(
|
|||
.padding(top = 3.dp)
|
||||
) {
|
||||
Icon(
|
||||
imageVector = CompoundIcons.Error(),
|
||||
imageVector = CompoundIcons.ErrorSolid(),
|
||||
contentDescription = null,
|
||||
modifier = Modifier
|
||||
.size(18.dp)
|
||||
|
|
|
|||
|
|
@ -18,4 +18,6 @@ package io.element.android.libraries.pushproviders.api
|
|||
data class Distributor(
|
||||
val value: String,
|
||||
val name: String,
|
||||
)
|
||||
) {
|
||||
val fullName = "$name ($value)"
|
||||
}
|
||||
|
|
|
|||
|
|
@ -98,7 +98,7 @@ private fun ColumnScope.TroubleshootTestView(
|
|||
Icon(
|
||||
contentDescription = null,
|
||||
modifier = Modifier.size(24.dp),
|
||||
imageVector = CompoundIcons.Error(),
|
||||
imageVector = CompoundIcons.ErrorSolid(),
|
||||
tint = ElementTheme.colors.textCriticalPrimary
|
||||
)
|
||||
}
|
||||
|
|
|
|||
|
|
@ -9,6 +9,7 @@
|
|||
<string name="a11y_pause">"Setter på pause"</string>
|
||||
<string name="a11y_pin_field">"PIN-felt"</string>
|
||||
<string name="a11y_play">"Spill av"</string>
|
||||
<string name="a11y_poll">"Avstemning"</string>
|
||||
<string name="a11y_poll_end">"Avsluttet avstemning"</string>
|
||||
<string name="a11y_react_with">"Reager med %1$s"</string>
|
||||
<string name="a11y_react_with_other_emojis">"Reager med andre emojier"</string>
|
||||
|
|
@ -143,14 +144,17 @@
|
|||
<string name="common_encryption_enabled">"Kryptering aktivert"</string>
|
||||
<string name="common_enter_your_pin">"Skriv inn PIN-koden din"</string>
|
||||
<string name="common_error">"Feil"</string>
|
||||
<string name="common_everyone">"Alle"</string>
|
||||
<string name="common_failed">"Mislyktes"</string>
|
||||
<string name="common_favourite">"Favoritt"</string>
|
||||
<string name="common_file">"Fil"</string>
|
||||
<string name="common_file_saved_on_disk_android">"Fil lagret i Nedlastinger"</string>
|
||||
<string name="common_forward_message">"Videresend melding"</string>
|
||||
<string name="common_gif">"GIF"</string>
|
||||
<string name="common_image">"Bilde"</string>
|
||||
<string name="common_in_reply_to">"Som svar på %1$s"</string>
|
||||
<string name="common_install_apk_android">"Installer APK"</string>
|
||||
<string name="common_invite_unknown_profile">"Finner ikke denne Matrix-IDen, så invitasjonen blir kanskje ikke mottatt."</string>
|
||||
<string name="common_leaving_room">"Forlater rommet"</string>
|
||||
<string name="common_light">"Lys"</string>
|
||||
<string name="common_link_copied_to_clipboard">"Lenke kopiert til utklippstavlen"</string>
|
||||
|
|
@ -220,6 +224,7 @@
|
|||
<string name="common_syncing">"Synkroniserer"</string>
|
||||
<string name="common_system">"System"</string>
|
||||
<string name="common_text">"Tekst"</string>
|
||||
<string name="common_third_party_notices">"Varsler fra tredjeparter"</string>
|
||||
<string name="common_thread">"Tråd"</string>
|
||||
<string name="common_topic">"Emne"</string>
|
||||
<string name="common_topic_placeholder">"Hva er dette rommet for?"</string>
|
||||
|
|
@ -250,7 +255,11 @@
|
|||
<string name="dialog_unsaved_changes_description_android">"Endringene dine er ikke lagret. Er du sikker på at du vil gå tilbake?"</string>
|
||||
<string name="dialog_unsaved_changes_title">"Lagre endringer?"</string>
|
||||
<string name="error_failed_creating_the_permalink">"Opprettelse av permalenken mislyktes"</string>
|
||||
<string name="error_failed_loading_map">"%1$s kunne ikke laste inn kartet. Prøv igjen senere."</string>
|
||||
<string name="error_failed_loading_messages">"Kunne ikke laste inn meldinger"</string>
|
||||
<string name="error_failed_locating_user">"%1$s fikk ikke tilgang til lokasjonen din. Vennligst prøv igjen senere."</string>
|
||||
<string name="error_missing_location_auth_android">"%1$s har ikke tilgang til lokasjonen din. Du kan aktivere tilgang i Innstillinger."</string>
|
||||
<string name="error_missing_location_rationale_android">"%1$s har ikke tilgang til lokasjonen din. Aktiver tilgang nedenfor."</string>
|
||||
<string name="error_some_messages_have_not_been_sent">"Noen meldinger er ikke sendt"</string>
|
||||
<string name="error_unknown">"Beklager, det oppstod en feil"</string>
|
||||
<string name="event_shield_reason_sent_in_clear">"Ikke kryptert."</string>
|
||||
|
|
@ -258,13 +267,18 @@
|
|||
<string name="invite_friends_text">"Hei, snakk med meg på %1$s: %2$s"</string>
|
||||
<string name="login_initial_device_name_android">"%1$s Android"</string>
|
||||
<string name="screen_media_picker_error_failed_selection">"Kunne ikke velge medium, prøv igjen."</string>
|
||||
<string name="screen_media_upload_preview_error_failed_processing">"Kunne ikke behandle media for opplasting, vennligst prøv igjen."</string>
|
||||
<string name="screen_media_upload_preview_error_failed_sending">"Opplasting av media mislyktes, vennligst prøv igjen."</string>
|
||||
<string name="screen_room_error_failed_processing_media">"Kunne ikke behandle media for opplasting, vennligst prøv igjen."</string>
|
||||
<string name="screen_media_upload_preview_error_failed_processing">"Kunne ikke behandle medier for opplasting, vennligst prøv igjen."</string>
|
||||
<string name="screen_media_upload_preview_error_failed_sending">"Opplasting av medier mislyktes, vennligst prøv igjen."</string>
|
||||
<string name="screen_room_error_failed_processing_media">"Kunne ikke behandle medier for opplasting, vennligst prøv igjen."</string>
|
||||
<string name="screen_room_error_failed_retrieving_user_details">"Kunne ikke hente brukerdetaljer"</string>
|
||||
<string name="screen_share_location_title">"Del lokasjon"</string>
|
||||
<string name="screen_share_my_location_action">"Del min lokasjon"</string>
|
||||
<string name="screen_share_open_apple_maps">"Åpne i Apple Maps"</string>
|
||||
<string name="screen_share_open_google_maps">"Åpne i Google Maps"</string>
|
||||
<string name="screen_share_open_osm_maps">"Åpne i OpenStreetMap"</string>
|
||||
<string name="screen_share_this_location_action">"Del denne lokasjonen"</string>
|
||||
<string name="screen_timeline_item_menu_send_failure_unsigned_device">"Meldingen ble ikke sendt fordi %1$s ikke har verifisert alle enheter."</string>
|
||||
<string name="screen_view_location_title">"Lokasjon"</string>
|
||||
<string name="settings_version_number">"Versjon: %1$s (%2$s)"</string>
|
||||
<string name="test_language_identifier">"en"</string>
|
||||
</resources>
|
||||
|
|
|
|||
|
|
@ -1,3 +1,3 @@
|
|||
version https://git-lfs.github.com/spec/v1
|
||||
oid sha256:846bef7dc54b4d051bc0cd6ea90d66ba406a11d7dda36455dbdf3ee74aab2aae
|
||||
size 8379
|
||||
oid sha256:30efa4ef62ce38f3599c1a6f2a99c9a36e5704a70c99d83670b5f2169a8648f3
|
||||
size 8378
|
||||
|
|
|
|||
|
|
@ -1,3 +1,3 @@
|
|||
version https://git-lfs.github.com/spec/v1
|
||||
oid sha256:6baed152f58ed5335d559b7e6bc78867147ddd0b8df63e1881875caf0c10f470
|
||||
size 10486
|
||||
oid sha256:e3c97dbafc4e1e74be95014f9e4f4e10f9b6516d98e89a149791d61c2e1c5ddf
|
||||
size 10484
|
||||
|
|
|
|||
|
|
@ -1,3 +1,3 @@
|
|||
version https://git-lfs.github.com/spec/v1
|
||||
oid sha256:a9d7f9f3ba4857862530f0f278186dfbaa347d589abca7e2baf5142b2740ede4
|
||||
size 7999
|
||||
oid sha256:a1a5ca1ae30e3b1c4c2b242b3527a3c09b09acb415ad11333ad4b1f07182cbed
|
||||
size 8005
|
||||
|
|
|
|||
|
|
@ -1,3 +1,3 @@
|
|||
version https://git-lfs.github.com/spec/v1
|
||||
oid sha256:813cedb8cb525406a5d475a8b431bc94888f5952009e28f71f983a03198227db
|
||||
size 10028
|
||||
oid sha256:eae95926adb295182d13dbbebcf1650ab1bf816a9d5edeb908cbd8683fec0c66
|
||||
size 10031
|
||||
|
|
|
|||
|
|
@ -1,3 +1,3 @@
|
|||
version https://git-lfs.github.com/spec/v1
|
||||
oid sha256:4944bbdf4621ecfef659746bb7f3fa16d2a107269cbb60d057bf91c9360a1894
|
||||
size 82388
|
||||
oid sha256:255709a0c6b3ffe337e5a3ce657e350539d9278a2a1c7994ac40752a0bffecff
|
||||
size 82449
|
||||
|
|
|
|||
|
|
@ -1,3 +1,3 @@
|
|||
version https://git-lfs.github.com/spec/v1
|
||||
oid sha256:c76c6454e90e4e23ad7ea92d930eeb47c7a68f81dcc7035b358203cb47639f13
|
||||
size 75518
|
||||
oid sha256:82812d497f41b7e34d00cf2fadbde22115200539fcb25660dd9f9c9378093f0e
|
||||
size 75610
|
||||
|
|
|
|||
|
|
@ -1,3 +1,3 @@
|
|||
version https://git-lfs.github.com/spec/v1
|
||||
oid sha256:686ef0bf0a5813e09f1afd7824d5aa909c914bebe553d03955a869673e8f9e16
|
||||
size 66270
|
||||
oid sha256:2f07a472c171966ad4dd9e8401a634b9c55a303e1ca4ab08cb44c32e17b1a128
|
||||
size 66278
|
||||
|
|
|
|||
|
|
@ -1,3 +1,3 @@
|
|||
version https://git-lfs.github.com/spec/v1
|
||||
oid sha256:c8f9f67b6bd11de3983dfdd76c3a72ceaf8d920daebb5e4e749bb74ab5d95dfa
|
||||
size 58396
|
||||
oid sha256:f5a4097408c093e0919e54bdacfe29f3901fe2db7b0984b72c2003499a6dba11
|
||||
size 58400
|
||||
|
|
|
|||
|
|
@ -1,3 +1,3 @@
|
|||
version https://git-lfs.github.com/spec/v1
|
||||
oid sha256:480dcf4628c371f8df8b6a26f73f0a5ed45e9ca89baf9f4ab52bd896ed1cc4d7
|
||||
size 77593
|
||||
oid sha256:5834fcf87293fd1c8887fceebba0b0e77be27af06843d5dea62a35e4becd2aca
|
||||
size 77581
|
||||
|
|
|
|||
|
|
@ -1,3 +1,3 @@
|
|||
version https://git-lfs.github.com/spec/v1
|
||||
oid sha256:96333cfda74bc44b7f9f95eab383ab26857b07d68ed30255ccb1ef3ae1558a4c
|
||||
size 78110
|
||||
oid sha256:ccae537ee569b5c4450b1e238aaaf4570818d050a228347eb6b09ea10997135c
|
||||
size 78100
|
||||
|
|
|
|||
|
|
@ -1,3 +1,3 @@
|
|||
version https://git-lfs.github.com/spec/v1
|
||||
oid sha256:d783fa26d1b4a891a000f638a3d6b7e3df08390b9f800e3e4d123e76cfc274fd
|
||||
size 82488
|
||||
oid sha256:75eff760370d8cbbd0d2795a049f06e5f9be75030ef064f3a0e6548750e0166e
|
||||
size 82468
|
||||
|
|
|
|||
|
|
@ -1,3 +1,3 @@
|
|||
version https://git-lfs.github.com/spec/v1
|
||||
oid sha256:3aabc27a2531ecd79a01de70cbb149ff4c77fb9d37f3cefd5727a083c3edf455
|
||||
size 42712
|
||||
oid sha256:82d60ec6eaddaa3a9cc4d9d23bf5fe2e6debbf0b441ecafa377e27770d26ecdb
|
||||
size 42697
|
||||
|
|
|
|||
|
|
@ -1,3 +1,3 @@
|
|||
version https://git-lfs.github.com/spec/v1
|
||||
oid sha256:adb68fcd10b66e37f774560e59991bf6488043d4e1b66e6b1f19a648c90a6333
|
||||
size 7572
|
||||
oid sha256:d175ae95fed4ac24e9b506678c4ee1e235c3c8405915498f7f97db0764e5470c
|
||||
size 7571
|
||||
|
|
|
|||
|
|
@ -1,3 +1,3 @@
|
|||
version https://git-lfs.github.com/spec/v1
|
||||
oid sha256:72dbe69b1952d3c2e00509bb1a5e0493baa30c0ef4e444f652f3fd7f81a8eccd
|
||||
oid sha256:0db80941c8c981d3f66bc6cd9364f0f8fd5b1e7033f81da46cdffe478f97c748
|
||||
size 6528
|
||||
|
|
|
|||
|
|
@ -1,3 +1,3 @@
|
|||
version https://git-lfs.github.com/spec/v1
|
||||
oid sha256:72dbe69b1952d3c2e00509bb1a5e0493baa30c0ef4e444f652f3fd7f81a8eccd
|
||||
oid sha256:0db80941c8c981d3f66bc6cd9364f0f8fd5b1e7033f81da46cdffe478f97c748
|
||||
size 6528
|
||||
|
|
|
|||
|
|
@ -1,3 +1,3 @@
|
|||
version https://git-lfs.github.com/spec/v1
|
||||
oid sha256:1ae3884c6bfded545fda8dfadfc94cb4c17bf2df9556c4d33a931c3509b8a885
|
||||
size 38429
|
||||
oid sha256:f49822ac3f9a328dcbc9747e49ab3b3af74de42f81f833640232199d85d8d961
|
||||
size 38428
|
||||
|
|
|
|||
|
|
@ -1,3 +1,3 @@
|
|||
version https://git-lfs.github.com/spec/v1
|
||||
oid sha256:daba14ee51067d64e9098815b1d187a89b405b0f11b22f7fa888106cfb388fa9
|
||||
oid sha256:0c2187b3eb917901c6d9fac36ae44c28c7c3946a055cbf156aab3063c8981e4e
|
||||
size 52055
|
||||
|
|
|
|||
|
|
@ -1,3 +1,3 @@
|
|||
version https://git-lfs.github.com/spec/v1
|
||||
oid sha256:878d81472018964e1217c36708e31469a62486e1a913da26fc5a209731c4f9a1
|
||||
size 11014
|
||||
oid sha256:57ee28833b587ec86f93c685d716f0cce94b60e0752de3fc1a1a3d7ac05cbdb6
|
||||
size 11013
|
||||
|
|
|
|||
|
|
@ -1,3 +1,3 @@
|
|||
version https://git-lfs.github.com/spec/v1
|
||||
oid sha256:72dbe69b1952d3c2e00509bb1a5e0493baa30c0ef4e444f652f3fd7f81a8eccd
|
||||
oid sha256:0db80941c8c981d3f66bc6cd9364f0f8fd5b1e7033f81da46cdffe478f97c748
|
||||
size 6528
|
||||
|
|
|
|||
|
|
@ -1,3 +1,3 @@
|
|||
version https://git-lfs.github.com/spec/v1
|
||||
oid sha256:e8638e7c07500bddc9c67480685d2548f0b50772977fee7565fb92ae72eaefcb
|
||||
size 7504
|
||||
oid sha256:d174f1f8e77c9cd02506b487e410a7bcbf4d571f048f739d4f10582c72e682d0
|
||||
size 7501
|
||||
|
|
|
|||
|
|
@ -1,3 +1,3 @@
|
|||
version https://git-lfs.github.com/spec/v1
|
||||
oid sha256:000dbaa58af2f75293be0a3fed993447275582abaa33088b3f9c533ac4e0fec6
|
||||
size 6298
|
||||
oid sha256:000c36468af4793e4956a4a2a2be1867afefa13140219e2dd8b17b1f7670b6de
|
||||
size 6299
|
||||
|
|
|
|||
|
|
@ -1,3 +1,3 @@
|
|||
version https://git-lfs.github.com/spec/v1
|
||||
oid sha256:000dbaa58af2f75293be0a3fed993447275582abaa33088b3f9c533ac4e0fec6
|
||||
size 6298
|
||||
oid sha256:000c36468af4793e4956a4a2a2be1867afefa13140219e2dd8b17b1f7670b6de
|
||||
size 6299
|
||||
|
|
|
|||
|
|
@ -1,3 +1,3 @@
|
|||
version https://git-lfs.github.com/spec/v1
|
||||
oid sha256:375315a6a917f013079bfaa0d96bb3b90f72d485c3c4ed7b30c3f86dd9277793
|
||||
size 39184
|
||||
oid sha256:ed09d7879d10d22bc90bf0757bc649436f90428347cc8df2780c05e4c1c95fe5
|
||||
size 39183
|
||||
|
|
|
|||
|
|
@ -1,3 +1,3 @@
|
|||
version https://git-lfs.github.com/spec/v1
|
||||
oid sha256:618164f424e1b2d334051d7d55dac014d77ea00ac8f15ae0f62fdd0fa77705fe
|
||||
oid sha256:8cec0dc2a2b0870c7ee43a0329f9e8b67b42e7e4f26f349543e8c5d5841830fd
|
||||
size 53161
|
||||
|
|
|
|||
|
|
@ -1,3 +1,3 @@
|
|||
version https://git-lfs.github.com/spec/v1
|
||||
oid sha256:b81f55a04ecf3d4c3f266d5e0b67413be226933816195307e830d081a2bbc286
|
||||
oid sha256:5694d2ee8d939aa3cc5107b7601ff251481fc8226981208b603507d407dcb12a
|
||||
size 10637
|
||||
|
|
|
|||
|
|
@ -1,3 +1,3 @@
|
|||
version https://git-lfs.github.com/spec/v1
|
||||
oid sha256:000dbaa58af2f75293be0a3fed993447275582abaa33088b3f9c533ac4e0fec6
|
||||
size 6298
|
||||
oid sha256:000c36468af4793e4956a4a2a2be1867afefa13140219e2dd8b17b1f7670b6de
|
||||
size 6299
|
||||
|
|
|
|||
|
|
@ -1,3 +1,3 @@
|
|||
version https://git-lfs.github.com/spec/v1
|
||||
oid sha256:72855bb6717291b00777e21711c0a5c8a7049e7b09cac7684dee9ae28e5be9f8
|
||||
size 29925
|
||||
oid sha256:58a0ee838378b313643ce3ebf3ea5c12565ff3da5e4fb1edb16a795f1c1a645e
|
||||
size 29964
|
||||
|
|
|
|||
|
|
@ -1,3 +1,3 @@
|
|||
version https://git-lfs.github.com/spec/v1
|
||||
oid sha256:2fa0cc7a8cfa1e1726d0ec75186cfd99fd67e9d5b168b0c6be669e355af2a1d6
|
||||
size 43007
|
||||
oid sha256:583665542f91d2a2d4788ff5475e063ac6168a077c75fb675fa8e4f2ae6e9aad
|
||||
size 43055
|
||||
|
|
|
|||
|
|
@ -1,3 +1,3 @@
|
|||
version https://git-lfs.github.com/spec/v1
|
||||
oid sha256:79c69f5ca1c04d4e6544decea4150eb5f43bdde58070d1dfe57d0a4c94022dd5
|
||||
size 58850
|
||||
oid sha256:22928ada21a391607fbcf349a5e086e98a2acd8bd6b48ed33cc118b8b0fd0747
|
||||
size 58898
|
||||
|
|
|
|||
|
|
@ -1,3 +1,3 @@
|
|||
version https://git-lfs.github.com/spec/v1
|
||||
oid sha256:d99e10bf3d0322ed25d883aa80376b0f1bd92d8174a6623e099272b4002fbfc4
|
||||
size 56880
|
||||
oid sha256:9333e27748a0699fdec91fcd805373b20776237d0a84c1d9b84b07d24cdc3394
|
||||
size 56956
|
||||
|
|
|
|||
|
|
@ -1,3 +1,3 @@
|
|||
version https://git-lfs.github.com/spec/v1
|
||||
oid sha256:e6f28ae60d74769a903228a58ed97f5753ec6e9a054b8e94d39d6c83ecb363d5
|
||||
size 58260
|
||||
oid sha256:51ddfe120825a6c3d1bd64d4e5711e6499e8c8b99d2e341352669b1c10d21458
|
||||
size 58336
|
||||
|
|
|
|||
|
|
@ -1,3 +1,3 @@
|
|||
version https://git-lfs.github.com/spec/v1
|
||||
oid sha256:2e987390f164dcacfafd455a3ccd3f4ae9af7d8e057d91772670d28c6f6e6310
|
||||
size 56056
|
||||
oid sha256:19aebb87ad9b9cc7808d63fe2c540428ebde6efef52e871320abd6afe4be0367
|
||||
size 56105
|
||||
|
|
|
|||
|
|
@ -1,3 +1,3 @@
|
|||
version https://git-lfs.github.com/spec/v1
|
||||
oid sha256:5b420340d9471294fce2458149f14c55df979060b248dba7cdd8bacfe71a39da
|
||||
size 30808
|
||||
oid sha256:67d05d7bdd0420627263d8bce97c871bcd44904a1652d6f475e9585c61883846
|
||||
size 30875
|
||||
|
|
|
|||
|
|
@ -1,3 +1,3 @@
|
|||
version https://git-lfs.github.com/spec/v1
|
||||
oid sha256:05e71ef5a6fa821961c2a78885bab91eeeb783bac1fdaa495f32fd4173ecc615
|
||||
size 43621
|
||||
oid sha256:69c5790e896024624698b386b00803eb2d21627cf47024661dcf5cea81e0b6ac
|
||||
size 43681
|
||||
|
|
|
|||
|
|
@ -1,3 +1,3 @@
|
|||
version https://git-lfs.github.com/spec/v1
|
||||
oid sha256:cca307360497a2a298bb9968678c35afb44cdc68e2dd46a350868833bf770464
|
||||
size 59968
|
||||
oid sha256:5e06262926945b00d5625d85a662c110b1e6ce99689a89230e4c85fddf4009ba
|
||||
size 60029
|
||||
|
|
|
|||
|
|
@ -1,3 +1,3 @@
|
|||
version https://git-lfs.github.com/spec/v1
|
||||
oid sha256:9426c57dc59d8341087b3800a40847e63b8e6ee3c4e65cfe1712b3f5fa884618
|
||||
size 58696
|
||||
oid sha256:153dea4f37cf4ff00f61df87a71229704daa4df69d34fc6072ddfcc13ff58606
|
||||
size 58777
|
||||
|
|
|
|||
|
|
@ -1,3 +1,3 @@
|
|||
version https://git-lfs.github.com/spec/v1
|
||||
oid sha256:6527ca9d39895038bf0fec9cb9c1426f95db9f4b9460eff699c34bb59d11aaf8
|
||||
size 60122
|
||||
oid sha256:eedf66a56831cd3eb577abf89c20062caf109abb8c202d7bc925e7d2fa8c2a58
|
||||
size 60193
|
||||
|
|
|
|||
|
|
@ -1,3 +1,3 @@
|
|||
version https://git-lfs.github.com/spec/v1
|
||||
oid sha256:c5d4014d2701847fadd4e163c26e7ba220577c4b1e10ebd35c95b1c6aa81507b
|
||||
size 57814
|
||||
oid sha256:dd57076708a9a9100b0e59df7bae44513fe811ec4091cb9a7b9c5b35d3f2874b
|
||||
size 57870
|
||||
|
|
|
|||
|
|
@ -1,3 +1,3 @@
|
|||
version https://git-lfs.github.com/spec/v1
|
||||
oid sha256:c3c89ad3af16b43b6798c30077651b7c9eefd0059d847f5ff643877a2d3d3403
|
||||
size 17025
|
||||
oid sha256:32e129c360deb12a615861c12ee2505c6e6250cbee681d4d60e58d3b0dcb492b
|
||||
size 17022
|
||||
|
|
|
|||
|
|
@ -1,3 +1,3 @@
|
|||
version https://git-lfs.github.com/spec/v1
|
||||
oid sha256:30c89188415418f6015349fe9371792052f8c171272ce7ccb45352e79b15774f
|
||||
size 20192
|
||||
oid sha256:3169e88f2369e5f4d6cc8d5055af99e589c3a91bcd166acc246614a1206afb7b
|
||||
size 20196
|
||||
|
|
|
|||
|
|
@ -1,3 +1,3 @@
|
|||
version https://git-lfs.github.com/spec/v1
|
||||
oid sha256:a67b688327c3507e0072fad948b62c19acfb454aa05ac42832ee1a980c725492
|
||||
size 20174
|
||||
oid sha256:ff518448cacd57889acee5c330f251fa20ff7b9261d4538f89818acc217b1c6a
|
||||
size 20186
|
||||
|
|
|
|||
|
|
@ -1,3 +1,3 @@
|
|||
version https://git-lfs.github.com/spec/v1
|
||||
oid sha256:9be8c0f212d2ba8d1e4746038280114f50367f078e5ef63ae4e5faa730552630
|
||||
size 15629
|
||||
oid sha256:afd1edb1c5bd6e04ffcfe583697d24be3a18e778da9e4f991f90f3bc2da78e33
|
||||
size 15637
|
||||
|
|
|
|||
|
|
@ -1,3 +1,3 @@
|
|||
version https://git-lfs.github.com/spec/v1
|
||||
oid sha256:e04c7204d560370bcd2ed9bf775a892b65f22bd395f7079375e963cd46cce8ec
|
||||
oid sha256:60a4b7d344da0151ed6b4153ec527d063233b7a6824264afd73c73af9d5a6586
|
||||
size 18710
|
||||
|
|
|
|||
|
|
@ -1,3 +1,3 @@
|
|||
version https://git-lfs.github.com/spec/v1
|
||||
oid sha256:d9824bb57bbe04b48d5a2750a56a9cd36cd32bf4a4a2ebf9dd19c213e1cfb9d6
|
||||
size 18565
|
||||
oid sha256:5f592e046b694f20261ac2b154b50f766ecf3228dd69525eceae35fde9e7055c
|
||||
size 18566
|
||||
|
|
|
|||
|
|
@ -1,3 +1,3 @@
|
|||
version https://git-lfs.github.com/spec/v1
|
||||
oid sha256:f19636ec23d81de10c454b3a0f4c957b999b0fd706363854eb81b62d3072ebcd
|
||||
size 25781
|
||||
oid sha256:f7e9fe54b399dde0a7831ff37309c8a9d6acb5a369d54e9583892b4e2dc59c02
|
||||
size 25779
|
||||
|
|
|
|||
|
|
@ -1,3 +1,3 @@
|
|||
version https://git-lfs.github.com/spec/v1
|
||||
oid sha256:0838f9b076ed75cb55ea1119aa097401314bf175ead2c34ee84d7cefb65f38c6
|
||||
size 19851
|
||||
oid sha256:208e9d9f42a929c0bdb280c4442faf0211f43d3d350c48246b20ca3256a11690
|
||||
size 19846
|
||||
|
|
|
|||
|
|
@ -1,3 +1,3 @@
|
|||
version https://git-lfs.github.com/spec/v1
|
||||
oid sha256:bcd340b12fb26fed072d336f68ce6fde749025b0043866be0de0ef507dab49c5
|
||||
size 26671
|
||||
oid sha256:f9988f9337ef201957b5eaac5277cb3d1243a2396c57bd3df725b692693fa482
|
||||
size 26666
|
||||
|
|
|
|||
|
|
@ -1,3 +1,3 @@
|
|||
version https://git-lfs.github.com/spec/v1
|
||||
oid sha256:e86339de00f7e6d44c1d36004c79a9c077d7d99d55ba01da8ea9e4d3b4567367
|
||||
size 53085
|
||||
oid sha256:bfde1df500000d69e1014077b973cfe7c4a5130419184d19d794bd7a975e67bb
|
||||
size 53080
|
||||
|
|
|
|||
|
|
@ -1,3 +1,3 @@
|
|||
version https://git-lfs.github.com/spec/v1
|
||||
oid sha256:8554336730b48bb509fc60fc6a7e8eb5cc21cc8e08bb2eee87a4e719b26c13f8
|
||||
size 41765
|
||||
oid sha256:0460a8404ecb789ae10223a4d948e7f93567f041342a2398b354aca39143276c
|
||||
size 41781
|
||||
|
|
|
|||
|
|
@ -1,3 +1,3 @@
|
|||
version https://git-lfs.github.com/spec/v1
|
||||
oid sha256:c9f8d6270b9db5463649ce357463cec93945d924bebaeb7da14bfa2936088620
|
||||
size 24735
|
||||
oid sha256:e1f3d513a10202d05a3cbba270e1a5d63bbaceb74bf968d21aef01fb92c9e425
|
||||
size 24730
|
||||
|
|
|
|||
|
|
@ -1,3 +1,3 @@
|
|||
version https://git-lfs.github.com/spec/v1
|
||||
oid sha256:1b96b798e72a139710e318a2eb5203078654a1b39126bc07eb46bc0cf5d65114
|
||||
size 18783
|
||||
oid sha256:fa26d53e0373f886180c38c7398597737dd808ef98e658a5f98e0fc74f150f36
|
||||
size 18764
|
||||
|
|
|
|||
|
|
@ -1,3 +1,3 @@
|
|||
version https://git-lfs.github.com/spec/v1
|
||||
oid sha256:6a1ce3733e36875756923872eb2f862c9248ad25af5189771ec29ccf3f8d15cd
|
||||
size 25121
|
||||
oid sha256:462c1055336d5cfe8342d87335a3ec89f57c5d1efb4e81da8b928a390acc1a59
|
||||
size 25104
|
||||
|
|
|
|||
|
|
@ -1,3 +1,3 @@
|
|||
version https://git-lfs.github.com/spec/v1
|
||||
oid sha256:baa7c2ce997853e150eeb0193798af8d2ec1084b1791da579b2de6544e07d06f
|
||||
size 52657
|
||||
oid sha256:8deed7312d246c817c33b4c0034f139faa788e43dbfb5152fe613dc07320b2fd
|
||||
size 52655
|
||||
|
|
|
|||
|
|
@ -1,3 +1,3 @@
|
|||
version https://git-lfs.github.com/spec/v1
|
||||
oid sha256:c3a52624a8bf7e12b374e769eabbe369fc2ec3ff7d9497b7dc093af4ca63df3e
|
||||
size 40222
|
||||
oid sha256:e08c4b737016219338da25ff1088b433c67af0ea7d74b451a99f496458a38b17
|
||||
size 40239
|
||||
|
|
|
|||
|
|
@ -1,3 +1,3 @@
|
|||
version https://git-lfs.github.com/spec/v1
|
||||
oid sha256:b80198aeffe7bfec1e5747edf031af3bb892797950a98bdbe4063841fcf69da6
|
||||
size 269244
|
||||
oid sha256:72a54bb0c6c72e992468d81df80d0d1d274bb8b94f6883df1d2891483a855c56
|
||||
size 269259
|
||||
|
|
|
|||
|
|
@ -1,3 +1,3 @@
|
|||
version https://git-lfs.github.com/spec/v1
|
||||
oid sha256:5188a7358c698d1a67ee483a5e9277cf1158dbeb98b94933ed71f779918cf1ab
|
||||
size 345464
|
||||
oid sha256:2ea10f84e31b3591596dbfb4b3930fb108ce5d7704bdda108a8dac9b78ccbca3
|
||||
size 345504
|
||||
|
|
|
|||
|
|
@ -1,3 +1,3 @@
|
|||
version https://git-lfs.github.com/spec/v1
|
||||
oid sha256:a7f1d691d5fcf689cb4da9108f9a5d6608d6e18fa73c204c28202f6e71388be5
|
||||
size 50333
|
||||
oid sha256:634df4b9fab9797663e11293e5894de9854e918184d227e73e47be047bcb9623
|
||||
size 50335
|
||||
|
|
|
|||
|
|
@ -1,3 +1,3 @@
|
|||
version https://git-lfs.github.com/spec/v1
|
||||
oid sha256:d3e563a24b827e5f4f7519edc271b6e899852e6b9e33ef37763f018bb5f73f40
|
||||
size 51279
|
||||
oid sha256:a971216d0cfc58f65b3589479420c02f2a04010ac27d79ea2434075dcd6b4f7c
|
||||
size 51283
|
||||
|
|
|
|||
|
|
@ -1,3 +1,3 @@
|
|||
version https://git-lfs.github.com/spec/v1
|
||||
oid sha256:2c6c5eb2b3ecfabd9344898bcc581ebb81ac1620f8f749d8d5e76f19abbfe049
|
||||
size 29395
|
||||
oid sha256:fbdd42f8092b3bf8fc58ea012972a77444bff2200585fc4d9e0765453e98c251
|
||||
size 29425
|
||||
|
|
|
|||
|
|
@ -1,3 +1,3 @@
|
|||
version https://git-lfs.github.com/spec/v1
|
||||
oid sha256:fdf7ba134d16e9f6458d5bb88e43802fdc4c82fd7e0996c79c776add89c7702f
|
||||
size 36363
|
||||
oid sha256:e5bb0724cbb42ffe66a8c54e4301eccfac8e4f2f68621697c6859aa6a230405d
|
||||
size 36376
|
||||
|
|
|
|||
|
|
@ -1,3 +1,3 @@
|
|||
version https://git-lfs.github.com/spec/v1
|
||||
oid sha256:86727f6cc8b7fcf6b73e71a861d316f32869fe76f8ce5c7a8e014dc6de1c1220
|
||||
size 39469
|
||||
oid sha256:8d3b3f549530f475fd984f839c7b28a7963ad7c8903b5f308d3925a60132991b
|
||||
size 39468
|
||||
|
|
|
|||
|
|
@ -1,3 +1,3 @@
|
|||
version https://git-lfs.github.com/spec/v1
|
||||
oid sha256:dbd568c10eede6ac86ca33b69f1917e7e1f1aa11e0c793cadc5c04ee99751ca3
|
||||
size 34936
|
||||
oid sha256:e97676e6f90749d608c8289137c39668c122228f6660af9ed4b056f4f05d61ca
|
||||
size 34946
|
||||
|
|
|
|||
|
|
@ -1,3 +1,3 @@
|
|||
version https://git-lfs.github.com/spec/v1
|
||||
oid sha256:73ededbedd5da3678425db2c85164fdc4839fcfb5dce8efa68a7c8e02aeaa75f
|
||||
size 50130
|
||||
oid sha256:90b00f22d1d2d1b22f6260c95ea3fe39851682d258df7012b89c68db2af01601
|
||||
size 50133
|
||||
|
|
|
|||
|
|
@ -1,3 +1,3 @@
|
|||
version https://git-lfs.github.com/spec/v1
|
||||
oid sha256:731df5fbdcde3b3d7bf89777aefa1d0169cfc78a614ae2fce1f41a33d4d21a44
|
||||
size 50993
|
||||
oid sha256:18d2e25e32b0dc63b72a2c8c32213d2c7d9d499bf568b88addf24709e433ce34
|
||||
size 50997
|
||||
|
|
|
|||
|
|
@ -1,3 +1,3 @@
|
|||
version https://git-lfs.github.com/spec/v1
|
||||
oid sha256:c6cfe8b7ff36288df2f4cc63f8d61d272b55a17e46c29f337fcbc6079c9c0abc
|
||||
size 28768
|
||||
oid sha256:c35203dccee8ae4c1f7257d54ce84394fcc1b433a1dbd3ca66f8989eb776edf1
|
||||
size 28789
|
||||
|
|
|
|||
|
|
@ -1,3 +1,3 @@
|
|||
version https://git-lfs.github.com/spec/v1
|
||||
oid sha256:a3fb9749128fddfecf31764c27f941f789961c8540b0b8e51455d62e2f16d1a2
|
||||
size 35455
|
||||
oid sha256:66785e81ea5d103a8ea1aca54e537850d67becb84f3b4cdb463189b7b21afa68
|
||||
size 35453
|
||||
|
|
|
|||
|
|
@ -1,3 +1,3 @@
|
|||
version https://git-lfs.github.com/spec/v1
|
||||
oid sha256:fe18077f8a3a64c9474376f7fac669321306837ae3c01437746d6060a290caf2
|
||||
size 38425
|
||||
oid sha256:913a9b7a9abe56116062436d405c97105d87d07ccbb012e65b5a6365974a6d66
|
||||
size 38439
|
||||
|
|
|
|||
|
|
@ -1,3 +1,3 @@
|
|||
version https://git-lfs.github.com/spec/v1
|
||||
oid sha256:f8cffbb53b029acdbdd0fcaf74dd5d4aa1f1099108137e1e6e4b29279f79678f
|
||||
size 34264
|
||||
oid sha256:d4a30364d8f94b77b7f518107c531f0fe2e1e9e16729777e8d84958e06b198af
|
||||
size 34270
|
||||
|
|
|
|||
|
|
@ -1,3 +1,3 @@
|
|||
version https://git-lfs.github.com/spec/v1
|
||||
oid sha256:a67bb9ba78ea1d8802ce503e7d6a16be2ff46415df0e435efd7a36f3ee711b0d
|
||||
size 26453
|
||||
oid sha256:4b588d1d5a02e4ccfd2e5d44d3c38723612e5fe4a051c5c582bc81bd250850df
|
||||
size 26452
|
||||
|
|
|
|||
|
|
@ -1,3 +1,3 @@
|
|||
version https://git-lfs.github.com/spec/v1
|
||||
oid sha256:fe9aa023cb136da6bcb54fb4c371c16c9526d81bbda718ffa61a6a7e758fd64a
|
||||
oid sha256:e533e9b4a2e10fed24d8379b2f2d96e5a2cc460d9059989f8ad29d535684343f
|
||||
size 42170
|
||||
|
|
|
|||
|
|
@ -1,3 +1,3 @@
|
|||
version https://git-lfs.github.com/spec/v1
|
||||
oid sha256:be2ae50ce1b0e23fec7bcbbe9ca0f0381af4d0f29f1e7498be837d9d53b75542
|
||||
size 26003
|
||||
oid sha256:fca69fe3a6bcaae65f686e3c26e2b6935de8e33c9080b0e9f3e58ce3448c0573
|
||||
size 26004
|
||||
|
|
|
|||
|
|
@ -1,3 +1,3 @@
|
|||
version https://git-lfs.github.com/spec/v1
|
||||
oid sha256:dc8f93a9c4ec2437ab05f1f1065d5518719942d8d55550b9911384442346c463
|
||||
size 41086
|
||||
oid sha256:084ae1a4a101781ef76bf1a3f68bfb1e8c80ca6ab1de773eaddedb92a12265a5
|
||||
size 41087
|
||||
|
|
|
|||
|
|
@ -1,3 +1,3 @@
|
|||
version https://git-lfs.github.com/spec/v1
|
||||
oid sha256:8f4a7102b45fc1acd7c8cba59282548ae36bf8a3e65acc12c4041990f0cc61c0
|
||||
size 30165
|
||||
oid sha256:5248793987bd2f6f98e571366e6fcc87085fdba5372a4a31314a52a13efcc78a
|
||||
size 30160
|
||||
|
|
|
|||
|
|
@ -1,3 +1,3 @@
|
|||
version https://git-lfs.github.com/spec/v1
|
||||
oid sha256:7b16d4f9226d4df9efa9b57a0f6573e9fd6b0301f2e4cde2794de2863cf31ac5
|
||||
size 31373
|
||||
oid sha256:2d835fa6c041ca10d362e7c0dd77fe784e2f3b903523b9a813e1cd47a04f53df
|
||||
size 31365
|
||||
|
|
|
|||
Some files were not shown because too many files have changed in this diff Show more
Loading…
Add table
Add a link
Reference in a new issue