diff --git a/app/src/main/java/org/thoughtcrime/securesms/components/webrtc/controls/CallInfoView.kt b/app/src/main/java/org/thoughtcrime/securesms/components/webrtc/controls/CallInfoView.kt index 8c22e3443d..8b5beec65d 100644 --- a/app/src/main/java/org/thoughtcrime/securesms/components/webrtc/controls/CallInfoView.kt +++ b/app/src/main/java/org/thoughtcrime/securesms/components/webrtc/controls/CallInfoView.kt @@ -540,7 +540,7 @@ private fun CallParticipantRow( } Icon( - painter = painterResource(id = R.drawable.symbol_minus_circle_24), + painter = SignalIcons.MinusCircle.painter, contentDescription = null, modifier = Modifier .clickable(onClick = onBlockClicked) diff --git a/app/src/main/java/org/thoughtcrime/securesms/components/webrtc/controls/ParticipantActionsSheet.kt b/app/src/main/java/org/thoughtcrime/securesms/components/webrtc/controls/ParticipantActionsSheet.kt index bd30497097..bc1f7e9fdb 100644 --- a/app/src/main/java/org/thoughtcrime/securesms/components/webrtc/controls/ParticipantActionsSheet.kt +++ b/app/src/main/java/org/thoughtcrime/securesms/components/webrtc/controls/ParticipantActionsSheet.kt @@ -33,6 +33,7 @@ import org.signal.core.ui.compose.AllNightPreviews import org.signal.core.ui.compose.Dividers import org.signal.core.ui.compose.Previews import org.signal.core.ui.compose.Rows +import org.signal.core.ui.compose.SignalIcons import org.signal.core.ui.compose.horizontalGutters import org.thoughtcrime.securesms.R import org.thoughtcrime.securesms.components.AvatarImageView @@ -119,7 +120,7 @@ private fun ParticipantActionsSheetContent( Rows.TextRow( text = stringResource(id = R.string.CallParticipantSheet__remove_from_call), - icon = painterResource(id = R.drawable.symbol_minus_circle_24), + icon = SignalIcons.MinusCircle.painter, onClick = { onRemoveFromCall(callParticipant) onDismiss() diff --git a/app/src/main/java/org/thoughtcrime/securesms/components/webrtc/v2/CallScreen.kt b/app/src/main/java/org/thoughtcrime/securesms/components/webrtc/v2/CallScreen.kt index ff0f59cb3e..4fbad1231b 100644 --- a/app/src/main/java/org/thoughtcrime/securesms/components/webrtc/v2/CallScreen.kt +++ b/app/src/main/java/org/thoughtcrime/securesms/components/webrtc/v2/CallScreen.kt @@ -69,6 +69,7 @@ import kotlinx.coroutines.launch import org.signal.core.ui.compose.AllNightPreviews import org.signal.core.ui.compose.BottomSheets import org.signal.core.ui.compose.Previews +import org.signal.core.ui.compose.SignalIcons import org.signal.core.ui.compose.TriggerAlignedPopupState import org.signal.core.ui.compose.theme.SignalTheme import org.signal.core.util.DimensionUnit @@ -660,7 +661,7 @@ private fun ParticipantContextMenu( if (isSelfAdmin && isCallLink) { DropdownMenuItem( text = { Text(stringResource(R.string.CallParticipantSheet__remove_from_call)) }, - leadingIcon = { Icon(painter = painterResource(R.drawable.symbol_minus_circle_24), contentDescription = null) }, + leadingIcon = { Icon(painter = SignalIcons.MinusCircle.painter, contentDescription = null) }, onClick = { onRemoveFromCall(resolved) onDismiss() diff --git a/app/src/main/java/org/thoughtcrime/securesms/contacts/paged/ContactSearchModels.kt b/app/src/main/java/org/thoughtcrime/securesms/contacts/paged/ContactSearchModels.kt index c5f4d4f4d0..e526e2546c 100644 --- a/app/src/main/java/org/thoughtcrime/securesms/contacts/paged/ContactSearchModels.kt +++ b/app/src/main/java/org/thoughtcrime/securesms/contacts/paged/ContactSearchModels.kt @@ -428,7 +428,7 @@ object ContactSearchModels { private fun getGroupStoryContextMenuActions(model: StoryModel, callbacks: ContactSearchAdapter.StoryContextMenuCallbacks): List { return listOf( - ActionItem(R.drawable.symbol_minus_circle_24, context.getString(R.string.ContactSearchItems__remove_story)) { + ActionItem(CoreUiR.drawable.symbol_minus_circle_24, context.getString(R.string.ContactSearchItems__remove_story)) { callbacks.onRemoveGroupStory(model.story, model.isSelected) } ) diff --git a/app/src/main/java/org/thoughtcrime/securesms/conversation/ScheduledMessagesBottomSheet.kt b/app/src/main/java/org/thoughtcrime/securesms/conversation/ScheduledMessagesBottomSheet.kt index 18407f1cfe..547d3c6e58 100644 --- a/app/src/main/java/org/thoughtcrime/securesms/conversation/ScheduledMessagesBottomSheet.kt +++ b/app/src/main/java/org/thoughtcrime/securesms/conversation/ScheduledMessagesBottomSheet.kt @@ -170,7 +170,7 @@ class ScheduledMessagesBottomSheet : FixedRoundedCornerBottomSheetDialogFragment if (canCopy) { items.add(ActionItem(CoreUiR.drawable.symbol_copy_android_24, resources.getString(R.string.conversation_selection__menu_copy), action = { handleCopyMessage(message) })) } - items.add(ActionItem(R.drawable.symbol_send_24, resources.getString(R.string.ScheduledMessagesBottomSheet_menu_send_now), action = { handleSendMessageNow(message.messageRecord) })) + items.add(ActionItem(CoreUiR.drawable.symbol_send_24, resources.getString(R.string.ScheduledMessagesBottomSheet_menu_send_now), action = { handleSendMessageNow(message.messageRecord) })) items.add(ActionItem(R.drawable.symbol_calendar_24, resources.getString(R.string.ScheduledMessagesBottomSheet_menu_reschedule), action = { handleRescheduleMessage(message.messageRecord) })) return items } diff --git a/app/src/main/java/org/thoughtcrime/securesms/conversation/v2/ConversationFragment.kt b/app/src/main/java/org/thoughtcrime/securesms/conversation/v2/ConversationFragment.kt index d190402953..7d86c1d970 100644 --- a/app/src/main/java/org/thoughtcrime/securesms/conversation/v2/ConversationFragment.kt +++ b/app/src/main/java/org/thoughtcrime/securesms/conversation/v2/ConversationFragment.kt @@ -354,11 +354,14 @@ import org.thoughtcrime.securesms.registration.ui.RegistrationActivity import org.thoughtcrime.securesms.revealable.ViewOnceMessageActivity import org.thoughtcrime.securesms.revealable.ViewOnceUtil import org.thoughtcrime.securesms.safety.SafetyNumberBottomSheet +import org.thoughtcrime.securesms.sharing.MultiShareArgs import org.thoughtcrime.securesms.sharing.v2.ShareActivity import org.thoughtcrime.securesms.sms.MessageSender import org.thoughtcrime.securesms.stickers.StickerEventListener import org.thoughtcrime.securesms.stickers.StickerLocator import org.thoughtcrime.securesms.stickers.StickerPackInstallEvent +import org.thoughtcrime.securesms.stickers.StickerUrl +import org.thoughtcrime.securesms.stickers.manage.StickerManagementRepository import org.thoughtcrime.securesms.stickers.manage.StickerManagementScreen import org.thoughtcrime.securesms.stickers.preview.StickerPackPreviewActivityV2 import org.thoughtcrime.securesms.stories.StoryViewerArgs @@ -714,6 +717,38 @@ class ConversationFragment : startActivity(StickerPackPreviewActivityV2.createIntent(StickerPackId(action.packId), StickerPackKey(action.packKey))) } + // Sending a pack means sending its link, so it goes through the same forward sheet as a + // message. A child of this fragment, as with sticker search. + is MediaKeyboardAction.SendStickerPackClicked -> { + container.onHostWindowShown() + MultiselectForwardFragment.showBottomSheet( + supportFragmentManager = childFragmentManager, + multiselectForwardFragmentArgs = MultiselectForwardFragmentArgs( + multiShareArgs = listOf( + MultiShareArgs.Builder() + .withDraftText(StickerUrl.createShareLink(action.packId, action.packKey)) + .build() + ), + title = R.string.StickerManagement_share_sheet_title + ) + ) + } + + is MediaKeyboardAction.RemoveStickerPackClicked -> { + container.onHostWindowShown() + MaterialAlertDialogBuilder(requireContext()) + .setTitle(resources.getQuantityString(R.plurals.StickerManagement_delete_n_packs_confirmation, 1, 1)) + .setMessage(resources.getQuantityString(R.plurals.StickerManagement_delete_n_packs_confirmation_body, 1, 1)) + .setPositiveButton(R.string.StickerManagement_menu_remove_pack) { _, _ -> + viewLifecycleOwner.lifecycleScope.launch { + StickerManagementRepository.uninstallStickerPacks(mapOf(StickerPackId(action.packId) to StickerPackKey(action.packKey))) + } + } + .setNegativeButton(android.R.string.cancel, null) + .setOnDismissListener { container.onHostWindowHidden() } + .show() + } + // A screen of its own rather than a window over this one, and picking a gif carries on into // media send, so the keyboard has no reason to still be up on the way back. MediaKeyboardAction.GifSearchClicked -> { diff --git a/app/src/main/java/org/thoughtcrime/securesms/database/StickerTables.kt b/app/src/main/java/org/thoughtcrime/securesms/database/StickerTables.kt index f8f4cb02ae..2cc81ea214 100644 --- a/app/src/main/java/org/thoughtcrime/securesms/database/StickerTables.kt +++ b/app/src/main/java/org/thoughtcrime/securesms/database/StickerTables.kt @@ -381,6 +381,17 @@ class StickerTables( notifyStickerPackListeners() } + fun clearRecentlyUsedStickers() { + writableDatabase + .update(Sticker.TABLE_NAME) + .values(Sticker.LAST_USED to 0) + .where("${Sticker.LAST_USED} > 0 AND ${Sticker.COVER} = 0") + .run() + + notifyStickerListeners() + notifyStickerPackListeners() + } + fun markPackAsInstalled(packId: String, notify: Boolean) { val transitioned = updatePackInstalled( db = databaseHelper.signalWritableDatabase, diff --git a/app/src/main/java/org/thoughtcrime/securesms/mediakeyboard/SignalStickerKeyboardRepository.kt b/app/src/main/java/org/thoughtcrime/securesms/mediakeyboard/SignalStickerKeyboardRepository.kt index 08d669b4f9..11afbb610b 100644 --- a/app/src/main/java/org/thoughtcrime/securesms/mediakeyboard/SignalStickerKeyboardRepository.kt +++ b/app/src/main/java/org/thoughtcrime/securesms/mediakeyboard/SignalStickerKeyboardRepository.kt @@ -62,6 +62,12 @@ class SignalStickerKeyboardRepository(private val context: Context) : StickerKey } } + override fun clearRecentStickers() { + SignalExecutors.BOUNDED_IO.execute { + SignalDatabase.stickers.clearRecentlyUsedStickers() + } + } + private fun loadStickerPacks(): List { val stickerTable = SignalDatabase.stickers @@ -74,6 +80,7 @@ class SignalStickerKeyboardRepository(private val context: Context) : StickerKey KeyboardStickerPack( id = pack.packId, + packKey = pack.packKey, title = pack.title.nullIfBlank(), cover = DecryptableUri(pack.cover.uri), stickers = stickers @@ -87,6 +94,7 @@ class SignalStickerKeyboardRepository(private val context: Context) : StickerKey val recentPack = KeyboardStickerPack( id = StickerKeyboardRepository.RECENT_PACK_ID, + packKey = null, title = context.getString(R.string.StickerKeyboard__recently_used), cover = null, stickers = recentStickers.map { it.toKeyboardSticker() } diff --git a/app/src/main/java/org/thoughtcrime/securesms/stickers/preview/StickerPackPreviewActivityV2.kt b/app/src/main/java/org/thoughtcrime/securesms/stickers/preview/StickerPackPreviewActivityV2.kt index f726c77539..4b00db63b2 100644 --- a/app/src/main/java/org/thoughtcrime/securesms/stickers/preview/StickerPackPreviewActivityV2.kt +++ b/app/src/main/java/org/thoughtcrime/securesms/stickers/preview/StickerPackPreviewActivityV2.kt @@ -243,7 +243,7 @@ private fun StickerPackPreviewScreen( if (loadedState.isPackInstalled) { DropdownMenus.ItemWithIcon( menuController = menuController, - imageVector = ImageVector.vectorResource(R.drawable.symbol_minus_circle_24), + imageVector = SignalIcons.MinusCircle.imageVector, stringResId = R.string.StickerManagement_menu_remove_pack, onClick = { onEvent(StickerPackPreviewEvent.UninstallClicked) } ) @@ -511,7 +511,7 @@ private fun StickerOptions( Buttons.ActionButton( onClick = { onEvent(StickerPackPreviewEvent.UninstallClicked) }, - imageVector = ImageVector.vectorResource(R.drawable.symbol_minus_circle_24), + imageVector = SignalIcons.MinusCircle.imageVector, label = stringResource(R.string.StickerManagement_menu_remove_pack) ) } diff --git a/app/src/main/res/drawable/symbol_minus_circle_24.xml b/app/src/main/res/drawable/symbol_minus_circle_24.xml deleted file mode 100644 index 29c0e0eff8..0000000000 --- a/app/src/main/res/drawable/symbol_minus_circle_24.xml +++ /dev/null @@ -1,12 +0,0 @@ - - - - diff --git a/app/src/main/res/drawable/symbol_send_24.xml b/app/src/main/res/drawable/symbol_send_24.xml deleted file mode 100644 index 8eb29dac23..0000000000 --- a/app/src/main/res/drawable/symbol_send_24.xml +++ /dev/null @@ -1,10 +0,0 @@ - - - diff --git a/core/ui/src/main/java/org/signal/core/ui/compose/SignalIcons.kt b/core/ui/src/main/java/org/signal/core/ui/compose/SignalIcons.kt index 57371b585f..872930cf08 100644 --- a/core/ui/src/main/java/org/signal/core/ui/compose/SignalIcons.kt +++ b/core/ui/src/main/java/org/signal/core/ui/compose/SignalIcons.kt @@ -80,6 +80,7 @@ enum class SignalIcons(private val icon: SignalIcon) : SignalIcon by icon { LockFill(icon(R.drawable.symbol_lock_fill_24)), Maximize(icon(R.drawable.symbol_maximize_24)), Mic(icon(R.drawable.symbol_mic_24)), + MinusCircle(icon(R.drawable.symbol_minus_circle_24)), MobileNextDisplay(icon(R.drawable.symbol_mobile_next_display_48)), MoreVertical(icon(R.drawable.symbol_more_vertical_24)), Nighttime(icon(R.drawable.ic_nighttime_26)), @@ -100,6 +101,7 @@ enum class SignalIcons(private val icon: SignalIcon) : SignalIcon by icon { Refresh(icon(R.drawable.symbol_refresh_24)), Save(icon(R.drawable.symbol_save_android_24)), Search(icon(R.drawable.symbol_search_24)), + Send(icon(R.drawable.symbol_send_24)), SendFill(icon(R.drawable.symbol_send_fill_24)), Settings(icon(R.drawable.symbol_settings_android_24)), Share(icon(R.drawable.symbol_share_android_24)), diff --git a/core/ui/src/main/res/drawable/symbol_minus_circle_24.xml b/core/ui/src/main/res/drawable/symbol_minus_circle_24.xml new file mode 100644 index 0000000000..a8d54f1229 --- /dev/null +++ b/core/ui/src/main/res/drawable/symbol_minus_circle_24.xml @@ -0,0 +1,9 @@ + + + diff --git a/core/ui/src/main/res/drawable/symbol_send_24.xml b/core/ui/src/main/res/drawable/symbol_send_24.xml new file mode 100644 index 0000000000..6e9b809c28 --- /dev/null +++ b/core/ui/src/main/res/drawable/symbol_send_24.xml @@ -0,0 +1,9 @@ + + + diff --git a/feature/media-keyboard/src/main/java/org/signal/mediakeyboard/MediaKeyboardAction.kt b/feature/media-keyboard/src/main/java/org/signal/mediakeyboard/MediaKeyboardAction.kt index db251bf879..cf6148663b 100644 --- a/feature/media-keyboard/src/main/java/org/signal/mediakeyboard/MediaKeyboardAction.kt +++ b/feature/media-keyboard/src/main/java/org/signal/mediakeyboard/MediaKeyboardAction.kt @@ -57,4 +57,20 @@ sealed interface MediaKeyboardAction { * @param packKey Its key, which identifies the pack alongside [packId]. */ data class ViewStickerPackClicked(val packId: String, val packKey: String) : MediaKeyboardAction + + /** + * Let the user send a sticker pack to someone, as a link. + * + * @param packId The pack to send. + * @param packKey Its key, which identifies the pack alongside [packId]. + */ + data class SendStickerPackClicked(val packId: String, val packKey: String) : MediaKeyboardAction + + /** + * Uninstall a sticker pack, confirming with the user first. + * + * @param packId The pack to remove. + * @param packKey Its key, which identifies the pack alongside [packId]. + */ + data class RemoveStickerPackClicked(val packId: String, val packKey: String) : MediaKeyboardAction } diff --git a/feature/media-keyboard/src/main/java/org/signal/mediakeyboard/data/StickerKeyboardRepository.kt b/feature/media-keyboard/src/main/java/org/signal/mediakeyboard/data/StickerKeyboardRepository.kt index 451012c2ec..ff5ba2d666 100644 --- a/feature/media-keyboard/src/main/java/org/signal/mediakeyboard/data/StickerKeyboardRepository.kt +++ b/feature/media-keyboard/src/main/java/org/signal/mediakeyboard/data/StickerKeyboardRepository.kt @@ -30,6 +30,11 @@ interface StickerKeyboardRepository { */ fun onStickerUsed(sticker: KeyboardSticker) = Unit + /** + * Forget every recently-used sticker, emptying the synthetic [RECENT_PACK_ID] pack. + */ + fun clearRecentStickers() = Unit + companion object { const val RECENT_PACK_ID = "media-keyboard-recents" } @@ -53,10 +58,13 @@ data class KeyboardSticker( ) /** + * @param packKey The pack's key, which identifies it alongside [id] wherever it is opened or + * forwarded. Null for the synthetic recents pack, which is not a real pack. * @param cover A Glide-loadable model for the pack's cover image. */ data class KeyboardStickerPack( val id: String, + val packKey: String?, val title: String?, val cover: Any?, val stickers: List diff --git a/feature/media-keyboard/src/main/java/org/signal/mediakeyboard/screens/sticker/StickerPageScreen.kt b/feature/media-keyboard/src/main/java/org/signal/mediakeyboard/screens/sticker/StickerPageScreen.kt index 8acc48139e..27384909f3 100644 --- a/feature/media-keyboard/src/main/java/org/signal/mediakeyboard/screens/sticker/StickerPageScreen.kt +++ b/feature/media-keyboard/src/main/java/org/signal/mediakeyboard/screens/sticker/StickerPageScreen.kt @@ -8,6 +8,8 @@ package org.signal.mediakeyboard.screens.sticker import androidx.compose.foundation.background import androidx.compose.foundation.combinedClickable import androidx.compose.foundation.layout.Box +import androidx.compose.foundation.layout.Column +import androidx.compose.foundation.layout.Row import androidx.compose.foundation.layout.aspectRatio import androidx.compose.foundation.layout.fillMaxSize import androidx.compose.foundation.layout.fillMaxWidth @@ -36,9 +38,13 @@ import androidx.compose.ui.Alignment import androidx.compose.ui.Modifier import androidx.compose.ui.draw.clip import androidx.compose.ui.res.stringResource +import androidx.compose.ui.text.style.TextOverflow +import androidx.compose.ui.tooling.preview.PreviewWrapper import androidx.compose.ui.unit.dp +import org.signal.core.ui.compose.DayNightPreviews import org.signal.core.ui.compose.DropdownMenus import org.signal.core.ui.compose.SignalIcons +import org.signal.core.ui.compose.SignalPreviewWrapper import org.signal.core.ui.compose.theme.SignalTheme import org.signal.glide.compose.GlideImage import org.signal.mediakeyboard.R @@ -190,18 +196,7 @@ private fun StickerGrid( state.packs.forEach { pack -> item(key = "header:${pack.id}", span = { GridItemSpan(maxLineSpan) }) { - val title = if (pack.id == StickerKeyboardRepository.RECENT_PACK_ID) { - stringResource(R.string.MediaKeyboard__recently_used) - } else { - pack.title.orEmpty() - } - - Text( - text = title, - style = MaterialTheme.typography.labelLarge, - color = MaterialTheme.colorScheme.onSurfaceVariant, - modifier = Modifier.padding(start = 8.dp, top = 12.dp, bottom = 4.dp) - ) + StickerPackHeader(pack = pack, onEvent = onEvent) } pack.stickers.forEachIndexed { index, sticker -> @@ -217,6 +212,137 @@ private fun StickerGrid( } } +@Composable +private fun StickerPackHeader( + pack: KeyboardStickerPack, + onEvent: (StickerPageScreenEvents) -> Unit, + modifier: Modifier = Modifier +) { + val isRecents = pack.id == StickerKeyboardRepository.RECENT_PACK_ID + val menuController = remember { DropdownMenus.MenuController() } + + Row( + verticalAlignment = Alignment.CenterVertically, + modifier = modifier + .fillMaxWidth() + .padding(start = 8.dp, end = 4.dp, top = 12.dp, bottom = 4.dp) + ) { + Text( + text = if (isRecents) stringResource(R.string.MediaKeyboard__recently_used) else pack.title.orEmpty(), + style = MaterialTheme.typography.labelLarge, + color = MaterialTheme.colorScheme.onSurfaceVariant, + maxLines = 1, + overflow = TextOverflow.Ellipsis, + modifier = Modifier.weight(1f) + ) + + Box { + IconButton( + onClick = { menuController.show() }, + modifier = Modifier.size(32.dp) + ) { + Icon( + imageVector = SignalIcons.MoreVertical.imageVector, + contentDescription = stringResource(R.string.MediaKeyboard__more_options), + tint = MaterialTheme.colorScheme.onSurfaceVariant + ) + } + + StickerPackHeaderMenu( + pack = pack, + isRecents = isRecents, + menuController = menuController, + onEvent = onEvent + ) + } + } +} + +@Composable +private fun StickerPackHeaderMenu( + pack: KeyboardStickerPack, + isRecents: Boolean, + menuController: DropdownMenus.MenuController, + onEvent: (StickerPageScreenEvents) -> Unit +) { + DropdownMenus.Menu( + controller = menuController, + offsetX = 0.dp + ) { + if (isRecents) { + DropdownMenus.ItemWithIcon( + menuController = menuController, + imageVector = SignalIcons.Trash.imageVector, + stringResId = R.string.MediaKeyboard__clear_recents, + onClick = { + onEvent(StickerPageScreenEvents.ClearRecentStickersClicked) + } + ) + + return@Menu + } + + // Everything below acts on the pack itself, which needs the key the recents pack does not have. + val packKey = pack.packKey ?: return@Menu + + DropdownMenus.ItemWithIcon( + menuController = menuController, + imageVector = SignalIcons.Send.imageVector, + stringResId = R.string.MediaKeyboard__send, + onClick = { + onEvent(StickerPageScreenEvents.SendStickerPackClicked(pack.id, packKey)) + } + ) + + DropdownMenus.ItemWithIcon( + menuController = menuController, + imageVector = SignalIcons.StickerPack.imageVector, + stringResId = R.string.MediaKeyboard__view_pack, + onClick = { + onEvent(StickerPageScreenEvents.ViewStickerPackClicked(pack.id, packKey)) + } + ) + + DropdownMenus.ItemWithIcon( + menuController = menuController, + imageVector = SignalIcons.MinusCircle.imageVector, + stringResId = R.string.MediaKeyboard__remove_pack, + onClick = { + onEvent(StickerPageScreenEvents.RemoveStickerPackClicked(pack.id, packKey)) + } + ) + } +} + +@PreviewWrapper(SignalPreviewWrapper::class) +@DayNightPreviews +@Composable +private fun StickerPackHeaderPreview() { + Column { + StickerPackHeader( + pack = KeyboardStickerPack( + id = StickerKeyboardRepository.RECENT_PACK_ID, + packKey = null, + title = null, + cover = null, + stickers = emptyList() + ), + onEvent = {} + ) + + StickerPackHeader( + pack = KeyboardStickerPack( + id = "pack-1", + packKey = "pack-1-key", + title = "Bandit the Cat", + cover = null, + stickers = emptyList() + ), + onEvent = {} + ) + } +} + @Composable private fun StickerCell( sticker: KeyboardSticker, @@ -252,7 +378,7 @@ private fun StickerCell( ) { DropdownMenus.ItemWithIcon( menuController = controller, - imageVector = SignalIcons.SendFill.imageVector, + imageVector = SignalIcons.Send.imageVector, stringResId = R.string.MediaKeyboard__send, onClick = { onEvent(StickerPageScreenEvents.StickerClicked(sticker)) diff --git a/feature/media-keyboard/src/main/java/org/signal/mediakeyboard/screens/sticker/StickerPageScreenEvents.kt b/feature/media-keyboard/src/main/java/org/signal/mediakeyboard/screens/sticker/StickerPageScreenEvents.kt index 067e5d1d98..ca351dc062 100644 --- a/feature/media-keyboard/src/main/java/org/signal/mediakeyboard/screens/sticker/StickerPageScreenEvents.kt +++ b/feature/media-keyboard/src/main/java/org/signal/mediakeyboard/screens/sticker/StickerPageScreenEvents.kt @@ -17,4 +17,7 @@ sealed interface StickerPageScreenEvents { data class StickerClicked(val sticker: KeyboardSticker) : StickerPageScreenEvents data object SearchClicked : StickerPageScreenEvents data class ViewStickerPackClicked(val packId: String, val packKey: String) : StickerPageScreenEvents + data class SendStickerPackClicked(val packId: String, val packKey: String) : StickerPageScreenEvents + data class RemoveStickerPackClicked(val packId: String, val packKey: String) : StickerPageScreenEvents + data object ClearRecentStickersClicked : StickerPageScreenEvents } diff --git a/feature/media-keyboard/src/main/java/org/signal/mediakeyboard/screens/sticker/StickerPageViewModel.kt b/feature/media-keyboard/src/main/java/org/signal/mediakeyboard/screens/sticker/StickerPageViewModel.kt index 77a409f553..9b05d118ae 100644 --- a/feature/media-keyboard/src/main/java/org/signal/mediakeyboard/screens/sticker/StickerPageViewModel.kt +++ b/feature/media-keyboard/src/main/java/org/signal/mediakeyboard/screens/sticker/StickerPageViewModel.kt @@ -83,6 +83,18 @@ class StickerPageViewModel( is StickerPageScreenEvents.ViewStickerPackClicked -> { onAction(MediaKeyboardAction.ViewStickerPackClicked(event.packId, event.packKey)) } + + is StickerPageScreenEvents.SendStickerPackClicked -> { + onAction(MediaKeyboardAction.SendStickerPackClicked(event.packId, event.packKey)) + } + + is StickerPageScreenEvents.RemoveStickerPackClicked -> { + onAction(MediaKeyboardAction.RemoveStickerPackClicked(event.packId, event.packKey)) + } + + is StickerPageScreenEvents.ClearRecentStickersClicked -> { + repository.clearRecentStickers() + } } } diff --git a/feature/media-keyboard/src/main/res/values/strings.xml b/feature/media-keyboard/src/main/res/values/strings.xml index 3598f2944a..7df1cac318 100644 --- a/feature/media-keyboard/src/main/res/values/strings.xml +++ b/feature/media-keyboard/src/main/res/values/strings.xml @@ -55,10 +55,16 @@ Manage stickers - + Send - + View pack + + More options + + Remove + + Clear recents diff --git a/feature/media-keyboard/src/test/java/org/signal/mediakeyboard/screens/sticker/StickerPageViewModelTest.kt b/feature/media-keyboard/src/test/java/org/signal/mediakeyboard/screens/sticker/StickerPageViewModelTest.kt index 2d48cc1aa2..2433dd89b3 100644 --- a/feature/media-keyboard/src/test/java/org/signal/mediakeyboard/screens/sticker/StickerPageViewModelTest.kt +++ b/feature/media-keyboard/src/test/java/org/signal/mediakeyboard/screens/sticker/StickerPageViewModelTest.kt @@ -31,8 +31,8 @@ class StickerPageViewModelTest { private val sticker = KeyboardSticker(packId = "pack-1", packKey = "pack-1-key", stickerId = 1, emoji = "😀", image = "image-1") private val packs = listOf( - KeyboardStickerPack(id = "pack-1", title = "Pack One", cover = null, stickers = listOf(sticker)), - KeyboardStickerPack(id = "pack-2", title = "Pack Two", cover = null, stickers = emptyList()) + KeyboardStickerPack(id = "pack-1", packKey = "pack-1-key", title = "Pack One", cover = null, stickers = listOf(sticker)), + KeyboardStickerPack(id = "pack-2", packKey = "pack-2-key", title = "Pack Two", cover = null, stickers = emptyList()) ) private lateinit var repository: StickerKeyboardRepository