Skip to content

Commit

Permalink
feat: image preview improvements
Browse files Browse the repository at this point in the history
  • Loading branch information
Garzas committed May 21, 2024
1 parent f6c35c0 commit e26a74f
Show file tree
Hide file tree
Showing 23 changed files with 447 additions and 266 deletions.
23 changes: 0 additions & 23 deletions app/src/main/kotlin/com/wire/android/navigation/Extras.kt

This file was deleted.

18 changes: 18 additions & 0 deletions app/src/main/kotlin/com/wire/android/navigation/NavigationUtils.kt
Original file line number Diff line number Diff line change
Expand Up @@ -35,6 +35,8 @@ import com.wire.android.ui.NavGraphs
import com.wire.android.ui.destinations.Destination
import com.wire.android.util.CustomTabsHelper
import com.wire.kalium.logger.obfuscateId
import kotlinx.serialization.ExperimentalSerializationApi
import kotlinx.serialization.json.Json

@SuppressLint("RestrictedApi")
internal fun NavController.navigateToItem(command: NavigationCommand) {
Expand All @@ -44,6 +46,7 @@ internal fun NavController.navigateToItem(command: NavigationCommand) {
fun lastNestedGraph() = lastDestination()?.takeIf { it.navGraph() != navGraph }?.navGraph()
fun firstDestinationWithRoute(route: String) =
currentBackStack.value.firstOrNull { it.destination.route?.getBaseRoute() == route.getBaseRoute() }

fun lastDestinationFromOtherGraph(graph: NavGraphSpec) = currentBackStack.value.lastOrNull { it.navGraph() != graph }

appLogger.d("[$TAG] -> command: ${command.destination.route.obfuscateId()}")
Expand Down Expand Up @@ -115,4 +118,19 @@ fun Direction.handleNavigation(context: Context, handleOtherDirection: (Directio
else -> handleOtherDirection(this)
}

object ArgsSerializer {
@OptIn(ExperimentalSerializationApi::class)
private val instance: Json by lazy {
Json {
encodeDefaults = true
explicitNulls = false
// to enable the serialization of maps with complex keys
// e.g. Map<QualifiedIDEntity, PersistenceSession>
allowStructuredMapKeys = true
}
}

operator fun invoke() = instance
}

private const val TAG = "NavigationUtils"
Original file line number Diff line number Diff line change
Expand Up @@ -30,8 +30,7 @@ import com.wire.kalium.logic.data.asset.AttachmentType
@Composable
fun AssetTooLargeDialog(dialogState: AssetTooLargeDialogState, hideDialog: () -> Unit) {
when (dialogState) {
is AssetTooLargeDialogState.SingleVisible,
is AssetTooLargeDialogState.MultipleVisible -> {
is AssetTooLargeDialogState.Visible -> {
WireDialog(
title = getTitle(dialogState),
text = getLabel(dialogState),
Expand All @@ -52,38 +51,43 @@ fun AssetTooLargeDialog(dialogState: AssetTooLargeDialogState, hideDialog: () ->
@Composable
private fun getTitle(dialogState: AssetTooLargeDialogState) = when (dialogState) {
AssetTooLargeDialogState.Hidden -> ""
is AssetTooLargeDialogState.MultipleVisible -> stringResource(id = R.string.title_assets_could_not_be_sent)
is AssetTooLargeDialogState.SingleVisible -> when (dialogState.assetType) {
AttachmentType.IMAGE -> stringResource(R.string.title_image_could_not_be_sent)
AttachmentType.VIDEO -> stringResource(R.string.title_video_could_not_be_sent)
AttachmentType.AUDIO, // TODO
AttachmentType.GENERIC_FILE -> stringResource(R.string.title_file_could_not_be_sent)
}
is AssetTooLargeDialogState.Visible ->
if (dialogState.multipleAssets) {
stringResource(id = R.string.title_assets_could_not_be_sent)
} else {
when (dialogState.assetType) {
AttachmentType.IMAGE -> stringResource(R.string.title_image_could_not_be_sent)
AttachmentType.VIDEO -> stringResource(R.string.title_video_could_not_be_sent)
AttachmentType.AUDIO, // TODO
AttachmentType.GENERIC_FILE -> stringResource(R.string.title_file_could_not_be_sent)
}
}
}

@Composable
private fun getLabel(dialogState: AssetTooLargeDialogState) = when (dialogState) {
AssetTooLargeDialogState.Hidden -> ""
is AssetTooLargeDialogState.MultipleVisible -> stringResource(id = R.string.label_shared_asset_too_large, dialogState.maxLimitInMB)
is AssetTooLargeDialogState.SingleVisible -> when (dialogState.assetType) {
is AssetTooLargeDialogState.Visible -> when (dialogState.assetType) {
AttachmentType.IMAGE -> stringResource(R.string.label_shared_image_too_large, dialogState.maxLimitInMB)
AttachmentType.VIDEO -> stringResource(R.string.label_shared_video_too_large, dialogState.maxLimitInMB)
AttachmentType.AUDIO, // TODO
AttachmentType.GENERIC_FILE -> stringResource(R.string.label_shared_file_too_large, dialogState.maxLimitInMB)
}.let {
if (dialogState.savedToDevice) it + "\n" + stringResource(R.string.label_file_saved_to_device)
else it
var label = it
if (dialogState.multipleAssets) label = label + "\n" + stringResource(R.string.label_shared_multiple_assets_error)
if (dialogState.savedToDevice) label = label + "\n" + stringResource(R.string.label_file_saved_to_device)
label
}
}

@Preview
@Composable
fun PreviewAssetTooLargeDialog() {
AssetTooLargeDialog(AssetTooLargeDialogState.SingleVisible(AttachmentType.VIDEO, 100, true)) {}
AssetTooLargeDialog(AssetTooLargeDialogState.Visible(AttachmentType.VIDEO, 100, true)) {}
}

@Preview
@Composable
fun PreviewMultipleAssetTooLargeDialog() {
AssetTooLargeDialog(AssetTooLargeDialogState.MultipleVisible(20)) {}
AssetTooLargeDialog(AssetTooLargeDialogState.Visible(AttachmentType.VIDEO, 100, false, true)) {}
}
Original file line number Diff line number Diff line change
Expand Up @@ -17,9 +17,13 @@
*/
package com.wire.android.ui.home.conversations

import com.wire.android.ui.home.conversations.model.AssetBundle
import com.wire.kalium.logic.data.id.ConversationId
import kotlinx.serialization.Serializable

@Serializable
data class ConversationNavArgs(
val conversationId: ConversationId,
val searchedMessageId: String? = null
val searchedMessageId: String? = null,
val pendingBundles: ArrayList<AssetBundle>? = null
)
Original file line number Diff line number Diff line change
Expand Up @@ -82,6 +82,7 @@ import com.wire.android.appLogger
import com.wire.android.media.audiomessage.AudioState
import com.wire.android.model.Clickable
import com.wire.android.model.SnackBarMessage
import com.wire.android.navigation.ArgsSerializer
import com.wire.android.navigation.BackStackMode
import com.wire.android.navigation.NavigationCommand
import com.wire.android.navigation.Navigator
Expand Down Expand Up @@ -127,6 +128,7 @@ import com.wire.android.ui.home.conversations.edit.EditMessageMenuItems
import com.wire.android.ui.home.conversations.info.ConversationDetailsData
import com.wire.android.ui.home.conversations.info.ConversationInfoViewModel
import com.wire.android.ui.home.conversations.info.ConversationInfoViewState
import com.wire.android.ui.home.conversations.media.preview.ImagesPreviewNavBackArgs
import com.wire.android.ui.home.conversations.messages.ConversationMessagesViewModel
import com.wire.android.ui.home.conversations.messages.ConversationMessagesViewState
import com.wire.android.ui.home.conversations.messages.draft.MessageDraftViewModel
Expand All @@ -141,6 +143,7 @@ import com.wire.android.ui.home.conversations.sendmessage.SendMessageViewModel
import com.wire.android.ui.home.gallery.MediaGalleryActionType
import com.wire.android.ui.home.gallery.MediaGalleryNavBackArgs
import com.wire.android.ui.home.messagecomposer.MessageComposer
import com.wire.android.ui.home.messagecomposer.model.ComposableMessageBundle
import com.wire.android.ui.home.messagecomposer.model.MessageBundle
import com.wire.android.ui.home.messagecomposer.model.MessageComposition
import com.wire.android.ui.home.messagecomposer.state.MessageComposerStateHolder
Expand Down Expand Up @@ -207,6 +210,7 @@ fun ConversationScreen(
messageDraftViewModel: MessageDraftViewModel = hiltViewModel(),
groupDetailsScreenResultRecipient: ResultRecipient<GroupConversationDetailsScreenDestination, GroupConversationDetailsNavBackArgs>,
mediaGalleryScreenResultRecipient: ResultRecipient<MediaGalleryScreenDestination, MediaGalleryNavBackArgs>,
imagePreviewScreenResultRecipient: ResultRecipient<ImagesPreviewScreenDestination, String>,
resultNavigator: ResultBackNavigator<GroupConversationDetailsNavBackArgs>,
) {
val coroutineScope = rememberCoroutineScope()
Expand Down Expand Up @@ -615,6 +619,23 @@ fun ConversationScreen(
}
}
}

imagePreviewScreenResultRecipient.onNavResult { result ->
when (result) {
Canceled -> {}
is Value -> {
val pendingBundles = ArgsSerializer().decodeFromString<ImagesPreviewNavBackArgs>(result.value).pendingBundles
sendMessageViewModel.trySendMessages(
pendingBundles.map { assetBundle ->
ComposableMessageBundle.AttachmentPickedBundle(
conversationId = conversationMessagesViewModel.conversationId,
assetBundle = assetBundle
)
}
)
}
}
}
}

private fun conversationScreenOnBackButtonClick(
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -36,8 +36,12 @@ data class MessageComposerViewState(

sealed class AssetTooLargeDialogState {
data object Hidden : AssetTooLargeDialogState()
data class SingleVisible(val assetType: AttachmentType, val maxLimitInMB: Int, val savedToDevice: Boolean) : AssetTooLargeDialogState()
data class MultipleVisible(val maxLimitInMB: Int) : AssetTooLargeDialogState()
data class Visible(
val assetType: AttachmentType,
val maxLimitInMB: Int,
val savedToDevice: Boolean,
val multipleAssets: Boolean = false
) : AssetTooLargeDialogState()
}

sealed class VisitLinkDialogState {
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,52 @@
/*
* 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.home.conversations.media

import androidx.compose.runtime.getValue
import androidx.compose.runtime.mutableStateOf
import androidx.compose.runtime.setValue
import androidx.lifecycle.ViewModel
import com.wire.android.ui.home.conversations.AssetTooLargeDialogState
import com.wire.android.ui.home.conversations.model.AssetBundle
import com.wire.android.ui.sharing.ImportedMediaAsset
import dagger.hilt.android.lifecycle.HiltViewModel
import javax.inject.Inject

@HiltViewModel
class CheckAssetRestrictionsViewModel @Inject constructor() : ViewModel() {

var assetTooLargeDialogState: AssetTooLargeDialogState by mutableStateOf(
AssetTooLargeDialogState.Hidden
)
private set

fun checkRestrictions(importedMediaList: List<ImportedMediaAsset>, onSuccess: (bundleList: List<AssetBundle>) -> Unit) {
importedMediaList.firstOrNull { it.assetSizeExceeded != null }?.let {
assetTooLargeDialogState = AssetTooLargeDialogState.Visible(
assetType = it.assetBundle.assetType,
maxLimitInMB = it.assetSizeExceeded!!,
savedToDevice = false,
multipleAssets = true
)
}?: onSuccess(importedMediaList.map { it.assetBundle })
}

fun hideDialog() {
assetTooLargeDialogState = AssetTooLargeDialogState.Hidden
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -18,10 +18,15 @@
package com.wire.android.ui.home.conversations.media.preview

import android.net.Uri
import com.wire.android.ui.home.conversations.model.AssetBundle
import com.wire.kalium.logic.data.id.ConversationId
import kotlinx.serialization.Serializable

data class ImagesPreviewNavArgs(
val conversationId: ConversationId,
val conversationName: String,
val assetUriList: ArrayList<Uri>
)

@Serializable
data class ImagesPreviewNavBackArgs(val pendingBundles: List<AssetBundle>)
Loading

0 comments on commit e26a74f

Please sign in to comment.