rewriting translate feature to use MVVM

Signed-off-by: Julius Linus <julius.linus@nextcloud.com>
This commit is contained in:
rapterjet2004 2023-05-22 11:13:46 -05:00
parent 26134343d4
commit 00f86144d8
5 changed files with 88 additions and 73 deletions

View file

@ -47,6 +47,8 @@ import com.nextcloud.talk.repositories.unifiedsearch.UnifiedSearchRepository
import com.nextcloud.talk.repositories.unifiedsearch.UnifiedSearchRepositoryImpl import com.nextcloud.talk.repositories.unifiedsearch.UnifiedSearchRepositoryImpl
import com.nextcloud.talk.shareditems.repositories.SharedItemsRepository import com.nextcloud.talk.shareditems.repositories.SharedItemsRepository
import com.nextcloud.talk.shareditems.repositories.SharedItemsRepositoryImpl import com.nextcloud.talk.shareditems.repositories.SharedItemsRepositoryImpl
import com.nextcloud.talk.translate.repositories.TranslateRepository
import com.nextcloud.talk.translate.repositories.TranslateRepositoryImpl
import com.nextcloud.talk.utils.DateUtils import com.nextcloud.talk.utils.DateUtils
import com.nextcloud.talk.utils.database.user.CurrentUserProviderNew import com.nextcloud.talk.utils.database.user.CurrentUserProviderNew
import dagger.Module import dagger.Module
@ -107,4 +109,10 @@ class RepositoryModule {
RequestAssistanceRepository { RequestAssistanceRepository {
return RequestAssistanceRepositoryImpl(ncApi, userProvider) return RequestAssistanceRepositoryImpl(ncApi, userProvider)
} }
@Provides
fun translateRepository(ncApi: NcApi):
TranslateRepository {
return TranslateRepositoryImpl(ncApi)
}
} }

View file

@ -31,6 +31,7 @@ import com.nextcloud.talk.polls.viewmodels.PollVoteViewModel
import com.nextcloud.talk.raisehand.viewmodel.RaiseHandViewModel import com.nextcloud.talk.raisehand.viewmodel.RaiseHandViewModel
import com.nextcloud.talk.remotefilebrowser.viewmodels.RemoteFileBrowserItemsViewModel import com.nextcloud.talk.remotefilebrowser.viewmodels.RemoteFileBrowserItemsViewModel
import com.nextcloud.talk.shareditems.viewmodels.SharedItemsViewModel import com.nextcloud.talk.shareditems.viewmodels.SharedItemsViewModel
import com.nextcloud.talk.translate.viewmodels.TranslateViewModel
import com.nextcloud.talk.viewmodels.CallRecordingViewModel import com.nextcloud.talk.viewmodels.CallRecordingViewModel
import dagger.Binds import dagger.Binds
import dagger.MapKey import dagger.MapKey
@ -101,4 +102,9 @@ abstract class ViewModelModule {
@IntoMap @IntoMap
@ViewModelKey(RaiseHandViewModel::class) @ViewModelKey(RaiseHandViewModel::class)
abstract fun raiseHandViewModel(viewModel: RaiseHandViewModel): ViewModel abstract fun raiseHandViewModel(viewModel: RaiseHandViewModel): ViewModel
@Binds
@IntoMap
@ViewModelKey(TranslateViewModel::class)
abstract fun translateViewModel(viewModel: TranslateViewModel): ViewModel
} }

View file

@ -2,8 +2,9 @@ package com.nextcloud.talk.translate.repositories
import com.nextcloud.talk.api.NcApi import com.nextcloud.talk.api.NcApi
import io.reactivex.Observable import io.reactivex.Observable
import javax.inject.Inject
class TranslateRepositoryImpl(private val ncApi: NcApi) : TranslateRepository { class TranslateRepositoryImpl @Inject constructor(private val ncApi: NcApi) : TranslateRepository {
override fun translateMessage( override fun translateMessage(
authorization: String, authorization: String,
@ -12,7 +13,7 @@ class TranslateRepositoryImpl(private val ncApi: NcApi) : TranslateRepository {
toLanguage: String, toLanguage: String,
fromLanguage: String? fromLanguage: String?
): Observable<String> { ): Observable<String> {
return ncApi.translateMessage(authorization, url, text, toLanguage, fromLanguage).map { it?.ocs?.data!!.text} return ncApi.translateMessage(authorization, url, text, toLanguage, fromLanguage).map { it.ocs?.data!!.text}
} }
} }

View file

@ -31,7 +31,6 @@ import android.text.method.ScrollingMovementMethod
import android.view.View import android.view.View
import android.widget.AdapterView import android.widget.AdapterView
import android.widget.ArrayAdapter import android.widget.ArrayAdapter
import androidx.lifecycle.Observer
import androidx.lifecycle.ViewModelProvider import androidx.lifecycle.ViewModelProvider
import autodagger.AutoInjector import autodagger.AutoInjector
import com.google.android.material.dialog.MaterialAlertDialogBuilder import com.google.android.material.dialog.MaterialAlertDialogBuilder
@ -56,9 +55,11 @@ class TranslateActivity : BaseActivity() {
@Inject @Inject
lateinit var viewModelFactory: ViewModelProvider.Factory lateinit var viewModelFactory: ViewModelProvider.Factory
private lateinit var viewModel: TranslateViewModel lateinit var viewModel: TranslateViewModel
private lateinit var binding: ActivityTranslateBinding lateinit var binding: ActivityTranslateBinding
private var toLanguages : Array<String>? = null
private var fromLanguages : Array<String>? = null
override fun onCreate(savedInstanceState: Bundle?) { override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState) super.onCreate(savedInstanceState)
@ -66,9 +67,23 @@ class TranslateActivity : BaseActivity() {
NextcloudTalkApplication.sharedApplication!!.componentApplication.inject(this) NextcloudTalkApplication.sharedApplication!!.componentApplication.inject(this)
binding = ActivityTranslateBinding.inflate(layoutInflater) binding = ActivityTranslateBinding.inflate(layoutInflater)
viewModel = ViewModelProvider(this, viewModelFactory)[TranslateViewModel::class.java] // fixme bug here viewModel = ViewModelProvider(this, viewModelFactory)[TranslateViewModel::class.java]
viewModel.viewState.observe(this) { state ->
when(state) {
is TranslateViewModel.StartState -> {
onStartState()
}
is TranslateViewModel.TranslatedState -> {
onTranslatedState(state.msg)
}
is TranslateViewModel.ErrorState -> {
onErrorState()
}
}
}
setupActionBar() setupActionBar()
setContentView(binding.root) setContentView(binding.root)
setupSystemColors() setupSystemColors()
@ -77,25 +92,9 @@ class TranslateActivity : BaseActivity() {
setupSpinners() setupSpinners()
setupCopyButton() setupCopyButton()
val translateViewModelObserver = Observer<TranslateViewModel.TranslateUiState> { state ->
enableSpinners(state.enableSpinners)
binding.progressBar.visibility = if(state.showProgressBar) View.VISIBLE else View.GONE
binding.translatedMessageContainer.visibility =
if(state.showTranslatedMessageContainer) View.VISIBLE else View.GONE
if(state.translatedMessageText != null)
binding.translatedMessageTextview.text = state.translatedMessageText
if(state.errorOccurred)
showDialog()
}
viewModel.viewState.observe(this, translateViewModelObserver)
if (savedInstanceState == null) { if (savedInstanceState == null) {
viewModel.translateMessage(Locale.getDefault().language, null) val text = intent.extras !!.getString(BundleKeys.KEY_TRANSLATE_MESSAGE)
viewModel.translateMessage(Locale.getDefault().language, null, text!!)
} else { } else {
binding.translatedMessageTextview.text = savedInstanceState.getString(BundleKeys.SAVED_TRANSLATED_MESSAGE) binding.translatedMessageTextview.text = savedInstanceState.getString(BundleKeys.SAVED_TRANSLATED_MESSAGE)
} }
@ -151,10 +150,8 @@ class TranslateActivity : BaseActivity() {
binding.originalMessageTextview.movementMethod = ScrollingMovementMethod() binding.originalMessageTextview.movementMethod = ScrollingMovementMethod()
binding.translatedMessageTextview.movementMethod = ScrollingMovementMethod() binding.translatedMessageTextview.movementMethod = ScrollingMovementMethod()
val bundle = intent.extras val text =intent.extras !!.getString(BundleKeys.KEY_TRANSLATE_MESSAGE)
val text = bundle?.getString(BundleKeys.KEY_TRANSLATE_MESSAGE)
binding.originalMessageTextview.text = text binding.originalMessageTextview.text = text
viewModel.viewState.value!!.originalMessageText = text
} }
private fun getLanguageOptions() { private fun getLanguageOptions() {
@ -173,8 +170,8 @@ class TranslateActivity : BaseActivity() {
fromLanguagesSet.add(current.getString(TO_LABEL)) fromLanguagesSet.add(current.getString(TO_LABEL))
} }
viewModel.viewState.value!!.toLanguages = toLanguagesSet.toTypedArray() toLanguages = toLanguagesSet.toTypedArray()
viewModel.viewState.value!!.fromLanguages = fromLanguagesSet.toTypedArray() fromLanguages = fromLanguagesSet.toTypedArray()
} }
private fun enableSpinners(value: Boolean) { private fun enableSpinners(value: Boolean) {
@ -205,8 +202,6 @@ class TranslateActivity : BaseActivity() {
) )
} }
private fun getISOFromLanguage(language: String): String { private fun getISOFromLanguage(language: String): String {
if (resources.getString(R.string.translation_device_settings) == language) { if (resources.getString(R.string.translation_device_settings) == language) {
return Locale.getDefault().language return Locale.getDefault().language
@ -233,42 +228,61 @@ class TranslateActivity : BaseActivity() {
viewThemeUtils.material.colorTextInputLayout(binding.fromLanguageInputLayout) viewThemeUtils.material.colorTextInputLayout(binding.fromLanguageInputLayout)
viewThemeUtils.material.colorTextInputLayout(binding.toLanguageInputLayout) viewThemeUtils.material.colorTextInputLayout(binding.toLanguageInputLayout)
fillSpinners() fillSpinners()
val text = intent.extras !!.getString(BundleKeys.KEY_TRANSLATE_MESSAGE)
binding.fromLanguage.onItemClickListener = AdapterView.OnItemClickListener { parent, _, position, _ -> binding.fromLanguage.onItemClickListener = AdapterView.OnItemClickListener { parent, _, position, _ ->
val fromLabel: String = getISOFromLanguage(parent.getItemAtPosition(position).toString()) val fromLabel: String = getISOFromLanguage(parent.getItemAtPosition(position).toString())
val toLabel: String = getISOFromLanguage(binding.toLanguage.text.toString()) val toLabel: String = getISOFromLanguage(binding.toLanguage.text.toString())
viewModel.translateMessage(toLabel, fromLabel) viewModel.translateMessage(toLabel, fromLabel, text!!)
} }
binding.toLanguage.onItemClickListener = AdapterView.OnItemClickListener { parent, _, position, _ -> binding.toLanguage.onItemClickListener = AdapterView.OnItemClickListener { parent, _, position, _ ->
val toLabel: String = getISOFromLanguage(parent.getItemAtPosition(position).toString()) val toLabel: String = getISOFromLanguage(parent.getItemAtPosition(position).toString())
val fromLabel: String = getISOFromLanguage(binding.fromLanguage.text.toString()) val fromLabel: String = getISOFromLanguage(binding.fromLanguage.text.toString())
viewModel.translateMessage(toLabel, fromLabel) viewModel.translateMessage(toLabel, fromLabel, text!!)
} }
} }
private fun fillSpinners() { private fun fillSpinners() {
val fromLanguages = viewModel.viewState.value!!.fromLanguages!!
val toLanguages = viewModel.viewState.value!!.toLanguages!!
binding.fromLanguage.setAdapter( binding.fromLanguage.setAdapter(
ArrayAdapter(this, android.R.layout.simple_spinner_dropdown_item, fromLanguages) ArrayAdapter(this, android.R.layout.simple_spinner_dropdown_item, fromLanguages!!)
) )
if (fromLanguages.isNotEmpty()) { if (fromLanguages!!.isNotEmpty()) {
binding.fromLanguage.setText(fromLanguages[0]) binding.fromLanguage.setText(fromLanguages!![0])
} }
binding.toLanguage.setAdapter( binding.toLanguage.setAdapter(
ArrayAdapter(this, android.R.layout.simple_spinner_dropdown_item, toLanguages) ArrayAdapter(this, android.R.layout.simple_spinner_dropdown_item, toLanguages!!)
) )
if (toLanguages.isNotEmpty()) { if (toLanguages!!.isNotEmpty()) {
binding.toLanguage.setText(toLanguages[0]) binding.toLanguage.setText(toLanguages!![0])
} }
} }
private fun setItems() { private fun setItems() {
binding.fromLanguage.setSimpleItems(viewModel.viewState.value!!.fromLanguages!!) binding.fromLanguage.setSimpleItems(fromLanguages!!)
binding.toLanguage.setSimpleItems(viewModel.viewState.value!!.toLanguages!!) binding.toLanguage.setSimpleItems(toLanguages!!)
}
private fun onStartState() {
enableSpinners(false)
binding.translatedMessageContainer.visibility = View.GONE
binding.progressBar.visibility = View.VISIBLE
binding.copyTranslatedMessage.visibility = View.GONE
}
private fun onTranslatedState(msg : String) {
binding.progressBar.visibility = View.GONE
binding.translatedMessageContainer.visibility = View.VISIBLE
binding.translatedMessageTextview.text = msg
binding.copyTranslatedMessage.visibility = View.VISIBLE
enableSpinners(true)
}
private fun onErrorState() {
binding.progressBar.visibility = View.GONE
enableSpinners(true)
showDialog()
} }
companion object { companion object {

View file

@ -14,33 +14,26 @@ import io.reactivex.disposables.Disposable
import io.reactivex.schedulers.Schedulers import io.reactivex.schedulers.Schedulers
import javax.inject.Inject import javax.inject.Inject
class TranslateViewModel @Inject constructor(private val repository: TranslateRepository) : ViewModel() { class TranslateViewModel @Inject constructor(private val repository: TranslateRepository,
private val userManager: UserManager) : ViewModel() {
@Inject sealed interface ViewState
lateinit var userManager: UserManager
data class TranslateUiState( object StartState : ViewState
var enableSpinners : Boolean = false, class TranslatedState(val msg: String) : ViewState
var showProgressBar : Boolean = false, object ErrorState : ViewState
var showTranslatedMessageContainer : Boolean = false,
var translatedMessageText : String? = null,
var originalMessageText : String? = null,
var errorOccurred : Boolean = false,
var toLanguages : Array<String>? = null,
var fromLanguages : Array<String>? = null
)
private val _viewState = MutableLiveData(TranslateUiState()) private val _viewState : MutableLiveData<ViewState> = MutableLiveData(StartState)
val viewState : LiveData<TranslateUiState> val viewState : LiveData<ViewState>
get() = _viewState get() = _viewState
fun translateMessage(toLanguage: String, fromLanguage: String?) { fun translateMessage(toLanguage: String, fromLanguage: String?, text: String) {
val currentUser: User = userManager.currentUser.blockingGet() val currentUser: User = userManager.currentUser.blockingGet()
val authorization: String = ApiUtils.getCredentials(currentUser.username, currentUser.token) val authorization: String = ApiUtils.getCredentials(currentUser.username, currentUser.token)
val url: String = ApiUtils.getUrlForTranslation(currentUser.baseUrl) val url: String = ApiUtils.getUrlForTranslation(currentUser.baseUrl)
val calculatedFromLanguage = if (fromLanguage == null || fromLanguage == "") { null } else { fromLanguage } val calculatedFromLanguage = if (fromLanguage == null || fromLanguage == "") { null } else { fromLanguage }
Log.i(TAG, "translateMessage Called")
repository.translateMessage(authorization, url,_viewState.value!!.originalMessageText!!,toLanguage, repository.translateMessage(authorization, url,text,toLanguage,
calculatedFromLanguage) calculatedFromLanguage)
.subscribeOn(Schedulers.io()) .subscribeOn(Schedulers.io())
?.observeOn(AndroidSchedulers.mainThread()) ?.observeOn(AndroidSchedulers.mainThread())
@ -49,23 +42,16 @@ class TranslateViewModel @Inject constructor(private val repository: TranslateRe
inner class TranslateObserver() : Observer<String> { inner class TranslateObserver() : Observer<String> {
override fun onSubscribe(d: Disposable) { override fun onSubscribe(d: Disposable) {
_viewState.value!!.enableSpinners = false _viewState.value = StartState
_viewState.value!!.showTranslatedMessageContainer = false
_viewState.value!!.showProgressBar = true
} }
override fun onNext(translatedMessage: String) { override fun onNext(translatedMessage: String) {
_viewState.value!!.showProgressBar = false _viewState.value = TranslatedState(translatedMessage)
_viewState.value!!.showTranslatedMessageContainer = true
_viewState.value!!.translatedMessageText = translatedMessage
_viewState.value!!.enableSpinners = true
} }
override fun onError(e: Throwable) { override fun onError(e: Throwable) {
_viewState.value!!.showProgressBar = false _viewState.value = ErrorState
_viewState.value!!.errorOccurred = true Log.e(TAG, "Error while translating message", e)
_viewState.value!!.enableSpinners = true
Log.w(TAG, "Error while translating message", e)
} }
override fun onComplete() { override fun onComplete() {