浏览代码

Merge pull request #3812 from nextcloud/share_conversation_link

share conversation link to other apps
Marcel Hibbe 1 年之前
父节点
当前提交
1983f2aadb

+ 17 - 8
app/src/main/java/com/nextcloud/talk/conversationinfo/ConversationInfoActivity.kt

@@ -43,8 +43,8 @@ import com.nextcloud.talk.application.NextcloudTalkApplication
 import com.nextcloud.talk.bottomsheet.items.BasicListItemWithImage
 import com.nextcloud.talk.bottomsheet.items.listItemsWithImage
 import com.nextcloud.talk.contacts.ContactsActivity
-import com.nextcloud.talk.conversationinfoedit.ConversationInfoEditActivity
 import com.nextcloud.talk.conversationinfo.viewmodel.ConversationInfoViewModel
+import com.nextcloud.talk.conversationinfoedit.ConversationInfoEditActivity
 import com.nextcloud.talk.data.user.model.User
 import com.nextcloud.talk.databinding.ActivityConversationInfoBinding
 import com.nextcloud.talk.events.EventStatus
@@ -69,12 +69,13 @@ import com.nextcloud.talk.models.json.participants.ParticipantsOverall
 import com.nextcloud.talk.repositories.conversations.ConversationsRepository
 import com.nextcloud.talk.shareditems.activities.SharedItemsActivity
 import com.nextcloud.talk.utils.ApiUtils
-import com.nextcloud.talk.utils.SpreedFeatures
+import com.nextcloud.talk.utils.CapabilitiesUtil
 import com.nextcloud.talk.utils.ConversationUtils
 import com.nextcloud.talk.utils.DateConstants
 import com.nextcloud.talk.utils.DateUtils
+import com.nextcloud.talk.utils.ShareUtils
+import com.nextcloud.talk.utils.SpreedFeatures
 import com.nextcloud.talk.utils.bundle.BundleKeys
-import com.nextcloud.talk.utils.CapabilitiesUtil
 import com.nextcloud.talk.utils.database.user.CurrentUserProviderNew
 import com.nextcloud.talk.utils.preferences.preferencestorage.DatabaseStorageModule
 import eu.davidea.flexibleadapter.FlexibleAdapter
@@ -161,7 +162,6 @@ class ConversationInfoActivity :
         conversationToken = intent.getStringExtra(BundleKeys.KEY_ROOM_TOKEN)!!
         hasAvatarSpacing = intent.getBooleanExtra(BundleKeys.KEY_ROOM_ONE_TO_ONE, false)
         credentials = ApiUtils.getCredentials(conversationUser.username, conversationUser.token)!!
-
         initObservers()
     }
 
@@ -203,6 +203,17 @@ class ConversationInfoActivity :
                 is ConversationInfoViewModel.GetRoomSuccessState -> {
                     conversation = state.conversationModel
                     viewModel.getCapabilities(conversationUser, conversationToken, conversation!!)
+                    if (ConversationUtils.isNoteToSelfConversation(conversation)) {
+                        binding.shareConversationButton.visibility = GONE
+                    }
+                    binding.shareConversationButton.setOnClickListener {
+                        ShareUtils.shareConversationLink(
+                            this,
+                            conversationUser.baseUrl,
+                            conversation?.token,
+                            conversation?.name
+                        )
+                    }
                 }
 
                 is ConversationInfoViewModel.GetRoomErrorState -> {
@@ -862,11 +873,9 @@ class ConversationInfoActivity :
                 val v: String = resources.getStringArray(R.array.message_expiring_values)[position]
                 databaseStorageModule!!.saveString("conversation_settings_dropdown", v)
             }
-
-            binding.conversationSettingsDropdown.visibility = VISIBLE
-            binding.conversationInfoExpireMessagesExplanation.visibility = VISIBLE
+            binding.messageExpirationSettings.visibility = VISIBLE
         } else {
-            binding.conversationSettings.visibility = GONE
+            binding.messageExpirationSettings.visibility = GONE
         }
     }
 

+ 0 - 31
app/src/main/java/com/nextcloud/talk/conversationinfo/GuestAccessHelper.kt

@@ -8,7 +8,6 @@
  */
 package com.nextcloud.talk.conversationinfo
 
-import android.content.Intent
 import android.util.Log
 import android.view.LayoutInflater
 import android.view.View
@@ -24,8 +23,6 @@ import com.nextcloud.talk.models.domain.ConversationType
 import com.nextcloud.talk.models.json.capabilities.SpreedCapability
 import com.nextcloud.talk.repositories.conversations.ConversationsRepository
 import com.nextcloud.talk.utils.ConversationUtils
-import com.nextcloud.talk.utils.Mimetype
-import com.nextcloud.talk.utils.ShareUtils
 import io.reactivex.Observer
 import io.reactivex.android.schedulers.AndroidSchedulers
 import io.reactivex.disposables.Disposable
@@ -82,10 +79,6 @@ class GuestAccessHelper(
             }
         }
 
-        binding.guestAccessView.shareConversationButton.setOnClickListener {
-            shareUrl()
-        }
-
         binding.guestAccessView.resendInvitationsButton.setOnClickListener {
             conversationsRepository.resendInvitations(conversation.token!!).subscribeOn(Schedulers.io())
                 .observeOn(AndroidSchedulers.mainThread()).subscribe(ResendInvitationsObserver())
@@ -123,28 +116,6 @@ class GuestAccessHelper(
         )
     }
 
-    private fun shareUrl() {
-        val sendIntent: Intent = Intent().apply {
-            action = Intent.ACTION_SEND
-            type = Mimetype.TEXT_PLAIN
-            putExtra(
-                Intent.EXTRA_SUBJECT,
-                String.format(
-                    activity.resources.getString(R.string.nc_share_subject),
-                    activity.resources.getString(R.string.nc_app_product_name)
-                )
-            )
-
-            putExtra(
-                Intent.EXTRA_TEXT,
-                ShareUtils.getStringForIntent(activity, conversationUser, conversation)
-            )
-        }
-
-        val shareIntent = Intent.createChooser(sendIntent, null)
-        activity.startActivity(shareIntent)
-    }
-
     inner class ResendInvitationsObserver : Observer<ConversationsRepository.ResendInvitationsResult> {
 
         private lateinit var resendInvitationsResult: ConversationsRepository.ResendInvitationsResult
@@ -200,7 +171,6 @@ class GuestAccessHelper(
 
     private fun showAllOptions() {
         binding.guestAccessView.guestAccessSettingsPasswordProtection.visibility = View.VISIBLE
-        binding.guestAccessView.shareConversationButton.visibility = View.VISIBLE
         if (conversationUser.capabilities?.spreedCapability?.features?.contains("sip-support") == true) {
             binding.guestAccessView.resendInvitationsButton.visibility = View.VISIBLE
         }
@@ -208,7 +178,6 @@ class GuestAccessHelper(
 
     private fun hideAllOptions() {
         binding.guestAccessView.guestAccessSettingsPasswordProtection.visibility = View.GONE
-        binding.guestAccessView.shareConversationButton.visibility = View.GONE
         binding.guestAccessView.resendInvitationsButton.visibility = View.GONE
     }
 

+ 5 - 0
app/src/main/java/com/nextcloud/talk/models/json/conversations/Conversation.kt

@@ -214,6 +214,11 @@ data class Conversation(
         }
     }
 
+    @Deprecated("Use ConversationUtil")
+    fun isNoteToSelfConversation(): Boolean {
+        return type == ConversationType.NOTE_TO_SELF
+    }
+
     enum class NotificationLevel {
         DEFAULT,
         ALWAYS,

+ 11 - 2
app/src/main/java/com/nextcloud/talk/ui/dialog/ConversationsListBottomDialog.kt

@@ -30,10 +30,11 @@ import com.nextcloud.talk.models.json.generic.GenericOverall
 import com.nextcloud.talk.ui.theme.ViewThemeUtils
 import com.nextcloud.talk.users.UserManager
 import com.nextcloud.talk.utils.ApiUtils
-import com.nextcloud.talk.utils.bundle.BundleKeys.KEY_INTERNAL_USER_ID
-import com.nextcloud.talk.utils.bundle.BundleKeys.KEY_ROOM_TOKEN
 import com.nextcloud.talk.utils.CapabilitiesUtil
+import com.nextcloud.talk.utils.ShareUtils
 import com.nextcloud.talk.utils.SpreedFeatures
+import com.nextcloud.talk.utils.bundle.BundleKeys.KEY_INTERNAL_USER_ID
+import com.nextcloud.talk.utils.bundle.BundleKeys.KEY_ROOM_TOKEN
 import io.reactivex.Observer
 import io.reactivex.android.schedulers.AndroidSchedulers
 import io.reactivex.disposables.Disposable
@@ -123,6 +124,9 @@ class ConversationsListBottomDialog(
         binding.conversationOperationRename.visibility = setVisibleIf(
             conversation.isNameEditable(currentUser)
         )
+        binding.conversationLinkShare.visibility = setVisibleIf(
+            !conversation.isNoteToSelfConversation()
+        )
 
         binding.conversationOperationDelete.visibility = setVisibleIf(
             canModerate
@@ -161,6 +165,11 @@ class ConversationsListBottomDialog(
             markConversationAsUnread()
         }
 
+        binding.conversationLinkShare.setOnClickListener {
+            ShareUtils.shareConversationLink(activity, currentUser.baseUrl, conversation.token, conversation.name)
+            dismiss()
+        }
+
         binding.conversationOperationRename.setOnClickListener {
             renameConversation()
         }

+ 31 - 8
app/src/main/java/com/nextcloud/talk/utils/ShareUtils.kt

@@ -6,17 +6,40 @@
  */
 package com.nextcloud.talk.utils
 
-import android.content.Context
+import android.app.Activity
+import android.content.Intent
+import android.net.Uri
 import com.nextcloud.talk.R
-import com.nextcloud.talk.data.user.model.User
-import com.nextcloud.talk.models.domain.ConversationModel
 
 object ShareUtils {
-    fun getStringForIntent(context: Context, user: User, conversation: ConversationModel?): String {
-        return String.format(
-            context.resources.getString(R.string.nc_share_text),
-            user.baseUrl,
-            conversation?.token
+
+    fun shareConversationLink(context: Activity, baseUrl: String?, roomToken: String?, conversationName: String?) {
+        if (baseUrl.isNullOrBlank() || roomToken.isNullOrBlank() || conversationName.isNullOrBlank()) {
+            return
+        }
+
+        val uriToShareConversation = Uri.parse(baseUrl)
+            .buildUpon()
+            .appendPath("index.php")
+            .appendPath("call")
+            .appendPath(roomToken)
+            .build()
+
+        val shareConversationLink = String.format(
+            context.getString(
+                R.string.share_link_to_conversation,
+                conversationName,
+                uriToShareConversation.toString()
+            )
         )
+
+        val sendIntent: Intent = Intent().apply {
+            action = Intent.ACTION_SEND
+            putExtra(Intent.EXTRA_TEXT, shareConversationLink)
+            type = "text/plain"
+        }
+
+        val shareIntent = Intent.createChooser(sendIntent, context.getString(R.string.nc_share_link))
+        context.startActivity(shareIntent)
     }
 }

+ 58 - 21
app/src/main/res/layout/activity_conversation_info.xml

@@ -229,38 +229,75 @@
                     android:layout_width="match_parent"
                     android:layout_height="wrap_content"
                     android:padding="@dimen/standard_padding"
-                    android:text="@string/message_expiration_title"
+                    android:text="@string/nc_conversation_settings"
                     android:textSize="@dimen/headline_text_size"
                     android:textStyle="bold" />
 
-                <com.google.android.material.textfield.TextInputLayout
-                    android:id="@+id/conversation_info_chat_settings_input_layout"
-                    style="@style/Widget.MaterialComponents.TextInputLayout.OutlinedBox.ExposedDropdownMenu"
+                <LinearLayout
+                    android:id="@+id/message_expiration_settings"
                     android:layout_width="match_parent"
                     android:layout_height="wrap_content"
-                    android:layout_marginHorizontal="@dimen/standard_margin"
-                    android:layout_marginTop="@dimen/standard_half_margin"
-                    android:hint="@string/nc_expire_messages">
+                    android:orientation="vertical">
 
-                    <com.google.android.material.textfield.MaterialAutoCompleteTextView
-                        android:id="@+id/conversation_settings_dropdown"
+                    <com.google.android.material.textfield.TextInputLayout
+                        android:id="@+id/conversation_info_chat_settings_input_layout"
+                        style="@style/Widget.MaterialComponents.TextInputLayout.OutlinedBox.ExposedDropdownMenu"
                         android:layout_width="match_parent"
                         android:layout_height="wrap_content"
-                        android:inputType="none"
-                        android:lines="1"
-                        android:popupTheme="@style/ThemeOverlay.AppTheme.PopupMenu"
-                        android:text="" />
+                        android:layout_marginHorizontal="@dimen/standard_margin"
+                        android:layout_marginTop="@dimen/standard_half_margin"
+                        android:hint="@string/nc_expire_messages">
+
+                        <com.google.android.material.textfield.MaterialAutoCompleteTextView
+                            android:id="@+id/conversation_settings_dropdown"
+                            android:layout_width="match_parent"
+                            android:layout_height="wrap_content"
+                            android:inputType="none"
+                            android:lines="1"
+                            android:popupTheme="@style/ThemeOverlay.AppTheme.PopupMenu"
+                            android:text="" />
+
+                    </com.google.android.material.textfield.TextInputLayout>
 
-                </com.google.android.material.textfield.TextInputLayout>
+                    <com.google.android.material.textview.MaterialTextView
+                        android:id="@+id/conversation_info_expire_messages_explanation"
+                        android:layout_width="match_parent"
+                        android:layout_height="wrap_content"
+                        android:layout_margin="@dimen/standard_margin"
+                        android:text="@string/nc_expire_messages_explanation"
+                        android:textColor="@color/disabled_text"
+                        android:textSize="@dimen/supporting_text_text_size" />
+                </LinearLayout>
+
+            <LinearLayout
+                android:id="@+id/share_conversation_button"
+                android:layout_width="match_parent"
+                android:layout_height="wrap_content"
+                android:paddingStart="@dimen/standard_margin"
+                android:paddingTop="@dimen/standard_half_margin"
+                android:paddingEnd="@dimen/standard_margin"
+                android:paddingBottom="@dimen/standard_half_margin"
+                android:orientation="horizontal"
+                android:background="?android:attr/selectableItemBackground">
+
+
+                <ImageView
+                    android:layout_width="24dp"
+                    android:layout_height="40dp"
+                    android:layout_marginEnd="@dimen/standard_margin"
+                    android:contentDescription="@null"
+                    android:src="@drawable/ic_share_variant"
+                    app:tint="@color/grey_600" />
 
                 <com.google.android.material.textview.MaterialTextView
-                    android:id="@+id/conversation_info_expire_messages_explanation"
-                    android:layout_width="match_parent"
-                    android:layout_height="wrap_content"
-                    android:layout_margin="@dimen/standard_margin"
-                    android:text="@string/nc_expire_messages_explanation"
-                    android:textColor="@color/disabled_text"
-                    android:textSize="@dimen/supporting_text_text_size" />
+                    android:layout_width="wrap_content"
+                    android:layout_height="match_parent"
+                    android:gravity="center_vertical"
+                    android:text="@string/nc_guest_access_share_link"
+                    android:textSize="@dimen/headline_text_size" />
+
+            </LinearLayout>
+
             </LinearLayout>
 
             <LinearLayout

+ 30 - 0
app/src/main/res/layout/dialog_conversation_operations.xml

@@ -165,6 +165,36 @@
                     android:textSize="@dimen/bottom_sheet_text_size" />
             </LinearLayout>
 
+            <LinearLayout
+                android:id="@+id/conversation_link_share"
+                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"
+                android:paddingStart="@dimen/standard_padding"
+                android:paddingEnd="@dimen/standard_padding"
+                tools:ignore="UseCompoundDrawables">
+
+                <ImageView
+                    android:layout_width="wrap_content"
+                    android:layout_height="wrap_content"
+                    android:contentDescription="@null"
+                    android:src="@drawable/ic_share_action"
+                    app:tint="@color/high_emphasis_menu_icon" />
+
+                <androidx.appcompat.widget.AppCompatTextView
+                    android:layout_width="match_parent"
+                    android:layout_height="wrap_content"
+                    android:layout_gravity="start|center_vertical"
+                    android:paddingStart="40dp"
+                    android:paddingEnd="@dimen/zero"
+                    android:text="@string/nc_share_link"
+                    android:textAlignment="viewStart"
+                    android:textColor="@color/high_emphasis_text"
+                    android:textSize="@dimen/bottom_sheet_text_size" />
+            </LinearLayout>
+
             <LinearLayout
                 android:id="@+id/conversation_operation_rename"
                 android:layout_width="match_parent"

+ 0 - 28
app/src/main/res/layout/item_guest_access_settings.xml

@@ -108,34 +108,6 @@
 
                 </LinearLayout>
 
-                <LinearLayout
-                    android:id="@+id/share_conversation_button"
-                    android:layout_width="match_parent"
-                    android:layout_height="wrap_content"
-                    android:paddingStart="@dimen/standard_margin"
-                    android:paddingTop="@dimen/standard_half_margin"
-                    android:paddingEnd="@dimen/standard_margin"
-                    android:paddingBottom="@dimen/standard_half_margin"
-                    android:orientation="horizontal"
-                    android:background="?android:attr/selectableItemBackground">
-
-                    <ImageView
-                        android:layout_width="24dp"
-                        android:layout_height="40dp"
-                        android:layout_marginEnd="@dimen/standard_margin"
-                        android:contentDescription="@null"
-                        android:src="@drawable/ic_share_variant"
-                        app:tint="@color/grey_600" />
-
-                    <com.google.android.material.textview.MaterialTextView
-                        android:layout_width="wrap_content"
-                        android:layout_height="match_parent"
-                        android:gravity="center_vertical"
-                        android:text="@string/nc_guest_access_share_link"
-                        android:textSize="@dimen/headline_text_size" />
-
-                </LinearLayout>
-
                 <LinearLayout
                     android:id="@+id/resend_invitations_button"
                     android:layout_width="match_parent"

+ 5 - 4
app/src/main/res/values/strings.xml

@@ -329,9 +329,8 @@ How to translate with transifex:
     <string name="nc_call_name">Conversation name</string>
     <string name="create_conversation">Create conversation</string>
     <string name="nc_add_emojis">Add emojis</string>
-    <string name="nc_share_text">Join the conversation at %1$s/index.php/call/%2$s</string>
-    <string name="nc_share_subject">%1$s invitation</string>
-    <string name="nc_share_text_pass">\nPassword: %1$s</string>
+
+
 
     <string name="nc_push_to_talk">Push-to-talk</string>
     <string name="nc_push_to_talk_desc">With microphone disabled, click&amp;hold to use Push-to-talk</string>
@@ -435,6 +434,7 @@ How to translate with transifex:
     <string name="nc_guest_access_resend_invitations">Resend invitations</string>
     <string name="nc_guest_access_resend_invitations_successful">Invitations were sent out again.</string>
     <string name="nc_guest_access_resend_invitations_failed">Invitations were not send due to an error.</string>
+    <string name="nc_share_link">Share link</string>
 
     <!-- Content descriptions -->
     <string name="nc_description_send_message_button">Send message</string>
@@ -712,7 +712,6 @@ How to translate with transifex:
     <string name="nc_conversation_description">Conversation description</string>
 
     <!-- Expiring messages -->
-    <string name="message_expiration_title">Message expiration</string>
     <string name="nc_expire_messages">Expire chat messages</string>
     <string name="nc_expire_message_off">Off</string>
     <string name="nc_expire_message_four_weeks">4 weeks</string>
@@ -785,4 +784,6 @@ How to translate with transifex:
     <string name="nc_edit_icon">Edit Icon</string>
     <string name="get_invitations_error">Failed to fetch pending invitations</string>
     <string name="message_last_edited_by">Edited by %1$s</string>
+    <string name="share_link_to_conversation">Join conversation %1$s at %2$s</string>
+    <string name="nc_conversation_settings">Conversation settings</string>
 </resources>

+ 0 - 67
app/src/test/java/com/nextcloud/talk/utils/ShareUtilsTest.kt

@@ -1,67 +0,0 @@
-/*
- * Nextcloud Talk - Android Client
- *
- * SPDX-FileCopyrightText: 2017-2019 Mario Danic <mario@lovelyhq.com>
- * SPDX-License-Identifier: GPL-3.0-or-later
- */
-package com.nextcloud.talk.utils
-
-import android.content.Context
-import android.content.res.Resources
-import com.nextcloud.talk.R
-import com.nextcloud.talk.data.user.model.User
-import com.nextcloud.talk.models.domain.ConversationModel
-import com.nextcloud.talk.users.UserManager
-import io.reactivex.Maybe
-import org.junit.Assert
-import org.junit.Before
-import org.junit.Test
-import org.mockito.Mock
-import org.mockito.Mockito
-import org.mockito.MockitoAnnotations
-
-class ShareUtilsTest {
-    @Mock
-    private val context: Context? = null
-
-    @Mock
-    private val resources: Resources? = null
-
-    @Mock
-    private val userManager: UserManager? = null
-
-    @Mock
-    private val user: User? = null
-
-    private val baseUrl = "https://my.nextcloud.com"
-    private val token = "2aotbrjr"
-
-    private lateinit var conversation: ConversationModel
-
-    @Before
-    fun setUp() {
-        MockitoAnnotations.openMocks(this)
-        Mockito.`when`(userManager!!.currentUser).thenReturn(Maybe.just(user))
-        Mockito.`when`(user!!.baseUrl).thenReturn(baseUrl)
-        Mockito.`when`(context!!.resources).thenReturn(resources)
-        Mockito.`when`(resources!!.getString(R.string.nc_share_text))
-            .thenReturn("Join the conversation at %1\$s/index.php/call/%2\$s")
-        Mockito.`when`(resources.getString(R.string.nc_share_text_pass)).thenReturn("\nPassword: %1\$s")
-
-        conversation = ConversationModel(token = token)
-    }
-
-    @Test
-    fun stringForIntent_noPasswordGiven_correctStringWithoutPasswordReturned() {
-        val expectedResult = String.format(
-            "Join the conversation at %s/index.php/call/%s",
-            baseUrl,
-            token
-        )
-        Assert.assertEquals(
-            "Intent string was not as expected",
-            expectedResult,
-            ShareUtils.getStringForIntent(context!!, userManager!!.currentUser.blockingGet(), conversation)
-        )
-    }
-}