Add CFV2 Sticker Suggestions.

This commit is contained in:
Alex Hart
2023-06-16 12:26:23 -03:00
committed by Nicholas Tinsley
parent 2fbcc23451
commit 4ce05a064c
6 changed files with 160 additions and 24 deletions

View File

@@ -2175,7 +2175,7 @@ public class ConversationParentFragment extends Fragment
}
private void initializeStickerObserver() {
StickerSearchRepository repository = new StickerSearchRepository(requireContext());
StickerSearchRepository repository = new StickerSearchRepository();
stickerViewModel = new ViewModelProvider(this, (ViewModelProvider.Factory) new ConversationStickerViewModel.Factory(requireActivity().getApplication(), repository))
.get(ConversationStickerViewModel.class);

View File

@@ -188,6 +188,7 @@ import org.thoughtcrime.securesms.groups.ui.migration.GroupsV1MigrationInitiatio
import org.thoughtcrime.securesms.groups.ui.migration.GroupsV1MigrationSuggestionsDialog
import org.thoughtcrime.securesms.groups.v2.GroupBlockJoinRequestResult
import org.thoughtcrime.securesms.invites.InviteActions
import org.thoughtcrime.securesms.keyboard.KeyboardPage
import org.thoughtcrime.securesms.keyvalue.SignalStore
import org.thoughtcrime.securesms.linkpreview.LinkPreview
import org.thoughtcrime.securesms.linkpreview.LinkPreviewViewModelV2
@@ -229,6 +230,7 @@ import org.thoughtcrime.securesms.revealable.ViewOnceMessageActivity
import org.thoughtcrime.securesms.revealable.ViewOnceUtil
import org.thoughtcrime.securesms.safety.SafetyNumberBottomSheet
import org.thoughtcrime.securesms.stickers.StickerLocator
import org.thoughtcrime.securesms.stickers.StickerPackInstallEvent
import org.thoughtcrime.securesms.stickers.StickerPackPreviewActivity
import org.thoughtcrime.securesms.stories.StoryViewerArgs
import org.thoughtcrime.securesms.stories.viewer.StoryViewerActivity
@@ -333,6 +335,10 @@ class ConversationFragment :
ConversationSearchViewModel(getString(R.string.note_to_self))
}
private val stickerViewModel: StickerSuggestionsViewModel by viewModel {
StickerSuggestionsViewModel()
}
private val conversationTooltips = ConversationTooltips(this)
private val colorizer = Colorizer()
private val textDraftSaveDebouncer = Debouncer(500)
@@ -430,6 +436,7 @@ class ConversationFragment :
container.fragmentManager = childFragmentManager
ToolbarDependentMarginListener(binding.toolbar)
initializeMediaKeyboardToggle()
}
override fun onViewStateRestored(savedInstanceState: Bundle?) {
@@ -676,6 +683,7 @@ class ConversationFragment :
initializeSearch()
initializeLinkPreviews()
initializeStickerSuggestions()
inputPanel.setListener(InputPanelListener())
}
@@ -1056,6 +1064,36 @@ class ConversationFragment :
.addTo(disposables)
}
private fun initializeMediaKeyboardToggle() {
val isSystemEmojiPreferred = SignalStore.settings().isPreferSystemEmoji
val keyboardMode: TextSecurePreferences.MediaKeyboardMode = TextSecurePreferences.getMediaKeyboardMode(requireContext())
val stickerIntro: Boolean = !TextSecurePreferences.hasSeenStickerIntroTooltip(requireContext())
inputPanel.showMediaKeyboardToggle(true)
val toggleMode = when (keyboardMode) {
TextSecurePreferences.MediaKeyboardMode.EMOJI -> if (isSystemEmojiPreferred) KeyboardPage.STICKER else KeyboardPage.EMOJI
TextSecurePreferences.MediaKeyboardMode.STICKER -> KeyboardPage.STICKER
TextSecurePreferences.MediaKeyboardMode.GIF -> KeyboardPage.GIF
}
inputPanel.setMediaKeyboardToggleMode(toggleMode)
if (stickerIntro) {
TextSecurePreferences.setMediaKeyboardMode(requireContext(), TextSecurePreferences.MediaKeyboardMode.STICKER)
inputPanel.setMediaKeyboardToggleMode(KeyboardPage.STICKER)
conversationTooltips.displayStickerIntroductionTooltip(inputPanel.mediaKeyboardToggleAnchorView) {
EventBus.getDefault().removeStickyEvent(StickerPackInstallEvent::class.java)
}
}
}
private fun initializeStickerSuggestions() {
stickerViewModel.stickers
.subscribeBy(onNext = inputPanel::setStickerSuggestions)
.addTo(disposables)
}
private fun updateLinkPreviewState() {
if (/* TODO [cfv2] -- viewModel.isPushAvailable && */ !attachmentManager.isAttachmentPresent && context != null) {
linkPreviewViewModel.onEnabled()
@@ -2739,7 +2777,8 @@ class ConversationFragment :
if (composeText.textTrimmed.isEmpty() || beforeLength == 0) {
composeText.postDelayed({ updateToggleButtonState() }, 50)
}
// todo [cfv2] stickerViewModel.onInputTextUpdated(s.toString())
stickerViewModel.onInputTextUpdated(s.toString())
}
override fun onFocusChange(v: View, hasFocus: Boolean) {
@@ -2942,6 +2981,23 @@ class ConversationFragment :
viewModel.updateIdentityRecords()
}
@Subscribe(threadMode = ThreadMode.MAIN, sticky = true)
fun onStickerPackInstalled(event: StickerPackInstallEvent?) {
if (event == null) {
return
}
if (!TextSecurePreferences.hasSeenStickerIntroTooltip(requireContext())) {
return
}
EventBus.getDefault().removeStickyEvent(event)
if (!inputPanel.isStickerMode) {
conversationTooltips.displayStickerPackInstalledTooltip(inputPanel.mediaKeyboardToggleAnchorView, event)
}
}
//endregion
private inner class SearchEventListener : ConversationSearchBottomBar.EventListener {

View File

@@ -9,6 +9,8 @@ import org.signal.core.util.logging.Log
import org.thoughtcrime.securesms.R
import org.thoughtcrime.securesms.components.TooltipPopup
import org.thoughtcrime.securesms.keyvalue.SignalStore
import org.thoughtcrime.securesms.stickers.StickerPackInstallEvent
import org.thoughtcrime.securesms.util.TextSecurePreferences
/**
* Any and all tooltips that the conversation can display, and a light amount of related presentation logic.
@@ -51,6 +53,31 @@ class ConversationTooltips(fragment: Fragment) {
.show(TooltipPopup.POSITION_BELOW)
}
/**
* Displayed to teach the user about sticker packs
*/
fun displayStickerIntroductionTooltip(anchor: View, onDismiss: () -> Unit) {
TooltipPopup.forTarget(anchor)
.setBackgroundTint(ContextCompat.getColor(anchor.context, R.color.core_ultramarine))
.setTextColor(ContextCompat.getColor(anchor.context, R.color.core_white))
.setText(R.string.ConversationActivity_new_say_it_with_stickers)
.setOnDismissListener {
TextSecurePreferences.setHasSeenStickerIntroTooltip(anchor.context, true)
onDismiss()
}
.show(TooltipPopup.POSITION_ABOVE)
}
/**
* Displayed after a sticker pack is installed
*/
fun displayStickerPackInstalledTooltip(anchor: View, event: StickerPackInstallEvent) {
TooltipPopup.forTarget(anchor)
.setText(R.string.ConversationActivity_sticker_pack_installed)
.setIconGlideModel(event.iconGlideModel)
.show(TooltipPopup.POSITION_ABOVE)
}
/**
* ViewModel which holds different bits of session-local persistent state for different tooltips.
*/

View File

@@ -0,0 +1,26 @@
/*
* Copyright 2023 Signal Messenger, LLC
* SPDX-License-Identifier: AGPL-3.0-only
*/
package org.thoughtcrime.securesms.conversation.v2
import androidx.lifecycle.ViewModel
import io.reactivex.rxjava3.core.Flowable
import io.reactivex.rxjava3.processors.BehaviorProcessor
import org.thoughtcrime.securesms.database.model.StickerRecord
import org.thoughtcrime.securesms.stickers.StickerSearchRepository
class StickerSuggestionsViewModel(
private val stickerSearchRepository: StickerSearchRepository = StickerSearchRepository()
) : ViewModel() {
private val stickerSearchProcessor = BehaviorProcessor.createDefault("")
val stickers: Flowable<List<StickerRecord>> = stickerSearchProcessor
.switchMapSingle { stickerSearchRepository.searchByEmoji(it) }
fun onInputTextUpdated(text: String) {
stickerSearchProcessor.onNext(text)
}
}