mirror of
https://github.com/nextcloud/talk-android.git
synced 2024-11-28 17:38:55 +03:00
Merge pull request #3038 from nextcloud/translate-message-mvvm-impl
rewriting translate feature to use MVVM
This commit is contained in:
commit
fd5fec937f
12 changed files with 212 additions and 100 deletions
|
@ -190,7 +190,7 @@
|
|||
android:theme="@style/AppTheme" />
|
||||
|
||||
<activity
|
||||
android:name=".translate.TranslateActivity"
|
||||
android:name=".translate.ui.TranslateActivity"
|
||||
android:theme="@style/AppTheme" />
|
||||
|
||||
<activity
|
||||
|
|
|
@ -44,7 +44,7 @@ import com.nextcloud.talk.models.json.search.ContactsByNumberOverall;
|
|||
import com.nextcloud.talk.models.json.signaling.SignalingOverall;
|
||||
import com.nextcloud.talk.models.json.signaling.settings.SignalingSettingsOverall;
|
||||
import com.nextcloud.talk.models.json.status.StatusOverall;
|
||||
import com.nextcloud.talk.models.json.translations.TranslationsOverall;
|
||||
import com.nextcloud.talk.translate.repositories.model.TranslationsOverall;
|
||||
import com.nextcloud.talk.models.json.unifiedsearch.UnifiedSearchOverall;
|
||||
import com.nextcloud.talk.models.json.userprofile.UserProfileFieldsOverall;
|
||||
import com.nextcloud.talk.models.json.userprofile.UserProfileOverall;
|
||||
|
|
|
@ -155,8 +155,8 @@ import com.nextcloud.talk.remotefilebrowser.activities.RemoteFileBrowserActivity
|
|||
import com.nextcloud.talk.repositories.reactions.ReactionsRepository
|
||||
import com.nextcloud.talk.shareditems.activities.SharedItemsActivity
|
||||
import com.nextcloud.talk.signaling.SignalingMessageReceiver
|
||||
import com.nextcloud.talk.translate.ui.TranslateActivity
|
||||
import com.nextcloud.talk.signaling.SignalingMessageSender
|
||||
import com.nextcloud.talk.translate.TranslateActivity
|
||||
import com.nextcloud.talk.ui.bottom.sheet.ProfileBottomSheet
|
||||
import com.nextcloud.talk.ui.dialog.AttachmentDialog
|
||||
import com.nextcloud.talk.ui.dialog.MessageActionsDialog
|
||||
|
|
|
@ -47,6 +47,8 @@ import com.nextcloud.talk.repositories.unifiedsearch.UnifiedSearchRepository
|
|||
import com.nextcloud.talk.repositories.unifiedsearch.UnifiedSearchRepositoryImpl
|
||||
import com.nextcloud.talk.shareditems.repositories.SharedItemsRepository
|
||||
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.database.user.CurrentUserProviderNew
|
||||
import dagger.Module
|
||||
|
@ -107,4 +109,10 @@ class RepositoryModule {
|
|||
RequestAssistanceRepository {
|
||||
return RequestAssistanceRepositoryImpl(ncApi, userProvider)
|
||||
}
|
||||
|
||||
@Provides
|
||||
fun translateRepository(ncApi: NcApi):
|
||||
TranslateRepository {
|
||||
return TranslateRepositoryImpl(ncApi)
|
||||
}
|
||||
}
|
||||
|
|
|
@ -31,6 +31,7 @@ import com.nextcloud.talk.polls.viewmodels.PollVoteViewModel
|
|||
import com.nextcloud.talk.raisehand.viewmodel.RaiseHandViewModel
|
||||
import com.nextcloud.talk.remotefilebrowser.viewmodels.RemoteFileBrowserItemsViewModel
|
||||
import com.nextcloud.talk.shareditems.viewmodels.SharedItemsViewModel
|
||||
import com.nextcloud.talk.translate.viewmodels.TranslateViewModel
|
||||
import com.nextcloud.talk.viewmodels.CallRecordingViewModel
|
||||
import dagger.Binds
|
||||
import dagger.MapKey
|
||||
|
@ -101,4 +102,9 @@ abstract class ViewModelModule {
|
|||
@IntoMap
|
||||
@ViewModelKey(RaiseHandViewModel::class)
|
||||
abstract fun raiseHandViewModel(viewModel: RaiseHandViewModel): ViewModel
|
||||
|
||||
@Binds
|
||||
@IntoMap
|
||||
@ViewModelKey(TranslateViewModel::class)
|
||||
abstract fun translateViewModel(viewModel: TranslateViewModel): ViewModel
|
||||
}
|
||||
|
|
|
@ -0,0 +1,14 @@
|
|||
package com.nextcloud.talk.translate.repositories
|
||||
|
||||
import io.reactivex.Observable
|
||||
|
||||
interface TranslateRepository {
|
||||
|
||||
fun translateMessage(
|
||||
authorization: String,
|
||||
url: String,
|
||||
text: String,
|
||||
toLanguage: String,
|
||||
fromLanguage: String?
|
||||
): Observable<String>
|
||||
}
|
|
@ -0,0 +1,18 @@
|
|||
package com.nextcloud.talk.translate.repositories
|
||||
|
||||
import com.nextcloud.talk.api.NcApi
|
||||
import io.reactivex.Observable
|
||||
import javax.inject.Inject
|
||||
|
||||
class TranslateRepositoryImpl @Inject constructor(private val ncApi: NcApi) : TranslateRepository {
|
||||
|
||||
override fun translateMessage(
|
||||
authorization: String,
|
||||
url: String,
|
||||
text: String,
|
||||
toLanguage: String,
|
||||
fromLanguage: String?
|
||||
): Observable<String> {
|
||||
return ncApi.translateMessage(authorization, url, text, toLanguage, fromLanguage).map { it.ocs?.data!!.text }
|
||||
}
|
||||
}
|
|
@ -17,7 +17,7 @@
|
|||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
package com.nextcloud.talk.models.json.translations
|
||||
package com.nextcloud.talk.translate.repositories.model
|
||||
|
||||
import android.os.Parcelable
|
||||
import com.bluelinelabs.logansquare.annotation.JsonField
|
|
@ -17,7 +17,7 @@
|
|||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
package com.nextcloud.talk.models.json.translations
|
||||
package com.nextcloud.talk.translate.repositories.model
|
||||
|
||||
import android.os.Parcelable
|
||||
import com.bluelinelabs.logansquare.annotation.JsonField
|
|
@ -17,7 +17,7 @@
|
|||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
package com.nextcloud.talk.models.json.translations
|
||||
package com.nextcloud.talk.translate.repositories.model
|
||||
|
||||
import android.os.Parcelable
|
||||
import com.bluelinelabs.logansquare.annotation.JsonField
|
|
@ -19,68 +19,82 @@
|
|||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
package com.nextcloud.talk.translate
|
||||
package com.nextcloud.talk.translate.ui
|
||||
|
||||
import android.app.AlertDialog
|
||||
import android.content.ClipData
|
||||
import android.content.ClipboardManager
|
||||
import android.content.Context
|
||||
import android.graphics.drawable.ColorDrawable
|
||||
import android.os.Bundle
|
||||
import android.text.method.ScrollingMovementMethod
|
||||
import android.util.Log
|
||||
import android.view.View
|
||||
import android.widget.AdapterView
|
||||
import android.widget.ArrayAdapter
|
||||
import androidx.appcompat.app.AlertDialog
|
||||
import androidx.lifecycle.ViewModelProvider
|
||||
import autodagger.AutoInjector
|
||||
import com.google.android.material.dialog.MaterialAlertDialogBuilder
|
||||
import com.nextcloud.talk.R
|
||||
import com.nextcloud.talk.activities.BaseActivity
|
||||
import com.nextcloud.talk.api.NcApi
|
||||
import com.nextcloud.talk.application.NextcloudTalkApplication
|
||||
import com.nextcloud.talk.data.user.model.User
|
||||
import com.nextcloud.talk.databinding.ActivityTranslateBinding
|
||||
import com.nextcloud.talk.models.json.translations.TranslationsOverall
|
||||
import com.nextcloud.talk.translate.viewmodels.TranslateViewModel
|
||||
import com.nextcloud.talk.users.UserManager
|
||||
import com.nextcloud.talk.utils.ApiUtils
|
||||
import com.nextcloud.talk.utils.bundle.BundleKeys
|
||||
import com.nextcloud.talk.utils.database.user.CapabilitiesUtilNew
|
||||
import io.reactivex.Observer
|
||||
import io.reactivex.android.schedulers.AndroidSchedulers
|
||||
import io.reactivex.disposables.Disposable
|
||||
import io.reactivex.schedulers.Schedulers
|
||||
import org.json.JSONArray
|
||||
import java.util.Locale
|
||||
import javax.inject.Inject
|
||||
|
||||
@AutoInjector(NextcloudTalkApplication::class)
|
||||
class TranslateActivity : BaseActivity() {
|
||||
private lateinit var binding: ActivityTranslateBinding
|
||||
|
||||
@Inject
|
||||
lateinit var ncApi: NcApi
|
||||
|
||||
@Inject
|
||||
lateinit var userManager: UserManager
|
||||
|
||||
private var fromLanguages = arrayOf<String>()
|
||||
private var toLanguages = arrayOf<String>()
|
||||
private var text: String? = null
|
||||
@Inject
|
||||
lateinit var viewModelFactory: ViewModelProvider.Factory
|
||||
|
||||
lateinit var viewModel: TranslateViewModel
|
||||
lateinit var binding: ActivityTranslateBinding
|
||||
|
||||
private var toLanguages: Array<String>? = null
|
||||
private var fromLanguages: Array<String>? = null
|
||||
|
||||
override fun onCreate(savedInstanceState: Bundle?) {
|
||||
super.onCreate(savedInstanceState)
|
||||
|
||||
NextcloudTalkApplication.sharedApplication!!.componentApplication.inject(this)
|
||||
|
||||
binding = ActivityTranslateBinding.inflate(layoutInflater)
|
||||
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()
|
||||
setContentView(binding.root)
|
||||
setupSystemColors()
|
||||
setupTextViews()
|
||||
getLanguageOptions()
|
||||
setupSpinners()
|
||||
setupCopyButton()
|
||||
getLanguageOptions()
|
||||
|
||||
if (savedInstanceState == null) {
|
||||
translate(null, Locale.getDefault().language)
|
||||
val text = intent.extras!!.getString(BundleKeys.KEY_TRANSLATE_MESSAGE)
|
||||
viewModel.translateMessage(Locale.getDefault().language, null, text!!)
|
||||
} else {
|
||||
binding.translatedMessageTextview.text = savedInstanceState.getString(BundleKeys.SAVED_TRANSLATED_MESSAGE)
|
||||
}
|
||||
|
@ -90,7 +104,6 @@ class TranslateActivity : BaseActivity() {
|
|||
super.onResume()
|
||||
setItems()
|
||||
}
|
||||
|
||||
override fun onSaveInstanceState(outState: Bundle) {
|
||||
outState.run {
|
||||
putString(BundleKeys.SAVED_TRANSLATED_MESSAGE, binding.translatedMessageTextview.text.toString())
|
||||
|
@ -137,14 +150,12 @@ class TranslateActivity : BaseActivity() {
|
|||
|
||||
binding.originalMessageTextview.movementMethod = ScrollingMovementMethod()
|
||||
binding.translatedMessageTextview.movementMethod = ScrollingMovementMethod()
|
||||
|
||||
val bundle = intent.extras
|
||||
binding.originalMessageTextview.text = bundle?.getString(BundleKeys.KEY_TRANSLATE_MESSAGE)
|
||||
text = bundle?.getString(BundleKeys.KEY_TRANSLATE_MESSAGE)
|
||||
val text = intent.extras!!.getString(BundleKeys.KEY_TRANSLATE_MESSAGE)
|
||||
binding.originalMessageTextview.text = text
|
||||
}
|
||||
|
||||
private fun getLanguageOptions() {
|
||||
val currentUser: User = userManager.currentUser.blockingGet()
|
||||
val currentUser = userManager.currentUser.blockingGet()
|
||||
val json = JSONArray(CapabilitiesUtilNew.getLanguages(currentUser).toString())
|
||||
|
||||
val fromLanguagesSet = mutableSetOf(resources.getString(R.string.translation_detect_language))
|
||||
|
@ -159,9 +170,8 @@ class TranslateActivity : BaseActivity() {
|
|||
fromLanguagesSet.add(current.getString(TO_LABEL))
|
||||
}
|
||||
|
||||
fromLanguages = fromLanguagesSet.toTypedArray()
|
||||
toLanguages = toLanguagesSet.toTypedArray()
|
||||
fillSpinners()
|
||||
fromLanguages = fromLanguagesSet.toTypedArray()
|
||||
}
|
||||
|
||||
private fun enableSpinners(value: Boolean) {
|
||||
|
@ -169,35 +179,7 @@ class TranslateActivity : BaseActivity() {
|
|||
binding.toLanguageInputLayout.isEnabled = value
|
||||
}
|
||||
|
||||
private fun translate(fromLanguage: String?, toLanguage: String) {
|
||||
val currentUser: User = userManager.currentUser.blockingGet()
|
||||
val credentials: String = ApiUtils.getCredentials(currentUser.username, currentUser.token)
|
||||
val translateURL = ApiUtils.getUrlForTranslation(currentUser.baseUrl)
|
||||
val calculatedFromLanguage = if (fromLanguage == null || fromLanguage == "") {
|
||||
null
|
||||
} else {
|
||||
fromLanguage
|
||||
}
|
||||
|
||||
ncApi.translateMessage(credentials, translateURL, text, toLanguage, calculatedFromLanguage)
|
||||
?.subscribeOn(Schedulers.io())
|
||||
?.observeOn(AndroidSchedulers.mainThread())
|
||||
?.subscribe(object : Observer<TranslationsOverall> {
|
||||
override fun onSubscribe(d: Disposable) {
|
||||
enableSpinners(false)
|
||||
binding.translatedMessageContainer.visibility = View.GONE
|
||||
binding.progressBar.visibility = View.VISIBLE
|
||||
}
|
||||
|
||||
override fun onNext(translationOverall: TranslationsOverall) {
|
||||
binding.progressBar.visibility = View.GONE
|
||||
binding.translatedMessageContainer.visibility = View.VISIBLE
|
||||
binding.translatedMessageTextview.text = translationOverall.ocs?.data?.text
|
||||
}
|
||||
|
||||
override fun onError(e: Throwable) {
|
||||
Log.w(TAG, "Error while translating message", e)
|
||||
binding.progressBar.visibility = View.GONE
|
||||
private fun showDialog() {
|
||||
val dialogBuilder = MaterialAlertDialogBuilder(this@TranslateActivity)
|
||||
.setIcon(
|
||||
viewThemeUtils.dialog.colorMaterialAlertDialogIcon(
|
||||
|
@ -220,14 +202,6 @@ class TranslateActivity : BaseActivity() {
|
|||
)
|
||||
}
|
||||
|
||||
override fun onComplete() {
|
||||
// nothing?
|
||||
}
|
||||
})
|
||||
|
||||
enableSpinners(true)
|
||||
}
|
||||
|
||||
private fun getISOFromLanguage(language: String): String {
|
||||
if (resources.getString(R.string.translation_device_settings) == language) {
|
||||
return Locale.getDefault().language
|
||||
|
@ -237,7 +211,7 @@ class TranslateActivity : BaseActivity() {
|
|||
}
|
||||
|
||||
private fun getISOFromServer(language: String): String {
|
||||
val currentUser: User = userManager.currentUser.blockingGet()
|
||||
val currentUser = userManager.currentUser.blockingGet()
|
||||
val json = JSONArray(CapabilitiesUtilNew.getLanguages(currentUser).toString())
|
||||
|
||||
for (i in 0 until json.length()) {
|
||||
|
@ -254,43 +228,64 @@ class TranslateActivity : BaseActivity() {
|
|||
viewThemeUtils.material.colorTextInputLayout(binding.fromLanguageInputLayout)
|
||||
viewThemeUtils.material.colorTextInputLayout(binding.toLanguageInputLayout)
|
||||
fillSpinners()
|
||||
val text = intent.extras!!.getString(BundleKeys.KEY_TRANSLATE_MESSAGE)
|
||||
|
||||
binding.fromLanguage.onItemClickListener = AdapterView.OnItemClickListener { parent, _, position, _ ->
|
||||
val fromLabel: String = getISOFromLanguage(parent.getItemAtPosition(position).toString())
|
||||
val toLabel: String = getISOFromLanguage(binding.toLanguage.text.toString())
|
||||
translate(fromLabel, toLabel)
|
||||
viewModel.translateMessage(toLabel, fromLabel, text!!)
|
||||
}
|
||||
|
||||
binding.toLanguage.onItemClickListener = AdapterView.OnItemClickListener { parent, _, position, _ ->
|
||||
val toLabel: String = getISOFromLanguage(parent.getItemAtPosition(position).toString())
|
||||
val fromLabel: String = getISOFromLanguage(binding.fromLanguage.text.toString())
|
||||
translate(fromLabel, toLabel)
|
||||
viewModel.translateMessage(toLabel, fromLabel, text!!)
|
||||
}
|
||||
}
|
||||
|
||||
private fun fillSpinners() {
|
||||
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()) {
|
||||
binding.fromLanguage.setText(fromLanguages[0])
|
||||
if (fromLanguages!!.isNotEmpty()) {
|
||||
binding.fromLanguage.setText(fromLanguages!![0])
|
||||
}
|
||||
|
||||
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()) {
|
||||
binding.toLanguage.setText(toLanguages[0])
|
||||
if (toLanguages!!.isNotEmpty()) {
|
||||
binding.toLanguage.setText(toLanguages!![0])
|
||||
}
|
||||
}
|
||||
|
||||
private fun setItems() {
|
||||
binding.fromLanguage.setSimpleItems(fromLanguages)
|
||||
binding.toLanguage.setSimpleItems(toLanguages)
|
||||
binding.fromLanguage.setSimpleItems(fromLanguages!!)
|
||||
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 {
|
||||
private val TAG = TranslateActivity::class.simpleName
|
||||
private const val FROM_ID = "from"
|
||||
private const val FROM_LABEL = "fromLabel"
|
||||
private const val TO_LABEL = "toLabel"
|
|
@ -0,0 +1,71 @@
|
|||
package com.nextcloud.talk.translate.viewmodels
|
||||
|
||||
import android.util.Log
|
||||
import androidx.lifecycle.LiveData
|
||||
import androidx.lifecycle.MutableLiveData
|
||||
import androidx.lifecycle.ViewModel
|
||||
import com.nextcloud.talk.data.user.model.User
|
||||
import com.nextcloud.talk.translate.repositories.TranslateRepository
|
||||
import com.nextcloud.talk.users.UserManager
|
||||
import com.nextcloud.talk.utils.ApiUtils
|
||||
import io.reactivex.Observer
|
||||
import io.reactivex.android.schedulers.AndroidSchedulers
|
||||
import io.reactivex.disposables.Disposable
|
||||
import io.reactivex.schedulers.Schedulers
|
||||
import javax.inject.Inject
|
||||
|
||||
class TranslateViewModel @Inject constructor(
|
||||
private val repository: TranslateRepository,
|
||||
private val userManager: UserManager
|
||||
) : ViewModel() {
|
||||
|
||||
sealed interface ViewState
|
||||
|
||||
object StartState : ViewState
|
||||
class TranslatedState(val msg: String) : ViewState
|
||||
object ErrorState : ViewState
|
||||
|
||||
private val _viewState: MutableLiveData<ViewState> = MutableLiveData(StartState)
|
||||
val viewState: LiveData<ViewState>
|
||||
get() = _viewState
|
||||
|
||||
fun translateMessage(toLanguage: String, fromLanguage: String?, text: String) {
|
||||
val currentUser: User = userManager.currentUser.blockingGet()
|
||||
val authorization: String = ApiUtils.getCredentials(currentUser.username, currentUser.token)
|
||||
val url: String = ApiUtils.getUrlForTranslation(currentUser.baseUrl)
|
||||
val calculatedFromLanguage = if (fromLanguage == null || fromLanguage == "") { null } else { fromLanguage }
|
||||
Log.i(TAG, "translateMessage Called")
|
||||
repository.translateMessage(
|
||||
authorization,
|
||||
url,
|
||||
text,
|
||||
toLanguage,
|
||||
calculatedFromLanguage
|
||||
)
|
||||
.subscribeOn(Schedulers.io())
|
||||
?.observeOn(AndroidSchedulers.mainThread())
|
||||
?.subscribe(TranslateObserver())
|
||||
}
|
||||
|
||||
inner class TranslateObserver : Observer<String> {
|
||||
override fun onSubscribe(d: Disposable) {
|
||||
_viewState.value = StartState
|
||||
}
|
||||
|
||||
override fun onNext(translatedMessage: String) {
|
||||
_viewState.value = TranslatedState(translatedMessage)
|
||||
}
|
||||
|
||||
override fun onError(e: Throwable) {
|
||||
_viewState.value = ErrorState
|
||||
Log.e(TAG, "Error while translating message", e)
|
||||
}
|
||||
|
||||
override fun onComplete() {
|
||||
// nothing?
|
||||
}
|
||||
}
|
||||
companion object {
|
||||
private val TAG = TranslateViewModel::class.simpleName
|
||||
}
|
||||
}
|
Loading…
Reference in a new issue