Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
8 changes: 2 additions & 6 deletions app/src/main/java/com/nextcloud/talk/chat/ChatActivity.kt
Original file line number Diff line number Diff line change
Expand Up @@ -56,6 +56,7 @@ import androidx.activity.result.ActivityResultLauncher
import androidx.activity.result.PickVisualMediaRequest
import androidx.activity.result.contract.ActivityResultContracts
import androidx.activity.result.contract.ActivityResultContracts.PickVisualMedia
import androidx.activity.viewModels
import androidx.appcompat.app.AlertDialog
import androidx.appcompat.view.ContextThemeWrapper
import androidx.cardview.widget.CardView
Expand Down Expand Up @@ -292,7 +293,7 @@ class ChatActivity :

lateinit var conversationInfoViewModel: ConversationInfoViewModel
lateinit var contextChatViewModel: ContextChatViewModel
lateinit var messageInputViewModel: MessageInputViewModel
val messageInputViewModel: MessageInputViewModel by viewModels()

private var chatMenu: Menu? = null

Expand Down Expand Up @@ -543,11 +544,6 @@ class ChatActivity :
}

messageInputFragment = getMessageInputFragment()
messageInputViewModel =
ViewModelProvider(this@ChatActivity, viewModelFactory)[
MessageInputViewModel::class
.java
]
messageInputViewModel.setData(chatViewModel.getChatRepository())

initObservers()
Expand Down
28 changes: 15 additions & 13 deletions app/src/main/java/com/nextcloud/talk/chat/MessageInputFragment.kt
Original file line number Diff line number Diff line change
Expand Up @@ -43,6 +43,7 @@ import androidx.core.view.isVisible
import androidx.core.widget.doAfterTextChanged
import androidx.emoji2.widget.EmojiTextView
import androidx.fragment.app.Fragment
import androidx.fragment.app.activityViewModels
import androidx.lifecycle.Lifecycle
import androidx.lifecycle.LifecycleOwner
import androidx.lifecycle.LiveData
Expand Down Expand Up @@ -118,6 +119,7 @@ class MessageInputFragment : Fragment() {
@Inject
lateinit var messageUtils: MessageUtils

private val messageInputViewModel: MessageInputViewModel by activityViewModels()
lateinit var binding: FragmentMessageInputBinding
private lateinit var conversationInternalId: String
private var typedWhileTypingTimerIsRunning: Boolean = false
Expand Down Expand Up @@ -206,7 +208,7 @@ class MessageInputFragment : Fragment() {
}
}

chatActivity.messageInputViewModel.getReplyChatMessage.observe(viewLifecycleOwner) { message ->
messageInputViewModel.getReplyChatMessage.observe(viewLifecycleOwner) { message ->
message?.let {
chatActivity.chatViewModel.messageDraft.quotedMessageText = message.text
chatActivity.chatViewModel.messageDraft.quotedDisplayName = message.actorDisplayName
Expand All @@ -222,13 +224,13 @@ class MessageInputFragment : Fragment() {

viewLifecycleOwner.lifecycleScope.launch {
repeatOnLifecycle(Lifecycle.State.CREATED) {
chatActivity.messageInputViewModel.getEditChatMessage.collect { message ->
messageInputViewModel.getEditChatMessage.collect { message ->
message?.let { setEditUI(it as ChatMessage) } ?: clearEditUI()
}
}
}

chatActivity.messageInputViewModel.createThreadViewState.observe(viewLifecycleOwner) { state ->
messageInputViewModel.createThreadViewState.observe(viewLifecycleOwner) { state ->
when (state) {
is MessageInputViewModel.CreateThreadStartState ->
binding.fragmentCreateThreadView.createThreadView.visibility = View.GONE
Expand Down Expand Up @@ -261,7 +263,7 @@ class MessageInputFragment : Fragment() {
val connectionGained = (!wasOnline && isOnline)
Log.d(TAG, "isOnline: $isOnline\nwasOnline: $wasOnline\nconnectionGained: $connectionGained")
if (connectionGained) {
chatActivity.messageInputViewModel.sendUnsentMessages(
messageInputViewModel.sendUnsentMessages(
chatActivity.conversationUser!!.getCredentials(),
ApiUtils.getUrlForChat(
chatActivity.chatApiVersion,
Expand All @@ -274,7 +276,7 @@ class MessageInputFragment : Fragment() {
}.collect()
}

chatActivity.messageInputViewModel.callStartedFlow.observe(viewLifecycleOwner) {
messageInputViewModel.callStartedFlow.observe(viewLifecycleOwner) {
val (message, show) = it
if (show) {
binding.fragmentCallStarted.callAuthorChip.text = message.actorDisplayName
Expand Down Expand Up @@ -364,7 +366,7 @@ class MessageInputFragment : Fragment() {
binding.fragmentMessageInputView.messageInput.setSelection(draft.messageCursor)

if (draft.threadTitle?.isNotEmpty() == true) {
chatActivity.messageInputViewModel.startThreadCreation()
messageInputViewModel.startThreadCreation()
}

if (draft.messageText != "") {
Expand Down Expand Up @@ -479,7 +481,7 @@ class MessageInputFragment : Fragment() {
replaceMentionChipSpans(editable)
val inputEditText = editable.toString()

val message = chatActivity.messageInputViewModel.getEditChatMessage.value as ChatMessage
val message = messageInputViewModel.getEditChatMessage.value as ChatMessage
if (message.message!!.trim() != inputEditText.trim()) {
if (message.messageParameters != null) {
val editedMessage = messageUtils.processEditMessageParameters(
Expand Down Expand Up @@ -566,7 +568,7 @@ class MessageInputFragment : Fragment() {
val base = SystemClock.elapsedRealtime()
voiceRecordStartTime = System.currentTimeMillis()
binding.fragmentMessageInputView.audioRecordDuration.base = base
chatActivity.messageInputViewModel.setRecordingTime(base)
messageInputViewModel.setRecordingTime(base)
binding.fragmentMessageInputView.audioRecordDuration.start()
chatActivity.chatViewModel.startAudioRecording(requireContext(), chatActivity.currentConversation!!)
showRecordAudioUi(true)
Expand Down Expand Up @@ -938,7 +940,7 @@ class MessageInputFragment : Fragment() {
}

private fun sendMessage(message: String, sendWithoutNotification: Boolean) {
chatActivity.messageInputViewModel.sendChatMessage(
messageInputViewModel.sendChatMessage(
credentials = chatActivity.conversationUser!!.getCredentials(),
url = ApiUtils.getUrlForChat(
chatActivity.chatApiVersion,
Expand Down Expand Up @@ -1004,12 +1006,12 @@ class MessageInputFragment : Fragment() {
val apiVersion: Int = ApiUtils.getChatApiVersion(spreedCapabilities, intArrayOf(1))

if (message.isTemporary) {
chatActivity.messageInputViewModel.editTempChatMessage(
messageInputViewModel.editTempChatMessage(
message,
editedMessageText
)
} else {
chatActivity.messageInputViewModel.editChatMessage(
messageInputViewModel.editChatMessage(
chatActivity.credentials!!,
ApiUtils.getUrlForChatMessage(
apiVersion,
Expand Down Expand Up @@ -1044,7 +1046,7 @@ class MessageInputFragment : Fragment() {
binding.fragmentMessageInputView.inputEditText.setText("")
binding.fragmentEditView.editMessageView.visibility = View.GONE
binding.fragmentMessageInputView.attachmentButton.visibility = View.VISIBLE
chatActivity.messageInputViewModel.edit(null)
messageInputViewModel.edit(null)
handleButtonsVisibility()
}

Expand Down Expand Up @@ -1127,7 +1129,7 @@ class MessageInputFragment : Fragment() {

private fun cancelCreateThread() {
chatActivity.cancelCreateThread()
chatActivity.messageInputViewModel.stopThreadCreation()
messageInputViewModel.stopThreadCreation()
binding.fragmentCreateThreadView.createThreadView.visibility = View.GONE
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -16,13 +16,15 @@ import android.widget.SeekBar
import android.widget.SeekBar.OnSeekBarChangeListener
import androidx.core.content.ContextCompat
import androidx.fragment.app.Fragment
import androidx.fragment.app.activityViewModels
import androidx.lifecycle.lifecycleScope
import autodagger.AutoInjector
import com.nextcloud.android.common.ui.theme.utils.ColorRole
import com.nextcloud.talk.R
import com.nextcloud.talk.application.NextcloudTalkApplication
import com.nextcloud.talk.application.NextcloudTalkApplication.Companion.sharedApplication
import com.nextcloud.talk.chat.data.io.AudioFocusRequestManager
import com.nextcloud.talk.chat.viewmodels.MessageInputViewModel
import com.nextcloud.talk.databinding.FragmentMessageInputVoiceRecordingBinding
import com.nextcloud.talk.ui.theme.ViewThemeUtils
import kotlinx.coroutines.flow.collect
Expand All @@ -43,6 +45,8 @@ class MessageInputVoiceRecordingFragment : Fragment() {
@Inject
lateinit var viewThemeUtils: ViewThemeUtils

private val messageInputViewModel: MessageInputViewModel by activityViewModels()

lateinit var binding: FragmentMessageInputVoiceRecordingBinding
private lateinit var chatActivity: ChatActivity
private var pause = false
Expand All @@ -58,48 +62,48 @@ class MessageInputVoiceRecordingFragment : Fragment() {
themeVoiceRecordingView()
initVoiceRecordingView()
initObservers()
this.lifecycle.addObserver(chatActivity.messageInputViewModel)
this.lifecycle.addObserver(messageInputViewModel)
return binding.root
}

override fun onDestroyView() {
super.onDestroyView()
chatActivity.messageInputViewModel.stopMediaPlayer() // if it wasn't stopped already
this.lifecycle.removeObserver(chatActivity.messageInputViewModel)
messageInputViewModel.stopMediaPlayer() // if it wasn't stopped already
this.lifecycle.removeObserver(messageInputViewModel)
}

private fun initObservers() {
chatActivity.messageInputViewModel.startMicInput(requireContext())
chatActivity.messageInputViewModel.micInputAudioObserver.observe(viewLifecycleOwner) {
messageInputViewModel.startMicInput(requireContext())
messageInputViewModel.micInputAudioObserver.observe(viewLifecycleOwner) {
binding.micInputCloud.setRotationSpeed(it.first, it.second)
}

lifecycleScope.launch {
chatActivity.messageInputViewModel.mediaPlayerSeekbarObserver.onEach { progress ->
messageInputViewModel.mediaPlayerSeekbarObserver.onEach { progress ->
if (progress >= SEEK_LIMIT) {
togglePausePlay()
binding.seekbar.progress = 0
} else if (!pause && chatActivity.messageInputViewModel.isVoicePreviewPlaying.value == true) {
} else if (!pause && messageInputViewModel.isVoicePreviewPlaying.value == true) {
binding.seekbar.progress = progress
}
}.collect()
}

chatActivity.messageInputViewModel.getAudioFocusChange.observe(viewLifecycleOwner) { state ->
messageInputViewModel.getAudioFocusChange.observe(viewLifecycleOwner) { state ->
when (state) {
AudioFocusRequestManager.ManagerState.AUDIO_FOCUS_CHANGE_LOSS -> {
if (chatActivity.messageInputViewModel.isVoicePreviewPlaying.value == true) {
chatActivity.messageInputViewModel.stopMediaPlayer()
if (messageInputViewModel.isVoicePreviewPlaying.value == true) {
messageInputViewModel.stopMediaPlayer()
}
}
AudioFocusRequestManager.ManagerState.AUDIO_FOCUS_CHANGE_LOSS_TRANSIENT -> {
if (chatActivity.messageInputViewModel.isVoicePreviewPlaying.value == true) {
chatActivity.messageInputViewModel.pauseMediaPlayer()
if (messageInputViewModel.isVoicePreviewPlaying.value == true) {
messageInputViewModel.pauseMediaPlayer()
}
}
AudioFocusRequestManager.ManagerState.BROADCAST_RECEIVED -> {
if (chatActivity.messageInputViewModel.isVoicePreviewPlaying.value == true) {
chatActivity.messageInputViewModel.pauseMediaPlayer()
if (messageInputViewModel.isVoicePreviewPlaying.value == true) {
messageInputViewModel.pauseMediaPlayer()
}
}
}
Expand Down Expand Up @@ -129,13 +133,13 @@ class MessageInputVoiceRecordingFragment : Fragment() {
togglePausePlay()
}

binding.audioRecordDuration.base = chatActivity.messageInputViewModel.getRecordingTime.value ?: 0L
binding.audioRecordDuration.base = messageInputViewModel.getRecordingTime.value ?: 0L
binding.audioRecordDuration.start()

binding.seekbar.setOnSeekBarChangeListener(object : OnSeekBarChangeListener {
override fun onProgressChanged(seekbar: SeekBar, progress: Int, fromUser: Boolean) {
if (fromUser) {
chatActivity.messageInputViewModel.seekMediaPlayerTo(progress)
messageInputViewModel.seekMediaPlayerTo(progress)
}
}

Expand All @@ -151,23 +155,23 @@ class MessageInputVoiceRecordingFragment : Fragment() {

private fun clear() {
chatActivity.chatViewModel.setVoiceRecordingLocked(false)
chatActivity.messageInputViewModel.stopMicInput()
messageInputViewModel.stopMicInput()
chatActivity.chatViewModel.stopAudioRecording()
chatActivity.messageInputViewModel.stopMediaPlayer()
messageInputViewModel.stopMediaPlayer()
binding.audioRecordDuration.stop()
binding.audioRecordDuration.clearAnimation()
}

private fun togglePreviewVisibility() {
val visibility = binding.voicePreviewContainer.visibility
binding.voicePreviewContainer.visibility = if (visibility == View.VISIBLE) {
chatActivity.messageInputViewModel.stopMediaPlayer()
messageInputViewModel.stopMediaPlayer()
binding.playPauseBtn.icon = ContextCompat.getDrawable(
requireContext(),
R.drawable.ic_baseline_play_arrow_voice_message_24
)
pause = true
chatActivity.messageInputViewModel.startMicInput(requireContext())
messageInputViewModel.startMicInput(requireContext())
chatActivity.chatViewModel.startAudioRecording(requireContext(), chatActivity.currentConversation!!)
binding.audioRecordDuration.visibility = View.VISIBLE
binding.audioRecordDuration.base = SystemClock.elapsedRealtime()
Expand All @@ -176,7 +180,7 @@ class MessageInputVoiceRecordingFragment : Fragment() {
} else {
pause = false
binding.seekbar.progress = 0
chatActivity.messageInputViewModel.stopMicInput()
messageInputViewModel.stopMicInput()
chatActivity.chatViewModel.stopAudioRecording()
binding.audioRecordDuration.visibility = View.GONE
binding.audioRecordDuration.stop()
Expand All @@ -186,18 +190,18 @@ class MessageInputVoiceRecordingFragment : Fragment() {

private fun togglePausePlay() {
val path = chatActivity.chatViewModel.getCurrentVoiceRecordFile()
if (chatActivity.messageInputViewModel.isVoicePreviewPlaying.value == true) {
if (messageInputViewModel.isVoicePreviewPlaying.value == true) {
binding.playPauseBtn.icon = ContextCompat.getDrawable(
requireContext(),
R.drawable.ic_baseline_play_arrow_voice_message_24
)
chatActivity.messageInputViewModel.stopMediaPlayer()
messageInputViewModel.stopMediaPlayer()
} else {
binding.playPauseBtn.icon = ContextCompat.getDrawable(
requireContext(),
R.drawable.ic_baseline_pause_voice_message_24
)
chatActivity.messageInputViewModel.startMediaPlayer(path)
messageInputViewModel.startMediaPlayer(path)
}
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,8 @@ import androidx.lifecycle.LiveData
import androidx.lifecycle.MutableLiveData
import androidx.lifecycle.ViewModel
import androidx.lifecycle.viewModelScope
import autodagger.AutoInjector
import com.nextcloud.talk.application.NextcloudTalkApplication
import com.nextcloud.talk.chat.data.ChatMessageRepository
import com.nextcloud.talk.chat.data.io.AudioFocusRequestManager
import com.nextcloud.talk.chat.data.io.AudioRecorderManager
Expand All @@ -31,11 +33,9 @@ import kotlinx.coroutines.launch
import javax.inject.Inject

@Suppress("Detekt.TooManyFunctions")
class MessageInputViewModel @Inject constructor(
private val audioRecorderManager: AudioRecorderManager,
private val mediaPlayerManager: MediaPlayerManager,
private val audioFocusRequestManager: AudioFocusRequestManager
) : ViewModel(),
@AutoInjector(NextcloudTalkApplication::class)
class MessageInputViewModel :
ViewModel(),
DefaultLifecycleObserver {

enum class LifeCycleFlag {
Expand All @@ -44,6 +44,19 @@ class MessageInputViewModel @Inject constructor(
STOPPED
}

init {
NextcloudTalkApplication.sharedApplication?.componentApplication?.inject(this)
}

@Inject
lateinit var audioRecorderManager: AudioRecorderManager

@Inject
lateinit var mediaPlayerManager: MediaPlayerManager

@Inject
lateinit var audioFocusRequestManager: AudioFocusRequestManager

lateinit var chatRepository: ChatMessageRepository
lateinit var currentLifeCycleFlag: LifeCycleFlag
val disposableSet = mutableSetOf<Disposable>()
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,6 @@ import androidx.lifecycle.ViewModelProvider
import com.nextcloud.talk.account.viewmodels.BrowserLoginActivityViewModel
import com.nextcloud.talk.activities.CallViewModel
import com.nextcloud.talk.chat.viewmodels.ChatViewModel
import com.nextcloud.talk.chat.viewmodels.MessageInputViewModel
import com.nextcloud.talk.chooseaccount.StatusViewModel
import com.nextcloud.talk.contacts.ContactsViewModel
import com.nextcloud.talk.contextchat.ContextChatViewModel
Expand Down Expand Up @@ -125,11 +124,6 @@ abstract class ViewModelModule {
@ViewModelKey(ChatViewModel::class)
abstract fun chatViewModel(viewModel: ChatViewModel): ViewModel

@Binds
@IntoMap
@ViewModelKey(MessageInputViewModel::class)
abstract fun messageInputViewModel(viewModel: MessageInputViewModel): ViewModel

@Binds
@IntoMap
@ViewModelKey(ConversationInfoViewModel::class)
Expand Down
Loading