Skip to content

Commit

Permalink
fix: share text to wire (WPB-1872) (#2168)
Browse files Browse the repository at this point in the history
  • Loading branch information
alexandreferris authored Sep 5, 2023
1 parent b310d4d commit a19f4b4
Show file tree
Hide file tree
Showing 3 changed files with 115 additions and 53 deletions.
12 changes: 12 additions & 0 deletions app/src/main/AndroidManifest.xml
Original file line number Diff line number Diff line change
Expand Up @@ -141,6 +141,12 @@
<data android:mimeType="audio/*" />
</intent-filter>

<intent-filter>
<action android:name="android.intent.action.SEND_MULTIPLE" />
<category android:name="android.intent.category.DEFAULT" />
<data android:mimeType="text/*" />
</intent-filter>

<intent-filter>
<action android:name="android.intent.action.SEND_MULTIPLE" />
<category android:name="android.intent.category.DEFAULT" />
Expand All @@ -165,6 +171,12 @@
<data android:mimeType="audio/*" />
</intent-filter>

<intent-filter>
<action android:name="android.intent.action.SEND" />
<category android:name="android.intent.category.DEFAULT" />
<data android:mimeType="text/*" />
</intent-filter>

<intent-filter>
<action android:name="android.intent.action.SEND" />
<category android:name="android.intent.category.DEFAULT" />
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -45,6 +45,7 @@ import com.wire.kalium.logic.feature.asset.GetAssetSizeLimitUseCase
import com.wire.kalium.logic.feature.asset.ScheduleNewAssetMessageResult
import com.wire.kalium.logic.feature.asset.ScheduleNewAssetMessageUseCase
import com.wire.kalium.logic.feature.conversation.ObserveConversationListDetailsUseCase
import com.wire.kalium.logic.feature.message.SendTextMessageUseCase
import com.wire.kalium.logic.feature.selfDeletingMessages.ObserveSelfDeletionTimerSettingsForConversationUseCase
import com.wire.kalium.logic.feature.selfDeletingMessages.PersistNewSelfDeletionTimerUseCase
import com.wire.kalium.logic.feature.selfDeletingMessages.SelfDeletionTimer
Expand Down Expand Up @@ -78,6 +79,7 @@ class ImportMediaAuthenticatedViewModel @Inject constructor(
private val observeConversationListDetails: ObserveConversationListDetailsUseCase,
private val fileManager: FileManager,
private val sendAssetMessage: ScheduleNewAssetMessageUseCase,
private val sendTextMessage: SendTextMessageUseCase,
private val kaliumFileSystem: KaliumFileSystem,
private val getAssetSizeLimit: GetAssetSizeLimitUseCase,
private val persistNewSelfDeletionTimerUseCase: PersistNewSelfDeletionTimerUseCase,
Expand Down Expand Up @@ -260,8 +262,7 @@ class ImportMediaAuthenticatedViewModel @Inject constructor(
appLogger.e("Received data from sharing intent ${incomingIntent.streamCount}")
importMediaState = importMediaState.copy(isImporting = true)
if (incomingIntent.streamCount == 0) {
// if stream count is 0 the type will be text, we check the type to double check if it is text
// todo : handle the text , we can get the text from incomingIntent.text
handleSharedText(incomingIntent.text.toString())
} else {
if (incomingIntent.isSingleShare) {
// ACTION_SEND
Expand All @@ -274,6 +275,10 @@ class ImportMediaAuthenticatedViewModel @Inject constructor(
importMediaState = importMediaState.copy(isImporting = false)
}

private fun handleSharedText(text: String) {
importMediaState = importMediaState.copy(importedText = text)
}

private suspend fun handleSingleIntent(
incomingIntent: ShareCompat.IntentReader,
activity: AppCompatActivity
Expand Down Expand Up @@ -303,45 +308,58 @@ class ImportMediaAuthenticatedViewModel @Inject constructor(
importMediaState = importMediaState.copy(importedAssets = importedMediaAssets)
}

fun checkRestrictionsAndSendImportedMedia(onSent: (ConversationId) -> Unit) = viewModelScope.launch(dispatchers.default()) {
val conversation = importMediaState.selectedConversationItem.firstOrNull() ?: return@launch
val assetsToSend = importMediaState.importedAssets
fun checkRestrictionsAndSendImportedMedia(onSent: (ConversationId) -> Unit) =
viewModelScope.launch(dispatchers.default()) {
val conversation =
importMediaState.selectedConversationItem.firstOrNull() ?: return@launch
val assetsToSend = importMediaState.importedAssets
val textToSend = importMediaState.importedText

if (assetsToSend.size > MAX_LIMIT_MEDIA_IMPORT) {
onSnackbarMessage(ImportMediaSnackbarMessages.MaxAmountOfAssetsReached)
} else {
val jobs: MutableCollection<Job> = mutableListOf()
assetsToSend.forEach { importedAsset ->
val isImage = importedAsset is ImportedMediaAsset.Image
val job = viewModelScope.launch {
sendAssetMessage(
if (assetsToSend.size > MAX_LIMIT_MEDIA_IMPORT) {
onSnackbarMessage(ImportMediaSnackbarMessages.MaxAmountOfAssetsReached)
} else {
val jobs: MutableCollection<Job> = mutableListOf()

textToSend?.let {
sendTextMessage(
conversationId = conversation.conversationId,
assetDataPath = importedAsset.dataPath,
assetName = importedAsset.name,
assetDataSize = importedAsset.size,
assetMimeType = importedAsset.mimeType,
assetWidth = if (isImage) (importedAsset as ImportedMediaAsset.Image).width else 0,
assetHeight = if (isImage) (importedAsset as ImportedMediaAsset.Image).height else 0,
audioLengthInMs = getAudioLengthInMs(
dataPath = importedAsset.dataPath,
mimeType = importedAsset.mimeType
)
).also {
if (it is ScheduleNewAssetMessageResult.Failure) {
appLogger.e("Failed to import asset message to conversationId=${conversation.conversationId.toLogString()} ")
} else {
appLogger.d("Success importing asset message to conversationId=${conversation.conversationId.toLogString()}")
text = it
)
} ?: assetsToSend.forEach { importedAsset ->
val isImage = importedAsset is ImportedMediaAsset.Image
val job = viewModelScope.launch {
sendAssetMessage(
conversationId = conversation.conversationId,
assetDataPath = importedAsset.dataPath,
assetName = importedAsset.name,
assetDataSize = importedAsset.size,
assetMimeType = importedAsset.mimeType,
assetWidth = if (isImage) (importedAsset as ImportedMediaAsset.Image).width else 0,
assetHeight = if (isImage) (importedAsset as ImportedMediaAsset.Image).height else 0,
audioLengthInMs = getAudioLengthInMs(
dataPath = importedAsset.dataPath,
mimeType = importedAsset.mimeType
)
).also {
val logConversationId = conversation.conversationId.toLogString()
if (it is ScheduleNewAssetMessageResult.Failure) {
appLogger.e("Failed to import asset message to " +
"conversationId=$logConversationId")
} else {
appLogger.d("Success importing asset message to " +
"conversationId=$logConversationId")
}
}
}
jobs.add(job)
}

jobs.joinAll()
withContext(dispatchers.main()) {
onSent(conversation.conversationId)
}
jobs.add(job)
}
jobs.joinAll()
withContext(dispatchers.main()) {
onSent(conversation.conversationId)
}
}
}

fun onNewConversationPicked(conversationId: ConversationId) = viewModelScope.launch {
importMediaState = importMediaState.copy(
Expand Down Expand Up @@ -455,6 +473,7 @@ class ImportMediaAuthenticatedViewModel @Inject constructor(
data class ImportMediaAuthenticatedState(
val avatarAsset: ImageAsset.UserAvatarAsset? = null,
val importedAssets: List<ImportedMediaAsset> = emptyList(),
val importedText: String? = null,
val isImporting: Boolean = false,
val shareableConversationListState: ShareableConversationListState = ShareableConversationListState(),
val selectedConversationItem: List<ConversationItem> = emptyList(),
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,8 @@ import androidx.compose.foundation.layout.fillMaxWidth
import androidx.compose.foundation.layout.height
import androidx.compose.foundation.layout.padding
import androidx.compose.foundation.lazy.rememberLazyListState
import androidx.compose.foundation.pager.HorizontalPager
import androidx.compose.foundation.pager.rememberPagerState
import androidx.compose.material3.Divider
import androidx.compose.material3.MaterialTheme
import androidx.compose.material3.Scaffold
Expand All @@ -34,8 +36,6 @@ import androidx.compose.ui.text.style.TextOverflow
import androidx.compose.ui.tooling.preview.Preview
import androidx.compose.ui.unit.dp
import androidx.hilt.navigation.compose.hiltViewModel
import androidx.compose.foundation.pager.HorizontalPager
import androidx.compose.foundation.pager.rememberPagerState
import com.ramcosta.composedestinations.annotation.Destination
import com.ramcosta.composedestinations.annotation.RootNavGraph
import com.wire.android.R
Expand Down Expand Up @@ -69,8 +69,8 @@ import com.wire.android.util.CustomTabsHelper
import com.wire.android.util.extension.getActivity
import com.wire.android.util.ui.LinkText
import com.wire.android.util.ui.LinkTextData
import com.wire.kalium.logic.util.isPositiveNotNull
import com.wire.kalium.logic.data.id.ConversationId
import com.wire.kalium.logic.util.isPositiveNotNull
import kotlinx.collections.immutable.persistentMapOf
import kotlinx.coroutines.flow.MutableSharedFlow
import kotlinx.coroutines.flow.SharedFlow
Expand All @@ -84,7 +84,8 @@ fun ImportMediaScreen(
) {
featureFlagNotificationViewModel.loadInitialSync()

when (val fileSharingRestrictedState = featureFlagNotificationViewModel.featureFlagState.fileSharingRestrictedState) {
when (val fileSharingRestrictedState =
featureFlagNotificationViewModel.featureFlagState.fileSharingRestrictedState) {
FeatureFlagState.SharingRestrictedState.NO_USER -> {
ImportMediaLoggedOutContent(
fileSharingRestrictedState = fileSharingRestrictedState,
Expand All @@ -109,7 +110,12 @@ fun ImportMediaScreen(
onConversationClicked = importMediaViewModel::onConversationClicked,
checkRestrictionsAndSendImportedMedia = {
importMediaViewModel.checkRestrictionsAndSendImportedMedia {
navigator.navigate(NavigationCommand(ConversationScreenDestination(it), BackStackMode.CLEAR_TILL_START))
navigator.navigate(
NavigationCommand(
ConversationScreenDestination(it),
BackStackMode.CLEAR_TILL_START
)
)
}
},
onNewSelfDeletionTimerPicked = importMediaViewModel::onNewSelfDeletionTimerPicked,
Expand All @@ -119,7 +125,8 @@ fun ImportMediaScreen(
val context = LocalContext.current
LaunchedEffect(importMediaViewModel.importMediaState.importedAssets) {
if (importMediaViewModel.importMediaState.importedAssets.isEmpty()) {
context.getActivity()?.let { importMediaViewModel.handleReceivedDataFromSharingIntent(it) }
context.getActivity()
?.let { importMediaViewModel.handleReceivedDataFromSharingIntent(it) }
}
}
}
Expand Down Expand Up @@ -271,11 +278,12 @@ fun FileSharingRestrictedContent(
.padding(internalPadding)
.padding(horizontal = dimensions().spacing48x)
) {
val textRes = if (sharingRestrictedState == FeatureFlagState.SharingRestrictedState.NO_USER) {
R.string.file_sharing_restricted_description_no_users
} else {
R.string.file_sharing_restricted_description_by_team
}
val textRes =
if (sharingRestrictedState == FeatureFlagState.SharingRestrictedState.NO_USER) {
R.string.file_sharing_restricted_description_no_users
} else {
R.string.file_sharing_restricted_description_by_team
}
Text(
text = stringResource(textRes),
textAlign = TextAlign.Center,
Expand Down Expand Up @@ -318,9 +326,11 @@ private fun ImportMediaBottomBar(
} else {
stringResource(id = R.string.import_media_send_button_title)
}
val buttonCount =
if (state.importedAssets.isNotEmpty() || state.importedText != null) state.selectedConversationItem.size else 0
SendContentButton(
mainButtonText = mainButtonText,
count = if (state.importedAssets.isNotEmpty()) state.selectedConversationItem.size else 0,
count = buttonCount,
onMainButtonClick = checkRestrictionsAndSendImportedMedia,
selfDeletionTimer = selfDeletionTimer,
onSelfDeletionTimerClicked = importMediaScreenState::showBottomSheetMenu,
Expand Down Expand Up @@ -348,9 +358,13 @@ private fun ImportMediaContent(
) {
val horizontalPadding = dimensions().spacing8x
val screenWidth = LocalConfiguration.current.screenWidthDp.dp
val itemWidth = if (isMultipleImport) dimensions().importedMediaAssetSize + horizontalPadding.times(2)
else screenWidth - (horizontalPadding * 2)
val contentPadding = PaddingValues(start = horizontalPadding, end = (screenWidth - itemWidth + horizontalPadding))
val itemWidth =
if (isMultipleImport) dimensions().importedMediaAssetSize + horizontalPadding.times(2)
else screenWidth - (horizontalPadding * 2)
val contentPadding = PaddingValues(
start = horizontalPadding,
end = (screenWidth - itemWidth + horizontalPadding)
)
val lazyListState = rememberLazyListState()
if (state.isImporting) {
Box(
Expand Down Expand Up @@ -379,7 +393,11 @@ private fun ImportMediaContent(
}
}
}
Divider(color = colorsScheme().outline, thickness = 1.dp, modifier = Modifier.padding(top = dimensions().spacing12x))
Divider(
color = colorsScheme().outline,
thickness = 1.dp,
modifier = Modifier.padding(top = dimensions().spacing12x)
)
Box(Modifier.padding(dimensions().spacing6x)) {
SearchTopBar(
isSearchActive = searchBarState.isSearchActive,
Expand Down Expand Up @@ -420,7 +438,10 @@ private fun ImportMediaContent(
}

@Composable
private fun SnackBarMessage(infoMessages: SharedFlow<SnackBarMessage>, snackbarHostState: SnackbarHostState) {
private fun SnackBarMessage(
infoMessages: SharedFlow<SnackBarMessage>,
snackbarHostState: SnackbarHostState
) {
val context = LocalContext.current
LaunchedEffect(Unit) {
infoMessages.collect { message ->
Expand All @@ -438,13 +459,23 @@ fun PreviewImportMediaScreenLoggedOut() {
@Preview(showBackground = true)
@Composable
fun PreviewImportMediaScreenRestricted() {
ImportMediaRestrictedContent(FeatureFlagState.SharingRestrictedState.RESTRICTED_IN_TEAM, ImportMediaAuthenticatedState()) {}
ImportMediaRestrictedContent(
FeatureFlagState.SharingRestrictedState.RESTRICTED_IN_TEAM,
ImportMediaAuthenticatedState()
) {}
}

@Preview(showBackground = true)
@Composable
fun PreviewImportMediaScreenRegular() {
ImportMediaRegularContent(ImportMediaAuthenticatedState(), {}, {}, {}, {}, MutableSharedFlow()) {}
ImportMediaRegularContent(
ImportMediaAuthenticatedState(),
{},
{},
{},
{},
MutableSharedFlow()
) {}
}

@Preview(showBackground = true)
Expand Down

0 comments on commit a19f4b4

Please sign in to comment.