Can save media in message details page now

This commit is contained in:
ThomasSession 2024-09-04 14:28:52 +10:00 committed by fanchao
parent 86f89f8c61
commit d7bd0bf3ea
7 changed files with 64 additions and 37 deletions

View File

@ -118,6 +118,7 @@ import org.thoughtcrime.securesms.conversation.v2.MessageDetailActivity.Companio
import org.thoughtcrime.securesms.conversation.v2.MessageDetailActivity.Companion.ON_REPLY import org.thoughtcrime.securesms.conversation.v2.MessageDetailActivity.Companion.ON_REPLY
import org.thoughtcrime.securesms.conversation.v2.MessageDetailActivity.Companion.ON_RESEND import org.thoughtcrime.securesms.conversation.v2.MessageDetailActivity.Companion.ON_RESEND
import org.thoughtcrime.securesms.conversation.v2.MessageDetailActivity.Companion.ON_COPY import org.thoughtcrime.securesms.conversation.v2.MessageDetailActivity.Companion.ON_COPY
import org.thoughtcrime.securesms.conversation.v2.MessageDetailActivity.Companion.ON_SAVE
import org.thoughtcrime.securesms.conversation.v2.dialogs.BlockedDialog import org.thoughtcrime.securesms.conversation.v2.dialogs.BlockedDialog
import org.thoughtcrime.securesms.conversation.v2.dialogs.LinkPreviewDialog import org.thoughtcrime.securesms.conversation.v2.dialogs.LinkPreviewDialog
import org.thoughtcrime.securesms.conversation.v2.input_bar.InputBarButton import org.thoughtcrime.securesms.conversation.v2.input_bar.InputBarButton
@ -2206,6 +2207,9 @@ class ConversationActivityV2 : PassphraseRequiredActionBarActivity(), InputBarDe
ON_RESEND -> resendMessage(set) ON_RESEND -> resendMessage(set)
ON_DELETE -> deleteMessages(set) ON_DELETE -> deleteMessages(set)
ON_COPY -> copyMessages(set) ON_COPY -> copyMessages(set)
ON_SAVE -> {
if(message is MmsMessageRecord) saveAttachments(message)
}
} }
} }

View File

@ -96,6 +96,7 @@ class MessageDetailActivity : PassphraseRequiredActionBarActivity() {
const val ON_RESEND = 2 const val ON_RESEND = 2
const val ON_DELETE = 3 const val ON_DELETE = 3
const val ON_COPY = 4 const val ON_COPY = 4
const val ON_SAVE = 5
} }
override fun onCreate(savedInstanceState: Bundle?, ready: Boolean) { override fun onCreate(savedInstanceState: Bundle?, ready: Boolean) {
@ -126,6 +127,7 @@ class MessageDetailActivity : PassphraseRequiredActionBarActivity() {
state = state, state = state,
onReply = if (state.canReply) { { setResultAndFinish(ON_REPLY) } } else null, onReply = if (state.canReply) { { setResultAndFinish(ON_REPLY) } } else null,
onResend = state.error?.let { { setResultAndFinish(ON_RESEND) } }, onResend = state.error?.let { { setResultAndFinish(ON_RESEND) } },
onSave = if(state.mmsRecord != null) { { setResultAndFinish(ON_SAVE) } } else null,
onDelete = { setResultAndFinish(ON_DELETE) }, onDelete = { setResultAndFinish(ON_DELETE) },
onCopy = { setResultAndFinish(ON_COPY) }, onCopy = { setResultAndFinish(ON_COPY) },
onClickImage = { viewModel.onClickImage(it) }, onClickImage = { viewModel.onClickImage(it) },
@ -148,6 +150,7 @@ fun MessageDetails(
state: MessageDetailsState, state: MessageDetailsState,
onReply: (() -> Unit)? = null, onReply: (() -> Unit)? = null,
onResend: (() -> Unit)? = null, onResend: (() -> Unit)? = null,
onSave: (() -> Unit)? = null,
onDelete: () -> Unit = {}, onDelete: () -> Unit = {},
onCopy: () -> Unit = {}, onCopy: () -> Unit = {},
onClickImage: (Int) -> Unit = {}, onClickImage: (Int) -> Unit = {},
@ -183,10 +186,11 @@ fun MessageDetails(
state.nonImageAttachmentFileDetails?.let { FileDetails(it) } state.nonImageAttachmentFileDetails?.let { FileDetails(it) }
CellMetadata(state) CellMetadata(state)
CellButtons( CellButtons(
onReply, onReply = onReply,
onResend, onResend = onResend,
onDelete, onSave = onSave,
onCopy onDelete = onDelete,
onCopy = onCopy
) )
} }
} }
@ -222,6 +226,7 @@ fun CellMetadata(
fun CellButtons( fun CellButtons(
onReply: (() -> Unit)? = null, onReply: (() -> Unit)? = null,
onResend: (() -> Unit)? = null, onResend: (() -> Unit)? = null,
onSave: (() -> Unit)? = null,
onDelete: () -> Unit, onDelete: () -> Unit,
onCopy: () -> Unit onCopy: () -> Unit
) { ) {
@ -243,6 +248,15 @@ fun CellButtons(
) )
Divider() Divider()
onSave?.let {
LargeItemButton(
R.string.save,
R.drawable.ic_baseline_save_24,
onClick = it
)
Divider()
}
onResend?.let { onResend?.let {
LargeItemButton( LargeItemButton(
R.string.resend, R.string.resend,
@ -342,6 +356,7 @@ fun PreviewMessageDetailsButtons(
CellButtons( CellButtons(
onReply = {}, onReply = {},
onResend = {}, onResend = {},
onSave = {},
onDelete = {}, onDelete = {},
onCopy = {} onCopy = {}
) )

View File

@ -38,8 +38,6 @@ import com.canhub.cropper.CropImage
import com.canhub.cropper.CropImageContract import com.canhub.cropper.CropImageContract
import com.squareup.phrase.Phrase import com.squareup.phrase.Phrase
import dagger.hilt.android.AndroidEntryPoint import dagger.hilt.android.AndroidEntryPoint
import java.io.File
import javax.inject.Inject
import kotlinx.coroutines.Dispatchers import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.channels.awaitClose import kotlinx.coroutines.channels.awaitClose
import kotlinx.coroutines.flow.Flow import kotlinx.coroutines.flow.Flow
@ -60,7 +58,6 @@ import org.session.libsession.messaging.MessagingModuleConfiguration
import org.session.libsession.snode.OnionRequestAPI import org.session.libsession.snode.OnionRequestAPI
import org.session.libsession.snode.SnodeAPI import org.session.libsession.snode.SnodeAPI
import org.session.libsession.utilities.Address import org.session.libsession.utilities.Address
import org.session.libsession.utilities.NonTranslatableStringConstants.DEBUG_MENU
import org.session.libsession.utilities.ProfileKeyUtil import org.session.libsession.utilities.ProfileKeyUtil
import org.session.libsession.utilities.ProfilePictureUtilities import org.session.libsession.utilities.ProfilePictureUtilities
import org.session.libsession.utilities.SSKEnvironment.ProfileManagerProtocol import org.session.libsession.utilities.SSKEnvironment.ProfileManagerProtocol
@ -97,7 +94,8 @@ import org.thoughtcrime.securesms.util.BitmapUtil
import org.thoughtcrime.securesms.util.ConfigurationMessageUtilities import org.thoughtcrime.securesms.util.ConfigurationMessageUtilities
import org.thoughtcrime.securesms.util.NetworkUtils import org.thoughtcrime.securesms.util.NetworkUtils
import org.thoughtcrime.securesms.util.push import org.thoughtcrime.securesms.util.push
import org.thoughtcrime.securesms.util.show import java.io.File
import javax.inject.Inject
@AndroidEntryPoint @AndroidEntryPoint
class SettingsActivity : PassphraseRequiredActionBarActivity() { class SettingsActivity : PassphraseRequiredActionBarActivity() {

View File

@ -11,8 +11,12 @@ import androidx.compose.foundation.background
import androidx.compose.foundation.layout.Box import androidx.compose.foundation.layout.Box
import androidx.compose.foundation.layout.BoxScope import androidx.compose.foundation.layout.BoxScope
import androidx.compose.foundation.layout.Column import androidx.compose.foundation.layout.Column
import androidx.compose.foundation.layout.IntrinsicSize
import androidx.compose.foundation.layout.PaddingValues
import androidx.compose.foundation.layout.RowScope import androidx.compose.foundation.layout.RowScope
import androidx.compose.foundation.layout.Spacer import androidx.compose.foundation.layout.Spacer
import androidx.compose.foundation.layout.aspectRatio
import androidx.compose.foundation.layout.fillMaxHeight
import androidx.compose.foundation.layout.fillMaxWidth import androidx.compose.foundation.layout.fillMaxWidth
import androidx.compose.foundation.layout.height import androidx.compose.foundation.layout.height
import androidx.compose.foundation.layout.heightIn import androidx.compose.foundation.layout.heightIn
@ -45,6 +49,7 @@ import androidx.compose.ui.graphics.RectangleShape
import androidx.compose.ui.graphics.StrokeCap import androidx.compose.ui.graphics.StrokeCap
import androidx.compose.ui.graphics.drawscope.Stroke import androidx.compose.ui.graphics.drawscope.Stroke
import androidx.compose.ui.graphics.graphicsLayer import androidx.compose.ui.graphics.graphicsLayer
import androidx.compose.ui.graphics.painter.Painter
import androidx.compose.ui.platform.LocalContext import androidx.compose.ui.platform.LocalContext
import androidx.compose.ui.res.painterResource import androidx.compose.ui.res.painterResource
import androidx.compose.ui.res.stringResource import androidx.compose.ui.res.stringResource
@ -126,7 +131,7 @@ fun LargeItemButtonWithDrawable(
onClick: () -> Unit onClick: () -> Unit
) { ) {
ItemButtonWithDrawable( ItemButtonWithDrawable(
textId, icon, modifier.heightIn(min = LocalDimensions.current.minLargeItemButtonHeight), textId, icon, modifier,
LocalType.current.h8, colors, onClick LocalType.current.h8, colors, onClick
) )
} }
@ -167,8 +172,13 @@ fun LargeItemButton(
onClick: () -> Unit onClick: () -> Unit
) { ) {
ItemButton( ItemButton(
textId, icon, modifier.heightIn(min = LocalDimensions.current.minLargeItemButtonHeight), textId = textId,
LocalType.current.h8, colors, onClick icon = icon,
modifier = modifier,
minHeight = LocalDimensions.current.minLargeItemButtonHeight,
textStyle = LocalType.current.h8,
colors = colors,
onClick = onClick
) )
} }
@ -181,8 +191,13 @@ fun LargeItemButton(
onClick: () -> Unit onClick: () -> Unit
) { ) {
ItemButton( ItemButton(
text, icon, modifier.heightIn(min = LocalDimensions.current.minLargeItemButtonHeight), text = text,
LocalType.current.h8, colors, onClick icon = icon,
modifier = modifier,
minHeight = LocalDimensions.current.minLargeItemButtonHeight,
textStyle = LocalType.current.h8,
colors = colors,
onClick = onClick
) )
} }
@ -191,6 +206,7 @@ fun ItemButton(
text: String, text: String,
icon: Int, icon: Int,
modifier: Modifier, modifier: Modifier,
minHeight: Dp = LocalDimensions.current.minItemButtonHeight,
textStyle: TextStyle = LocalType.current.xl, textStyle: TextStyle = LocalType.current.xl,
colors: ButtonColors = transparentButtonColors(), colors: ButtonColors = transparentButtonColors(),
onClick: () -> Unit onClick: () -> Unit
@ -205,6 +221,7 @@ fun ItemButton(
modifier = Modifier.align(Alignment.Center) modifier = Modifier.align(Alignment.Center)
) )
}, },
minHeight = minHeight,
textStyle = textStyle, textStyle = textStyle,
colors = colors, colors = colors,
onClick = onClick onClick = onClick
@ -219,6 +236,7 @@ fun ItemButton(
@StringRes textId: Int, @StringRes textId: Int,
@DrawableRes icon: Int, @DrawableRes icon: Int,
modifier: Modifier = Modifier, modifier: Modifier = Modifier,
minHeight: Dp = LocalDimensions.current.minItemButtonHeight,
textStyle: TextStyle = LocalType.current.xl, textStyle: TextStyle = LocalType.current.xl,
colors: ButtonColors = transparentButtonColors(), colors: ButtonColors = transparentButtonColors(),
onClick: () -> Unit onClick: () -> Unit
@ -233,6 +251,7 @@ fun ItemButton(
modifier = Modifier.align(Alignment.Center) modifier = Modifier.align(Alignment.Center)
) )
}, },
minHeight = minHeight,
textStyle = textStyle, textStyle = textStyle,
colors = colors, colors = colors,
onClick = onClick onClick = onClick
@ -249,20 +268,23 @@ fun ItemButton(
text: String, text: String,
icon: @Composable BoxScope.() -> Unit, icon: @Composable BoxScope.() -> Unit,
modifier: Modifier = Modifier, modifier: Modifier = Modifier,
minHeight: Dp = LocalDimensions.current.minLargeItemButtonHeight,
textStyle: TextStyle = LocalType.current.xl, textStyle: TextStyle = LocalType.current.xl,
colors: ButtonColors = transparentButtonColors(), colors: ButtonColors = transparentButtonColors(),
onClick: () -> Unit onClick: () -> Unit
) { ) {
TextButton( TextButton(
modifier = modifier.fillMaxWidth(), modifier = modifier.fillMaxWidth()
.height(IntrinsicSize.Min)
.heightIn(min = minHeight)
.padding(horizontal = LocalDimensions.current.xsSpacing),
colors = colors, colors = colors,
onClick = onClick, onClick = onClick,
shape = RectangleShape, shape = RectangleShape,
) { ) {
Box( Box(
modifier = Modifier modifier = Modifier.fillMaxHeight()
.width(50.dp) .aspectRatio(1f)
.wrapContentHeight()
.align(Alignment.CenterVertically) .align(Alignment.CenterVertically)
) { ) {
icon() icon()
@ -274,7 +296,6 @@ fun ItemButton(
text, text,
Modifier Modifier
.fillMaxWidth() .fillMaxWidth()
.padding(vertical = LocalDimensions.current.xsSpacing)
.align(Alignment.CenterVertically), .align(Alignment.CenterVertically),
style = textStyle style = textStyle
) )
@ -371,7 +392,8 @@ fun Modifier.fadingEdges(
@Composable @Composable
fun Divider(modifier: Modifier = Modifier, startIndent: Dp = 0.dp) { fun Divider(modifier: Modifier = Modifier, startIndent: Dp = 0.dp) {
HorizontalDivider( HorizontalDivider(
modifier = modifier.padding(horizontal = LocalDimensions.current.smallSpacing) modifier = modifier
.padding(horizontal = LocalDimensions.current.smallSpacing)
.padding(start = startIndent), .padding(start = startIndent),
color = LocalColors.current.borders, color = LocalColors.current.borders,
) )

View File

@ -17,6 +17,7 @@ data class Dimensions(
val dividerIndent: Dp = 60.dp, val dividerIndent: Dp = 60.dp,
val appBarHeight: Dp = 64.dp, val appBarHeight: Dp = 64.dp,
val minItemButtonHeight: Dp = 50.dp,
val minLargeItemButtonHeight: Dp = 60.dp, val minLargeItemButtonHeight: Dp = 60.dp,
val indicatorHeight: Dp = 4.dp, val indicatorHeight: Dp = 4.dp,

View File

@ -1,17 +0,0 @@
<?xml version="1.0" encoding="utf-8"?>
<menu xmlns:android="http://schemas.android.com/apk/res/android" xmlns:app="http://schemas.android.com/apk/res-auto">
<item android:id="@+id/save"
android:title="@string/save"
android:icon="?attr/menu_save_icon"
app:showAsAction="always"/>
<item android:id="@+id/delete"
android:title="@string/delete"
android:icon="?attr/menu_trash_icon"
app:showAsAction="always"/>
<item android:id="@+id/select_all"
android:title="@string/selectAll"
android:icon="?menu_selectall_icon"
app:showAsAction="always"/>
</menu>

View File

@ -4,24 +4,28 @@
<item <item
android:id="@+id/media_preview__forward" android:id="@+id/media_preview__forward"
android:icon="?menu_forward_icon" android:icon="?menu_forward_icon"
android:iconTint="?android:textColorPrimary"
android:title="@string/share" android:title="@string/share"
app:showAsAction="always" /> app:showAsAction="always" />
<item <item
android:id="@+id/save" android:id="@+id/save"
android:icon="?menu_save_icon" android:icon="?menu_save_icon"
android:iconTint="?android:textColorPrimary"
android:title="@string/save" android:title="@string/save"
app:showAsAction="always" /> app:showAsAction="always" />
<item <item
android:id="@+id/media_preview__overview" android:id="@+id/media_preview__overview"
android:icon="?menu_photo_library_icon" android:icon="?menu_photo_library_icon"
android:iconTint="?android:textColorPrimary"
android:title="@string/conversationsSettingsAllMedia" android:title="@string/conversationsSettingsAllMedia"
app:showAsAction="ifRoom" /> app:showAsAction="ifRoom" />
<item <item
android:id="@+id/delete" android:id="@+id/delete"
android:icon="?menu_delete_icon" android:icon="?menu_delete_icon"
android:iconTint="?android:textColorPrimary"
android:title="@string/delete" android:title="@string/delete"
app:showAsAction="ifRoom" /> app:showAsAction="ifRoom" />
</menu> </menu>