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

Merge pull request #3329 from nextcloud/feature/noid/openFileShareLinkInFilesApp

Open internal file share links in chat via files client
Andy Scherzinger 1 жил өмнө
parent
commit
28ec0bae63

+ 155 - 0
app/src/androidTest/java/com/nextcloud/talk/utils/UriUtilsIT.kt

@@ -0,0 +1,155 @@
+/*
+ * Nextcloud Talk application
+ *
+ * @author Samanwith KSN
+ * Copyright (C) 2023 Samanwith KSN <samanwith21@gmail.com>
+ *
+ * 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 <http://www.gnu.org/licenses/>.
+ */
+package com.nextcloud.talk.utils
+
+import junit.framework.TestCase.assertEquals
+import junit.framework.TestCase.assertFalse
+import junit.framework.TestCase.assertTrue
+import org.junit.Test
+
+class UriUtilsIT {
+
+    @Test
+    fun testHasHttpProtocolPrefixed() {
+        val uriHttp = "http://www.example.com"
+        val resultHttp = UriUtils.hasHttpProtocolPrefixed(uriHttp)
+        assertTrue(resultHttp)
+
+        val uriHttps = "https://www.example.com"
+        val resultHttps = UriUtils.hasHttpProtocolPrefixed(uriHttps)
+        assertTrue(resultHttps)
+
+        val uriWithoutPrefix = "www.example.com"
+        val resultWithoutPrefix = UriUtils.hasHttpProtocolPrefixed(uriWithoutPrefix)
+        assertFalse(resultWithoutPrefix)
+    }
+
+    @Test
+    fun testExtractInstanceInternalFileFileId() {
+        assertEquals(
+            "42",
+            UriUtils.extractInstanceInternalFileFileId(
+                "https://cloud.nextcloud.com/apps/files/?dir=/Engineering&fileid=42"
+            )
+        )
+    }
+
+    @Test
+    fun testExtractInstanceInternalFileShareFileId() {
+        assertEquals(
+            "42",
+            UriUtils.extractInstanceInternalFileShareFileId("https://cloud.nextcloud.com/f/42")
+        )
+    }
+
+    @Test
+    fun testIsInstanceInternalFileShareUrl() {
+        assertTrue(
+            UriUtils.isInstanceInternalFileShareUrl(
+                "https://cloud.nextcloud.com",
+                "https://cloud.nextcloud.com/f/42"
+            )
+        )
+
+        assertFalse(
+            UriUtils.isInstanceInternalFileShareUrl(
+                "https://nextcloud.nextcloud.com",
+                "https://cloud.nextcloud.com/f/42"
+            )
+        )
+
+        assertFalse(
+            UriUtils.isInstanceInternalFileShareUrl(
+                "https://nextcloud.nextcloud.com",
+                "https://cloud.nextcloud.com/f/"
+            )
+        )
+
+        assertFalse(
+            UriUtils.isInstanceInternalFileShareUrl(
+                "https://nextcloud.nextcloud.com",
+                "https://cloud.nextcloud.com/f/test123"
+            )
+        )
+    }
+
+    @Test
+    fun testIsInstanceInternalFileUrl() {
+        assertTrue(
+            UriUtils.isInstanceInternalFileUrl(
+                "https://cloud.nextcloud.com",
+                "https://cloud.nextcloud.com/apps/files/?dir=/Engineering&fileid=41"
+            )
+        )
+
+        assertFalse(
+            UriUtils.isInstanceInternalFileUrl(
+                "https://nextcloud.nextcloud.com",
+                "https://cloud.nextcloud.com/apps/files/?dir=/Engineering&fileid=41"
+            )
+        )
+
+        assertFalse(
+            UriUtils.isInstanceInternalFileUrl(
+                "https://nextcloud.nextcloud.com",
+                "https://cloud.nextcloud.com/apps/files/?dir=/Engineering&fileid=test123"
+            )
+        )
+
+        assertFalse(
+            UriUtils.isInstanceInternalFileUrl(
+                "https://nextcloud.nextcloud.com",
+                "https://cloud.nextcloud.com/apps/files/?dir=/Engineering&fileid="
+            )
+        )
+
+        assertFalse(
+            UriUtils.isInstanceInternalFileUrl(
+                "https://cloud.nextcloud.com",
+                "https://cloud.nextcloud.com/apps/files/?dir=/Engineering"
+            )
+        )
+    }
+
+    @Test
+    fun testIsInstanceInternalFileUrlNew() {
+        assertTrue(
+            UriUtils.isInstanceInternalFileUrlNew(
+                "https://cloud.nextcloud.com",
+                "https://cloud.nextcloud.com/apps/files/files/41?dir=/"
+            )
+        )
+
+        assertFalse(
+            UriUtils.isInstanceInternalFileUrlNew(
+                "https://nextcloud.nextcloud.com",
+                "https://cloud.nextcloud.com/apps/files/files/41?dir=/"
+            )
+        )
+    }
+
+    @Test
+    fun testExtractInstanceInternalFileFileIdNew() {
+        assertEquals(
+            "42",
+            UriUtils.extractInstanceInternalFileFileIdNew("https://cloud.nextcloud.com/apps/files/files/42?dir=/")
+        )
+    }
+}

+ 1 - 1
app/src/main/java/com/nextcloud/talk/adapters/messages/IncomingLocationMessageViewHolder.kt

@@ -221,7 +221,7 @@ class IncomingLocationMessageViewHolder(incomingView: View, payload: Any) :
         binding.webview.webViewClient = object : WebViewClient() {
             @Deprecated("Use shouldOverrideUrlLoading(WebView view, WebResourceRequest request)")
             override fun shouldOverrideUrlLoading(view: WebView?, url: String?): Boolean {
-                return if (url != null && UriUtils.hasHttpProtocollPrefixed(url)
+                return if (url != null && UriUtils.hasHttpProtocolPrefixed(url)
                 ) {
                     view?.context?.startActivity(Intent(Intent.ACTION_VIEW, Uri.parse(url)))
                     true

+ 2 - 2
app/src/main/java/com/nextcloud/talk/adapters/messages/OutcomingLocationMessageViewHolder.kt

@@ -37,6 +37,7 @@ import autodagger.AutoInjector
 import coil.load
 import com.google.android.flexbox.FlexboxLayout
 import com.google.android.material.snackbar.Snackbar
+import com.nextcloud.android.common.ui.theme.utils.ColorRole
 import com.nextcloud.talk.R
 import com.nextcloud.talk.application.NextcloudTalkApplication
 import com.nextcloud.talk.application.NextcloudTalkApplication.Companion.sharedApplication
@@ -44,7 +45,6 @@ import com.nextcloud.talk.databinding.ItemCustomOutcomingLocationMessageBinding
 import com.nextcloud.talk.models.json.chat.ChatMessage
 import com.nextcloud.talk.models.json.chat.ReadStatus
 import com.nextcloud.talk.ui.theme.ViewThemeUtils
-import com.nextcloud.android.common.ui.theme.utils.ColorRole
 import com.nextcloud.talk.utils.ApiUtils
 import com.nextcloud.talk.utils.DateUtils
 import com.nextcloud.talk.utils.UriUtils
@@ -164,7 +164,7 @@ class OutcomingLocationMessageViewHolder(incomingView: View) :
         binding.webview.webViewClient = object : WebViewClient() {
             @Deprecated("Use shouldOverrideUrlLoading(WebView view, WebResourceRequest request)")
             override fun shouldOverrideUrlLoading(view: WebView?, url: String?): Boolean {
-                return if (url != null && UriUtils.hasHttpProtocollPrefixed(url)
+                return if (url != null && UriUtils.hasHttpProtocolPrefixed(url)
                 ) {
                     view?.context?.startActivity(Intent(Intent.ACTION_VIEW, Uri.parse(url)))
                     true

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

@@ -204,6 +204,7 @@ import com.nextcloud.talk.utils.MagicCharPolicy
 import com.nextcloud.talk.utils.Mimetype
 import com.nextcloud.talk.utils.NotificationUtils
 import com.nextcloud.talk.utils.ParticipantPermissions
+import com.nextcloud.talk.utils.UriUtils
 import com.nextcloud.talk.utils.VibrationUtils
 import com.nextcloud.talk.utils.bundle.BundleKeys
 import com.nextcloud.talk.utils.bundle.BundleKeys.KEY_CALL_VOICE_ONLY
@@ -2660,6 +2661,34 @@ class ChatActivity :
         )
     }
 
+    override fun startActivity(intent: Intent) {
+        val user = currentUserProvider.currentUser.blockingGet()
+        if (intent.data != null && TextUtils.equals(intent.action, Intent.ACTION_VIEW)) {
+            val uri = intent.data.toString()
+            if (uri.startsWith(user.baseUrl!!)) {
+                if (UriUtils.isInstanceInternalFileShareUrl(user.baseUrl!!, uri)) {
+                    // https://cloud.nextcloud.com/f/41
+                    val fileViewerUtils = FileViewerUtils(this, user)
+                    fileViewerUtils.openFileInFilesApp(uri, UriUtils.extractInstanceInternalFileShareFileId(uri))
+                } else if (UriUtils.isInstanceInternalFileUrl(user.baseUrl!!, uri)) {
+                    // https://cloud.nextcloud.com/apps/files/?dir=/Engineering&fileid=41
+                    val fileViewerUtils = FileViewerUtils(this, user)
+                    fileViewerUtils.openFileInFilesApp(uri, UriUtils.extractInstanceInternalFileFileId(uri))
+                } else if (UriUtils.isInstanceInternalFileUrlNew(user.baseUrl!!, uri)) {
+                    // https://cloud.nextcloud.com/apps/files/?dir=/Engineering&fileid=41
+                    val fileViewerUtils = FileViewerUtils(this, user)
+                    fileViewerUtils.openFileInFilesApp(uri, UriUtils.extractInstanceInternalFileFileIdNew(uri))
+                } else {
+                    super.startActivity(intent)
+                }
+            } else {
+                super.startActivity(intent)
+            }
+        } else {
+            super.startActivity(intent)
+        }
+    }
+
     fun sendSelectLocalFileIntent() {
         if (!permissionUtil.isFilesPermissionGranted()) {
             requestReadFilesPermissions()

+ 1 - 1
app/src/main/java/com/nextcloud/talk/controllers/AccountVerificationController.kt

@@ -124,7 +124,7 @@ class AccountVerificationController(args: Bundle? = null) : BaseController(
 
         if (
             isAccountImport &&
-            !UriUtils.hasHttpProtocollPrefixed(baseUrl!!) ||
+            !UriUtils.hasHttpProtocolPrefixed(baseUrl!!) ||
             isSameProtocol(baseUrl!!, originalProtocol!!)
         ) {
             determineBaseUrlProtocol(true)

+ 1 - 1
app/src/main/java/com/nextcloud/talk/controllers/ServerSelectionController.kt

@@ -216,7 +216,7 @@ class ServerSelectionController :
             url = url.substring(0, url.length - 1)
         }
 
-        if (UriUtils.hasHttpProtocollPrefixed(url)) {
+        if (UriUtils.hasHttpProtocolPrefixed(url)) {
             checkServer(url, false)
         } else {
             checkServer("https://$url", true)

+ 1 - 1
app/src/main/java/com/nextcloud/talk/controllers/bottomsheet/EntryMenuController.kt

@@ -272,7 +272,7 @@ class EntryMenuController(args: Bundle) :
                         }
                         binding?.textInputLayout?.isErrorEnabled = false
                     } else if (
-                        UriUtils.hasHttpProtocollPrefixed(binding?.textEdit?.text.toString()) &&
+                        UriUtils.hasHttpProtocolPrefixed(binding?.textEdit?.text.toString()) &&
                         binding?.textEdit?.text.toString().contains("/call/")
                     ) {
                         if (!binding?.okButton?.isEnabled!!) {

+ 1 - 1
app/src/main/java/com/nextcloud/talk/utils/AccountUtils.kt

@@ -69,7 +69,7 @@ object AccountUtils {
     private fun matchAccounts(importAccount: ImportAccount, user: User): Boolean {
         var accountFound = false
         if (importAccount.token != null) {
-            if (UriUtils.hasHttpProtocollPrefixed(importAccount.baseUrl)) {
+            if (UriUtils.hasHttpProtocolPrefixed(importAccount.baseUrl)) {
                 if (
                     user.username == importAccount.username &&
                     user.baseUrl == importAccount.baseUrl

+ 40 - 2
app/src/main/java/com/nextcloud/talk/utils/UriUtils.kt

@@ -22,11 +22,49 @@
 
 package com.nextcloud.talk.utils
 
+import android.net.Uri
+
 class UriUtils {
     companion object {
-
-        fun hasHttpProtocollPrefixed(uri: String): Boolean {
+        fun hasHttpProtocolPrefixed(uri: String): Boolean {
             return uri.startsWith("http://") || uri.startsWith("https://")
         }
+
+        fun extractInstanceInternalFileFileId(url: String): String {
+            // https://cloud.nextcloud.com/apps/files/?dir=/Engineering&fileid=41
+            return Uri.parse(url).getQueryParameter("fileid").toString()
+        }
+
+        fun isInstanceInternalFileShareUrl(baseUrl: String, url: String): Boolean {
+            // https://cloud.nextcloud.com/f/41
+            return url.startsWith("$baseUrl/f/") || url.startsWith("$baseUrl/index.php/f/") &&
+                Regex(".*/f/d*").matches(url)
+        }
+
+        fun extractInstanceInternalFileShareFileId(url: String): String {
+            // https://cloud.nextcloud.com/f/41
+            return Uri.parse(url).lastPathSegment ?: ""
+        }
+
+        fun isInstanceInternalFileUrl(baseUrl: String, url: String): Boolean {
+            // https://cloud.nextcloud.com/apps/files/?dir=/Engineering&fileid=41
+            return (
+                url.startsWith("$baseUrl/apps/files/") ||
+                    url.startsWith("$baseUrl/index.php/apps/files/")
+                ) &&
+                Uri.parse(url).queryParameterNames.contains("fileid") &&
+                Regex(""".*fileid=\d*""").matches(url)
+        }
+
+        fun isInstanceInternalFileUrlNew(baseUrl: String, url: String): Boolean {
+            // https://cloud.nextcloud.com/apps/files/files/41?dir=/
+            return url.startsWith("$baseUrl/apps/files/files/") ||
+                url.startsWith("$baseUrl/index.php/apps/files/files/")
+        }
+
+        fun extractInstanceInternalFileFileIdNew(url: String): String {
+            // https://cloud.nextcloud.com/apps/files/files/41?dir=/
+            return Uri.parse(url).lastPathSegment ?: ""
+        }
     }
 }

+ 0 - 41
app/src/test/java/com/nextcloud/talk/utils/UriUtilsTest.kt

@@ -1,41 +0,0 @@
-/*
- * Nextcloud Talk application
- *
- * @author Samanwith KSN
- * Copyright (C) 2023 Samanwith KSN <samanwith21@gmail.com>
- *
- * 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 <http://www.gnu.org/licenses/>.
- */
-package com.nextcloud.talk.utils
-
-import org.junit.Assert
-import org.junit.Test
-
-class UriUtilsTest {
-
-    @Test
-    fun testHasHttpProtocolPrefixed() {
-        val uriHttp = "http://www.example.com"
-        val resultHttp = UriUtils.hasHttpProtocollPrefixed(uriHttp)
-        Assert.assertTrue(resultHttp)
-
-        val uriHttps = "https://www.example.com"
-        val resultHttps = UriUtils.hasHttpProtocollPrefixed(uriHttps)
-        Assert.assertTrue(resultHttps)
-
-        val uriWithoutPrefix = "www.example.com"
-        val resultWithoutPrefix = UriUtils.hasHttpProtocollPrefixed(uriWithoutPrefix)
-        Assert.assertFalse(resultWithoutPrefix)
-    }
-}

+ 1 - 1
detekt.yml

@@ -1,5 +1,5 @@
 build:
-  maxIssues: 117
+  maxIssues: 116
   weights:
     # complexity: 2
     # LongParameterList: 1