Преглед изворни кода

issue 2931 progress
Signed-off-by: Julius Linus <juliuslinus1@gmail.com>

Signed-off-by: Andy Scherzinger <info@andy-scherzinger.de>

rapterjet2004 пре 2 година
родитељ
комит
8cdd8e9d8f

+ 4 - 0
app/src/main/AndroidManifest.xml

@@ -189,6 +189,10 @@
             android:name=".location.GeocodingActivity"
             android:theme="@style/AppTheme" />
 
+        <activity
+            android:name=".translate.TranslateActivity"
+            android:theme="@style/AppTheme" />
+
         <activity
             android:name=".profile.ProfileActivity"
             android:theme="@style/AppTheme" />

+ 15 - 0
app/src/main/java/com/nextcloud/talk/api/NcApi.java

@@ -44,6 +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.models.json.unifiedsearch.UnifiedSearchOverall;
 import com.nextcloud.talk.models.json.userprofile.UserProfileFieldsOverall;
 import com.nextcloud.talk.models.json.userprofile.UserProfileOverall;
@@ -654,4 +655,18 @@ public interface NcApi {
 
     @DELETE
     Observable<GenericOverall> sendCommonDeleteRequest(@Header("Authorization") String authorization, @Url String url);
+
+    @POST
+    Observable<TranslationsOverall> translateMessage(@Header("Authorization") String authorization,
+                                                     @Url String url,
+                                                     @Field("text") String text,
+                                                     @Field("fromLanguage") String fromLanguage,
+                                                     @Field("toLanguage") String toLanguage);
+
+//    @GET
+//    Observable<TranslationsOverall> getLanguageOptions(@Header("Authorization") String authorization,
+//                                                     @Url String url,
+//                                                     @Field("languageDetection") String fromLanguage,
+//                                                     @Field("languages")  Object languages[]);
+    // TODO finish ^ function declaration
 }

+ 11 - 0
app/src/main/java/com/nextcloud/talk/chat/ChatActivity.kt

@@ -150,6 +150,7 @@ 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.TranslateActivity
 import com.nextcloud.talk.ui.bottom.sheet.ProfileBottomSheet
 import com.nextcloud.talk.ui.dialog.AttachmentDialog
 import com.nextcloud.talk.ui.dialog.MessageActionsDialog
@@ -3231,6 +3232,16 @@ class ChatActivity :
         clipboardManager.setPrimaryClip(clipData)
     }
 
+    fun translateMessage(message: IMessage?) {
+        val bundle = Bundle()
+        bundle.putString(BundleKeys.KEY_TRANSLATE_MESSAGE, message?.text)
+
+        val intent = Intent(this, TranslateActivity::class.java)
+        intent.putExtras(bundle)
+        startActivity(intent)
+
+    }
+
     private fun hasVisibleItems(message: ChatMessage): Boolean {
         return !message.isDeleted || // copy message
             message.replyable || // reply to

+ 19 - 0
app/src/main/java/com/nextcloud/talk/models/json/translations/TranslateData.kt

@@ -0,0 +1,19 @@
+package com.nextcloud.talk.models.json.translations
+
+import android.os.Parcelable
+import com.bluelinelabs.logansquare.annotation.JsonField
+import com.bluelinelabs.logansquare.annotation.JsonObject
+import kotlinx.parcelize.Parcelize
+
+@Parcelize
+@JsonObject
+data class TranslateData(
+
+    @JsonField(name = ["text"])
+    var text: String?,
+    @JsonField(name = ["from"])
+    var fromLanguage: String?
+) : Parcelable {
+    // This constructor is added to work with the 'com.bluelinelabs.logansquare.annotation.JsonObject'
+    constructor() : this(null, null )
+}

+ 19 - 0
app/src/main/java/com/nextcloud/talk/models/json/translations/TranslateOCS.kt

@@ -0,0 +1,19 @@
+package com.nextcloud.talk.models.json.translations
+
+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 TranslateOCS( // TODO finish this model
+    @JsonField(name = ["meta"])
+    var meta: GenericMeta?,
+    @JsonField(name = ["data"])
+    var data: TranslateData?
+) : Parcelable {
+    // This constructor is added to work with the 'com.bluelinelabs.logansquare.annotation.JsonObject'
+    constructor() : this(null, TranslateData())
+}

+ 16 - 0
app/src/main/java/com/nextcloud/talk/models/json/translations/TranslationsOverall.kt

@@ -0,0 +1,16 @@
+package com.nextcloud.talk.models.json.translations
+
+import android.os.Parcelable
+import com.bluelinelabs.logansquare.annotation.JsonField
+import com.bluelinelabs.logansquare.annotation.JsonObject
+import kotlinx.parcelize.Parcelize
+
+@Parcelize
+@JsonObject
+class TranslationsOverall(
+    @JsonField(name = ["ocs"])
+    var ocs: TranslateOCS?
+    ) : Parcelable {
+        // This constructor is added to work with the 'com.bluelinelabs.logansquare.annotation.JsonObject'
+        constructor() : this(null)
+    }

+ 136 - 0
app/src/main/java/com/nextcloud/talk/translate/TranslateActivity.kt

@@ -0,0 +1,136 @@
+package com.nextcloud.talk.translate
+import android.graphics.drawable.ColorDrawable
+import android.os.Bundle
+import android.text.method.ScrollingMovementMethod
+import android.view.View
+import autodagger.AutoInjector
+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.users.UserManager
+import com.nextcloud.talk.utils.bundle.BundleKeys
+import javax.inject.Inject
+
+
+
+// TODO include license at top of the file
+
+
+@AutoInjector(NextcloudTalkApplication::class)
+class TranslateActivity : BaseActivity()
+{
+    private lateinit var binding: ActivityTranslateBinding
+
+    @Inject
+    lateinit var ncApi: NcApi
+
+    @Inject
+    lateinit var userManager: UserManager
+
+    lateinit var currentUser: User
+
+    val url : String? = currentUser.baseUrl + "/translation"
+
+    var text : String? = null
+
+    var fromLanguage : String = "en"
+
+    val toLanguage : String = "de"
+
+    override fun onCreate(savedInstanceState: Bundle?) {
+        super.onCreate(savedInstanceState)
+        binding = ActivityTranslateBinding.inflate(layoutInflater)
+
+
+        setupTextViews()
+        setupActionBar()
+        setupSpinners()
+        setContentView(binding.root)
+        // translate()
+    }
+
+    private fun setupActionBar() {
+        setSupportActionBar(binding.translationToolbar)
+        binding.translationToolbar.setNavigationOnClickListener {
+            onBackPressed()
+        }
+        supportActionBar?.setDisplayHomeAsUpEnabled(true)
+        supportActionBar?.setDisplayShowHomeEnabled(true)
+        supportActionBar?.setIcon(ColorDrawable(resources!!.getColor(R.color.transparent)))
+        supportActionBar?.title = "Translation"
+        viewThemeUtils.material.themeToolbar(binding.translationToolbar)
+    }
+
+    private fun setupTextViews() {
+        val original = binding.originalMessageTextview
+        val translation = binding.translatedMessageTextview
+
+        original.movementMethod = ScrollingMovementMethod()
+        translation.movementMethod = ScrollingMovementMethod()
+
+        val bundle = intent.extras
+        binding.originalMessageTextview.text = bundle?.getString(BundleKeys.KEY_TRANSLATE_MESSAGE)
+        text = binding.originalMessageTextview.text as String?
+    }
+
+
+    private fun getLanguageOptions() {
+        // TODO implement this function to retrieve an array of strings from the server for each language option
+        // this uses another call to their /languages endpoint which requires another separate function in ncAPI and
+        // seprarate models for the JSON :|
+    }
+
+    // TODO get this function working
+    // private fun translate() {
+    //     val credentials = ApiUtils.getCredentials(currentUser.username, currentUser.token)
+    //
+    //     val translateURL = url + "/translate"
+    //
+    //
+    //
+    //     ncApi.translateMessage(credentials, translateURL, text, fromLanguage, toLanguage)
+    //         ?.subscribeOn(Schedulers.io())
+    //         ?.observeOn(AndroidSchedulers.mainThread())
+    //         ?.subscribe(object : Observer<TranslationsOverall> {
+    //             override fun onSubscribe(d: Disposable) {
+    //                 // TODO set progress bar to show
+    //                 binding.translatedMessageTextview.visibility = View.GONE
+    //                 binding.progressBar.visibility = View.VISIBLE
+    //             }
+    //
+    //             override fun onNext(translationOverall: TranslationsOverall) {
+    //                 // TODO hide progress bar
+    //                 binding.progressBar.visibility = View.GONE
+    //                 binding.translatedMessageTextview.visibility = View.VISIBLE
+    //                 binding.translatedMessageTextview.text = translationOverall.ocs?.data?.text
+    //             }
+    //
+    //             override fun onError(e: Throwable) {
+    //                 Log.e("TranslateActivity", "Error")
+    //             }
+    //
+    //             override fun onComplete() {
+    //                 // not needed?
+    //             }
+    //         })
+    //
+    // }
+
+    private fun setupSpinners() {
+        // TODO set spinner options to use array from getLanguageOptions()
+
+        // TODO set onClickListener to call server using translate()
+        binding.toLanguageSpinner.setOnClickListener(View.OnClickListener {
+            // translate()
+        })
+
+        binding.fromLanguageSpinner.setOnClickListener(View.OnClickListener {
+            // translate()
+        })
+    }
+
+
+}

+ 12 - 0
app/src/main/java/com/nextcloud/talk/ui/dialog/MessageActionsDialog.kt

@@ -88,6 +88,7 @@ class MessageActionsDialog(
         viewThemeUtils.platform.themeDialog(dialogMessageActionsBinding.root)
         initEmojiBar(hasChatPermission)
         initMenuItemCopy(!message.isDeleted)
+        initMenuItemTranslate(!message.isDeleted)
         initMenuReplyToMessage(message.replyable && hasChatPermission)
         initMenuReplyPrivately(
             message.replyable &&
@@ -296,6 +297,17 @@ class MessageActionsDialog(
         dialogMessageActionsBinding.menuCopyMessage.visibility = getVisibility(visible)
     }
 
+    private fun initMenuItemTranslate(visible: Boolean) {
+        if (visible) {
+            dialogMessageActionsBinding.menuTranslateMessage.setOnClickListener {
+                chatActivity.translateMessage(message)
+                dismiss()
+            }
+        }
+
+        dialogMessageActionsBinding.menuCopyMessage.visibility = getVisibility(visible)
+    }
+
     private fun getVisibility(visible: Boolean): Int {
         return if (visible) {
             View.VISIBLE

+ 1 - 0
app/src/main/java/com/nextcloud/talk/utils/bundle/BundleKeys.kt

@@ -29,6 +29,7 @@ object BundleKeys {
     const val KEY_SELECTED_EMAILS = "KEY_SELECTED_EMAILS"
     const val KEY_USERNAME = "KEY_USERNAME"
     const val KEY_TOKEN = "KEY_TOKEN"
+    const val KEY_TRANSLATE_MESSAGE = "KEY_TRANSLATE_MESSAGE"
     const val KEY_BASE_URL = "KEY_BASE_URL"
     const val KEY_IS_ACCOUNT_IMPORT = "KEY_IS_ACCOUNT_IMPORT"
     const val KEY_ORIGINAL_PROTOCOL = "KEY_ORIGINAL_PROTOCOL"

+ 5 - 0
app/src/main/res/drawable/ic_baseline_translate_24.xml

@@ -0,0 +1,5 @@
+<vector android:height="24dp" android:tint="#000000"
+    android:viewportHeight="24" android:viewportWidth="24"
+    android:width="24dp" xmlns:android="http://schemas.android.com/apk/res/android">
+    <path android:fillColor="@android:color/white" android:pathData="M12.87,15.07l-2.54,-2.51 0.03,-0.03c1.74,-1.94 2.98,-4.17 3.71,-6.53L17,6L17,4h-7L10,2L8,2v2L1,4v1.99h11.17C11.5,7.92 10.44,9.75 9,11.35 8.07,10.32 7.3,9.19 6.69,8h-2c0.73,1.63 1.73,3.17 2.98,4.56l-5.09,5.02L4,19l5,-5 3.11,3.11 0.76,-2.04zM18.5,10h-2L12,22h2l1.12,-3h4.75L21,22h2l-4.5,-12zM15.88,17l1.62,-4.33L19.12,17h-3.24z"/>
+</vector>

+ 100 - 0
app/src/main/res/layout/activity_translate.xml

@@ -0,0 +1,100 @@
+<?xml version="1.0" encoding="utf-8"?>
+<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
+    xmlns:app="http://schemas.android.com/apk/res-auto"
+    xmlns:tools="http://schemas.android.com/tools"
+    android:orientation="vertical"
+    android:weightSum="2"
+    android:layout_width="match_parent"
+    android:layout_height="match_parent">
+
+    <com.google.android.material.appbar.AppBarLayout
+        android:id="@+id/translation_appbar"
+        android:layout_width="match_parent"
+        android:layout_height="wrap_content">
+        <com.google.android.material.appbar.MaterialToolbar
+            android:id="@+id/translation_toolbar"
+            android:layout_width="match_parent"
+            android:layout_height="?attr/actionBarSize"
+            android:background="@color/appbar"
+            android:theme="?attr/actionBarPopupTheme"
+            app:layout_scrollFlags="scroll|enterAlways"
+            app:navigationIconTint="@color/fontAppbar"
+            app:popupTheme="@style/appActionBarPopupMenu"
+            app:titleTextColor="@color/fontAppbar"
+            tools:title="" >
+
+        </com.google.android.material.appbar.MaterialToolbar>
+
+    </com.google.android.material.appbar.AppBarLayout>
+
+    <RelativeLayout
+        android:layout_width="match_parent"
+        android:layout_height="wrap_content" >
+        <TextView
+            android:id="@+id/fromLanguage"
+            android:layout_margin="@dimen/standard_margin"
+            android:textSize="@dimen/input_text_size"
+            android:layout_width="wrap_content"
+            android:layout_height="wrap_content"
+            android:text="From:"/>
+        <TextView
+            android:id="@+id/toLanguage"
+            android:layout_margin="@dimen/standard_margin"
+            android:textSize="@dimen/input_text_size"
+            android:layout_width="wrap_content"
+            android:layout_height="wrap_content"
+            android:layout_below="@id/fromLanguage"
+            android:text="To:"/>
+
+        <Spinner
+            android:id="@+id/fromLanguageSpinner"
+            android:layout_width="wrap_content"
+            android:layout_height="wrap_content"
+            android:layout_marginStart="@dimen/standard_margin"
+            android:layout_marginTop="@dimen/standard_margin"
+            android:layout_marginEnd="@dimen/standard_margin"
+            android:layout_marginBottom="@dimen/standard_margin"
+            android:layout_toRightOf="@id/fromLanguage" />
+        <Spinner
+            android:id="@+id/toLanguageSpinner"
+            android:layout_margin="@dimen/standard_margin"
+            android:layout_toRightOf="@id/toLanguage"
+            android:layout_below="@id/fromLanguage"
+            android:layout_width="wrap_content"
+            android:layout_height="wrap_content"/>
+
+    </RelativeLayout>
+
+    <TextView
+        android:id="@+id/original_message_textview"
+        android:layout_width="match_parent"
+        android:layout_height="wrap_content"
+        android:layout_weight="1"
+        android:textSize="@dimen/message_text_size"
+        android:textColor="@color/nc_incoming_text_default"
+        android:padding="@dimen/dialog_padding"
+        android:layout_margin="@dimen/standard_margin"
+        android:background="@drawable/shape_incoming_message"
+        android:scrollbars="vertical"
+        android:text="" />
+
+    <TextView
+        android:id="@+id/translated_message_textview"
+        android:layout_width="match_parent"
+        android:layout_height="wrap_content"
+        android:layout_margin="@dimen/standard_margin"
+        android:layout_weight="1"
+        android:scrollbars="vertical"
+        android:text=""
+        android:textSize="@dimen/message_text_size"
+        android:visibility="visible" />
+
+    <ProgressBar
+        android:id="@+id/progressBar"
+        style="?android:attr/progressBarStyle"
+        android:layout_width="match_parent"
+        android:layout_height="wrap_content"
+        android:visibility="gone" />
+
+
+</LinearLayout>

+ 33 - 0
app/src/main/res/layout/dialog_message_actions.xml

@@ -287,6 +287,39 @@
 
         </LinearLayout>
 
+        <LinearLayout
+            android:id="@+id/menu_translate_message"
+            android:layout_width="match_parent"
+            android:layout_height="@dimen/bottom_sheet_item_height"
+            android:background="?android:attr/selectableItemBackground"
+            android:gravity="center_vertical"
+            android:orientation="horizontal"
+            tools:ignore="UseCompoundDrawables">
+
+            <ImageView
+                android:id="@+id/menu_icon_translate_message"
+                android:layout_width="wrap_content"
+                android:layout_height="wrap_content"
+                android:contentDescription="@null"
+                android:paddingStart="@dimen/standard_padding"
+                android:paddingEnd="@dimen/zero"
+                android:src="@drawable/ic_baseline_translate_24"
+                app:tint="@color/high_emphasis_menu_icon" />
+
+            <androidx.appcompat.widget.AppCompatTextView
+                android:id="@+id/menu_text_translate_message"
+                android:layout_width="match_parent"
+                android:layout_height="wrap_content"
+                android:layout_gravity="start|center_vertical"
+                android:paddingStart="@dimen/standard_double_padding"
+                android:paddingEnd="@dimen/standard_padding"
+                android:text="@string/translate"
+                android:textAlignment="viewStart"
+                android:textColor="@color/high_emphasis_text"
+                android:textSize="@dimen/bottom_sheet_text_size" />
+
+        </LinearLayout>
+
         <LinearLayout
             android:id="@+id/menu_delete_message"
             android:layout_width="match_parent"

+ 2 - 0
app/src/main/res/values/strings.xml

@@ -656,5 +656,7 @@ How to translate with transifex:
     <string name="nc_not_allowed_to_activate_audio">You are not allowed to activate audio!</string>
     <string name="nc_not_allowed_to_activate_video">You are not allowed to activate video!</string>
     <string name="scroll_to_bottom">Scroll to bottom</string>
+    <string name="translate">Translate</string>
+    <string name="translation">Translation</string>
 
 </resources>