Skip to content

Commit

Permalink
Merge branch 'develop' into clear-mentions-list-after-sending-a-message
Browse files Browse the repository at this point in the history
  • Loading branch information
yamilmedina authored Dec 9, 2024
2 parents 6d47c0a + 7c5299e commit d6a77bd
Show file tree
Hide file tree
Showing 19 changed files with 59 additions and 148 deletions.
14 changes: 2 additions & 12 deletions app/src/main/kotlin/com/wire/android/model/ImageAsset.kt
Original file line number Diff line number Diff line change
Expand Up @@ -18,16 +18,13 @@

package com.wire.android.model

import androidx.appcompat.app.AppCompatActivity
import androidx.compose.runtime.Composable
import androidx.compose.runtime.Stable
import androidx.compose.ui.platform.LocalInspectionMode
import androidx.compose.ui.res.painterResource
import androidx.hilt.navigation.compose.hiltViewModel
import androidx.lifecycle.ViewModel
import androidx.lifecycle.viewmodel.compose.LocalViewModelStoreOwner
import com.wire.android.R
import com.wire.android.ui.LocalActivity
import com.wire.android.util.ui.WireSessionImageLoader
import com.wire.kalium.logic.data.id.ConversationId
import com.wire.kalium.logic.data.id.QualifiedIdMapper
Expand Down Expand Up @@ -73,15 +70,8 @@ sealed class ImageAsset {
withCrossfadeAnimation: Boolean = false
) = when {
LocalInspectionMode.current -> painterResource(id = R.drawable.ic_welcome_1)
else -> {
hiltViewModel<RemoteAssetImageViewModel>(
// limit the scope of the ViewModel to the current activity so that there's one image loader instance for the Activity
viewModelStoreOwner = checkNotNull(LocalActivity.current as? AppCompatActivity ?: LocalViewModelStoreOwner.current) {
"No ViewModelStoreOwner was provided via LocalViewModelStoreOwner"
},
key = "remote_asset_image_loader"
).imageLoader.paint(asset = this, fallbackData = fallbackData, withCrossfadeAnimation = withCrossfadeAnimation)
}
else -> hiltViewModel<RemoteAssetImageViewModel>().imageLoader
.paint(asset = this, fallbackData = fallbackData, withCrossfadeAnimation = withCrossfadeAnimation)
}
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -307,13 +307,22 @@ fun LoginErrorDialog(
dismissOnClickOutside = false
)

LoginState.Error.DialogError.PasswordNeededToRegisterClient -> TODO()

else -> LoginDialogErrorData(
title = stringResource(R.string.error_unknown_title),
body = AnnotatedString(stringResource(R.string.error_unknown_message)),
onDismiss = onDialogDismiss
)
LoginState.Error.DialogError.Request2FAWithHandle -> {
LoginDialogErrorData(
title = stringResource(R.string.login_error_request_2fa_with_handle_title),
body = AnnotatedString(stringResource(R.string.login_error_request_2fa_with_handle_message)),
onDismiss = onDialogDismiss
)
}
LoginState.Error.TextFieldError.InvalidValue,
LoginState.Error.DialogError.PasswordNeededToRegisterClient,
LoginState.Error.TooManyDevicesError -> {
LoginDialogErrorData(
title = stringResource(R.string.error_unknown_title),
body = AnnotatedString(stringResource(R.string.error_unknown_message)),
onDismiss = onDialogDismiss
)
}
}

WireDialog(
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -37,6 +37,7 @@ sealed class LoginState {
data object InvalidSSOCodeError : DialogError()
data object UserAlreadyExists : DialogError()
data object PasswordNeededToRegisterClient : DialogError()
data object Request2FAWithHandle : DialogError()
data class SSOResultError(val result: SSOFailureCodes) :
DialogError()
data object ServerVersionNotSupported : DialogError()
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -246,7 +246,14 @@ class LoginEmailViewModel @Inject constructor(
}

private suspend fun request2FACode(authScope: AuthenticationScope) {
val email = userIdentifierTextState.text.trim().toString()
val email = userIdentifierTextState.text.trim().toString().also {
// user is using handle to login when 2FA is required
if (!it.contains("@")) {
updateEmailFlowState(LoginState.Error.DialogError.Request2FAWithHandle)
return
}
}

val result = authScope.requestSecondFactorVerificationCode(
email = email,
verifiableAction = VerifiableAction.LOGIN_OR_CLIENT_REGISTRATION
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -177,8 +177,6 @@ fun OngoingCallScreen(
clearVideoPreview = sharedCallingViewModel::clearVideoPreview,
onCollapse = onCollapse,
requestVideoStreams = ongoingCallViewModel::requestVideoStreams,
onSelectedParticipant = ongoingCallViewModel::onSelectedParticipant,
selectedParticipantForFullScreen = ongoingCallViewModel.selectedParticipant,
hideDoubleTapToast = ongoingCallViewModel::hideDoubleTapToast,
onCameraPermissionPermanentlyDenied = onCameraPermissionPermanentlyDenied,
participants = sharedCallingViewModel.participantsState,
Expand Down Expand Up @@ -291,8 +289,6 @@ private fun OngoingCallContent(
hideDoubleTapToast: () -> Unit,
onCameraPermissionPermanentlyDenied: () -> Unit,
requestVideoStreams: (participants: List<UICallParticipant>) -> Unit,
onSelectedParticipant: (selectedParticipant: SelectedParticipant) -> Unit,
selectedParticipantForFullScreen: SelectedParticipant,
participants: PersistentList<UICallParticipant>,
inPictureInPictureMode: Boolean,
currentUserId: UserId,
Expand All @@ -307,6 +303,7 @@ private fun OngoingCallContent(
)

var shouldOpenFullScreen by remember { mutableStateOf(false) }
var selectedParticipantForFullScreen by remember { mutableStateOf(SelectedParticipant()) }

WireBottomSheetScaffold(
sheetDragHandle = null,
Expand Down Expand Up @@ -394,14 +391,11 @@ private fun OngoingCallContent(
selectedParticipant = selectedParticipantForFullScreen,
height = this@BoxWithConstraints.maxHeight - dimensions().spacing4x,
closeFullScreen = {
onSelectedParticipant(SelectedParticipant())
shouldOpenFullScreen = !shouldOpenFullScreen
},
onBackButtonClicked = {
onSelectedParticipant(SelectedParticipant())
shouldOpenFullScreen = !shouldOpenFullScreen
},
requestVideoStreams = requestVideoStreams,
setVideoPreview = setVideoPreview,
clearVideoPreview = clearVideoPreview,
participants = participants
Expand All @@ -418,7 +412,7 @@ private fun OngoingCallContent(
requestVideoStreams = requestVideoStreams,
currentUserId = currentUserId,
onDoubleTap = { selectedParticipant ->
onSelectedParticipant(selectedParticipant)
selectedParticipantForFullScreen = selectedParticipant
shouldOpenFullScreen = !shouldOpenFullScreen
},
)
Expand Down Expand Up @@ -586,8 +580,6 @@ fun PreviewOngoingCallContent(participants: PersistentList<UICallParticipant>) {
participants = participants,
inPictureInPictureMode = false,
currentUserId = UserId("userId", "domain"),
onSelectedParticipant = {},
selectedParticipantForFullScreen = SelectedParticipant(),
)
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -28,10 +28,8 @@ import com.wire.android.appLogger
import com.wire.android.datastore.GlobalDataStore
import com.wire.android.di.CurrentAccount
import com.wire.android.ui.calling.model.UICallParticipant
import com.wire.android.ui.calling.ongoing.fullscreen.SelectedParticipant
import com.wire.kalium.logic.data.call.Call
import com.wire.kalium.logic.data.call.CallClient
import com.wire.kalium.logic.data.call.CallQuality
import com.wire.kalium.logic.data.call.VideoState
import com.wire.kalium.logic.data.id.ConversationId
import com.wire.kalium.logic.data.user.UserId
Expand Down Expand Up @@ -65,8 +63,6 @@ class OngoingCallViewModel @AssistedInject constructor(

var state by mutableStateOf(OngoingCallState())
private set
var selectedParticipant by mutableStateOf(SelectedParticipant())
private set

init {
viewModelScope.launch {
Expand Down Expand Up @@ -128,32 +124,20 @@ class OngoingCallViewModel @AssistedInject constructor(
.also {
if (it.isNotEmpty()) {
val clients: List<CallClient> = it.map { uiParticipant ->
CallClient(
userId = uiParticipant.id.toString(),
clientId = uiParticipant.clientId,
quality = mapQualityStream(uiParticipant)
)
CallClient(uiParticipant.id.toString(), uiParticipant.clientId)
}
requestVideoStreams(conversationId, clients)
}
}
}
}

private fun mapQualityStream(uiParticipant: UICallParticipant): CallQuality {
return if (uiParticipant.clientId == selectedParticipant.clientId) {
CallQuality.HIGH
} else {
CallQuality.LOW
}
}

private fun startDoubleTapToastDisplayCountDown() {
doubleTapIndicatorCountDownTimer?.cancel()
doubleTapIndicatorCountDownTimer =
object : CountDownTimer(DOUBLE_TAP_TOAST_DISPLAY_TIME, COUNT_DOWN_INTERVAL) {
override fun onTick(p0: Long) {
appLogger.d("$TAG - startDoubleTapToastDisplayCountDown: $p0")
appLogger.i("startDoubleTapToastDisplayCountDown: $p0")
}

override fun onFinish() {
Expand Down Expand Up @@ -187,16 +171,10 @@ class OngoingCallViewModel @AssistedInject constructor(
}
}

fun onSelectedParticipant(selectedParticipant: SelectedParticipant) {
appLogger.d("$TAG - Selected participant: ${selectedParticipant.toLogString()}")
this.selectedParticipant = selectedParticipant
}

companion object {
const val DOUBLE_TAP_TOAST_DISPLAY_TIME = 7000L
const val COUNT_DOWN_INTERVAL = 1000L
const val DELAY_TO_SHOW_DOUBLE_TAP_TOAST = 500L
const val TAG = "OngoingCallViewModel"
}

@AssistedFactory
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -60,7 +60,6 @@ fun FullScreenTile(
closeFullScreen: (offset: Offset) -> Unit,
onBackButtonClicked: () -> Unit,
setVideoPreview: (View) -> Unit,
requestVideoStreams: (participants: List<UICallParticipant>) -> Unit,
clearVideoPreview: () -> Unit,
modifier: Modifier = Modifier,
contentPadding: Dp = dimensions().spacing4x,
Expand Down Expand Up @@ -120,10 +119,6 @@ fun FullScreenTile(
}
)
}

LaunchedEffect(selectedParticipant.userId) {
requestVideoStreams(listOf(it))
}
}
}

Expand All @@ -144,7 +139,6 @@ fun PreviewFullScreenTile() = WireTheme {
closeFullScreen = {},
onBackButtonClicked = {},
setVideoPreview = {},
requestVideoStreams = {},
clearVideoPreview = {},
participants = participants,
)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -17,16 +17,10 @@
*/
package com.wire.android.ui.calling.ongoing.fullscreen

import com.wire.kalium.logger.obfuscateId
import com.wire.kalium.logic.data.user.UserId

data class SelectedParticipant(
val userId: UserId = UserId("", ""),
val clientId: String = "",
val isSelfUser: Boolean = false
) {

fun toLogString(): String {
return "SelectedParticipant(userId=${userId.toLogString()}, clientId=${clientId.obfuscateId()}, isSelfUser=$isSelfUser)"
}
}
)
Original file line number Diff line number Diff line change
Expand Up @@ -1334,7 +1334,7 @@ fun JumpToLastMessageButton(
SmallFloatingActionButton(
onClick = { coroutineScope.launch { lazyListState.animateScrollToItem(0) } },
containerColor = MaterialTheme.wireColorScheme.secondaryText,
contentColor = MaterialTheme.wireColorScheme.primaryButtonEnabled,
contentColor = MaterialTheme.wireColorScheme.onPrimaryButtonEnabled,
shape = CircleShape,
elevation = FloatingActionButtonDefaults.elevation(dimensions().spacing0x),
modifier = Modifier
Expand Down
3 changes: 2 additions & 1 deletion app/src/main/res/values/strings.xml
Original file line number Diff line number Diff line change
Expand Up @@ -369,6 +369,8 @@
<string name="login_sso_code_label">SSO CODE OR EMAIL</string>
<string name="login_error_invalid_sso_code">Please enter a valid SSO code.</string>
<string name="login_error_invalid_sso_code_format">Enter a valid SSO code</string>
<string name="login_error_request_2fa_with_handle_title">Login with email</string>
<string name="login_error_request_2fa_with_handle_message">You can\'t use your username as two-factor authentication is activated. Please log in with your email instead.</string>
<string name="deleted_user_error_title">Deleted account</string>
<string name="deleted_user_error_message">You were logged out because your account was
deleted.
Expand Down Expand Up @@ -1637,5 +1639,4 @@ In group conversations, the group admin can overwrite this setting.</string>
<string name="personal_to_team_migration_error_message_already_in_team">You\'ve created or joined a team with this email address on another device.</string>
<string name="personal_to_team_migration_error_message_slow_network">Wire could not complete your team creation due to a slow internet connection.</string>
<string name="personal_to_team_migration_error_message_unknown_error">Wire could not complete your team creation due to an unknown error.</string>

</resources>
Original file line number Diff line number Diff line change
Expand Up @@ -45,7 +45,6 @@ object TestConversationDetails {

val GROUP = ConversationDetails.Group(
TestConversation.ONE_ON_ONE,
isSelfUserCreator = true,
isSelfUserMember = true,
selfRole = Conversation.Member.Role.Member
)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -65,6 +65,7 @@ import kotlinx.coroutines.test.StandardTestDispatcher
import kotlinx.coroutines.test.TestScope
import kotlinx.coroutines.test.advanceUntilIdle
import kotlinx.coroutines.test.runTest
import org.amshove.kluent.internal.assertEquals
import org.amshove.kluent.shouldBe
import org.amshove.kluent.shouldBeEqualTo
import org.amshove.kluent.shouldBeInstanceOf
Expand Down Expand Up @@ -491,6 +492,20 @@ class LoginEmailViewModelTest {
coVerify(exactly = 1) { getOrRegisterClientUseCase(match { it.secondFactorVerificationCode == null }) }
}

@Test
fun `given 2fa is needed, when user used handle to login, then show correct error message`() = runTest {
val email = "some.handle"
val code = "123456"
coEvery { loginUseCase(any(), any(), any(), any(), any()) } returns AuthenticationResult.Failure.InvalidCredentials.Missing2FA

loginViewModel.userIdentifierTextState.setTextAndPlaceCursorAtEnd(email)
loginViewModel.secondFactorVerificationCodeTextState.setTextAndPlaceCursorAtEnd(code)
advanceUntilIdle()
coVerify(exactly = 0) { addAuthenticatedUserUseCase(any(), any(), any(), any()) }
coVerify(exactly = 0) { getOrRegisterClientUseCase(any()) }
assertEquals(LoginState.Error.DialogError.Request2FAWithHandle, loginViewModel.loginState.flowState)
}

companion object {
val CLIENT = TestClient.CLIENT
val SSO_ID: SsoId = SsoId("scim_id", null, null)
Expand Down
Loading

0 comments on commit d6a77bd

Please sign in to comment.