mirror of
https://github.com/signalapp/Signal-Android.git
synced 2026-08-07 13:55:56 +01:00
Decouple add message dialog from old view model.
This commit is contained in:
committed by
Greyson Parrelli
parent
539276673a
commit
276d71d365
@@ -0,0 +1,18 @@
|
||||
/*
|
||||
* Copyright 2026 Signal Messenger, LLC
|
||||
* SPDX-License-Identifier: AGPL-3.0-only
|
||||
*/
|
||||
|
||||
package org.thoughtcrime.securesms.keyboard.emoji
|
||||
|
||||
import android.view.KeyEvent
|
||||
|
||||
/**
|
||||
* Mapping of [EmojiKeyboardCallback] methods into a sealed event class
|
||||
*/
|
||||
sealed interface EmojiKeyboardEvent {
|
||||
object OpenEmojiSearch : EmojiKeyboardEvent
|
||||
object CloseEmojiSearch : EmojiKeyboardEvent
|
||||
data class EmojiInsert(val emoji: String?) : EmojiKeyboardEvent
|
||||
data class EmojiKeyEvent(val keyEvent: KeyEvent?) : EmojiKeyboardEvent
|
||||
}
|
||||
+28
@@ -0,0 +1,28 @@
|
||||
/*
|
||||
* Copyright 2026 Signal Messenger, LLC
|
||||
* SPDX-License-Identifier: AGPL-3.0-only
|
||||
*/
|
||||
|
||||
package org.thoughtcrime.securesms.keyboard.emoji
|
||||
|
||||
import androidx.lifecycle.ViewModel
|
||||
import androidx.lifecycle.viewModelScope
|
||||
import kotlinx.coroutines.channels.Channel
|
||||
import kotlinx.coroutines.flow.Flow
|
||||
import kotlinx.coroutines.flow.receiveAsFlow
|
||||
import kotlinx.coroutines.launch
|
||||
|
||||
/**
|
||||
* Glue ViewModel that allows a component to dispatch emoji events to subcomponents.
|
||||
*/
|
||||
class EmojiKeyboardEventViewModel : ViewModel() {
|
||||
|
||||
private val eventChannel = Channel<EmojiKeyboardEvent>(Channel.BUFFERED)
|
||||
val events: Flow<EmojiKeyboardEvent> = eventChannel.receiveAsFlow()
|
||||
|
||||
fun onEvent(event: EmojiKeyboardEvent) {
|
||||
viewModelScope.launch {
|
||||
eventChannel.send(event)
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,7 +1,5 @@
|
||||
package org.thoughtcrime.securesms.mediasend.v2
|
||||
|
||||
import android.view.KeyEvent
|
||||
|
||||
sealed class HudCommand {
|
||||
object StartDraw : HudCommand()
|
||||
object StartCropAndRotate : HudCommand()
|
||||
@@ -11,9 +9,4 @@ sealed class HudCommand {
|
||||
object GoToCapture : HudCommand()
|
||||
|
||||
object ResumeEntryTransition : HudCommand()
|
||||
|
||||
object OpenEmojiSearch : HudCommand()
|
||||
object CloseEmojiSearch : HudCommand()
|
||||
data class EmojiInsert(val emoji: String?) : HudCommand()
|
||||
data class EmojiKeyEvent(val keyEvent: KeyEvent?) : HudCommand()
|
||||
}
|
||||
|
||||
@@ -37,6 +37,8 @@ import org.thoughtcrime.securesms.R
|
||||
import org.thoughtcrime.securesms.components.emoji.EmojiEventListener
|
||||
import org.thoughtcrime.securesms.contacts.paged.ContactSearchKey
|
||||
import org.thoughtcrime.securesms.conversation.MessageSendType
|
||||
import org.thoughtcrime.securesms.keyboard.emoji.EmojiKeyboardEvent
|
||||
import org.thoughtcrime.securesms.keyboard.emoji.EmojiKeyboardEventViewModel
|
||||
import org.thoughtcrime.securesms.keyboard.emoji.EmojiKeyboardPageFragment
|
||||
import org.thoughtcrime.securesms.keyboard.emoji.search.EmojiSearchFragment
|
||||
import org.thoughtcrime.securesms.linkpreview.LinkPreviewUtil
|
||||
@@ -52,6 +54,7 @@ import org.thoughtcrime.securesms.util.FullscreenHelper
|
||||
import org.thoughtcrime.securesms.util.WindowUtil
|
||||
import org.thoughtcrime.securesms.util.navigation.safeNavigate
|
||||
import org.thoughtcrime.securesms.util.visible
|
||||
import kotlin.getValue
|
||||
import org.signal.core.ui.R as CoreUiR
|
||||
|
||||
class MediaSelectionActivity :
|
||||
@@ -76,6 +79,8 @@ class MediaSelectionActivity :
|
||||
}
|
||||
)
|
||||
|
||||
private val addMessageCommandViewModel: EmojiKeyboardEventViewModel by viewModels()
|
||||
|
||||
private val destination: MediaSelectionDestination
|
||||
get() = MediaSelectionDestination.fromBundle(requireNotNull(intent.getBundleExtra(DESTINATION)))
|
||||
|
||||
@@ -350,19 +355,19 @@ class MediaSelectionActivity :
|
||||
private fun isCameraFirst(): Boolean = intent.getIntExtra(START_ACTION, -1) == R.id.action_directly_to_mediaCaptureFragment
|
||||
|
||||
override fun openEmojiSearch() {
|
||||
viewModel.sendCommand(HudCommand.OpenEmojiSearch)
|
||||
addMessageCommandViewModel.onEvent(EmojiKeyboardEvent.OpenEmojiSearch)
|
||||
}
|
||||
|
||||
override fun onEmojiSelected(emoji: String?) {
|
||||
viewModel.sendCommand(HudCommand.EmojiInsert(emoji))
|
||||
addMessageCommandViewModel.onEvent(EmojiKeyboardEvent.EmojiInsert(emoji))
|
||||
}
|
||||
|
||||
override fun onKeyEvent(keyEvent: KeyEvent?) {
|
||||
viewModel.sendCommand(HudCommand.EmojiKeyEvent(keyEvent))
|
||||
addMessageCommandViewModel.onEvent(EmojiKeyboardEvent.EmojiKeyEvent(keyEvent))
|
||||
}
|
||||
|
||||
override fun closeEmojiSearch() {
|
||||
viewModel.sendCommand(HudCommand.CloseEmojiSearch)
|
||||
addMessageCommandViewModel.onEvent(EmojiKeyboardEvent.CloseEmojiSearch)
|
||||
}
|
||||
|
||||
private inner class OnBackPressed : OnBackPressedCallback(true) {
|
||||
|
||||
@@ -8,8 +8,6 @@ import androidx.lifecycle.LiveData
|
||||
import androidx.lifecycle.ViewModel
|
||||
import androidx.lifecycle.ViewModelProvider
|
||||
import com.google.common.io.ByteStreams
|
||||
import io.reactivex.rxjava3.android.schedulers.AndroidSchedulers
|
||||
import io.reactivex.rxjava3.core.Flowable
|
||||
import io.reactivex.rxjava3.core.Maybe
|
||||
import io.reactivex.rxjava3.core.Observable
|
||||
import io.reactivex.rxjava3.core.Single
|
||||
@@ -17,13 +15,11 @@ import io.reactivex.rxjava3.disposables.CompositeDisposable
|
||||
import io.reactivex.rxjava3.disposables.Disposable
|
||||
import io.reactivex.rxjava3.kotlin.plusAssign
|
||||
import io.reactivex.rxjava3.kotlin.subscribeBy
|
||||
import io.reactivex.rxjava3.processors.BehaviorProcessor
|
||||
import io.reactivex.rxjava3.schedulers.Schedulers
|
||||
import io.reactivex.rxjava3.subjects.BehaviorSubject
|
||||
import io.reactivex.rxjava3.subjects.PublishSubject
|
||||
import io.reactivex.rxjava3.subjects.Subject
|
||||
import org.signal.core.models.media.Media
|
||||
import org.signal.core.util.BreakIteratorCompat
|
||||
import org.signal.core.util.Util
|
||||
import org.signal.core.util.getParcelableArrayListCompat
|
||||
import org.signal.core.util.getParcelableCompat
|
||||
@@ -33,7 +29,6 @@ import org.thoughtcrime.securesms.contacts.paged.ContactSearchKey
|
||||
import org.thoughtcrime.securesms.conversation.MessageSendType
|
||||
import org.thoughtcrime.securesms.conversation.MessageStyler
|
||||
import org.thoughtcrime.securesms.mediasend.MediaSendActivityResult
|
||||
import org.thoughtcrime.securesms.mediasend.v2.review.AddMessageCharacterCount
|
||||
import org.thoughtcrime.securesms.mediasend.v2.videos.VideoTrimData
|
||||
import org.thoughtcrime.securesms.mms.MediaConstraints
|
||||
import org.thoughtcrime.securesms.mms.SentMediaQuality
|
||||
@@ -74,8 +69,6 @@ class MediaSelectionViewModel(
|
||||
)
|
||||
)
|
||||
|
||||
private val addAMessageUpdatePublisher = BehaviorProcessor.create<CharSequence>()
|
||||
|
||||
val isContactSelectionRequired = destination == MediaSelectionDestination.ChooseAfterMediaSelection
|
||||
|
||||
val state: LiveData<MediaSelectionState> = store.stateLiveData
|
||||
@@ -87,22 +80,6 @@ class MediaSelectionViewModel(
|
||||
|
||||
private val disposables = CompositeDisposable()
|
||||
|
||||
fun watchAddAMessageCount(): Flowable<AddMessageCharacterCount> {
|
||||
return addAMessageUpdatePublisher
|
||||
.onBackpressureLatest()
|
||||
.map {
|
||||
val iterator = BreakIteratorCompat.getInstance()
|
||||
iterator.setText(it)
|
||||
AddMessageCharacterCount(iterator.countBreaks())
|
||||
}
|
||||
.subscribeOn(Schedulers.io())
|
||||
.observeOn(AndroidSchedulers.mainThread())
|
||||
}
|
||||
|
||||
fun updateAddAMessageCount(input: CharSequence?) {
|
||||
addAMessageUpdatePublisher.onNext(input ?: "")
|
||||
}
|
||||
|
||||
private val isMeteredDisposable: Disposable = repository.isMetered.subscribe { metered ->
|
||||
store.update {
|
||||
it.copy(
|
||||
|
||||
+62
-45
@@ -11,14 +11,21 @@ import android.view.ViewGroup
|
||||
import androidx.core.view.ViewCompat
|
||||
import androidx.core.widget.addTextChangedListener
|
||||
import androidx.fragment.app.FragmentManager
|
||||
import androidx.fragment.app.viewModels
|
||||
import androidx.fragment.app.activityViewModels
|
||||
import androidx.fragment.app.setFragmentResult
|
||||
import androidx.lifecycle.Lifecycle
|
||||
import androidx.lifecycle.ViewModelProvider
|
||||
import androidx.lifecycle.lifecycleScope
|
||||
import androidx.lifecycle.repeatOnLifecycle
|
||||
import io.reactivex.rxjava3.android.schedulers.AndroidSchedulers
|
||||
import io.reactivex.rxjava3.disposables.CompositeDisposable
|
||||
import io.reactivex.rxjava3.kotlin.plusAssign
|
||||
import kotlinx.coroutines.Dispatchers
|
||||
import kotlinx.coroutines.launch
|
||||
import org.signal.core.ui.view.Stub
|
||||
import org.signal.core.util.ByteLimitInputFilter
|
||||
import org.signal.core.util.EditTextUtil
|
||||
import org.signal.core.util.getParcelableCompat
|
||||
import org.thoughtcrime.securesms.R
|
||||
import org.thoughtcrime.securesms.backup.v2.ui.warning.guardAgainstRecoveryKeyPaste
|
||||
import org.thoughtcrime.securesms.components.KeyboardAwareLinearLayout
|
||||
@@ -36,32 +43,29 @@ import org.thoughtcrime.securesms.conversation.ui.mentions.MentionsPickerViewMod
|
||||
import org.thoughtcrime.securesms.databinding.V2MediaAddMessageDialogFragmentBinding
|
||||
import org.thoughtcrime.securesms.keyboard.KeyboardPage
|
||||
import org.thoughtcrime.securesms.keyboard.KeyboardPagerViewModel
|
||||
import org.thoughtcrime.securesms.mediasend.v2.HudCommand
|
||||
import org.thoughtcrime.securesms.mediasend.v2.MediaSelectionState
|
||||
import org.thoughtcrime.securesms.mediasend.v2.MediaSelectionViewModel
|
||||
import org.thoughtcrime.securesms.keyboard.emoji.EmojiKeyboardEvent
|
||||
import org.thoughtcrime.securesms.keyboard.emoji.EmojiKeyboardEventViewModel
|
||||
import org.thoughtcrime.securesms.recipients.Recipient
|
||||
import org.thoughtcrime.securesms.recipients.RecipientId
|
||||
import org.thoughtcrime.securesms.stories.Stories
|
||||
import org.thoughtcrime.securesms.util.MediaUtil
|
||||
import org.thoughtcrime.securesms.util.MessageUtil
|
||||
import org.thoughtcrime.securesms.util.ViewUtil
|
||||
import org.thoughtcrime.securesms.util.viewModel
|
||||
import org.thoughtcrime.securesms.util.visible
|
||||
|
||||
class AddMessageDialogFragment : KeyboardEntryDialogFragment(R.layout.v2_media_add_message_dialog_fragment) {
|
||||
|
||||
private val viewModel: MediaSelectionViewModel by viewModels(
|
||||
ownerProducer = { requireActivity() }
|
||||
)
|
||||
private val viewModel: AddMessageViewModel by viewModel {
|
||||
AddMessageViewModel(initialMessage = requireArguments().getCharSequence(ARG_INITIAL_TEXT, null))
|
||||
}
|
||||
|
||||
private val keyboardPagerViewModel: KeyboardPagerViewModel by viewModels(
|
||||
ownerProducer = { requireActivity() }
|
||||
)
|
||||
private val commandViewModel: EmojiKeyboardEventViewModel by activityViewModels()
|
||||
|
||||
private val keyboardPagerViewModel: KeyboardPagerViewModel by activityViewModels()
|
||||
|
||||
private lateinit var mentionsViewModel: MentionsPickerViewModel
|
||||
|
||||
private val inlineQueryViewModel: InlineQueryViewModel by viewModels(
|
||||
ownerProducer = { requireActivity() }
|
||||
)
|
||||
private val inlineQueryViewModel: InlineQueryViewModel by activityViewModels()
|
||||
|
||||
private val binding by ViewBinderDelegate(V2MediaAddMessageDialogFragmentBinding::bind, onBindingWillBeDestroyed = { binding ->
|
||||
binding.content.addAMessageInput.setInlineQueryChangedListener(null)
|
||||
@@ -86,6 +90,11 @@ class AddMessageDialogFragment : KeyboardEntryDialogFragment(R.layout.v2_media_a
|
||||
}
|
||||
|
||||
override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
|
||||
if (viewModel.isViewOnce) {
|
||||
dismissAllowingStateLoss()
|
||||
return
|
||||
}
|
||||
|
||||
emojiDrawerStub = Stub(binding.content.emojiDrawerStub)
|
||||
|
||||
if (Stories.isFeatureEnabled()) {
|
||||
@@ -97,7 +106,7 @@ class AddMessageDialogFragment : KeyboardEntryDialogFragment(R.layout.v2_media_a
|
||||
})
|
||||
|
||||
binding.content.addAMessageInput.setText(requireArguments().getCharSequence(ARG_INITIAL_TEXT))
|
||||
binding.content.addAMessageInput.addTextChangedListener { viewModel.setMessage(it) }
|
||||
binding.content.addAMessageInput.addTextChangedListener { viewModel.message = it }
|
||||
binding.content.addAMessageInput.filters += ByteLimitInputFilter(MessageUtil.MAX_TOTAL_BODY_SIZE_BYTES)
|
||||
binding.content.addAMessageInput.guardAgainstRecoveryKeyPaste(
|
||||
host = this,
|
||||
@@ -116,43 +125,36 @@ class AddMessageDialogFragment : KeyboardEntryDialogFragment(R.layout.v2_media_a
|
||||
binding.hud.setOnClickListener { dismissAllowingStateLoss() }
|
||||
|
||||
binding.content.viewOnceToggle.setOnClickListener {
|
||||
viewModel.message = null
|
||||
viewModel.isViewOnce = true
|
||||
|
||||
dismissAllowingStateLoss()
|
||||
viewModel.incrementViewOnceState()
|
||||
}
|
||||
|
||||
val confirm: View = view.findViewById(R.id.confirm_button)
|
||||
confirm.setOnClickListener { dismissAllowingStateLoss() }
|
||||
|
||||
disposables += viewModel.watchAddAMessageCount().subscribe { count ->
|
||||
binding.content.addAMessageLimit.visible = count.shouldDisplayCount()
|
||||
binding.content.addAMessageLimit.text = count.getRemaining().toString()
|
||||
viewLifecycleOwner.lifecycleScope.launch(Dispatchers.Main) {
|
||||
viewModel.watchAddAMessageCount().collect { count ->
|
||||
binding.content.addAMessageLimit.visible = count.shouldDisplayCount()
|
||||
binding.content.addAMessageLimit.text = count.getRemaining().toString()
|
||||
}
|
||||
}
|
||||
|
||||
disposables.add(
|
||||
viewModel.hudCommands.observeOn(AndroidSchedulers.mainThread()).subscribe {
|
||||
when (it) {
|
||||
HudCommand.OpenEmojiSearch -> openEmojiSearch()
|
||||
HudCommand.CloseEmojiSearch -> closeEmojiSearch()
|
||||
is HudCommand.EmojiKeyEvent -> onKeyEvent(it.keyEvent)
|
||||
is HudCommand.EmojiInsert -> onEmojiSelected(it.emoji)
|
||||
else -> Unit
|
||||
viewLifecycleOwner.lifecycleScope.launch {
|
||||
repeatOnLifecycle(state = Lifecycle.State.RESUMED) {
|
||||
commandViewModel.events.collect {
|
||||
when (it) {
|
||||
EmojiKeyboardEvent.CloseEmojiSearch -> closeEmojiSearch()
|
||||
is EmojiKeyboardEvent.EmojiInsert -> onEmojiSelected(it.emoji)
|
||||
is EmojiKeyboardEvent.EmojiKeyEvent -> onKeyEvent(it.keyEvent)
|
||||
EmojiKeyboardEvent.OpenEmojiSearch -> openEmojiSearch()
|
||||
}
|
||||
}
|
||||
}
|
||||
)
|
||||
|
||||
viewModel.state.observe(viewLifecycleOwner) { state ->
|
||||
val newChild = if (state.viewOnceToggleState == MediaSelectionState.ViewOnceToggleState.ONCE) 1 else 0
|
||||
if (binding.content.viewOnceToggle.displayedChild != newChild) {
|
||||
binding.content.viewOnceToggle.displayedChild = newChild
|
||||
}
|
||||
|
||||
if (state.viewOnceToggleState == MediaSelectionState.ViewOnceToggleState.ONCE) {
|
||||
binding.content.addAMessageInput.text = null
|
||||
dismiss()
|
||||
}
|
||||
binding.content.viewOnceToggle.visible = state.selectedMedia.size == 1 && !state.isStory && !MediaUtil.isDocumentType(state.focusedMedia?.contentType)
|
||||
}
|
||||
|
||||
binding.content.viewOnceToggle.visible = requireArguments().getBoolean(ARG_VIEW_ONCE_AVAILABLE, false)
|
||||
initializeMentions()
|
||||
}
|
||||
|
||||
@@ -165,9 +167,14 @@ class AddMessageDialogFragment : KeyboardEntryDialogFragment(R.layout.v2_media_a
|
||||
|
||||
override fun onDismiss(dialog: DialogInterface) {
|
||||
super.onDismiss(dialog)
|
||||
if (isResumed) {
|
||||
viewModel.setMessage(binding.content.addAMessageInput.text)
|
||||
}
|
||||
|
||||
setFragmentResult(
|
||||
REQUEST_KEY,
|
||||
Bundle().apply {
|
||||
putCharSequence(RESULT_MESSAGE, viewModel.message)
|
||||
putBoolean(RESULT_INCREMENT_VIEW_ONCE_STATE, viewModel.isViewOnce)
|
||||
}
|
||||
)
|
||||
}
|
||||
|
||||
override fun onKeyboardHidden() {
|
||||
@@ -213,10 +220,12 @@ class AddMessageDialogFragment : KeyboardEntryDialogFragment(R.layout.v2_media_a
|
||||
}
|
||||
inlineQueryViewModel.onQueryChange(inlineQuery)
|
||||
}
|
||||
|
||||
is InlineQuery.Emoji -> {
|
||||
inlineQueryViewModel.onQueryChange(inlineQuery)
|
||||
mentionsViewModel.onQueryChange(null)
|
||||
}
|
||||
|
||||
is NoQuery -> {
|
||||
mentionsViewModel.onQueryChange(null)
|
||||
inlineQueryViewModel.onQueryChange(inlineQuery)
|
||||
@@ -234,7 +243,7 @@ class AddMessageDialogFragment : KeyboardEntryDialogFragment(R.layout.v2_media_a
|
||||
.observeOn(AndroidSchedulers.mainThread())
|
||||
.subscribe { r -> binding.content.addAMessageInput.replaceText(r) }
|
||||
|
||||
val recipientId: RecipientId = viewModel.destination.getRecipientSearchKey()?.recipientId ?: return
|
||||
val recipientId: RecipientId = requireArguments().getParcelableCompat(ARG_DESTINATION, RecipientId::class.java) ?: return
|
||||
|
||||
Recipient.live(recipientId).observe(viewLifecycleOwner) { recipient ->
|
||||
this.recipient = recipient
|
||||
@@ -322,12 +331,20 @@ class AddMessageDialogFragment : KeyboardEntryDialogFragment(R.layout.v2_media_a
|
||||
|
||||
private const val ARG_INITIAL_TEXT = "arg.initial.text"
|
||||
private const val ARG_INITIAL_EMOJI_TOGGLE = "arg.initial.emojiToggle"
|
||||
private const val ARG_VIEW_ONCE_AVAILABLE = "arg.viewOnceAvailable"
|
||||
private const val ARG_DESTINATION = "arg.destination"
|
||||
|
||||
fun show(fragmentManager: FragmentManager, initialText: CharSequence?, startWithEmojiKeyboard: Boolean) {
|
||||
const val REQUEST_KEY = "AddMessageViewModel__RequestKey"
|
||||
const val RESULT_INCREMENT_VIEW_ONCE_STATE = "AddMessageViewModel_IncrementViewOnceState"
|
||||
const val RESULT_MESSAGE = "AddMessageViewModel__Message"
|
||||
|
||||
fun show(fragmentManager: FragmentManager, initialText: CharSequence?, startWithEmojiKeyboard: Boolean, isViewOnceAvailable: Boolean, destination: RecipientId?) {
|
||||
AddMessageDialogFragment().apply {
|
||||
arguments = Bundle().apply {
|
||||
putCharSequence(ARG_INITIAL_TEXT, initialText)
|
||||
putBoolean(ARG_INITIAL_EMOJI_TOGGLE, startWithEmojiKeyboard)
|
||||
putBoolean(ARG_VIEW_ONCE_AVAILABLE, isViewOnceAvailable)
|
||||
putParcelable(ARG_DESTINATION, destination)
|
||||
}
|
||||
}.show(fragmentManager, TAG)
|
||||
}
|
||||
|
||||
+42
@@ -0,0 +1,42 @@
|
||||
/*
|
||||
* Copyright 2026 Signal Messenger, LLC
|
||||
* SPDX-License-Identifier: AGPL-3.0-only
|
||||
*/
|
||||
|
||||
package org.thoughtcrime.securesms.mediasend.v2.review
|
||||
|
||||
import androidx.lifecycle.ViewModel
|
||||
import androidx.lifecycle.viewModelScope
|
||||
import kotlinx.coroutines.Dispatchers
|
||||
import kotlinx.coroutines.channels.Channel
|
||||
import kotlinx.coroutines.flow.Flow
|
||||
import kotlinx.coroutines.flow.flowOn
|
||||
import kotlinx.coroutines.flow.map
|
||||
import kotlinx.coroutines.flow.receiveAsFlow
|
||||
import kotlinx.coroutines.launch
|
||||
import org.signal.core.util.BreakIteratorCompat
|
||||
|
||||
class AddMessageViewModel(initialMessage: CharSequence?) : ViewModel() {
|
||||
|
||||
var message: CharSequence? = initialMessage
|
||||
var isViewOnce: Boolean = false
|
||||
|
||||
private val addAMessageUpdatePublisher = Channel<CharSequence>(Channel.CONFLATED)
|
||||
|
||||
fun watchAddAMessageCount(): Flow<AddMessageCharacterCount> {
|
||||
return addAMessageUpdatePublisher
|
||||
.receiveAsFlow()
|
||||
.map {
|
||||
val iterator = BreakIteratorCompat.getInstance()
|
||||
iterator.setText(it)
|
||||
AddMessageCharacterCount(iterator.countBreaks())
|
||||
}
|
||||
.flowOn(Dispatchers.IO)
|
||||
}
|
||||
|
||||
fun updateAddAMessageCount(input: CharSequence?) {
|
||||
viewModelScope.launch {
|
||||
addAMessageUpdatePublisher.send(input ?: "")
|
||||
}
|
||||
}
|
||||
}
|
||||
+27
-2
@@ -125,6 +125,15 @@ class MediaReviewFragment : Fragment(R.layout.v2_media_review_fragment), Schedul
|
||||
|
||||
disposables.bindTo(viewLifecycleOwner)
|
||||
|
||||
parentFragmentManager.setFragmentResultListener(AddMessageDialogFragment.REQUEST_KEY, viewLifecycleOwner) { _, bundle ->
|
||||
if (bundle.getBoolean(AddMessageDialogFragment.RESULT_INCREMENT_VIEW_ONCE_STATE)) {
|
||||
sharedViewModel.setMessage(null)
|
||||
sharedViewModel.incrementViewOnceState()
|
||||
} else {
|
||||
sharedViewModel.setMessage(bundle.getCharSequence(AddMessageDialogFragment.RESULT_MESSAGE, null))
|
||||
}
|
||||
}
|
||||
|
||||
callback = requireListener()
|
||||
|
||||
drawToolButton = view.findViewById(R.id.draw_tool)
|
||||
@@ -300,11 +309,27 @@ class MediaReviewFragment : Fragment(R.layout.v2_media_review_fragment), Schedul
|
||||
}
|
||||
|
||||
emojiButton.setOnClickListener {
|
||||
AddMessageDialogFragment.show(parentFragmentManager, sharedViewModel.state.value?.message, true)
|
||||
sharedViewModel.state.value?.let { state ->
|
||||
AddMessageDialogFragment.show(
|
||||
parentFragmentManager,
|
||||
state.message,
|
||||
true,
|
||||
state.selectedMedia.size == 1 && !state.isStory && !MediaUtil.isDocumentType(state.focusedMedia?.contentType),
|
||||
sharedViewModel.destination.getRecipientSearchKey()?.recipientId
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
addMessageButton.setOnClickListener {
|
||||
AddMessageDialogFragment.show(parentFragmentManager, sharedViewModel.state.value?.message, false)
|
||||
sharedViewModel.state.value?.let { state ->
|
||||
AddMessageDialogFragment.show(
|
||||
parentFragmentManager,
|
||||
state.message,
|
||||
false,
|
||||
state.selectedMedia.size == 1 && !state.isStory && !MediaUtil.isDocumentType(state.focusedMedia?.contentType),
|
||||
sharedViewModel.destination.getRecipientSearchKey()?.recipientId
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
if (sharedViewModel.isReply) {
|
||||
|
||||
Reference in New Issue
Block a user