diff --git a/app/src/main/java/com/nextcloud/talk/api/NcApi.java b/app/src/main/java/com/nextcloud/talk/api/NcApi.java index 6dad5fefc6c..2f18c3dba2d 100644 --- a/app/src/main/java/com/nextcloud/talk/api/NcApi.java +++ b/app/src/main/java/com/nextcloud/talk/api/NcApi.java @@ -49,6 +49,7 @@ import com.nextcloud.talk.models.json.userprofile.UserProfileFieldsOverall; import com.nextcloud.talk.models.json.userprofile.UserProfileOverall; import com.nextcloud.talk.polls.repositories.model.PollOverall; +import com.nextcloud.talk.translate.repositories.model.LanguagesOverall; import com.nextcloud.talk.translate.repositories.model.TranslationsOverall; import java.util.List; @@ -673,6 +674,10 @@ Observable translateMessage(@Header("Authorization") String @Query("toLanguage") String toLanguage, @Nullable @Query("fromLanguage") String fromLanguage); + @GET + Observable getLanguages(@Header("Authorization") String authorization, + @Url String url); + @GET Observable getReminder(@Header("Authorization") String authorization, @Url String url); diff --git a/app/src/main/java/com/nextcloud/talk/translate/repositories/TranslateRepository.kt b/app/src/main/java/com/nextcloud/talk/translate/repositories/TranslateRepository.kt index 0e925aee831..4760f1f4c75 100644 --- a/app/src/main/java/com/nextcloud/talk/translate/repositories/TranslateRepository.kt +++ b/app/src/main/java/com/nextcloud/talk/translate/repositories/TranslateRepository.kt @@ -11,4 +11,9 @@ interface TranslateRepository { toLanguage: String, fromLanguage: String? ): Observable + + fun getLanguages( + authorization: String, + url: String + ): Observable> } diff --git a/app/src/main/java/com/nextcloud/talk/translate/repositories/TranslateRepositoryImpl.kt b/app/src/main/java/com/nextcloud/talk/translate/repositories/TranslateRepositoryImpl.kt index 9a81d9248f4..288919e5305 100644 --- a/app/src/main/java/com/nextcloud/talk/translate/repositories/TranslateRepositoryImpl.kt +++ b/app/src/main/java/com/nextcloud/talk/translate/repositories/TranslateRepositoryImpl.kt @@ -15,4 +15,8 @@ class TranslateRepositoryImpl @Inject constructor(private val ncApi: NcApi) : Tr ): Observable { return ncApi.translateMessage(authorization, url, text, toLanguage, fromLanguage).map { it.ocs?.data!!.text } } + + override fun getLanguages(authorization: String, url: String): Observable> { + return ncApi.getLanguages(authorization, url).map { it.ocs?.data?.languages } + } } diff --git a/app/src/main/java/com/nextcloud/talk/translate/repositories/model/LanguagesData.kt b/app/src/main/java/com/nextcloud/talk/translate/repositories/model/LanguagesData.kt new file mode 100644 index 00000000000..626369aa4da --- /dev/null +++ b/app/src/main/java/com/nextcloud/talk/translate/repositories/model/LanguagesData.kt @@ -0,0 +1,37 @@ +/* + * Nextcloud Talk application + * + * @author Julius Linus + * Copyright (C) 2023 Julius Linus + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ +package com.nextcloud.talk.translate.repositories.model + +import android.os.Parcelable +import com.bluelinelabs.logansquare.annotation.JsonField +import com.bluelinelabs.logansquare.annotation.JsonObject +import kotlinx.parcelize.Parcelize + +@Parcelize +@JsonObject +data class LanguagesData( + @JsonField(name = ["languageDetection"]) + var languageDetection: Boolean?, + @JsonField(name = ["languages"]) + var languages: Array? +) : Parcelable { + // This constructor is added to work with the 'com.bluelinelabs.logansquare.annotation.JsonObject' + constructor() : this(null, null) +} diff --git a/app/src/main/java/com/nextcloud/talk/translate/repositories/model/LanguagesOCS.kt b/app/src/main/java/com/nextcloud/talk/translate/repositories/model/LanguagesOCS.kt new file mode 100644 index 00000000000..c6eff84f25c --- /dev/null +++ b/app/src/main/java/com/nextcloud/talk/translate/repositories/model/LanguagesOCS.kt @@ -0,0 +1,38 @@ +/* + * Nextcloud Talk application + * + * @author Julius Linus + * Copyright (C) 2023 Julius Linus + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ +package com.nextcloud.talk.translate.repositories.model + +import android.os.Parcelable +import com.bluelinelabs.logansquare.annotation.JsonField +import com.bluelinelabs.logansquare.annotation.JsonObject +import com.nextcloud.talk.models.json.generic.GenericMeta +import kotlinx.parcelize.Parcelize + +@Parcelize +@JsonObject +data class LanguagesOCS( + @JsonField(name = ["meta"]) + var meta: GenericMeta?, + @JsonField(name = ["data"]) + var data: LanguagesData? +) : Parcelable { + // This constructor is added to work with the 'com.bluelinelabs.logansquare.annotation.JsonObject' + constructor() : this(null, LanguagesData()) +} diff --git a/app/src/main/java/com/nextcloud/talk/translate/repositories/model/LanguagesOverall.kt b/app/src/main/java/com/nextcloud/talk/translate/repositories/model/LanguagesOverall.kt new file mode 100644 index 00000000000..1e8a35b9001 --- /dev/null +++ b/app/src/main/java/com/nextcloud/talk/translate/repositories/model/LanguagesOverall.kt @@ -0,0 +1,35 @@ +/* + * Nextcloud Talk application + * + * @author Julius Linus + * Copyright (C) 2023 Julius Linus + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ +package com.nextcloud.talk.translate.repositories.model + +import android.os.Parcelable +import com.bluelinelabs.logansquare.annotation.JsonField +import com.bluelinelabs.logansquare.annotation.JsonObject +import kotlinx.parcelize.Parcelize + +@Parcelize +@JsonObject +class LanguagesOverall( + @JsonField(name = ["ocs"]) + var ocs: LanguagesOCS? +) : Parcelable { + // This constructor is added to work with the 'com.bluelinelabs.logansquare.annotation.JsonObject' + constructor() : this(null) +} diff --git a/app/src/main/java/com/nextcloud/talk/translate/repositories/model/TranslateOCS.kt b/app/src/main/java/com/nextcloud/talk/translate/repositories/model/TranslateOCS.kt index 66cde16d3b7..617eb20a18a 100644 --- a/app/src/main/java/com/nextcloud/talk/translate/repositories/model/TranslateOCS.kt +++ b/app/src/main/java/com/nextcloud/talk/translate/repositories/model/TranslateOCS.kt @@ -27,7 +27,7 @@ import kotlinx.parcelize.Parcelize @Parcelize @JsonObject -data class TranslateOCS( // TODO finish this model +data class TranslateOCS( @JsonField(name = ["meta"]) var meta: GenericMeta?, @JsonField(name = ["data"]) diff --git a/app/src/main/java/com/nextcloud/talk/translate/ui/TranslateActivity.kt b/app/src/main/java/com/nextcloud/talk/translate/ui/TranslateActivity.kt index a65dd45db7a..10584d9bd1f 100644 --- a/app/src/main/java/com/nextcloud/talk/translate/ui/TranslateActivity.kt +++ b/app/src/main/java/com/nextcloud/talk/translate/ui/TranslateActivity.kt @@ -41,7 +41,6 @@ import com.nextcloud.talk.databinding.ActivityTranslateBinding import com.nextcloud.talk.translate.viewmodels.TranslateViewModel import com.nextcloud.talk.users.UserManager import com.nextcloud.talk.utils.bundle.BundleKeys -import com.nextcloud.talk.utils.database.user.CapabilitiesUtilNew import org.json.JSONArray import java.util.Locale import javax.inject.Inject @@ -60,6 +59,7 @@ class TranslateActivity : BaseActivity() { private var toLanguages: Array? = null private var fromLanguages: Array? = null + private var languages: Array? = null override fun onCreate(savedInstanceState: Bundle?) { super.onCreate(savedInstanceState) @@ -79,8 +79,16 @@ class TranslateActivity : BaseActivity() { onTranslatedState(state.msg) } - is TranslateViewModel.ErrorState -> { - onErrorState() + is TranslateViewModel.TranslationErrorState -> { + onTranslationErrorState() + } + + is TranslateViewModel.LanguagesErrorState -> { + onLanguagesErrorState() + } + + is TranslateViewModel.LanguagesRetrievedState -> { + languages = state.array } } } @@ -88,6 +96,7 @@ class TranslateActivity : BaseActivity() { setContentView(binding.root) setupSystemColors() setupTextViews() + viewModel.getLanguages() getLanguageOptions() setupSpinners() setupCopyButton() @@ -156,7 +165,7 @@ class TranslateActivity : BaseActivity() { private fun getLanguageOptions() { val currentUser = userManager.currentUser.blockingGet() - val json = JSONArray((CapabilitiesUtilNew.getLanguages(currentUser) as ArrayList<*>).toArray()) + val json = JSONArray(languages) val fromLanguagesSet = mutableSetOf(resources.getString(R.string.translation_detect_language)) val toLanguagesSet = mutableSetOf(resources.getString(R.string.translation_device_settings)) @@ -179,7 +188,7 @@ class TranslateActivity : BaseActivity() { binding.toLanguageInputLayout.isEnabled = value } - private fun showDialog() { + private fun showDialog(titleInt: Int, messageInt: Int) { val dialogBuilder = MaterialAlertDialogBuilder(this@TranslateActivity) .setIcon( viewThemeUtils.dialog.colorMaterialAlertDialogIcon( @@ -187,8 +196,8 @@ class TranslateActivity : BaseActivity() { R.drawable.ic_warning_white ) ) - .setTitle(R.string.translation_error_title) - .setMessage(R.string.translation_error_message) + .setTitle(titleInt) + .setMessage(messageInt) .setPositiveButton(R.string.nc_ok) { dialog, _ -> dialog.dismiss() } @@ -212,7 +221,7 @@ class TranslateActivity : BaseActivity() { private fun getISOFromServer(language: String): String { val currentUser = userManager.currentUser.blockingGet() - val json = JSONArray((CapabilitiesUtilNew.getLanguages(currentUser) as ArrayList<*>).toArray()) + val json = JSONArray(languages) for (i in 0 until json.length()) { val current = json.getJSONObject(i) @@ -279,10 +288,16 @@ class TranslateActivity : BaseActivity() { enableSpinners(true) } - private fun onErrorState() { + private fun onTranslationErrorState() { + binding.progressBar.visibility = View.GONE + enableSpinners(true) + showDialog(R.string.translation_error_title, R.string.translation_error_message) + } + + private fun onLanguagesErrorState() { binding.progressBar.visibility = View.GONE enableSpinners(true) - showDialog() + showDialog(R.string.languages_error_title, R.string.languages_error_message) } companion object { diff --git a/app/src/main/java/com/nextcloud/talk/translate/viewmodels/TranslateViewModel.kt b/app/src/main/java/com/nextcloud/talk/translate/viewmodels/TranslateViewModel.kt index a8952fde91f..850283094a8 100644 --- a/app/src/main/java/com/nextcloud/talk/translate/viewmodels/TranslateViewModel.kt +++ b/app/src/main/java/com/nextcloud/talk/translate/viewmodels/TranslateViewModel.kt @@ -21,9 +21,14 @@ class TranslateViewModel @Inject constructor( sealed interface ViewState - object StartState : ViewState + data object StartState : ViewState class TranslatedState(val msg: String) : ViewState - object ErrorState : ViewState + + class LanguagesRetrievedState(val array: Array) : ViewState + + data object LanguagesErrorState : ViewState + + data object TranslationErrorState : ViewState private val _viewState: MutableLiveData = MutableLiveData(StartState) val viewState: LiveData @@ -47,6 +52,33 @@ class TranslateViewModel @Inject constructor( ?.subscribe(TranslateObserver()) } + fun getLanguages() { + val currentUser: User = userManager.currentUser.blockingGet() + val authorization: String = ApiUtils.getCredentials(currentUser.username, currentUser.token) + val url: String = ApiUtils.getUrlForLanguages(currentUser.baseUrl) + repository.getLanguages(authorization, url) + .subscribeOn(Schedulers.io()) + ?.observeOn(AndroidSchedulers.mainThread()) + ?.subscribe(object : Observer> { + override fun onSubscribe(d: Disposable) { + // unused atm + } + + override fun onError(e: Throwable) { + _viewState.value = LanguagesErrorState + Log.e(TAG, "Error while retrieving languages") + } + + override fun onComplete() { + // unused atm + } + + override fun onNext(array: Array) { + _viewState.value = LanguagesRetrievedState(array) + } + }) + } + inner class TranslateObserver : Observer { override fun onSubscribe(d: Disposable) { _viewState.value = StartState @@ -57,7 +89,7 @@ class TranslateViewModel @Inject constructor( } override fun onError(e: Throwable) { - _viewState.value = ErrorState + _viewState.value = TranslationErrorState Log.e(TAG, "Error while translating message", e) } diff --git a/app/src/main/java/com/nextcloud/talk/ui/dialog/MessageActionsDialog.kt b/app/src/main/java/com/nextcloud/talk/ui/dialog/MessageActionsDialog.kt index 9fd90fbcaae..6a2eafde543 100644 --- a/app/src/main/java/com/nextcloud/talk/ui/dialog/MessageActionsDialog.kt +++ b/app/src/main/java/com/nextcloud/talk/ui/dialog/MessageActionsDialog.kt @@ -57,7 +57,6 @@ 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 javax.inject.Inject @AutoInjector(NextcloudTalkApplication::class) @@ -94,8 +93,7 @@ class MessageActionsDialog( initMenuItemTranslate( !message.isDeleted && ChatMessage.MessageType.REGULAR_TEXT_MESSAGE == message.getCalculateMessageType() && - CapabilitiesUtilNew.isTranslationsSupported(user) && - JSONArray((CapabilitiesUtilNew.getLanguages(user) as ArrayList<*>).toArray()).length() > 0 + CapabilitiesUtilNew.isTranslationsSupported(user) ) initMenuReplyToMessage(message.replyable && hasChatPermission) initMenuReplyPrivately( diff --git a/app/src/main/java/com/nextcloud/talk/utils/ApiUtils.java b/app/src/main/java/com/nextcloud/talk/utils/ApiUtils.java index 4b0ec13d9df..e400de42d0e 100644 --- a/app/src/main/java/com/nextcloud/talk/utils/ApiUtils.java +++ b/app/src/main/java/com/nextcloud/talk/utils/ApiUtils.java @@ -531,6 +531,10 @@ public static String getUrlForTranslation(String baseUrl) { return baseUrl + ocsApiVersion + "/translation/translate"; } + public static String getUrlForLanguages(String baseUrl) { + return baseUrl + ocsApiVersion + "/translation/languages"; + } + public static String getUrlForReminder(User user, String roomToken, String messageId, int version) { String url = ApiUtils.getUrlForChatMessage(version, user.getBaseUrl(), roomToken, messageId); return url + "/reminder"; diff --git a/app/src/main/java/com/nextcloud/talk/utils/database/user/CapabilitiesUtilNew.kt b/app/src/main/java/com/nextcloud/talk/utils/database/user/CapabilitiesUtilNew.kt index 5816fd356ad..50432c06178 100644 --- a/app/src/main/java/com/nextcloud/talk/utils/database/user/CapabilitiesUtilNew.kt +++ b/app/src/main/java/com/nextcloud/talk/utils/database/user/CapabilitiesUtilNew.kt @@ -214,12 +214,8 @@ object CapabilitiesUtilNew { @JvmStatic fun isLinkPreviewAvailable(user: User): Boolean { - if (user.capabilities?.coreCapability?.referenceApi != null && + return user.capabilities?.coreCapability?.referenceApi != null && user.capabilities?.coreCapability?.referenceApi == "true" - ) { - return true - } - return false } fun isTranslationsSupported(user: User?): Boolean { @@ -227,20 +223,13 @@ object CapabilitiesUtilNew { val capabilities = user.capabilities return capabilities?.spreedCapability?.config?.containsKey("chat") == true && capabilities.spreedCapability!!.config!!["chat"] != null && - capabilities.spreedCapability!!.config!!["chat"]!!.containsKey("translations") + capabilities.spreedCapability!!.config!!["chat"]!!.containsKey("has-translation-providers") && + capabilities.spreedCapability!!.config!!["chat"]!!["has-translation-providers"] == true } return false } - fun getLanguages(user: User?): Any? { - return if (isTranslationsSupported(user)) { - user!!.capabilities!!.spreedCapability!!.config!!["chat"]!!["translations"] - } else { - null - } - } - fun isRemindSupported(user: User?): Boolean { if (user?.capabilities != null) { val capabilities = user.capabilities diff --git a/app/src/main/res/values/strings.xml b/app/src/main/res/values/strings.xml index 8fa0ef657e9..1761849be1b 100644 --- a/app/src/main/res/values/strings.xml +++ b/app/src/main/res/values/strings.xml @@ -710,5 +710,7 @@ How to translate with transifex: Audio Call started a call Error 429 Too Many Requests + Retrieval failed + Languages could not be retrieved