Promote "history sharing on invite" out of developer options (#6647)
* Enable history sharing by default, unconditionally * Remove feature-flag dep from history viz icons in room header * Remove feature-flag dep from warning on inviting new people * Remove feature-flag dep from warning on starting chat with new people * Remove `enableKeyShareOnInvite` feature flag * Update screenshots * Remove redundant `FakeFeatureFlagService()` invocation, per review comment --------- Co-authored-by: ElementBot <android@element.io>
This commit is contained in:
parent
92ee479e91
commit
289dfff50a
63 changed files with 106 additions and 206 deletions
|
|
@ -13,7 +13,6 @@ import androidx.compose.foundation.text.input.rememberTextFieldState
|
|||
import androidx.compose.runtime.Composable
|
||||
import androidx.compose.runtime.LaunchedEffect
|
||||
import androidx.compose.runtime.MutableState
|
||||
import androidx.compose.runtime.collectAsState
|
||||
import androidx.compose.runtime.derivedStateOf
|
||||
import androidx.compose.runtime.getValue
|
||||
import androidx.compose.runtime.mutableStateOf
|
||||
|
|
@ -37,8 +36,6 @@ import io.element.android.libraries.core.coroutine.CoroutineDispatchers
|
|||
import io.element.android.libraries.designsystem.theme.components.SearchBarResultState
|
||||
import io.element.android.libraries.di.SessionScope
|
||||
import io.element.android.libraries.di.annotations.SessionCoroutineScope
|
||||
import io.element.android.libraries.featureflag.api.FeatureFlagService
|
||||
import io.element.android.libraries.featureflag.api.FeatureFlags
|
||||
import io.element.android.libraries.matrix.api.MatrixClient
|
||||
import io.element.android.libraries.matrix.api.core.RoomId
|
||||
import io.element.android.libraries.matrix.api.encryption.identity.IdentityState
|
||||
|
|
@ -74,7 +71,6 @@ class DefaultInvitePeoplePresenter(
|
|||
private val coroutineDispatchers: CoroutineDispatchers,
|
||||
@SessionCoroutineScope private val sessionCoroutineScope: CoroutineScope,
|
||||
private val appErrorStateService: AppErrorStateService,
|
||||
private val featureFlagService: FeatureFlagService,
|
||||
private val matrixClient: MatrixClient,
|
||||
) : InvitePeoplePresenter {
|
||||
@AssistedFactory
|
||||
|
|
@ -93,8 +89,6 @@ class DefaultInvitePeoplePresenter(
|
|||
val showSearchLoader = rememberSaveable { mutableStateOf(false) }
|
||||
val sendInvitesAction = remember { mutableStateOf<AsyncAction<Unit>>(AsyncAction.Uninitialized) }
|
||||
|
||||
val enableKeyShareOnInvite by featureFlagService.isFeatureEnabledFlow(FeatureFlags.EnableKeyShareOnInvite).collectAsState(initial = false)
|
||||
|
||||
val recentDirectRooms by produceState(emptyList(), roomMembers.value) {
|
||||
if (roomMembers.value.isSuccess()) {
|
||||
val activeMemberIds = roomMembers.value.dataOrNull().orEmpty()
|
||||
|
|
@ -137,12 +131,7 @@ class DefaultInvitePeoplePresenter(
|
|||
val selectedUserIdentities = produceState(
|
||||
emptyMap<MatrixUser, IdentityState?>().toImmutableMap(),
|
||||
selectedUsers.value,
|
||||
enableKeyShareOnInvite,
|
||||
) {
|
||||
if (!enableKeyShareOnInvite) {
|
||||
return@produceState
|
||||
}
|
||||
|
||||
val selected = selectedUsers.value
|
||||
|
||||
val cached = value
|
||||
|
|
@ -213,7 +202,7 @@ class DefaultInvitePeoplePresenter(
|
|||
}
|
||||
}
|
||||
is InvitePeopleEvents.SendInvites -> {
|
||||
if (enableKeyShareOnInvite && unknownUsers.isNotEmpty() && sendInvitesAction.value !is ConfirmingUnknownUserInvitation) {
|
||||
if (unknownUsers.isNotEmpty() && sendInvitesAction.value !is ConfirmingUnknownUserInvitation) {
|
||||
sendInvitesAction.value = ConfirmingUnknownUserInvitation(
|
||||
unknownUsers
|
||||
)
|
||||
|
|
|
|||
|
|
@ -15,9 +15,6 @@ import io.element.android.features.invitepeople.api.InvitePeopleEvents
|
|||
import io.element.android.libraries.architecture.AsyncData
|
||||
import io.element.android.libraries.core.coroutine.CoroutineDispatchers
|
||||
import io.element.android.libraries.designsystem.theme.components.SearchBarResultState
|
||||
import io.element.android.libraries.featureflag.api.FeatureFlagService
|
||||
import io.element.android.libraries.featureflag.api.FeatureFlags
|
||||
import io.element.android.libraries.featureflag.test.FakeFeatureFlagService
|
||||
import io.element.android.libraries.matrix.api.MatrixClient
|
||||
import io.element.android.libraries.matrix.api.core.RoomId
|
||||
import io.element.android.libraries.matrix.api.core.UserId
|
||||
|
|
@ -405,10 +402,14 @@ internal class DefaultInvitePeoplePresenterTest {
|
|||
val inviteUserResult = lambdaRecorder<UserId, Result<Unit>> { userId: UserId ->
|
||||
Result.success(Unit)
|
||||
}
|
||||
val encryptionService = FakeEncryptionService(
|
||||
getUserIdentityResult = { _ -> Result.success(null) },
|
||||
)
|
||||
val presenter = createDefaultInvitePeoplePresenter(
|
||||
userRepository = repository,
|
||||
inviteUserResult = inviteUserResult,
|
||||
coroutineDispatchers = testCoroutineDispatchers(useUnconfinedTestDispatcher = true)
|
||||
coroutineDispatchers = testCoroutineDispatchers(useUnconfinedTestDispatcher = true),
|
||||
matrixClient = FakeMatrixClient(encryptionService = encryptionService),
|
||||
)
|
||||
presenter.test {
|
||||
val initialState = awaitItem()
|
||||
|
|
@ -451,13 +452,18 @@ internal class DefaultInvitePeoplePresenterTest {
|
|||
Result.failure(AN_EXCEPTION)
|
||||
}
|
||||
val showErrorResResult = lambdaRecorder<Int, Int, Unit> { _, _ -> }
|
||||
|
||||
val encryptionService = FakeEncryptionService(
|
||||
getUserIdentityResult = { _ -> Result.success(null) },
|
||||
)
|
||||
val presenter = createDefaultInvitePeoplePresenter(
|
||||
userRepository = repository,
|
||||
inviteUserResult = inviteUserResult,
|
||||
coroutineDispatchers = testCoroutineDispatchers(useUnconfinedTestDispatcher = true),
|
||||
appErrorStateService = FakeAppErrorStateService(
|
||||
showErrorResResult = showErrorResResult,
|
||||
)
|
||||
),
|
||||
matrixClient = FakeMatrixClient(encryptionService = encryptionService),
|
||||
)
|
||||
presenter.test {
|
||||
val initialState = awaitItem()
|
||||
|
|
@ -632,15 +638,11 @@ internal class DefaultInvitePeoplePresenterTest {
|
|||
val encryptionService = FakeEncryptionService(
|
||||
getUserIdentityResult = getUserIdentityResult
|
||||
)
|
||||
val featureFlagService = FakeFeatureFlagService().apply {
|
||||
setFeatureEnabled(FeatureFlags.EnableKeyShareOnInvite, true)
|
||||
}
|
||||
|
||||
val presenter = createDefaultInvitePeoplePresenter(
|
||||
coroutineDispatchers = testCoroutineDispatchers(useUnconfinedTestDispatcher = true),
|
||||
inviteUserResult = inviteUserResult,
|
||||
matrixClient = FakeMatrixClient(encryptionService = encryptionService),
|
||||
featureFlagService = featureFlagService
|
||||
)
|
||||
presenter.test {
|
||||
val initialState = awaitItem()
|
||||
|
|
@ -703,15 +705,11 @@ internal class DefaultInvitePeoplePresenterTest {
|
|||
val encryptionService = FakeEncryptionService(
|
||||
getUserIdentityResult = getUserIdentityResult
|
||||
)
|
||||
val featureFlagService = FakeFeatureFlagService().apply {
|
||||
setFeatureEnabled(FeatureFlags.EnableKeyShareOnInvite, true)
|
||||
}
|
||||
|
||||
val presenter = createDefaultInvitePeoplePresenter(
|
||||
userRepository = repository,
|
||||
coroutineDispatchers = testCoroutineDispatchers(useUnconfinedTestDispatcher = true),
|
||||
matrixClient = FakeMatrixClient(encryptionService = encryptionService),
|
||||
featureFlagService = featureFlagService
|
||||
)
|
||||
presenter.test {
|
||||
val initialState = awaitItemAsDefault()
|
||||
|
|
@ -790,14 +788,10 @@ internal class DefaultInvitePeoplePresenterTest {
|
|||
val encryptionService = FakeEncryptionService(
|
||||
getUserIdentityResult = getUserIdentityResult
|
||||
)
|
||||
val featureFlagService = FakeFeatureFlagService().apply {
|
||||
setFeatureEnabled(FeatureFlags.EnableKeyShareOnInvite, true)
|
||||
}
|
||||
|
||||
val presenter = createDefaultInvitePeoplePresenter(
|
||||
coroutineDispatchers = testCoroutineDispatchers(useUnconfinedTestDispatcher = true),
|
||||
matrixClient = FakeMatrixClient(encryptionService = encryptionService),
|
||||
featureFlagService = featureFlagService
|
||||
)
|
||||
presenter.test {
|
||||
val initialState = awaitItem()
|
||||
|
|
@ -878,7 +872,6 @@ fun TestScope.createDefaultInvitePeoplePresenter(
|
|||
userRepository: UserRepository = FakeUserRepository(),
|
||||
coroutineDispatchers: CoroutineDispatchers = testCoroutineDispatchers(),
|
||||
appErrorStateService: AppErrorStateService = FakeAppErrorStateService(),
|
||||
featureFlagService: FeatureFlagService = FakeFeatureFlagService(),
|
||||
matrixClient: MatrixClient = FakeMatrixClient(),
|
||||
): DefaultInvitePeoplePresenter {
|
||||
return DefaultInvitePeoplePresenter(
|
||||
|
|
@ -888,7 +881,6 @@ fun TestScope.createDefaultInvitePeoplePresenter(
|
|||
coroutineDispatchers = coroutineDispatchers,
|
||||
sessionCoroutineScope = backgroundScope,
|
||||
appErrorStateService = appErrorStateService,
|
||||
featureFlagService = featureFlagService,
|
||||
matrixClient = matrixClient,
|
||||
)
|
||||
}
|
||||
|
|
|
|||
|
|
@ -217,12 +217,10 @@ class MessagesPresenter(
|
|||
val dmRoomMember by room.getDirectRoomMember(membersState)
|
||||
val roomMemberIdentityStateChanges = identityChangeState.roomMemberIdentityStateChanges
|
||||
|
||||
val isKeyShareOnInviteEnabled by featureFlagService.isFeatureEnabledFlow(FeatureFlags.EnableKeyShareOnInvite).collectAsState(initial = false)
|
||||
// The top bar should show a "history" icon if:
|
||||
// * History sharing is enabled,
|
||||
// * The room is encrypted, and:
|
||||
// * The room's history_visibility allows future users to see content.
|
||||
val topBarSharedHistoryIcon = if (isKeyShareOnInviteEnabled) roomInfo.sharedHistoryIcon() else SharedHistoryIcon.NONE
|
||||
val topBarSharedHistoryIcon = roomInfo.sharedHistoryIcon()
|
||||
|
||||
LifecycleResumeEffect(dmRoomMember, roomInfo.isEncrypted) {
|
||||
if (roomInfo.isEncrypted == true) {
|
||||
|
|
|
|||
|
|
@ -1228,9 +1228,6 @@ class MessagesPresenterTest {
|
|||
initialRoomInfo = aRoomInfo(isEncrypted = true, historyVisibility = RoomHistoryVisibility.Shared),
|
||||
),
|
||||
),
|
||||
featureFlagService = FakeFeatureFlagService(
|
||||
initialState = mapOf(FeatureFlags.EnableKeyShareOnInvite.key to true)
|
||||
)
|
||||
)
|
||||
presenter.testWithLifecycleOwner {
|
||||
awaitItem()
|
||||
|
|
@ -1249,9 +1246,6 @@ class MessagesPresenterTest {
|
|||
initialRoomInfo = aRoomInfo(isEncrypted = true, historyVisibility = RoomHistoryVisibility.WorldReadable),
|
||||
),
|
||||
),
|
||||
featureFlagService = FakeFeatureFlagService(
|
||||
initialState = mapOf(FeatureFlags.EnableKeyShareOnInvite.key to true)
|
||||
)
|
||||
)
|
||||
presenter.testWithLifecycleOwner {
|
||||
awaitItem()
|
||||
|
|
|
|||
|
|
@ -168,8 +168,6 @@ class RoomDetailsPresenter(
|
|||
|
||||
val canReportRoom by produceState(false) { value = client.canReportRoom() }
|
||||
|
||||
val enableKeyShareOnInvite by featureFlagService.isFeatureEnabledFlow(FeatureFlags.EnableKeyShareOnInvite).collectAsState(initial = false)
|
||||
|
||||
return RoomDetailsState(
|
||||
roomId = room.roomId,
|
||||
roomName = roomName,
|
||||
|
|
@ -199,7 +197,6 @@ class RoomDetailsPresenter(
|
|||
isTombstoned = roomInfo.successorRoom != null,
|
||||
showDebugInfo = isDeveloperModeEnabled,
|
||||
roomVersion = roomInfo.roomVersion,
|
||||
enableKeyShareOnInvite = enableKeyShareOnInvite,
|
||||
roomHistoryVisibility = roomInfo.historyVisibility,
|
||||
eventSink = ::handleEvent,
|
||||
)
|
||||
|
|
|
|||
|
|
@ -51,7 +51,6 @@ data class RoomDetailsState(
|
|||
val isTombstoned: Boolean,
|
||||
val showDebugInfo: Boolean,
|
||||
val roomVersion: String?,
|
||||
val enableKeyShareOnInvite: Boolean,
|
||||
val roomHistoryVisibility: RoomHistoryVisibility,
|
||||
val eventSink: (RoomDetailsEvent) -> Unit
|
||||
) {
|
||||
|
|
@ -64,7 +63,7 @@ data class RoomDetailsState(
|
|||
if (isPublic) {
|
||||
add(RoomBadge.PUBLIC)
|
||||
}
|
||||
if (enableKeyShareOnInvite && isEncrypted) {
|
||||
if (isEncrypted) {
|
||||
when (roomHistoryVisibility) {
|
||||
RoomHistoryVisibility.Invited, RoomHistoryVisibility.Joined -> add(RoomBadge.SHARED_HISTORY_HIDDEN)
|
||||
RoomHistoryVisibility.Shared -> add(RoomBadge.SHARED_HISTORY_SHARED)
|
||||
|
|
|
|||
|
|
@ -121,7 +121,6 @@ fun aRoomDetailsState(
|
|||
canReportRoom: Boolean = true,
|
||||
isTombstoned: Boolean = false,
|
||||
showDebugInfo: Boolean = false,
|
||||
enableKeyShareOnInvite: Boolean = false,
|
||||
roomHistoryVisibility: RoomHistoryVisibility = RoomHistoryVisibility.Shared,
|
||||
eventSink: (RoomDetailsEvent) -> Unit = {},
|
||||
) = RoomDetailsState(
|
||||
|
|
@ -153,7 +152,6 @@ fun aRoomDetailsState(
|
|||
isTombstoned = isTombstoned,
|
||||
showDebugInfo = showDebugInfo,
|
||||
roomVersion = "12",
|
||||
enableKeyShareOnInvite = enableKeyShareOnInvite,
|
||||
roomHistoryVisibility = roomHistoryVisibility,
|
||||
eventSink = eventSink,
|
||||
)
|
||||
|
|
@ -195,6 +193,5 @@ fun aSharedHistoryRoomDetailsState(
|
|||
roomHistoryVisibility: RoomHistoryVisibility
|
||||
) = aRoomDetailsState(
|
||||
isEncrypted = true,
|
||||
enableKeyShareOnInvite = true,
|
||||
roomHistoryVisibility = roomHistoryVisibility,
|
||||
)
|
||||
|
|
|
|||
|
|
@ -37,24 +37,24 @@ class RoomDetailsStateTest {
|
|||
}
|
||||
|
||||
@Test
|
||||
fun `room public encrypted should have encrypted and public badges`() {
|
||||
fun `room public encrypted should have encrypted, public, and history sharing shared badges`() {
|
||||
val sut = aRoomDetailsState(
|
||||
isPublic = true,
|
||||
isEncrypted = true,
|
||||
)
|
||||
assertThat(sut.roomBadges).isEqualTo(
|
||||
persistentListOf(RoomBadge.ENCRYPTED, RoomBadge.PUBLIC)
|
||||
persistentListOf(RoomBadge.ENCRYPTED, RoomBadge.PUBLIC, RoomBadge.SHARED_HISTORY_SHARED)
|
||||
)
|
||||
}
|
||||
|
||||
@Test
|
||||
fun `room not public encrypted should have encrypted badges`() {
|
||||
fun `room not public encrypted should have encrypted and history sharing shared badges`() {
|
||||
val sut = aRoomDetailsState(
|
||||
isPublic = false,
|
||||
isEncrypted = true,
|
||||
)
|
||||
assertThat(sut.roomBadges).isEqualTo(
|
||||
persistentListOf(RoomBadge.ENCRYPTED)
|
||||
persistentListOf(RoomBadge.ENCRYPTED, RoomBadge.SHARED_HISTORY_SHARED)
|
||||
)
|
||||
}
|
||||
|
||||
|
|
@ -62,7 +62,6 @@ class RoomDetailsStateTest {
|
|||
fun `room public not encrypted should not have history sharing badges`() {
|
||||
val sut = aRoomDetailsState(
|
||||
isEncrypted = false,
|
||||
enableKeyShareOnInvite = true,
|
||||
roomHistoryVisibility = RoomHistoryVisibility.Shared
|
||||
)
|
||||
assertThat(sut.roomBadges).isEqualTo(
|
||||
|
|
@ -74,7 +73,6 @@ class RoomDetailsStateTest {
|
|||
fun `room public encrypted should have history sharing hidden badge`() {
|
||||
val sut = aRoomDetailsState(
|
||||
isEncrypted = true,
|
||||
enableKeyShareOnInvite = true,
|
||||
roomHistoryVisibility = RoomHistoryVisibility.Joined
|
||||
)
|
||||
assertThat(sut.roomBadges).isEqualTo(
|
||||
|
|
@ -83,22 +81,9 @@ class RoomDetailsStateTest {
|
|||
}
|
||||
|
||||
@Test
|
||||
fun `room public encrypted should have history sharing shared badge`() {
|
||||
fun `room public encrypted with world_readable visibility should have history sharing world_readable badge`() {
|
||||
val sut = aRoomDetailsState(
|
||||
isEncrypted = true,
|
||||
enableKeyShareOnInvite = true,
|
||||
roomHistoryVisibility = RoomHistoryVisibility.Shared
|
||||
)
|
||||
assertThat(sut.roomBadges).isEqualTo(
|
||||
persistentListOf(RoomBadge.ENCRYPTED, RoomBadge.PUBLIC, RoomBadge.SHARED_HISTORY_SHARED)
|
||||
)
|
||||
}
|
||||
|
||||
@Test
|
||||
fun `room public encrypted should have history sharing world_readable badge`() {
|
||||
val sut = aRoomDetailsState(
|
||||
isEncrypted = true,
|
||||
enableKeyShareOnInvite = true,
|
||||
roomHistoryVisibility = RoomHistoryVisibility.WorldReadable
|
||||
)
|
||||
assertThat(sut.roomBadges).isEqualTo(
|
||||
|
|
|
|||
|
|
@ -15,8 +15,6 @@ import io.element.android.features.startchat.api.ConfirmingStartDmWithMatrixUser
|
|||
import io.element.android.features.startchat.api.StartDMAction
|
||||
import io.element.android.libraries.architecture.AsyncAction
|
||||
import io.element.android.libraries.di.SessionScope
|
||||
import io.element.android.libraries.featureflag.api.FeatureFlagService
|
||||
import io.element.android.libraries.featureflag.api.FeatureFlags
|
||||
import io.element.android.libraries.matrix.api.MatrixClient
|
||||
import io.element.android.libraries.matrix.api.core.RoomId
|
||||
import io.element.android.libraries.matrix.api.room.StartDMResult
|
||||
|
|
@ -28,7 +26,6 @@ import io.element.android.services.analytics.api.AnalyticsService
|
|||
class DefaultStartDMAction(
|
||||
private val matrixClient: MatrixClient,
|
||||
private val analyticsService: AnalyticsService,
|
||||
private val featureFlagService: FeatureFlagService,
|
||||
) : StartDMAction {
|
||||
override suspend fun execute(
|
||||
matrixUser: MatrixUser,
|
||||
|
|
@ -50,7 +47,7 @@ class DefaultStartDMAction(
|
|||
val identityState = matrixClient.encryptionService.getUserIdentity(matrixUser.userId, fallbackToServer = false).getOrNull()
|
||||
actionState.value = ConfirmingStartDmWithMatrixUser(
|
||||
matrixUser = matrixUser,
|
||||
isUserIdentityUnknown = featureFlagService.isFeatureEnabled(FeatureFlags.EnableKeyShareOnInvite) && identityState == null
|
||||
isUserIdentityUnknown = identityState == null
|
||||
)
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -58,8 +58,6 @@ class StartChatPresenter(
|
|||
featureFlagService.isFeatureEnabledFlow(FeatureFlags.RoomDirectorySearch)
|
||||
}.collectAsState(initial = false)
|
||||
|
||||
val enableKeyShareOnInvite = featureFlagService.isFeatureEnabledFlow(FeatureFlags.EnableKeyShareOnInvite).collectAsState(false)
|
||||
|
||||
fun handleEvent(event: StartChatEvents) {
|
||||
when (event) {
|
||||
is StartChatEvents.StartDM -> localCoroutineScope.launch {
|
||||
|
|
@ -78,7 +76,6 @@ class StartChatPresenter(
|
|||
userListState = userListState,
|
||||
startDmAction = startDmActionState.value,
|
||||
isRoomDirectorySearchEnabled = isRoomDirectorySearchEnabled,
|
||||
enableKeyShareOnInvite = enableKeyShareOnInvite.value,
|
||||
eventSink = ::handleEvent,
|
||||
)
|
||||
}
|
||||
|
|
|
|||
|
|
@ -17,6 +17,5 @@ data class StartChatState(
|
|||
val userListState: UserListState,
|
||||
val startDmAction: AsyncAction<RoomId>,
|
||||
val isRoomDirectorySearchEnabled: Boolean,
|
||||
val enableKeyShareOnInvite: Boolean,
|
||||
val eventSink: (StartChatEvents) -> Unit,
|
||||
)
|
||||
|
|
|
|||
|
|
@ -82,6 +82,5 @@ fun aCreateRoomRootState(
|
|||
userListState = userListState,
|
||||
startDmAction = startDmAction,
|
||||
isRoomDirectorySearchEnabled = isRoomDirectorySearchEnabled,
|
||||
enableKeyShareOnInvite = false,
|
||||
eventSink = eventSink,
|
||||
)
|
||||
|
|
|
|||
|
|
@ -130,7 +130,6 @@ fun StartChatView(
|
|||
if (data is ConfirmingStartDmWithMatrixUser) {
|
||||
CreateDmConfirmationBottomSheet(
|
||||
matrixUser = data.matrixUser,
|
||||
enableKeyShareOnInvite = state.enableKeyShareOnInvite,
|
||||
isUserIdentityUnknown = data.isUserIdentityUnknown,
|
||||
onSendInvite = {
|
||||
state.eventSink(StartChatEvents.StartDM(data.matrixUser))
|
||||
|
|
|
|||
|
|
@ -13,9 +13,6 @@ import com.google.common.truth.Truth.assertThat
|
|||
import im.vector.app.features.analytics.plan.CreatedRoom
|
||||
import io.element.android.features.startchat.api.ConfirmingStartDmWithMatrixUser
|
||||
import io.element.android.libraries.architecture.AsyncAction
|
||||
import io.element.android.libraries.featureflag.api.FeatureFlagService
|
||||
import io.element.android.libraries.featureflag.api.FeatureFlags
|
||||
import io.element.android.libraries.featureflag.test.FakeFeatureFlagService
|
||||
import io.element.android.libraries.matrix.api.MatrixClient
|
||||
import io.element.android.libraries.matrix.api.core.RoomId
|
||||
import io.element.android.libraries.matrix.api.core.UserId
|
||||
|
|
@ -88,7 +85,7 @@ class DefaultStartDMActionTest {
|
|||
val state = mutableStateOf<AsyncAction<RoomId>>(AsyncAction.Uninitialized)
|
||||
val matrixUser = aMatrixUser()
|
||||
action.execute(matrixUser, false, state)
|
||||
assertThat(state.value).isEqualTo(ConfirmingStartDmWithMatrixUser(matrixUser, isUserIdentityUnknown = false))
|
||||
assertThat(state.value).isEqualTo(ConfirmingStartDmWithMatrixUser(matrixUser, isUserIdentityUnknown = true))
|
||||
assertThat(analyticsService.capturedEvents).isEmpty()
|
||||
}
|
||||
|
||||
|
|
@ -107,37 +104,31 @@ class DefaultStartDMActionTest {
|
|||
}
|
||||
|
||||
@Test
|
||||
fun `when history sharing enabled, user identity fetched and identity unknown`() = runTest {
|
||||
fun `when user identity fetched and identity unknown`() = runTest {
|
||||
val getUserIdentityResult = lambdaRecorder<UserId, Result<IdentityState?>> { _ -> Result.success(null) }
|
||||
val encryptionService = FakeEncryptionService(getUserIdentityResult = getUserIdentityResult)
|
||||
val matrixClient = FakeMatrixClient(encryptionService = encryptionService).apply {
|
||||
givenFindDmResult(Result.success(null))
|
||||
}
|
||||
val featureFlagService = FakeFeatureFlagService().apply {
|
||||
setFeatureEnabled(FeatureFlags.EnableKeyShareOnInvite, true)
|
||||
}
|
||||
|
||||
val action = createStartDMAction(
|
||||
matrixClient = matrixClient,
|
||||
featureFlagService = featureFlagService
|
||||
)
|
||||
val state = mutableStateOf<AsyncAction<RoomId>>(AsyncAction.Uninitialized)
|
||||
|
||||
action.execute(aMatrixUser(), false, state)
|
||||
|
||||
assertThat(getUserIdentityResult.assertions().isCalledOnce())
|
||||
getUserIdentityResult.assertions().isCalledOnce()
|
||||
assertThat(state.value).isEqualTo(ConfirmingStartDmWithMatrixUser(aMatrixUser(), isUserIdentityUnknown = true))
|
||||
}
|
||||
|
||||
private fun createStartDMAction(
|
||||
matrixClient: MatrixClient = FakeMatrixClient(),
|
||||
analyticsService: AnalyticsService = FakeAnalyticsService(),
|
||||
featureFlagService: FeatureFlagService = FakeFeatureFlagService()
|
||||
): DefaultStartDMAction {
|
||||
return DefaultStartDMAction(
|
||||
matrixClient = matrixClient,
|
||||
analyticsService = analyticsService,
|
||||
featureFlagService = featureFlagService,
|
||||
)
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -26,7 +26,6 @@ data class UserProfileState(
|
|||
val dmRoomId: RoomId?,
|
||||
val canCall: Boolean,
|
||||
val snackbarMessage: SnackbarMessage?,
|
||||
val enableKeyShareOnInvite: Boolean,
|
||||
val eventSink: (UserProfileEvents) -> Unit
|
||||
) {
|
||||
enum class ConfirmationDialog {
|
||||
|
|
|
|||
|
|
@ -12,7 +12,6 @@ import androidx.compose.runtime.Composable
|
|||
import androidx.compose.runtime.LaunchedEffect
|
||||
import androidx.compose.runtime.MutableState
|
||||
import androidx.compose.runtime.State
|
||||
import androidx.compose.runtime.collectAsState
|
||||
import androidx.compose.runtime.getValue
|
||||
import androidx.compose.runtime.mutableStateOf
|
||||
import androidx.compose.runtime.produceState
|
||||
|
|
@ -32,8 +31,6 @@ import io.element.android.libraries.architecture.AsyncAction
|
|||
import io.element.android.libraries.architecture.AsyncData
|
||||
import io.element.android.libraries.architecture.Presenter
|
||||
import io.element.android.libraries.core.bool.orFalse
|
||||
import io.element.android.libraries.featureflag.api.FeatureFlagService
|
||||
import io.element.android.libraries.featureflag.api.FeatureFlags
|
||||
import io.element.android.libraries.matrix.api.MatrixClient
|
||||
import io.element.android.libraries.matrix.api.core.RoomId
|
||||
import io.element.android.libraries.matrix.api.core.UserId
|
||||
|
|
@ -53,7 +50,6 @@ class UserProfilePresenter(
|
|||
private val client: MatrixClient,
|
||||
private val startDMAction: StartDMAction,
|
||||
private val sessionEnterpriseService: SessionEnterpriseService,
|
||||
private val featureFlagService: FeatureFlagService,
|
||||
) : Presenter<UserProfileState> {
|
||||
@AssistedFactory
|
||||
interface Factory {
|
||||
|
|
@ -105,8 +101,6 @@ class UserProfilePresenter(
|
|||
}
|
||||
val userProfile by produceState<MatrixUser?>(null) { value = client.getProfile(userId).getOrNull() }
|
||||
|
||||
val enableKeyShareOnInvite = featureFlagService.isFeatureEnabledFlow(FeatureFlags.EnableKeyShareOnInvite).collectAsState(false)
|
||||
|
||||
fun handleEvent(event: UserProfileEvents) {
|
||||
when (event) {
|
||||
is UserProfileEvents.BlockUser -> {
|
||||
|
|
@ -159,7 +153,6 @@ class UserProfilePresenter(
|
|||
dmRoomId = dmRoomId,
|
||||
canCall = canCall,
|
||||
snackbarMessage = null,
|
||||
enableKeyShareOnInvite = enableKeyShareOnInvite.value,
|
||||
eventSink = ::handleEvent,
|
||||
)
|
||||
}
|
||||
|
|
|
|||
|
|
@ -24,7 +24,6 @@ import io.element.android.features.userprofile.api.UserProfileVerificationState
|
|||
import io.element.android.features.userprofile.impl.root.UserProfilePresenter
|
||||
import io.element.android.libraries.architecture.AsyncAction
|
||||
import io.element.android.libraries.architecture.AsyncData
|
||||
import io.element.android.libraries.featureflag.test.FakeFeatureFlagService
|
||||
import io.element.android.libraries.matrix.api.MatrixClient
|
||||
import io.element.android.libraries.matrix.api.core.RoomId
|
||||
import io.element.android.libraries.matrix.api.core.UserId
|
||||
|
|
@ -415,7 +414,6 @@ class UserProfilePresenterTest {
|
|||
sessionEnterpriseService = FakeSessionEnterpriseService(
|
||||
isElementCallAvailableResult = { isElementCallAvailable },
|
||||
),
|
||||
featureFlagService = FakeFeatureFlagService()
|
||||
)
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -61,6 +61,5 @@ fun aUserProfileState(
|
|||
dmRoomId = dmRoomId,
|
||||
canCall = canCall,
|
||||
snackbarMessage = snackbarMessage,
|
||||
enableKeyShareOnInvite = false,
|
||||
eventSink = eventSink,
|
||||
)
|
||||
|
|
|
|||
|
|
@ -114,7 +114,6 @@ fun UserProfileView(
|
|||
if (data is ConfirmingStartDmWithMatrixUser) {
|
||||
CreateDmConfirmationBottomSheet(
|
||||
matrixUser = data.matrixUser,
|
||||
enableKeyShareOnInvite = state.enableKeyShareOnInvite,
|
||||
isUserIdentityUnknown = data.isUserIdentityUnknown,
|
||||
onSendInvite = {
|
||||
state.eventSink(UserProfileEvents.StartDM)
|
||||
|
|
|
|||
|
|
@ -52,17 +52,6 @@ enum class FeatureFlags(
|
|||
defaultValue = { false },
|
||||
isFinished = false,
|
||||
),
|
||||
EnableKeyShareOnInvite(
|
||||
key = "feature.enableKeyShareOnInvite",
|
||||
title = "Share encrypted history with new members",
|
||||
description = "When inviting a user to an encrypted room that has history visibility set to \"shared\"," +
|
||||
" share encrypted history with that user, and accept encrypted history when you are invited to such a room." +
|
||||
"\nRequires an app restart to take effect." +
|
||||
"\n\nWARNING: this feature is EXPERIMENTAL and not all security precautions are implemented." +
|
||||
" Do not enable on production accounts.",
|
||||
defaultValue = { false },
|
||||
isFinished = false,
|
||||
),
|
||||
Knock(
|
||||
key = "feature.knock",
|
||||
title = "Ask to join",
|
||||
|
|
|
|||
|
|
@ -167,7 +167,7 @@ class RustMatrixClientFactory(
|
|||
}
|
||||
)
|
||||
)
|
||||
.enableShareHistoryOnInvite(featureFlagService.isFeatureEnabled(FeatureFlags.EnableKeyShareOnInvite))
|
||||
.enableShareHistoryOnInvite(true)
|
||||
.threadsEnabled(featureFlagService.isFeatureEnabled(FeatureFlags.Threads), threadSubscriptions = false)
|
||||
.requestConfig(
|
||||
RequestConfig(
|
||||
|
|
|
|||
|
|
@ -54,18 +54,17 @@ import io.element.android.libraries.ui.strings.CommonStrings
|
|||
@Composable
|
||||
fun CreateDmConfirmationBottomSheet(
|
||||
matrixUser: MatrixUser,
|
||||
enableKeyShareOnInvite: Boolean,
|
||||
isUserIdentityUnknown: Boolean,
|
||||
onSendInvite: () -> Unit,
|
||||
onDismiss: () -> Unit,
|
||||
modifier: Modifier = Modifier,
|
||||
) {
|
||||
val titleContent = if (enableKeyShareOnInvite && isUserIdentityUnknown) {
|
||||
val titleContent = if (isUserIdentityUnknown) {
|
||||
stringResource(R.string.screen_bottom_sheet_create_dm_unknown_user_title)
|
||||
} else {
|
||||
stringResource(R.string.screen_bottom_sheet_create_dm_title)
|
||||
}
|
||||
val descriptionContent = if (enableKeyShareOnInvite && isUserIdentityUnknown) {
|
||||
val descriptionContent = if (isUserIdentityUnknown) {
|
||||
stringResource(R.string.screen_bottom_sheet_create_dm_unknown_user_content)
|
||||
} else {
|
||||
stringResource(R.string.screen_bottom_sheet_create_dm_message, matrixUser.getFullName())
|
||||
|
|
@ -154,7 +153,6 @@ internal fun CreateDmConfirmationBottomSheetPreview(@PreviewParameter(
|
|||
) state: CreateDmConfirmationBottomSheetState) = ElementPreview {
|
||||
CreateDmConfirmationBottomSheet(
|
||||
matrixUser = state.matrixUser,
|
||||
enableKeyShareOnInvite = state.enableKeyShareOnInvite,
|
||||
isUserIdentityUnknown = state.isUserIdentityUnknown,
|
||||
onSendInvite = {},
|
||||
onDismiss = {},
|
||||
|
|
@ -163,14 +161,12 @@ internal fun CreateDmConfirmationBottomSheetPreview(@PreviewParameter(
|
|||
|
||||
data class CreateDmConfirmationBottomSheetState(
|
||||
val matrixUser: MatrixUser,
|
||||
val enableKeyShareOnInvite: Boolean,
|
||||
val isUserIdentityUnknown: Boolean,
|
||||
)
|
||||
|
||||
class CreateDmConfirmationBottomSheetStateProvider : PreviewParameterProvider<CreateDmConfirmationBottomSheetState> {
|
||||
override val values = sequenceOf(
|
||||
CreateDmConfirmationBottomSheetState(matrixUser = aMatrixUser(), enableKeyShareOnInvite = false, isUserIdentityUnknown = false),
|
||||
CreateDmConfirmationBottomSheetState(matrixUser = aMatrixUser(), enableKeyShareOnInvite = true, isUserIdentityUnknown = false),
|
||||
CreateDmConfirmationBottomSheetState(matrixUser = aMatrixUser(), enableKeyShareOnInvite = true, isUserIdentityUnknown = true),
|
||||
CreateDmConfirmationBottomSheetState(matrixUser = aMatrixUser(), isUserIdentityUnknown = false),
|
||||
CreateDmConfirmationBottomSheetState(matrixUser = aMatrixUser(), isUserIdentityUnknown = true),
|
||||
)
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,3 +1,3 @@
|
|||
version https://git-lfs.github.com/spec/v1
|
||||
oid sha256:dbbd62622843fbd1d8d35b63c7308eaed46b488e6b189e987983144e5395bd09
|
||||
size 78972
|
||||
oid sha256:2119838c9649710465dc1b8610550ce101f3016a1a6511c3f6dadc715fb75862
|
||||
size 82975
|
||||
|
|
|
|||
|
|
@ -1,3 +1,3 @@
|
|||
version https://git-lfs.github.com/spec/v1
|
||||
oid sha256:31d18a5e250e531fd7b986690306366cf69eedcfdbaba28148e3edd1d36ae597
|
||||
size 42912
|
||||
oid sha256:7ad7b9331a5d504b8d2145c4428e6b64ed838b371f1aad5c288e5545f8a20f1f
|
||||
size 45464
|
||||
|
|
|
|||
|
|
@ -1,3 +1,3 @@
|
|||
version https://git-lfs.github.com/spec/v1
|
||||
oid sha256:a04a5aa9e35df5eb82a0a708b2b743bb83a1a9408fee91beff60d5a1ce2c6d5d
|
||||
size 41599
|
||||
oid sha256:8d74ede198f221b1138ed49bac7e02ee0fefbccd38735b09237fda95a78f6bd2
|
||||
size 44174
|
||||
|
|
|
|||
|
|
@ -1,3 +1,3 @@
|
|||
version https://git-lfs.github.com/spec/v1
|
||||
oid sha256:ef69f889a28afe5704da86296ebf9916a7af1de751eb4c1ee4995ca3f70ea12d
|
||||
size 40737
|
||||
oid sha256:b3f483a9e05278928f806f9534720c121efa77bd11b93ea6afc8b543f51a6d7c
|
||||
size 43171
|
||||
|
|
|
|||
|
|
@ -1,3 +1,3 @@
|
|||
version https://git-lfs.github.com/spec/v1
|
||||
oid sha256:1d4312936ba67965a8b35e714bbc3014214320311c5d077d33382ebb5aca5738
|
||||
size 42172
|
||||
oid sha256:3045102b9695ce3c095ac81e3d3d26dbf182d433427903e280189613a74f2984
|
||||
size 44758
|
||||
|
|
|
|||
|
|
@ -1,3 +1,3 @@
|
|||
version https://git-lfs.github.com/spec/v1
|
||||
oid sha256:4b07f6c942ab083d94c22218010b4aa646cf03e87af41fbda89b16620f7b9752
|
||||
size 42079
|
||||
oid sha256:2bbbf23895558745ebe4fab7faee8ffb4acba07f48b652cc130c78ddf89bebef
|
||||
size 44684
|
||||
|
|
|
|||
|
|
@ -1,3 +1,3 @@
|
|||
version https://git-lfs.github.com/spec/v1
|
||||
oid sha256:1b6db26bd05f206661a5707a972cb6f843eef82c76e5e0035775625b4a6268a4
|
||||
size 42640
|
||||
oid sha256:1f72fb044fb52f226600ad2eb3344e8122edcce15c75800fb483f3b93a1c6e26
|
||||
size 45092
|
||||
|
|
|
|||
|
|
@ -1,3 +1,3 @@
|
|||
version https://git-lfs.github.com/spec/v1
|
||||
oid sha256:5f77eba1f623f67eba427312523def9a45c41581dd4e047701b2c75f787fcffc
|
||||
size 43178
|
||||
oid sha256:14261c716c286b17ee2afcb652378f9703b39f67b219256f6ac3cde61cd50947
|
||||
size 45589
|
||||
|
|
|
|||
|
|
@ -1,3 +1,3 @@
|
|||
version https://git-lfs.github.com/spec/v1
|
||||
oid sha256:a62965a57fea6665739d8e8b2fda9e15abf119ea59f6bbd5d7d8a269512064b9
|
||||
size 42421
|
||||
oid sha256:b1b1c3f8db4dc58dcaab91f254da2906138c09c65d4e57a77a5be9af371aaa5d
|
||||
size 44944
|
||||
|
|
|
|||
|
|
@ -1,3 +1,3 @@
|
|||
version https://git-lfs.github.com/spec/v1
|
||||
oid sha256:39780082d7826422d70902ac2b7859013c30b41d31f20aefc25ada8aeae196c2
|
||||
size 41684
|
||||
oid sha256:a5d3a4bd5c340c0d439ccd7d7e24f372d89255a775a9497e5d9b8847354cafb6
|
||||
size 44236
|
||||
|
|
|
|||
|
|
@ -1,3 +1,3 @@
|
|||
version https://git-lfs.github.com/spec/v1
|
||||
oid sha256:5917028dda35add5ed6b32fa9017a9cdcdfb8d273d230aa6d529bebfbf0b95c8
|
||||
size 39646
|
||||
oid sha256:6d9a464a1bc24dc76d1a10ae835fb24839b521ba446a1adad3e70f4ae5f17857
|
||||
size 42076
|
||||
|
|
|
|||
|
|
@ -1,3 +1,3 @@
|
|||
version https://git-lfs.github.com/spec/v1
|
||||
oid sha256:f65f298b3f14ecb0da53f03a20a5464a7f6ae138dfdf417ad936601a521fbb30
|
||||
size 39601
|
||||
oid sha256:29592dcede3af29136c857b03975c2697470682371ac5d606f2e6974f89ea268
|
||||
size 42030
|
||||
|
|
|
|||
|
|
@ -1,3 +1,3 @@
|
|||
version https://git-lfs.github.com/spec/v1
|
||||
oid sha256:df3ceef42a59cc072e3aa21c89e9b90f0524ac422d1538804b6fcb8abf97752e
|
||||
size 38090
|
||||
oid sha256:676908cf3eabc3417f228dabd2663bb0aa3d903d1b6f0e2fe770bdd6fbb48af2
|
||||
size 40407
|
||||
|
|
|
|||
|
|
@ -1,3 +1,3 @@
|
|||
version https://git-lfs.github.com/spec/v1
|
||||
oid sha256:0bf5c596196e64554117addd1247aa1e5be6e8095d85a595b1c2a6232ed483eb
|
||||
size 36591
|
||||
oid sha256:ae13e58b01e0e43591c0374474b33fea60574a5d8b22cb57092d15637dc58baa
|
||||
size 37920
|
||||
|
|
|
|||
|
|
@ -1,3 +1,3 @@
|
|||
version https://git-lfs.github.com/spec/v1
|
||||
oid sha256:6900db132e6b79de1c5ac986666af46e3f7ef65a9c4cc7d847dde6962eadd129
|
||||
size 41352
|
||||
oid sha256:a5bb345d25a8b90a34708123fc6ba72dd6aca2c09ade4c26b29e9168d65e18be
|
||||
size 42466
|
||||
|
|
|
|||
|
|
@ -1,3 +1,3 @@
|
|||
version https://git-lfs.github.com/spec/v1
|
||||
oid sha256:b7199817c8591ccf11241204af8a39d2ed1a60dfe238b06387749d57858cfa65
|
||||
size 39288
|
||||
oid sha256:c1d4af8779d9869938b17f26b155c584c10d119479c62918d5b819a0db30acac
|
||||
size 41720
|
||||
|
|
|
|||
|
|
@ -1,3 +1,3 @@
|
|||
version https://git-lfs.github.com/spec/v1
|
||||
oid sha256:ed4073d3b427b2a314667f5118b571e5896f1439582b9209077ec9c62ee0e061
|
||||
size 43097
|
||||
oid sha256:6cb0953ce6c69ad2e49213bf0dbff76a87505f88a092660b71d97ad1e75a5344
|
||||
size 45766
|
||||
|
|
|
|||
|
|
@ -1,3 +1,3 @@
|
|||
version https://git-lfs.github.com/spec/v1
|
||||
oid sha256:c68c895b189a41c7edf8fee58202560ef47e0a98082ddc3a346546f4f1346de7
|
||||
size 42100
|
||||
oid sha256:c0f655ed143e7b894e37d99fc64c75d44e6483e830055e04609a9da36830278c
|
||||
size 44670
|
||||
|
|
|
|||
|
|
@ -1,3 +1,3 @@
|
|||
version https://git-lfs.github.com/spec/v1
|
||||
oid sha256:e1879c3d54dfed55e4bb46d967c9c8c5a4f95f4e31e884afde4c9c517f35402e
|
||||
size 42093
|
||||
oid sha256:ac26ca718f2118d88315704ce4bc7960983ab2ac0c394199da2c5b3feeec4438
|
||||
size 44688
|
||||
|
|
|
|||
|
|
@ -1,3 +1,3 @@
|
|||
version https://git-lfs.github.com/spec/v1
|
||||
oid sha256:e2b5dc5cd20ccfdb7e6a1accabf6e139ff343c16378af19232168f835b1c97df
|
||||
size 43650
|
||||
oid sha256:9a9c05a4ace7dc7013e4b02b5e652296399cb2f391ed4bacb2f74d06b68c4be4
|
||||
size 46436
|
||||
|
|
|
|||
|
|
@ -1,3 +1,3 @@
|
|||
version https://git-lfs.github.com/spec/v1
|
||||
oid sha256:f9c7dce94908b2b0287c196f564c306a05306f058c71d75be3b298a45683bce4
|
||||
size 42321
|
||||
oid sha256:997444daf4024495291014f1cae1cee2ba389d160c0ccae706b120dcd908996e
|
||||
size 45024
|
||||
|
|
|
|||
|
|
@ -1,3 +1,3 @@
|
|||
version https://git-lfs.github.com/spec/v1
|
||||
oid sha256:743fcac827e8df7742127491722c3ce617a54c0b64fd3336f939994b45376966
|
||||
size 41470
|
||||
oid sha256:527d2c4574c8a5f6946ee94415e30152fdd9e153fd7651b5a40df789e8694d72
|
||||
size 43969
|
||||
|
|
|
|||
|
|
@ -1,3 +1,3 @@
|
|||
version https://git-lfs.github.com/spec/v1
|
||||
oid sha256:671ae1ee2f065705b38063cb354c4bb4a63247e01e1101dd155515b46decb660
|
||||
size 42926
|
||||
oid sha256:7da6bfdf7bc9878e1850f8a443adae82a3a4b0aaa5574cec74081ba6f88b879e
|
||||
size 45622
|
||||
|
|
|
|||
|
|
@ -1,3 +1,3 @@
|
|||
version https://git-lfs.github.com/spec/v1
|
||||
oid sha256:8f352ad92472cb8b152ef0660c7f66b55b956ec05bd11dbeb2c9aa543d0db2ca
|
||||
size 42849
|
||||
oid sha256:2e253e47f998774da8443926990526105fd918b79040955a3d884558a110db8a
|
||||
size 45538
|
||||
|
|
|
|||
|
|
@ -1,3 +1,3 @@
|
|||
version https://git-lfs.github.com/spec/v1
|
||||
oid sha256:5742ffdefde6a9e3f01ba021a75eea20599cc520fa4976aa45cf1c10e394f62b
|
||||
size 43367
|
||||
oid sha256:60a989450ffb8ed428d5dd021573b821d238a06f5515f21f9d50b855889ad985
|
||||
size 46022
|
||||
|
|
|
|||
|
|
@ -1,3 +1,3 @@
|
|||
version https://git-lfs.github.com/spec/v1
|
||||
oid sha256:0f6be8e586f9692013ce38c483c42fb23f8c135593e17a72f3be19381719fe6c
|
||||
size 43967
|
||||
oid sha256:37e6049854cd5aaeb50f38c4604e631fb561f0f309d4c58d41becf69a01ca036
|
||||
size 46596
|
||||
|
|
|
|||
|
|
@ -1,3 +1,3 @@
|
|||
version https://git-lfs.github.com/spec/v1
|
||||
oid sha256:7b4b470aa3f3650c26c6e1cf2491ffb7c3ea58db28dd00c0755a7f5727dc60f1
|
||||
size 43192
|
||||
oid sha256:05a841f7590a33ffea5b09ffc0975bc9090b03cace9e22c330965ce773431211
|
||||
size 45849
|
||||
|
|
|
|||
|
|
@ -1,3 +1,3 @@
|
|||
version https://git-lfs.github.com/spec/v1
|
||||
oid sha256:656c300cea79355aa3b35cd59666f8e35aa4c09d69dd422e816f256cbe6d420d
|
||||
size 42685
|
||||
oid sha256:8bc90cce90b0648a340e332276fe4395aec673408aaf938bd0d744d45c89dec2
|
||||
size 45396
|
||||
|
|
|
|||
|
|
@ -1,3 +1,3 @@
|
|||
version https://git-lfs.github.com/spec/v1
|
||||
oid sha256:93fe116bc34f9cf8ee3da2317948a98405e36a6fb98a58b2046a049af435e913
|
||||
size 40373
|
||||
oid sha256:c3ab8eeb4123df1feb35b4d9d9c7fbf166be943edfeb9fa23ac6549463763b10
|
||||
size 42853
|
||||
|
|
|
|||
|
|
@ -1,3 +1,3 @@
|
|||
version https://git-lfs.github.com/spec/v1
|
||||
oid sha256:09f89c67652965407ea147aef158d0b3281850b95cca35f7aec207693bb0af62
|
||||
size 40242
|
||||
oid sha256:a3eee4e61c8676a547c3ccbb1d6b9ea2ce0ae30286012de6b3a4f912b908d2e0
|
||||
size 42722
|
||||
|
|
|
|||
|
|
@ -1,3 +1,3 @@
|
|||
version https://git-lfs.github.com/spec/v1
|
||||
oid sha256:04c7f8e85d58591c3dd6ade913b9fe0861ff7f774fdb4b46e63c9f86ef5a918a
|
||||
size 38959
|
||||
oid sha256:02c734eb60efab5050988331527aae294fc6baf0b110e3395103429a79ba059c
|
||||
size 41424
|
||||
|
|
|
|||
|
|
@ -1,3 +1,3 @@
|
|||
version https://git-lfs.github.com/spec/v1
|
||||
oid sha256:27918a9baa05b2cb8dee7219b6e19cc10be1421be190d1e35724d237270761af
|
||||
size 37382
|
||||
oid sha256:ced1cdb2e11bff01ffce233ddf6cf826d6db266739abcd022f83b58d8bec012f
|
||||
size 38785
|
||||
|
|
|
|||
|
|
@ -1,3 +1,3 @@
|
|||
version https://git-lfs.github.com/spec/v1
|
||||
oid sha256:8ee0a79abd45fc9573e64b6f06491f33dfca34ddd96c0dbd3d8cf7a9052b47be
|
||||
size 42072
|
||||
oid sha256:db67d40bae68ec1ece950a06f618606fedc78aa997743b1804db4b69848ba65b
|
||||
size 43381
|
||||
|
|
|
|||
|
|
@ -1,3 +1,3 @@
|
|||
version https://git-lfs.github.com/spec/v1
|
||||
oid sha256:e7146d365a105c86eecc34027d2b824e90ca1615fcf77ca0f49ed920dbffe22d
|
||||
size 39903
|
||||
oid sha256:6cee9f291a3257f3960ea5d1490f3f219bb0d42b01109b9b398b941524b85971
|
||||
size 42383
|
||||
|
|
|
|||
|
|
@ -1,3 +1,3 @@
|
|||
version https://git-lfs.github.com/spec/v1
|
||||
oid sha256:863c5db2d8fd863b057d0ddfe26bb3804d15126c2fdb58fc03c0087d79c6a3b3
|
||||
size 44056
|
||||
oid sha256:79ac979bcc0339ed30c68c4617f082a9398edf657cc3aea1c80df04bd4b8bab2
|
||||
size 46724
|
||||
|
|
|
|||
|
|
@ -1,3 +1,3 @@
|
|||
version https://git-lfs.github.com/spec/v1
|
||||
oid sha256:16b815f5ec48c101a7bde78cd5a4e30e825138f359e415699ef2b14e6ea23869
|
||||
size 42968
|
||||
oid sha256:0d71c5e3a8dd2defe2dd37fee1a22921f49bbc9a52a766e5ad082b6595c6ff75
|
||||
size 45577
|
||||
|
|
|
|||
|
|
@ -1,3 +1,3 @@
|
|||
version https://git-lfs.github.com/spec/v1
|
||||
oid sha256:5c47ff32beec1987fdb9f92ef6e5c9b7eca04ab20ebab576a2028225a595ba12
|
||||
size 42911
|
||||
oid sha256:ada1e17913092a5e33b5f422a41826dd711102cfb5ab396d5d323e8e0f0b6589
|
||||
size 45590
|
||||
|
|
|
|||
|
|
@ -1,3 +1,3 @@
|
|||
version https://git-lfs.github.com/spec/v1
|
||||
oid sha256:bb4d6bfb9c412de00a2b4956032dd42906b5451eb99e6ebb1880dc01f6b55af5
|
||||
size 26077
|
||||
oid sha256:26bf76ccdb56d042422553f557d91d0f26d874a710f696ac106c5c2b5590d332
|
||||
size 38833
|
||||
|
|
|
|||
|
|
@ -1,3 +0,0 @@
|
|||
version https://git-lfs.github.com/spec/v1
|
||||
oid sha256:26bf76ccdb56d042422553f557d91d0f26d874a710f696ac106c5c2b5590d332
|
||||
size 38833
|
||||
|
|
@ -1,3 +1,3 @@
|
|||
version https://git-lfs.github.com/spec/v1
|
||||
oid sha256:b8c422787b67d477d3b7c8d5dee8879f33d47153dc93dd29bb3883e4ed863a41
|
||||
size 25232
|
||||
oid sha256:8413aed02383572cfe8c481c6ba8b0db4cfb3402334c37f2d8b54a73fe4bf594
|
||||
size 37343
|
||||
|
|
|
|||
|
|
@ -1,3 +0,0 @@
|
|||
version https://git-lfs.github.com/spec/v1
|
||||
oid sha256:8413aed02383572cfe8c481c6ba8b0db4cfb3402334c37f2d8b54a73fe4bf594
|
||||
size 37343
|
||||
Loading…
Add table
Add a link
Reference in a new issue