Эх сурвалжийг харах

Add editing of conversation name and description

Improvements to be done:
MVVM
emoji picker
horizontal design

Signed-off-by: Marcel Hibbe <dev@mhibbe.de>
Marcel Hibbe 2 жил өмнө
parent
commit
6152fa50fe

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

@@ -134,6 +134,12 @@ public interface NcApi {
                                           @Field("roomName") String roomName);
 
 
+    @FormUrlEncoded
+    @PUT
+    Observable<GenericOverall> setConversationDescription(@Header("Authorization") String authorization,
+                                                          @Url String url,
+                                          @Field("description") String description);
+
     /*
         QueryMap items are as follows:
             - "newParticipant" : "user"

+ 0 - 2
app/src/main/java/com/nextcloud/talk/conversation/info/ConversationInfoActivity.kt

@@ -219,8 +219,6 @@ class ConversationInfoActivity :
 
     override fun onPrepareOptionsMenu(menu: Menu): Boolean {
         super.onPrepareOptionsMenu(menu)
-        // menu.findItem(R.id.edit).isVisible = editableFields.size > 0
-
         return true
     }
 

+ 112 - 58
app/src/main/java/com/nextcloud/talk/conversation/info/ConversationInfoEditActivity.kt

@@ -1,14 +1,8 @@
 /*
  * Nextcloud Talk application
  *
- * @author Mario Danic
- * @author Andy Scherzinger
- * @author Tim Krüger
  * @author Marcel Hibbe
- * Copyright (C) 2022-2023 Marcel Hibbe (dev@mhibbe.de)
- * Copyright (C) 2021-2022 Tim Krüger <t@timkrueger.me>
- * Copyright (C) 2021 Andy Scherzinger (info@andy-scherzinger.de)
- * Copyright (C) 2017-2018 Mario Danic <mario@lovelyhq.com>
+ * Copyright (C) 2023 Marcel Hibbe (dev@mhibbe.de)
  *
  * 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
@@ -33,6 +27,7 @@ import android.os.Bundle
 import android.text.TextUtils
 import android.util.Log
 import android.view.Menu
+import android.view.MenuItem
 import android.widget.Toast
 import androidx.core.net.toFile
 import androidx.core.view.ViewCompat
@@ -51,11 +46,11 @@ import com.nextcloud.talk.models.json.conversations.Conversation
 import com.nextcloud.talk.models.json.generic.GenericOverall
 import com.nextcloud.talk.repositories.conversations.ConversationsRepository
 import com.nextcloud.talk.utils.ApiUtils
-import com.nextcloud.talk.utils.DateUtils
 import com.nextcloud.talk.utils.DisplayUtils
 import com.nextcloud.talk.utils.Mimetype
 import com.nextcloud.talk.utils.PickImage
 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
@@ -79,18 +74,12 @@ class ConversationInfoEditActivity :
     @Inject
     lateinit var conversationsRepository: ConversationsRepository
 
-    @Inject
-    lateinit var dateUtils: DateUtils
-
     private lateinit var conversationToken: String
     private lateinit var conversationUser: User
     private lateinit var credentials: String
 
     private var conversation: Conversation? = null
 
-    private lateinit var optionsMenu: Menu
-    private var edit = false
-
     private lateinit var pickImage: PickImage
 
     override fun onCreate(savedInstanceState: Bundle?) {
@@ -111,6 +100,9 @@ class ConversationInfoEditActivity :
             conversation = Parcels.unwrap<Conversation>(extras.getParcelable(BundleKeys.KEY_ACTIVE_CONVERSATION))
         }
 
+        viewThemeUtils.material.colorTextInputLayout(binding.conversationNameInputLayout)
+        viewThemeUtils.material.colorTextInputLayout(binding.conversationDescriptionInputLayout)
+
         credentials = ApiUtils.getCredentials(conversationUser.username, conversationUser.token)
     }
 
@@ -119,10 +111,14 @@ class ConversationInfoEditActivity :
 
         loadConversationAvatar()
 
-        binding.displayNameText.text = conversation!!.displayName
+        binding.conversationName.setText(conversation!!.displayName)
 
         if (conversation!!.description != null && conversation!!.description!!.isNotEmpty()) {
-            binding.descriptionText.text = conversation!!.description
+            binding.conversationDescription.setText(conversation!!.description)
+        }
+
+        if (!CapabilitiesUtilNew.isConversationDescriptionEndpointAvailable(conversationUser)) {
+            binding.conversationDescription.isEnabled = false
         }
 
         setupAvatarOptions()
@@ -157,47 +153,105 @@ class ConversationInfoEditActivity :
         viewThemeUtils.material.themeToolbar(binding.conversationInfoEditToolbar)
     }
 
-    // override fun onCreateOptionsMenu(menu: Menu): Boolean {
-    //     super.onCreateOptionsMenu(menu)
-    //
-    //     menuInflater.inflate(R.menu.menu_conversation_info, menu)
-    //     optionsMenu = menu
-    //     return true
-    // }
-    //
-    // override fun onPrepareOptionsMenu(menu: Menu): Boolean {
-    //     super.onPrepareOptionsMenu(menu)
-    //     // menu.findItem(R.id.edit).isVisible = editableFields.size > 0
-    //     setEditMode(true)
-    //     return true
-    // }
-    //
-    // override fun onOptionsItemSelected(item: MenuItem): Boolean {
-    //     if (item.itemId == R.id.edit) {
-    //         toggleEditMode()
-    //     }
-    //     return true
-    // }
-    //
-    //
-    // private fun toggleEditMode() {
-    //     edit = !edit
-    //     if (edit) {
-    //         setEditMode(true)
-    //     } else {
-    //         setEditMode(false)
-    //     }
-    // }
-    //
-    // private fun setEditMode(editing: Boolean) {
-    //     if (editing) {
-    //         optionsMenu.findItem(R.id.edit).setTitle(R.string.save)
-    //         edit = true
-    //     } else {
-    //         optionsMenu.findItem(R.id.edit).setTitle(R.string.edit)
-    //         edit = false
-    //     }
-    // }
+    override fun onCreateOptionsMenu(menu: Menu): Boolean {
+        super.onCreateOptionsMenu(menu)
+        menuInflater.inflate(R.menu.menu_conversation_info_edit, menu)
+        return true
+    }
+
+    override fun onPrepareOptionsMenu(menu: Menu): Boolean {
+        super.onPrepareOptionsMenu(menu)
+        return true
+    }
+
+    override fun onOptionsItemSelected(item: MenuItem): Boolean {
+        if (item.itemId == R.id.save) {
+            saveConversationNameAndDescription()
+        }
+        return true
+    }
+
+    private fun saveConversationNameAndDescription() {
+        val apiVersion =
+            ApiUtils.getConversationApiVersion(conversationUser, intArrayOf(ApiUtils.APIv4, ApiUtils.APIv1))
+
+        ncApi.renameRoom(
+            credentials,
+            ApiUtils.getUrlForRoom(
+                apiVersion,
+                conversationUser.baseUrl,
+                conversation!!.token
+            ),
+            binding.conversationName.text.toString()
+        )
+            .subscribeOn(Schedulers.io())
+            .observeOn(AndroidSchedulers.mainThread())
+            .retry(1)
+            .subscribe(object : Observer<GenericOverall> {
+                override fun onSubscribe(d: Disposable) {
+                    // unused atm
+                }
+
+                override fun onNext(genericOverall: GenericOverall) {
+                    if (CapabilitiesUtilNew.isConversationDescriptionEndpointAvailable(conversationUser)) {
+                        saveConversationDescription()
+                    } else {
+                        finish()
+                    }
+                }
+
+                override fun onError(e: Throwable) {
+                    Toast.makeText(
+                        applicationContext,
+                        context.getString(R.string.default_error_msg),
+                        Toast.LENGTH_LONG
+                    ).show()
+                    Log.e(TAG, "Error while saving conversation name", e)
+                }
+
+                override fun onComplete() {
+                }
+            })
+    }
+
+    fun saveConversationDescription() {
+        val apiVersion =
+            ApiUtils.getConversationApiVersion(conversationUser, intArrayOf(ApiUtils.APIv4, ApiUtils.APIv1))
+
+        ncApi.setConversationDescription(
+            credentials,
+            ApiUtils.getUrlForConversationDescription(
+                apiVersion,
+                conversationUser.baseUrl,
+                conversation!!.token
+            ),
+            binding.conversationDescription.text.toString()
+        )
+            .subscribeOn(Schedulers.io())
+            .observeOn(AndroidSchedulers.mainThread())
+            .retry(1)
+            .subscribe(object : Observer<GenericOverall> {
+                override fun onSubscribe(d: Disposable) {
+                    // unused atm
+                }
+
+                override fun onNext(genericOverall: GenericOverall) {
+                    finish()
+                }
+
+                override fun onError(e: Throwable) {
+                    Toast.makeText(
+                        applicationContext,
+                        context.getString(R.string.default_error_msg),
+                        Toast.LENGTH_LONG
+                    ).show()
+                    Log.e(TAG, "Error while saving conversation description", e)
+                }
+
+                override fun onComplete() {
+                }
+            })
+    }
 
     override fun onActivityResult(requestCode: Int, resultCode: Int, data: Intent?) {
         super.onActivityResult(requestCode, resultCode, data)
@@ -322,6 +376,6 @@ class ConversationInfoEditActivity :
     }
 
     companion object {
-        private const val TAG = "ConversationEditInfo"
+        private val TAG = ConversationInfoEditActivity::class.simpleName
     }
 }

+ 4 - 0
app/src/main/java/com/nextcloud/talk/utils/ApiUtils.java

@@ -506,4 +506,8 @@ public class ApiUtils {
     public static String getUrlForRequestAssistance(int version, String baseUrl, String token) {
         return getUrlForApi(version, baseUrl) + "/breakout-rooms/" + token + "/request-assistance";
     }
+
+    public static String getUrlForConversationDescription(int version, String baseUrl, String token) {
+        return getUrlForRoom(version, baseUrl, token) + "/description";
+    }
 }

+ 4 - 0
app/src/main/java/com/nextcloud/talk/utils/database/user/CapabilitiesUtilNew.kt

@@ -148,6 +148,10 @@ object CapabilitiesUtilNew {
         return user.capabilities?.spreedCapability?.features?.contains("avatar") == true
     }
 
+    fun isConversationDescriptionEndpointAvailable(user: User): Boolean {
+        return user.capabilities?.spreedCapability?.features?.contains("room-description") == true
+    }
+
     fun canEditScopes(user: User): Boolean {
         return user.capabilities?.provisioningCapability?.accountPropertyScopesVersion != null &&
             user.capabilities!!.provisioningCapability!!.accountPropertyScopesVersion!! > 1

+ 45 - 20
app/src/main/res/layout/activity_conversation_info_edit.xml

@@ -1,14 +1,8 @@
 <?xml version="1.0" encoding="utf-8"?><!--
   ~ Nextcloud Talk application
   ~
-  ~ @author Mario Danic
-  ~ @author Andy Scherzinger
   ~ @author Marcel Hibbe
-  ~ @author Tim Krüger
-  ~ Copyright (C) 2022 Tim Krüger <t@timkrueger.me>
-  ~ Copyright (C) 2022-2023 Marcel Hibbe <dev@mhibbe.de>
-  ~ Copyright (C) 2021 Andy Scherzinger <info@andy-scherzinger.de>
-  ~ Copyright (C) 2017-2018 Mario Danic <mario@lovelyhq.com>
+  ~ Copyright (C) 2023 Marcel Hibbe <dev@mhibbe.de>
   ~
   ~ 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
@@ -122,23 +116,54 @@
                 app:srcCompat="@drawable/trashbin" />
         </LinearLayout>
 
-        <androidx.emoji2.widget.EmojiTextView
-            android:id="@+id/display_name_text"
-            android:layout_width="wrap_content"
+        <com.google.android.material.textfield.TextInputLayout
+            android:id="@+id/conversation_name_input_layout"
+            style="@style/Widget.MaterialComponents.TextInputLayout.OutlinedBox"
+            android:layout_width="match_parent"
             android:layout_height="wrap_content"
-            android:layout_gravity="center"
-            android:layout_marginTop="@dimen/margin_between_elements"
-            tools:text="Jane Doe" />
+            android:layout_margin="@dimen/standard_margin"
+            android:minHeight="@dimen/min_size_clickable_area"
+            app:boxStrokeColor="@color/colorPrimary"
+            app:errorTextAppearance="@style/ErrorAppearance"
+            app:hintTextColor="@color/colorPrimary"
+            android:hint="@string/nc_call_name">
+
+            <com.nextcloud.talk.utils.EmojiTextInputEditText
+                android:id="@+id/conversation_name"
+                android:layout_width="match_parent"
+                android:layout_height="wrap_content"
+                android:imeOptions="actionNext"
+                android:inputType="text"
+                android:singleLine="true"
+                android:maxLength="255"
+                android:textAlignment="viewStart"
+                tools:text="Our conversation name" />
+
+        </com.google.android.material.textfield.TextInputLayout>
 
-        <androidx.emoji2.widget.EmojiTextView
-            android:id="@+id/description_text"
-            android:layout_width="wrap_content"
+        <com.google.android.material.textfield.TextInputLayout
+            android:id="@+id/conversation_description_input_layout"
+            style="@style/Widget.MaterialComponents.TextInputLayout.OutlinedBox"
+            android:layout_width="match_parent"
             android:layout_height="wrap_content"
-            android:layout_gravity="center"
             android:layout_margin="@dimen/standard_margin"
-            android:layout_marginTop="@dimen/margin_between_elements"
-            android:autoLink="web"
-            tools:text="Hello world!" />
+            android:minHeight="@dimen/min_size_clickable_area"
+            app:boxStrokeColor="@color/colorPrimary"
+            app:errorTextAppearance="@style/ErrorAppearance"
+            app:hintTextColor="@color/colorPrimary"
+            android:hint="@string/nc_conversation_description">
+
+            <com.nextcloud.talk.utils.EmojiTextInputEditText
+                android:id="@+id/conversation_description"
+                android:layout_width="match_parent"
+                android:layout_height="wrap_content"
+                android:imeOptions="actionNext"
+                android:inputType="text|textMultiLine"
+                android:singleLine="true"
+                android:textAlignment="viewStart"
+                tools:text="Our conversation description" />
+
+        </com.google.android.material.textfield.TextInputLayout>
 
     </LinearLayout>
 

+ 28 - 0
app/src/main/res/menu/menu_conversation_info_edit.xml

@@ -0,0 +1,28 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+  Nextcloud Android Talk application
+
+  @author Tobias Kaminsky
+  Copyright (C) 2021 Tobias Kaminsky
+  Copyright (C) 2021 Nextcloud GmbH
+ 
+  This program is free software: you can redistribute it and/or modify
+  it under the terms of the GNU Affero 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 Affero General Public License for more details.
+ 
+  You should have received a copy of the GNU Affero General Public License
+  along with this program. If not, see <https://www.gnu.org/licenses/>.
+-->
+<menu xmlns:android="http://schemas.android.com/apk/res/android"
+    xmlns:app="http://schemas.android.com/apk/res-auto">
+    <item
+        android:id="@+id/save"
+        android:title="@string/save"
+        app:showAsAction="ifRoom" />
+</menu>

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

@@ -637,6 +637,7 @@ How to translate with transifex:
     <string name="set_avatar_from_camera">Set avatar from camera</string>
 
     <string name="nc_conversation_settings">Conversation settings</string>
+    <string name="nc_conversation_description">Conversation description</string>
 
     <!-- Expiring messages -->
     <string name="nc_expire_messages">Expire chat messages</string>