Skip to content

Commit 83d1cb4

Browse files
committed
WIP - refactoring the MessageInputFragment.kt to use kotlins by viewModel for guaranteed instantiation
Signed-off-by: rapterjet2004 <juliuslinus1@gmail.com>
1 parent eb54580 commit 83d1cb4

4 files changed

Lines changed: 56 additions & 49 deletions

File tree

app/src/main/java/com/nextcloud/talk/chat/ChatActivity.kt

Lines changed: 2 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -57,6 +57,7 @@ import androidx.activity.result.ActivityResultLauncher
5757
import androidx.activity.result.PickVisualMediaRequest
5858
import androidx.activity.result.contract.ActivityResultContracts
5959
import androidx.activity.result.contract.ActivityResultContracts.PickVisualMedia
60+
import androidx.activity.viewModels
6061
import androidx.appcompat.app.AlertDialog
6162
import androidx.appcompat.view.ContextThemeWrapper
6263
import androidx.cardview.widget.CardView
@@ -321,7 +322,7 @@ class ChatActivity :
321322

322323
lateinit var conversationInfoViewModel: ConversationInfoViewModel
323324
lateinit var contextChatViewModel: ContextChatViewModel
324-
lateinit var messageInputViewModel: MessageInputViewModel
325+
val messageInputViewModel: MessageInputViewModel by viewModels()
325326

326327
private var chatMenu: Menu? = null
327328

@@ -572,11 +573,6 @@ class ChatActivity :
572573
}
573574

574575
messageInputFragment = getMessageInputFragment()
575-
messageInputViewModel =
576-
ViewModelProvider(this@ChatActivity, viewModelFactory)[
577-
MessageInputViewModel::class
578-
.java
579-
]
580576
messageInputViewModel.setData(chatViewModel.getChatRepository())
581577

582578
initObservers()

app/src/main/java/com/nextcloud/talk/chat/MessageInputFragment.kt

Lines changed: 16 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -43,6 +43,7 @@ import androidx.core.view.isVisible
4343
import androidx.core.widget.doAfterTextChanged
4444
import androidx.emoji2.widget.EmojiTextView
4545
import androidx.fragment.app.Fragment
46+
import androidx.fragment.app.activityViewModels
4647
import androidx.lifecycle.Lifecycle
4748
import androidx.lifecycle.LifecycleOwner
4849
import androidx.lifecycle.LiveData
@@ -117,6 +118,8 @@ class MessageInputFragment : Fragment() {
117118

118119
@Inject
119120
lateinit var messageUtils: MessageUtils
121+
122+
private val messageInputViewModel: MessageInputViewModel by activityViewModels()
120123

121124
lateinit var binding: FragmentMessageInputBinding
122125
private lateinit var conversationInternalId: String
@@ -206,7 +209,7 @@ class MessageInputFragment : Fragment() {
206209
}
207210
}
208211

209-
chatActivity.messageInputViewModel.getReplyChatMessage.observe(viewLifecycleOwner) { message ->
212+
messageInputViewModel.getReplyChatMessage.observe(viewLifecycleOwner) { message ->
210213
message?.let {
211214
chatActivity.chatViewModel.messageDraft.quotedMessageText = message.text
212215
chatActivity.chatViewModel.messageDraft.quotedDisplayName = message.actorDisplayName
@@ -222,13 +225,13 @@ class MessageInputFragment : Fragment() {
222225

223226
viewLifecycleOwner.lifecycleScope.launch {
224227
repeatOnLifecycle(Lifecycle.State.CREATED) {
225-
chatActivity.messageInputViewModel.getEditChatMessage.collect { message ->
228+
messageInputViewModel.getEditChatMessage.collect { message ->
226229
message?.let { setEditUI(it as ChatMessage) } ?: clearEditUI()
227230
}
228231
}
229232
}
230233

231-
chatActivity.messageInputViewModel.createThreadViewState.observe(viewLifecycleOwner) { state ->
234+
messageInputViewModel.createThreadViewState.observe(viewLifecycleOwner) { state ->
232235
when (state) {
233236
is MessageInputViewModel.CreateThreadStartState ->
234237
binding.fragmentCreateThreadView.createThreadView.visibility = View.GONE
@@ -261,7 +264,7 @@ class MessageInputFragment : Fragment() {
261264
val connectionGained = (!wasOnline && isOnline)
262265
Log.d(TAG, "isOnline: $isOnline\nwasOnline: $wasOnline\nconnectionGained: $connectionGained")
263266
if (connectionGained) {
264-
chatActivity.messageInputViewModel.sendUnsentMessages(
267+
messageInputViewModel.sendUnsentMessages(
265268
chatActivity.conversationUser!!.getCredentials(),
266269
ApiUtils.getUrlForChat(
267270
chatActivity.chatApiVersion,
@@ -274,7 +277,7 @@ class MessageInputFragment : Fragment() {
274277
}.collect()
275278
}
276279

277-
chatActivity.messageInputViewModel.callStartedFlow.observe(viewLifecycleOwner) {
280+
messageInputViewModel.callStartedFlow.observe(viewLifecycleOwner) {
278281
val (message, show) = it
279282
if (show) {
280283
binding.fragmentCallStarted.callAuthorChip.text = message.actorDisplayName
@@ -364,7 +367,7 @@ class MessageInputFragment : Fragment() {
364367
binding.fragmentMessageInputView.messageInput.setSelection(draft.messageCursor)
365368

366369
if (draft.threadTitle?.isNotEmpty() == true) {
367-
chatActivity.messageInputViewModel.startThreadCreation()
370+
messageInputViewModel.startThreadCreation()
368371
}
369372

370373
if (draft.messageText != "") {
@@ -479,7 +482,7 @@ class MessageInputFragment : Fragment() {
479482
replaceMentionChipSpans(editable)
480483
val inputEditText = editable.toString()
481484

482-
val message = chatActivity.messageInputViewModel.getEditChatMessage.value as ChatMessage
485+
val message = messageInputViewModel.getEditChatMessage.value as ChatMessage
483486
if (message.message!!.trim() != inputEditText.trim()) {
484487
if (message.messageParameters != null) {
485488
val editedMessage = messageUtils.processEditMessageParameters(
@@ -566,7 +569,7 @@ class MessageInputFragment : Fragment() {
566569
val base = SystemClock.elapsedRealtime()
567570
voiceRecordStartTime = System.currentTimeMillis()
568571
binding.fragmentMessageInputView.audioRecordDuration.base = base
569-
chatActivity.messageInputViewModel.setRecordingTime(base)
572+
messageInputViewModel.setRecordingTime(base)
570573
binding.fragmentMessageInputView.audioRecordDuration.start()
571574
chatActivity.chatViewModel.startAudioRecording(requireContext(), chatActivity.currentConversation!!)
572575
showRecordAudioUi(true)
@@ -938,7 +941,7 @@ class MessageInputFragment : Fragment() {
938941
}
939942

940943
private fun sendMessage(message: String, sendWithoutNotification: Boolean) {
941-
chatActivity.messageInputViewModel.sendChatMessage(
944+
messageInputViewModel.sendChatMessage(
942945
credentials = chatActivity.conversationUser!!.getCredentials(),
943946
url = ApiUtils.getUrlForChat(
944947
chatActivity.chatApiVersion,
@@ -1004,12 +1007,12 @@ class MessageInputFragment : Fragment() {
10041007
val apiVersion: Int = ApiUtils.getChatApiVersion(spreedCapabilities, intArrayOf(1))
10051008

10061009
if (message.isTemporary) {
1007-
chatActivity.messageInputViewModel.editTempChatMessage(
1010+
messageInputViewModel.editTempChatMessage(
10081011
message,
10091012
editedMessageText
10101013
)
10111014
} else {
1012-
chatActivity.messageInputViewModel.editChatMessage(
1015+
messageInputViewModel.editChatMessage(
10131016
chatActivity.credentials!!,
10141017
ApiUtils.getUrlForChatMessage(
10151018
apiVersion,
@@ -1044,7 +1047,7 @@ class MessageInputFragment : Fragment() {
10441047
binding.fragmentMessageInputView.inputEditText.setText("")
10451048
binding.fragmentEditView.editMessageView.visibility = View.GONE
10461049
binding.fragmentMessageInputView.attachmentButton.visibility = View.VISIBLE
1047-
chatActivity.messageInputViewModel.edit(null)
1050+
messageInputViewModel.edit(null)
10481051
handleButtonsVisibility()
10491052
}
10501053

@@ -1127,7 +1130,7 @@ class MessageInputFragment : Fragment() {
11271130

11281131
private fun cancelCreateThread() {
11291132
chatActivity.cancelCreateThread()
1130-
chatActivity.messageInputViewModel.stopThreadCreation()
1133+
messageInputViewModel.stopThreadCreation()
11311134
binding.fragmentCreateThreadView.createThreadView.visibility = View.GONE
11321135
}
11331136

app/src/main/java/com/nextcloud/talk/chat/MessageInputVoiceRecordingFragment.kt

Lines changed: 28 additions & 24 deletions
Original file line numberDiff line numberDiff line change
@@ -16,13 +16,15 @@ import android.widget.SeekBar
1616
import android.widget.SeekBar.OnSeekBarChangeListener
1717
import androidx.core.content.ContextCompat
1818
import androidx.fragment.app.Fragment
19+
import androidx.fragment.app.activityViewModels
1920
import androidx.lifecycle.lifecycleScope
2021
import autodagger.AutoInjector
2122
import com.nextcloud.android.common.ui.theme.utils.ColorRole
2223
import com.nextcloud.talk.R
2324
import com.nextcloud.talk.application.NextcloudTalkApplication
2425
import com.nextcloud.talk.application.NextcloudTalkApplication.Companion.sharedApplication
2526
import com.nextcloud.talk.chat.data.io.AudioFocusRequestManager
27+
import com.nextcloud.talk.chat.viewmodels.MessageInputViewModel
2628
import com.nextcloud.talk.databinding.FragmentMessageInputVoiceRecordingBinding
2729
import com.nextcloud.talk.ui.theme.ViewThemeUtils
2830
import kotlinx.coroutines.flow.collect
@@ -43,6 +45,8 @@ class MessageInputVoiceRecordingFragment : Fragment() {
4345
@Inject
4446
lateinit var viewThemeUtils: ViewThemeUtils
4547

48+
private val messageInputViewModel: MessageInputViewModel by activityViewModels()
49+
4650
lateinit var binding: FragmentMessageInputVoiceRecordingBinding
4751
private lateinit var chatActivity: ChatActivity
4852
private var pause = false
@@ -58,48 +62,48 @@ class MessageInputVoiceRecordingFragment : Fragment() {
5862
themeVoiceRecordingView()
5963
initVoiceRecordingView()
6064
initObservers()
61-
this.lifecycle.addObserver(chatActivity.messageInputViewModel)
65+
this.lifecycle.addObserver(messageInputViewModel)
6266
return binding.root
6367
}
6468

6569
override fun onDestroyView() {
6670
super.onDestroyView()
67-
chatActivity.messageInputViewModel.stopMediaPlayer() // if it wasn't stopped already
68-
this.lifecycle.removeObserver(chatActivity.messageInputViewModel)
71+
messageInputViewModel.stopMediaPlayer() // if it wasn't stopped already
72+
this.lifecycle.removeObserver(messageInputViewModel)
6973
}
7074

7175
private fun initObservers() {
72-
chatActivity.messageInputViewModel.startMicInput(requireContext())
73-
chatActivity.messageInputViewModel.micInputAudioObserver.observe(viewLifecycleOwner) {
76+
messageInputViewModel.startMicInput(requireContext())
77+
messageInputViewModel.micInputAudioObserver.observe(viewLifecycleOwner) {
7478
binding.micInputCloud.setRotationSpeed(it.first, it.second)
7579
}
7680

7781
lifecycleScope.launch {
78-
chatActivity.messageInputViewModel.mediaPlayerSeekbarObserver.onEach { progress ->
82+
messageInputViewModel.mediaPlayerSeekbarObserver.onEach { progress ->
7983
if (progress >= SEEK_LIMIT) {
8084
togglePausePlay()
8185
binding.seekbar.progress = 0
82-
} else if (!pause && chatActivity.messageInputViewModel.isVoicePreviewPlaying.value == true) {
86+
} else if (!pause && messageInputViewModel.isVoicePreviewPlaying.value == true) {
8387
binding.seekbar.progress = progress
8488
}
8589
}.collect()
8690
}
8791

88-
chatActivity.messageInputViewModel.getAudioFocusChange.observe(viewLifecycleOwner) { state ->
92+
messageInputViewModel.getAudioFocusChange.observe(viewLifecycleOwner) { state ->
8993
when (state) {
9094
AudioFocusRequestManager.ManagerState.AUDIO_FOCUS_CHANGE_LOSS -> {
91-
if (chatActivity.messageInputViewModel.isVoicePreviewPlaying.value == true) {
92-
chatActivity.messageInputViewModel.stopMediaPlayer()
95+
if (messageInputViewModel.isVoicePreviewPlaying.value == true) {
96+
messageInputViewModel.stopMediaPlayer()
9397
}
9498
}
9599
AudioFocusRequestManager.ManagerState.AUDIO_FOCUS_CHANGE_LOSS_TRANSIENT -> {
96-
if (chatActivity.messageInputViewModel.isVoicePreviewPlaying.value == true) {
97-
chatActivity.messageInputViewModel.pauseMediaPlayer()
100+
if (messageInputViewModel.isVoicePreviewPlaying.value == true) {
101+
messageInputViewModel.pauseMediaPlayer()
98102
}
99103
}
100104
AudioFocusRequestManager.ManagerState.BROADCAST_RECEIVED -> {
101-
if (chatActivity.messageInputViewModel.isVoicePreviewPlaying.value == true) {
102-
chatActivity.messageInputViewModel.pauseMediaPlayer()
105+
if (messageInputViewModel.isVoicePreviewPlaying.value == true) {
106+
messageInputViewModel.pauseMediaPlayer()
103107
}
104108
}
105109
}
@@ -129,13 +133,13 @@ class MessageInputVoiceRecordingFragment : Fragment() {
129133
togglePausePlay()
130134
}
131135

132-
binding.audioRecordDuration.base = chatActivity.messageInputViewModel.getRecordingTime.value ?: 0L
136+
binding.audioRecordDuration.base = messageInputViewModel.getRecordingTime.value ?: 0L
133137
binding.audioRecordDuration.start()
134138

135139
binding.seekbar.setOnSeekBarChangeListener(object : OnSeekBarChangeListener {
136140
override fun onProgressChanged(seekbar: SeekBar, progress: Int, fromUser: Boolean) {
137141
if (fromUser) {
138-
chatActivity.messageInputViewModel.seekMediaPlayerTo(progress)
142+
messageInputViewModel.seekMediaPlayerTo(progress)
139143
}
140144
}
141145

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

152156
private fun clear() {
153157
chatActivity.chatViewModel.setVoiceRecordingLocked(false)
154-
chatActivity.messageInputViewModel.stopMicInput()
158+
messageInputViewModel.stopMicInput()
155159
chatActivity.chatViewModel.stopAudioRecording()
156-
chatActivity.messageInputViewModel.stopMediaPlayer()
160+
messageInputViewModel.stopMediaPlayer()
157161
binding.audioRecordDuration.stop()
158162
binding.audioRecordDuration.clearAnimation()
159163
}
160164

161165
private fun togglePreviewVisibility() {
162166
val visibility = binding.voicePreviewContainer.visibility
163167
binding.voicePreviewContainer.visibility = if (visibility == View.VISIBLE) {
164-
chatActivity.messageInputViewModel.stopMediaPlayer()
168+
messageInputViewModel.stopMediaPlayer()
165169
binding.playPauseBtn.icon = ContextCompat.getDrawable(
166170
requireContext(),
167171
R.drawable.ic_baseline_play_arrow_voice_message_24
168172
)
169173
pause = true
170-
chatActivity.messageInputViewModel.startMicInput(requireContext())
174+
messageInputViewModel.startMicInput(requireContext())
171175
chatActivity.chatViewModel.startAudioRecording(requireContext(), chatActivity.currentConversation!!)
172176
binding.audioRecordDuration.visibility = View.VISIBLE
173177
binding.audioRecordDuration.base = SystemClock.elapsedRealtime()
@@ -176,7 +180,7 @@ class MessageInputVoiceRecordingFragment : Fragment() {
176180
} else {
177181
pause = false
178182
binding.seekbar.progress = 0
179-
chatActivity.messageInputViewModel.stopMicInput()
183+
messageInputViewModel.stopMicInput()
180184
chatActivity.chatViewModel.stopAudioRecording()
181185
binding.audioRecordDuration.visibility = View.GONE
182186
binding.audioRecordDuration.stop()
@@ -186,18 +190,18 @@ class MessageInputVoiceRecordingFragment : Fragment() {
186190

187191
private fun togglePausePlay() {
188192
val path = chatActivity.chatViewModel.getCurrentVoiceRecordFile()
189-
if (chatActivity.messageInputViewModel.isVoicePreviewPlaying.value == true) {
193+
if (messageInputViewModel.isVoicePreviewPlaying.value == true) {
190194
binding.playPauseBtn.icon = ContextCompat.getDrawable(
191195
requireContext(),
192196
R.drawable.ic_baseline_play_arrow_voice_message_24
193197
)
194-
chatActivity.messageInputViewModel.stopMediaPlayer()
198+
messageInputViewModel.stopMediaPlayer()
195199
} else {
196200
binding.playPauseBtn.icon = ContextCompat.getDrawable(
197201
requireContext(),
198202
R.drawable.ic_baseline_pause_voice_message_24
199203
)
200-
chatActivity.messageInputViewModel.startMediaPlayer(path)
204+
messageInputViewModel.startMediaPlayer(path)
201205
}
202206
}
203207

app/src/main/java/com/nextcloud/talk/chat/viewmodels/MessageInputViewModel.kt

Lines changed: 10 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -31,19 +31,23 @@ import kotlinx.coroutines.launch
3131
import javax.inject.Inject
3232

3333
@Suppress("Detekt.TooManyFunctions")
34-
class MessageInputViewModel @Inject constructor(
35-
private val audioRecorderManager: AudioRecorderManager,
36-
private val mediaPlayerManager: MediaPlayerManager,
37-
private val audioFocusRequestManager: AudioFocusRequestManager
38-
) : ViewModel(),
39-
DefaultLifecycleObserver {
34+
class MessageInputViewModel @Inject constructor() : ViewModel(), DefaultLifecycleObserver {
4035

4136
enum class LifeCycleFlag {
4237
PAUSED,
4338
RESUMED,
4439
STOPPED
4540
}
4641

42+
@Inject
43+
lateinit var audioRecorderManager: AudioRecorderManager
44+
45+
@Inject
46+
lateinit var mediaPlayerManager: MediaPlayerManager
47+
48+
@Inject
49+
lateinit var audioFocusRequestManager: AudioFocusRequestManager // FIXME why wasn't this instantiated
50+
4751
lateinit var chatRepository: ChatMessageRepository
4852
lateinit var currentLifeCycleFlag: LifeCycleFlag
4953
val disposableSet = mutableSetOf<Disposable>()

0 commit comments

Comments
 (0)