Skip to content

Commit

Permalink
Merge remote-tracking branch 'refs/remotes/origin/feat/WPB-8592' into…
Browse files Browse the repository at this point in the history
… feat/pass-signature-algorithm-when-registring-mls-client

# Conflicts:
#	app/src/main/kotlin/com/wire/android/di/accountScoped/ConversationModule.kt
#	app/src/main/kotlin/com/wire/android/ui/connection/ConnectionActionButtonViewModel.kt
#	app/src/main/kotlin/com/wire/android/ui/home/conversations/SystemMessageItem.kt
#	app/src/main/kotlin/com/wire/android/ui/home/conversations/details/participants/usecase/ObserveParticipantsForConversationUseCase.kt
#	app/src/main/kotlin/com/wire/android/ui/userprofile/other/OtherUserProfileState.kt
#	app/src/test/kotlin/com/wire/android/ui/home/conversations/details/participants/usecase/ObserveParticipantsForConversationUseCaseTest.kt
#	core/ui-common/src/main/kotlin/com/wire/android/ui/common/WireDialog.kt
#	kalium
  • Loading branch information
MohamadJaara committed Apr 29, 2024
2 parents c63dd6f + 88dac92 commit 834e95c
Show file tree
Hide file tree
Showing 18 changed files with 1,350 additions and 73 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -51,7 +51,7 @@ class KaliumConfigsModule {
forceConstantBitrateCalls = BuildConfig.FORCE_CONSTANT_BITRATE_CALLS,
// we use upsert, available from SQL3.24, which is supported from Android API30, so for older APIs we have to use SQLCipher
shouldEncryptData = !BuildConfig.DEBUG || Build.VERSION.SDK_INT < Build.VERSION_CODES.R,
lowerKeyPackageLimits = BuildConfig.PRIVATE_BUILD,
lowerKeyPackageLimits = BuildConfig.LOWER_KEYPACKAGE_LIMIT,
lowerKeyingMaterialsUpdateThreshold = BuildConfig.PRIVATE_BUILD,
isMLSSupportEnabled = BuildConfig.MLS_SUPPORT_ENABLED,
developmentApiEnabled = BuildConfig.DEVELOPMENT_API_ENABLED,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,7 @@ import com.wire.kalium.logic.feature.conversation.CreateGroupConversationUseCase
import com.wire.kalium.logic.feature.conversation.GetConversationUnreadEventsCountUseCase
import com.wire.kalium.logic.feature.conversation.GetOneToOneConversationUseCase
import com.wire.kalium.logic.feature.conversation.GetOrCreateOneToOneConversationUseCase
import com.wire.kalium.logic.feature.conversation.IsOneToOneConversationCreatedUseCase
import com.wire.kalium.logic.feature.conversation.JoinConversationViaCodeUseCase
import com.wire.kalium.logic.feature.conversation.LeaveConversationUseCase
import com.wire.kalium.logic.feature.conversation.NotifyConversationIsOpenUseCase
Expand All @@ -38,9 +39,9 @@ import com.wire.kalium.logic.feature.conversation.ObserveConversationDetailsUseC
import com.wire.kalium.logic.feature.conversation.ObserveConversationInteractionAvailabilityUseCase
import com.wire.kalium.logic.feature.conversation.ObserveConversationListDetailsUseCase
import com.wire.kalium.logic.feature.conversation.ObserveConversationMembersUseCase
import com.wire.kalium.logic.feature.conversation.ObserveConversationUnderLegalHoldNotifiedUseCase
import com.wire.kalium.logic.feature.conversation.ObserveDegradedConversationNotifiedUseCase
import com.wire.kalium.logic.feature.conversation.ObserveIsSelfUserMemberUseCase
import com.wire.kalium.logic.feature.conversation.ObserveConversationUnderLegalHoldNotifiedUseCase
import com.wire.kalium.logic.feature.conversation.ObserveUserListByIdUseCase
import com.wire.kalium.logic.feature.conversation.ObserveUsersTypingUseCase
import com.wire.kalium.logic.feature.conversation.RefreshConversationsWithoutMetadataUseCase
Expand All @@ -49,7 +50,6 @@ import com.wire.kalium.logic.feature.conversation.RenameConversationUseCase
import com.wire.kalium.logic.feature.conversation.SendTypingEventUseCase
import com.wire.kalium.logic.feature.conversation.SetNotifiedAboutConversationUnderLegalHoldUseCase
import com.wire.kalium.logic.feature.conversation.SetUserInformedAboutVerificationUseCase
import com.wire.kalium.logic.feature.conversation.SyncConversationCodeUseCase
import com.wire.kalium.logic.feature.conversation.UpdateConversationAccessRoleUseCase
import com.wire.kalium.logic.feature.conversation.UpdateConversationArchivedStatusUseCase
import com.wire.kalium.logic.feature.conversation.UpdateConversationMemberRoleUseCase
Expand Down Expand Up @@ -292,6 +292,6 @@ class ConversationModule {

@ViewModelScoped
@Provides
fun provideSyncConversationCodeUseCase(conversationScope: ConversationScope): SyncConversationCodeUseCase =
conversationScope.syncConversationCode
fun provideIsOneToOneConversationCreatedUseCase(conversationScope: ConversationScope): IsOneToOneConversationCreatedUseCase =
conversationScope.isOneToOneConversationCreatedUseCase
}
167 changes: 167 additions & 0 deletions app/src/main/kotlin/com/wire/android/ui/common/TextWithLinkSuffix.kt
Original file line number Diff line number Diff line change
@@ -0,0 +1,167 @@
/*
* Wire
* Copyright (C) 2024 Wire Swiss GmbH
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see http://www.gnu.org/licenses/.
*/
package com.wire.android.ui.common

import androidx.compose.foundation.clickable
import androidx.compose.foundation.layout.width
import androidx.compose.foundation.text.InlineTextContent
import androidx.compose.foundation.text.appendInlineContent
import androidx.compose.material3.MaterialTheme
import androidx.compose.material3.Text
import androidx.compose.runtime.Composable
import androidx.compose.ui.Modifier
import androidx.compose.ui.graphics.Color
import androidx.compose.ui.platform.LocalDensity
import androidx.compose.ui.platform.testTag
import androidx.compose.ui.text.AnnotatedString
import androidx.compose.ui.text.Placeholder
import androidx.compose.ui.text.PlaceholderVerticalAlign
import androidx.compose.ui.text.TextLayoutResult
import androidx.compose.ui.text.TextStyle
import androidx.compose.ui.text.buildAnnotatedString
import androidx.compose.ui.text.rememberTextMeasurer
import androidx.compose.ui.text.style.TextDecoration
import androidx.compose.ui.unit.Dp
import com.wire.android.ui.theme.WireTheme
import com.wire.android.ui.theme.wireColorScheme
import com.wire.android.ui.theme.wireTypography
import com.wire.android.util.ui.PreviewMultipleThemes

@Composable
fun TextWithLinkSuffix(
text: AnnotatedString,
linkText: String? = null,
onLinkClick: () -> Unit = {},
linkTag: String = "link",
textStyle: TextStyle = MaterialTheme.wireTypography.body01,
textColor: Color = MaterialTheme.wireColorScheme.onBackground,
linkStyle: TextStyle = MaterialTheme.wireTypography.body02,
linkColor: Color = MaterialTheme.wireColorScheme.primary,
linkDecoration: TextDecoration = TextDecoration.Underline,
onTextLayout: (TextLayoutResult) -> Unit = {},
modifier: Modifier = Modifier,
) {
val textMeasurer = rememberTextMeasurer()
val linkId = "link"
val inlineText = if (linkText != null) {
text.plus(
buildAnnotatedString {
append(" ")
appendInlineContent(linkId, "[link]")
}
)
} else text
val inlineContent = buildMap {
if (linkText != null) {
val textLayoutResult: TextLayoutResult = textMeasurer.measure(
text = linkText,
style = linkStyle.copy(textDecoration = linkDecoration),
)
val textSize = textLayoutResult.size
val density = LocalDensity.current
val (linkWidthSp, linkHeightSp) = with(density) { textSize.width.toSp() to textSize.height.toSp() }

put(linkId, InlineTextContent(
placeholder = Placeholder(
width = linkWidthSp,
height = linkHeightSp,
placeholderVerticalAlign = PlaceholderVerticalAlign.Bottom
),
children = {
Text(
text = linkText,
style = linkStyle,
color = linkColor,
textDecoration = linkDecoration,
modifier = Modifier
.testTag(linkTag)
.clickable(onClick = onLinkClick)
)
}
)
)
}
}

Text(
text = inlineText,
style = textStyle,
color = textColor,
inlineContent = inlineContent,
onTextLayout = onTextLayout,
modifier = modifier,
)
}

@Composable
private fun PreviewTextWithLinkSuffixBuilder(
textLines: List<String> = listOf("This is a text with a link"),
linkText: String = "link",
calculateWidth: (lastTextLineWidthDp: Dp, linkWidthDp: Dp) -> Dp
) {
val textStyle = MaterialTheme.wireTypography.body01
val linkStyle = MaterialTheme.wireTypography.body02.copy(textDecoration = TextDecoration.Underline)
val textMeasurer = rememberTextMeasurer()
val lastTextLineLayoutResult = textMeasurer.measure(text = "${textLines.last()} ", style = textStyle)
val linkLayoutResult = textMeasurer.measure(text = linkText, style = linkStyle)
val density = LocalDensity.current
val lastTextLineWidthDp = with(density) { lastTextLineLayoutResult.size.width.toDp() }
val linkWidthDp = with(density) { linkLayoutResult.size.width.toDp() }
TextWithLinkSuffix(
text = AnnotatedString(textLines.joinToString(separator = "\n")),
linkText = linkText,
onLinkClick = {},
modifier = Modifier.width(calculateWidth(lastTextLineWidthDp, linkWidthDp))
)
}

@PreviewMultipleThemes
@Composable
fun PreviewTextWithLinkSuffixWithoutALink() = WireTheme {
TextWithLinkSuffix(text = AnnotatedString("This is a text without a link"))
}

@PreviewMultipleThemes
@Composable
fun PreviewTextWithLinkSuffixFittingInSameLine() = WireTheme {
PreviewTextWithLinkSuffixBuilder { lastTextLineWidthDp, linkWidthDp -> lastTextLineWidthDp + linkWidthDp }
}

@PreviewMultipleThemes
@Composable
fun PreviewTextWithLinkSuffixNotFittingInSameLine() = WireTheme {
PreviewTextWithLinkSuffixBuilder { lastTextLineWidthDp, linkWidthDp -> lastTextLineWidthDp + (linkWidthDp / 2) }
}

@PreviewMultipleThemes
@Composable
fun PreviewTextWithLinkSuffixMultilineFittingInLastLine() = WireTheme {
PreviewTextWithLinkSuffixBuilder(
textLines = listOf("This is a text with a link", "This is a text with a"),
linkText = "link",
) { lastTextLineWidthDp, linkWidthDp -> lastTextLineWidthDp + linkWidthDp }
}

@PreviewMultipleThemes
@Composable
fun PreviewTextWithLinkSuffixMultilineNotFittingInLastLine() = WireTheme {
PreviewTextWithLinkSuffixBuilder(
textLines = listOf("This is a text with a", "This is a text with a"),
linkText = "link"
) { lastTextLineWidthDp, linkWidthDp -> lastTextLineWidthDp + (linkWidthDp / 2) }
}
Original file line number Diff line number Diff line change
Expand Up @@ -23,25 +23,35 @@ import androidx.compose.foundation.layout.Spacer
import androidx.compose.foundation.layout.height
import androidx.compose.foundation.layout.padding
import androidx.compose.material3.Icon
import androidx.compose.material3.MaterialTheme
import androidx.compose.runtime.Composable
import androidx.compose.ui.Modifier
import androidx.compose.ui.platform.LocalContext
import androidx.compose.ui.res.painterResource
import androidx.compose.ui.res.stringResource
import com.wire.android.R
import com.wire.android.di.hiltViewModelScoped
import com.wire.android.model.ClickBlockParams
import com.wire.android.ui.common.VisibilityState
import com.wire.android.ui.common.WireDialog
import com.wire.android.ui.common.WireDialogButtonProperties
import com.wire.android.ui.common.WireDialogButtonType
import com.wire.android.ui.common.button.WireButtonState
import com.wire.android.ui.common.button.WirePrimaryButton
import com.wire.android.ui.common.button.WireSecondaryButton
import com.wire.android.ui.common.colorsScheme
import com.wire.android.ui.common.dialogs.UnblockUserDialogContent
import com.wire.android.ui.common.dialogs.UnblockUserDialogState
import com.wire.android.ui.common.dimensions
import com.wire.android.ui.common.snackbar.LocalSnackbarHostState
import com.wire.android.ui.common.snackbar.collectAndShowSnackbar
import com.wire.android.ui.common.visbility.VisibilityState
import com.wire.android.ui.common.visbility.rememberVisibilityState
import com.wire.android.ui.legalhold.dialog.connectionfailed.LegalHoldSubjectConnectionFailedDialog
import com.wire.android.ui.theme.WireTheme
import com.wire.android.ui.theme.wireTypography
import com.wire.android.util.ui.PreviewMultipleThemes
import com.wire.android.util.ui.stringWithStyledArgs
import com.wire.kalium.logic.data.id.ConversationId
import com.wire.kalium.logic.data.user.ConnectionState
import com.wire.kalium.logic.data.user.UserId
Expand All @@ -50,7 +60,9 @@ import com.wire.kalium.logic.data.user.UserId
fun ConnectionActionButton(
userId: UserId,
userName: String,
fullName: String,
connectionStatus: ConnectionState,
isConversationStarted: Boolean,
onConnectionRequestIgnored: (String) -> Unit = {},
onOpenConversation: (ConversationId) -> Unit = {},
viewModel: ConnectionActionButtonViewModel =
Expand All @@ -60,13 +72,16 @@ fun ConnectionActionButton(
) {
LocalSnackbarHostState.current.collectAndShowSnackbar(snackbarFlow = viewModel.infoMessage)
val unblockUserDialogState = rememberVisibilityState<UnblockUserDialogState>()
val unableStartConversationDialogState = rememberVisibilityState<UnableStartConversationDialogState>()

UnblockUserDialogContent(
dialogState = unblockUserDialogState,
onUnblock = { viewModel.onUnblockUser() },
isLoading = viewModel.actionableState().isPerformingAction,
)

UnableStartConversationDialogContent(dialogState = unableStartConversationDialogState)

if (!viewModel.actionableState().isPerformingAction) {
unblockUserDialogState.dismiss()
}
Expand All @@ -86,9 +101,13 @@ fun ConnectionActionButton(
)

ConnectionState.ACCEPTED -> WirePrimaryButton(
text = stringResource(R.string.label_open_conversation),
text = stringResource(if (isConversationStarted) R.string.label_open_conversation else R.string.label_start_conversation),
loading = viewModel.actionableState().isPerformingAction,
onClick = { viewModel.onOpenConversation(onOpenConversation) },
onClick = {
viewModel.onOpenConversation(onOpenConversation) {
unableStartConversationDialogState.show(UnableStartConversationDialogState(fullName))
}
},
)

ConnectionState.IGNORED -> WirePrimaryButton(
Expand Down Expand Up @@ -174,14 +193,41 @@ fun ConnectionActionButton(
}
}

@Composable
fun UnableStartConversationDialogContent(dialogState: VisibilityState<UnableStartConversationDialogState>) {
VisibilityState(dialogState) { state ->
WireDialog(
title = stringResource(id = R.string.missing_keypackage_dialog_title),
text = LocalContext.current.resources.stringWithStyledArgs(
R.string.missing_keypackage_dialog_body,
MaterialTheme.wireTypography.body01,
MaterialTheme.wireTypography.body02,
colorsScheme().onBackground,
colorsScheme().onBackground,
state.userName
),
onDismiss = dialogState::dismiss,
optionButton1Properties = WireDialogButtonProperties(
onClick = dialogState::dismiss,
text = stringResource(id = R.string.label_ok),
type = WireDialogButtonType.Primary,
),
)
}
}

data class UnableStartConversationDialogState(val userName: String)

@Composable
@PreviewMultipleThemes
fun PreviewOtherUserConnectionActionButtonPending() {
WireTheme {
ConnectionActionButton(
userId = UserId("value", "domain"),
userName = "Username",
fullName = "some user",
connectionStatus = ConnectionState.PENDING,
isConversationStarted = false
)
}
}
Expand All @@ -193,7 +239,9 @@ fun PreviewOtherUserConnectionActionButtonNotConnected() {
ConnectionActionButton(
userId = UserId("value", "domain"),
userName = "Username",
fullName = "some user",
connectionStatus = ConnectionState.NOT_CONNECTED,
isConversationStarted = false
)
}
}
Expand All @@ -205,7 +253,9 @@ fun PreviewOtherUserConnectionActionButtonBlocked() {
ConnectionActionButton(
userId = UserId("value", "domain"),
userName = "Username",
fullName = "some user",
connectionStatus = ConnectionState.BLOCKED,
isConversationStarted = false
)
}
}
Expand All @@ -217,7 +267,9 @@ fun PreviewOtherUserConnectionActionButtonCanceled() {
ConnectionActionButton(
userId = UserId("value", "domain"),
userName = "Username",
fullName = "some user",
connectionStatus = ConnectionState.CANCELLED,
isConversationStarted = false
)
}
}
Expand All @@ -229,7 +281,9 @@ fun PreviewOtherUserConnectionActionButtonAccepted() {
ConnectionActionButton(
userId = UserId("value", "domain"),
userName = "Username",
fullName = "some user",
connectionStatus = ConnectionState.ACCEPTED,
isConversationStarted = false
)
}
}
Expand All @@ -241,7 +295,9 @@ fun PreviewOtherUserConnectionActionButtonSent() {
ConnectionActionButton(
userId = UserId("value", "domain"),
userName = "Username",
fullName = "some user",
connectionStatus = ConnectionState.SENT,
isConversationStarted = false
)
}
}
Loading

0 comments on commit 834e95c

Please sign in to comment.