diff --git a/owncloudApp/src/main/AndroidManifest.xml b/owncloudApp/src/main/AndroidManifest.xml
index ba709a1c1f0..4df13b7519a 100644
--- a/owncloudApp/src/main/AndroidManifest.xml
+++ b/owncloudApp/src/main/AndroidManifest.xml
@@ -80,8 +80,8 @@
* Cached after first call, until changed. */ private Uri mExposedFileUri; @@ -133,7 +134,7 @@ public static AvailableOfflineStatus fromValue(int value) { /** * Create new {@link OCFile} with given path. - * + *
* The path received must be URL-decoded. Path separator must be File.separator, and it must be the first * character in 'path'. * @@ -179,6 +180,7 @@ private OCFile(Parcel source) { mEtagInConflict = source.readString(); mSharedWithSharee = source.readInt() == 1; mPrivateLink = source.readString(); + mOwner = source.readString(); } @@ -206,6 +208,7 @@ public void writeToParcel(Parcel dest, int flags) { dest.writeString(mEtagInConflict); dest.writeInt(mSharedWithSharee ? 1 : 0); dest.writeString(mPrivateLink); + dest.writeString(mOwner); } /** @@ -352,7 +355,7 @@ public long getModificationTimestamp() { /** * Set a UNIX timestamp of the time the time the file was modified. - * + *
* To update with the value returned by the server in every synchronization of the properties * of this file. * @@ -374,7 +377,7 @@ public long getModificationTimestampAtLastSyncForData() { /** * Set a UNIX timestamp of the time the time the file was modified. - * + *
* To update with the value returned by the server in every synchronization of THE CONTENTS * of this file. * @@ -396,7 +399,7 @@ public String getFileName() { /** * Sets the name of the file - * + *
* Does nothing if the new name is null, empty or includes "/" ; or if the file is the root
* directory
*/
@@ -507,6 +510,7 @@ public long getParentId() {
/**
* get remote path of parent file
+ *
* @return remote path
*/
public String getParentRemotePath() {
@@ -547,7 +551,7 @@ public AvailableOfflineStatus getAvailableOfflineStatus() {
}
/**
- * @return 'True' when
+ * @return 'True' when
*/
public boolean isAvailableOffline() {
return (mAvailableOfflineStatus != AvailableOfflineStatus.NOT_AVAILABLE_OFFLINE);
@@ -651,8 +655,8 @@ public boolean isText() {
}
/**
- * @param type Type to match in the file MIME type; it's MUST include the trailing "/"
- * @return 'True' if the file MIME type matches the received parameter in the type part.
+ * @param type Type to match in the file MIME type; it's MUST include the trailing "/"
+ * @return 'True' if the file MIME type matches the received parameter in the type part.
*/
private boolean isOfType(String type) {
return (
@@ -750,4 +754,12 @@ public void copyLocalPropertiesFrom(OCFile sourceFile) {
setTreeEtag(sourceFile.getTreeEtag());
setEtagInConflict(sourceFile.getEtagInConflict());
}
+
+ public String getOwner() {
+ return mOwner;
+ }
+
+ public void setOwner(String owner) {
+ mOwner = (owner == null) ? "" : owner;
+ }
}
diff --git a/owncloudApp/src/main/java/com/owncloud/android/ui/activity/FileActivity.java b/owncloudApp/src/main/java/com/owncloud/android/ui/activity/FileActivity.java
index bccba2ebc95..44e78a1b56c 100644
--- a/owncloudApp/src/main/java/com/owncloud/android/ui/activity/FileActivity.java
+++ b/owncloudApp/src/main/java/com/owncloud/android/ui/activity/FileActivity.java
@@ -73,6 +73,8 @@ public class FileActivity extends DrawerActivity
public static final String EXTRA_ACCOUNT = "com.owncloud.android.ui.activity.ACCOUNT";
public static final String EXTRA_FROM_NOTIFICATION =
"com.owncloud.android.ui.activity.FROM_NOTIFICATION";
+ public static final String EXTRA_ALREADY_HANDLED_DEEP_LINK =
+ "com.owncloud.android.ui.activity.ALREADY_HANDLED_DEEP_LINK";
public static final String EXTRA_FILE_LIST_OPTION = "EXTRA_FILE_LIST_OPTION";
private static final String KEY_WAITING_FOR_OP_ID = "WAITING_FOR_OP_ID";
@@ -98,6 +100,8 @@ public class FileActivity extends DrawerActivity
*/
private boolean mFromNotification;
+ private boolean mAlreadyHandledDeepLink = false;
+
/**
* Messages handler associated to the main thread and the life cycle of the activity
*/
@@ -131,6 +135,7 @@ protected void onCreate(Bundle savedInstanceState) {
if (savedInstanceState != null) {
mFile = savedInstanceState.getParcelable(FileActivity.EXTRA_FILE);
mFromNotification = savedInstanceState.getBoolean(FileActivity.EXTRA_FROM_NOTIFICATION);
+ mAlreadyHandledDeepLink = savedInstanceState.getBoolean(FileActivity.EXTRA_ALREADY_HANDLED_DEEP_LINK);
mFileOperationsHelper.setOpIdWaitingFor(
savedInstanceState.getLong(KEY_WAITING_FOR_OP_ID, Long.MAX_VALUE)
);
@@ -214,6 +219,7 @@ protected void onSaveInstanceState(Bundle outState) {
super.onSaveInstanceState(outState);
outState.putParcelable(FileActivity.EXTRA_FILE, mFile);
outState.putBoolean(FileActivity.EXTRA_FROM_NOTIFICATION, mFromNotification);
+ outState.putBoolean(FileActivity.EXTRA_ALREADY_HANDLED_DEEP_LINK, mAlreadyHandledDeepLink);
outState.putLong(KEY_WAITING_FOR_OP_ID, mFileOperationsHelper.getOpIdWaitingFor());
if (getSupportActionBar() != null && getSupportActionBar().getTitle() != null) {
// Null check in case the actionbar is used in ActionBar.NAVIGATION_MODE_LIST
@@ -247,6 +253,14 @@ public boolean fromNotification() {
return mFromNotification;
}
+ public void setAlreadyHandledDeepLink(boolean alreadyHandledDeepLink) {
+ mAlreadyHandledDeepLink = alreadyHandledDeepLink;
+ }
+
+ public boolean isAlreadyHandledDeepLink() {
+ return mAlreadyHandledDeepLink;
+ }
+
public OperationsServiceBinder getOperationsServiceBinder() {
return mOperationsServiceBinder;
}
diff --git a/owncloudApp/src/main/java/com/owncloud/android/ui/activity/FileDisplayActivity.kt b/owncloudApp/src/main/java/com/owncloud/android/ui/activity/FileDisplayActivity.kt
index 7afd278a38b..4363aaf927d 100644
--- a/owncloudApp/src/main/java/com/owncloud/android/ui/activity/FileDisplayActivity.kt
+++ b/owncloudApp/src/main/java/com/owncloud/android/ui/activity/FileDisplayActivity.kt
@@ -7,8 +7,9 @@
* @author Christian Schabesberger
* @author Shashvat Kedia
* @author Abel García de Prada
+ * @author Fernando Sanz Velasco
* Copyright (C) 2011 Bartek Przybylski
- * Copyright (C) 2020 ownCloud GmbH.
+ * Copyright (C) 2022 ownCloud GmbH.
*
*
* This program is free software: you can redistribute it and/or modify
@@ -51,6 +52,7 @@ import com.owncloud.android.AppRater
import com.owncloud.android.BuildConfig
import com.owncloud.android.MainApp
import com.owncloud.android.R
+import com.owncloud.android.authentication.AccountUtils
import com.owncloud.android.databinding.ActivityMainBinding
import com.owncloud.android.datamodel.FileDataStorageManager
import com.owncloud.android.datamodel.OCFile
@@ -225,6 +227,11 @@ class FileDisplayActivity : FileActivity(), FileFragment.ContainerActivity, OnEn
createMinFragments()
}
+ val dataIntent: Uri? = intent.data
+ dataIntent?.let {
+ handleDeepLink(dataIntent)
+ }
+
setBackgroundText()
}
@@ -415,7 +422,12 @@ class FileDisplayActivity : FileActivity(), FileFragment.ContainerActivity, OnEn
fun refreshListOfFilesFragment(reloadData: Boolean) {
val fileListFragment = listOfFilesFragment
- fileListFragment?.listDirectory(reloadData)
+ if (intent.data == null || isAlreadyHandledDeepLink) {
+ fileListFragment?.listDirectory(reloadData)
+ } else {
+ fileListFragment?.listDirectory(getFileDiscovered(intent.data))
+ }
+
}
override fun onCreateOptionsMenu(menu: Menu): Boolean {
@@ -1647,6 +1659,47 @@ class FileDisplayActivity : FileActivity(), FileFragment.ContainerActivity, OnEn
manageOptionLockSelected(type)
}
+ private fun handleDeepLink(uri: Uri?) {
+ if (uri != null && AccountUtils.getAccounts(applicationContext).isEmpty()) {
+ showMessageInSnackbar(message = getString(R.string.no_account_configured))
+ } else if (uri != null && AccountUtils.getAccounts(applicationContext).size == 1) {
+ getFileDiscovered(uri).let { oCFile ->
+ if (oCFile != null) {
+ manageItem(oCFile)
+ } else {
+ showMessageInSnackbar(message = getString(R.string.no_file_found))
+ }
+ }
+ }
+ }
+
+ private fun getFileDiscovered(uri: Uri?): OCFile? {
+ return if (storageManager != null) {
+ storageManager.getFileByPrivateLink(uri.toString())
+ } else {
+ null
+ }
+ }
+
+ private fun manageItem(file: OCFile) {
+ onBrowsedDownTo(file)
+ setFile(file)
+ account = AccountUtils.getOwnCloudAccountByName(this, file.owner)
+
+ if (file.isFolder) {
+ refreshListOfFilesFragment(true)
+ return
+ }
+
+ if (PreviewImageFragment.canBePreviewed(file)) {
+ showDetails(file)
+ } else {
+ initFragmentsWithFile()
+ }
+
+ isAlreadyHandledDeepLink = true
+ }
+
companion object {
private const val TAG_LIST_OF_FILES = "LIST_OF_FILES"
private const val TAG_SECOND_FRAGMENT = "SECOND_FRAGMENT"
diff --git a/owncloudApp/src/main/java/com/owncloud/android/ui/fragment/FileDetailFragment.java b/owncloudApp/src/main/java/com/owncloud/android/ui/fragment/FileDetailFragment.java
index 850ce3904f9..082711bfe5d 100644
--- a/owncloudApp/src/main/java/com/owncloud/android/ui/fragment/FileDetailFragment.java
+++ b/owncloudApp/src/main/java/com/owncloud/android/ui/fragment/FileDetailFragment.java
@@ -53,6 +53,9 @@
import com.owncloud.android.ui.controller.TransferProgressController;
import com.owncloud.android.ui.dialog.RemoveFilesDialogFragment;
import com.owncloud.android.ui.dialog.RenameFileDialogFragment;
+import com.owncloud.android.ui.preview.PreviewAudioFragment;
+import com.owncloud.android.ui.preview.PreviewImageFragment;
+import com.owncloud.android.ui.preview.PreviewTextFragment;
import com.owncloud.android.utils.DisplayUtils;
import com.owncloud.android.utils.MimetypeIconUtil;
import com.owncloud.android.utils.PreferenceUtils;
@@ -329,11 +332,33 @@ public void onClick(View v) {
((FileDisplayActivity) mContainerActivity).cancelTransference(getFile());
break;
}
+ case R.id.fdIcon: {
+ displayFile(getFile());
+ }
default:
Timber.e("Incorrect view clicked!");
}
}
+ private void displayFile(OCFile file) {
+ if (PreviewImageFragment.canBePreviewed(file)) {
+ // preview image - it handles the sync, if needed
+ ((FileDisplayActivity) mContainerActivity).startImagePreview(file);
+ } else if (PreviewTextFragment.canBePreviewed(file)) {
+ ((FileDisplayActivity) mContainerActivity).startTextPreview(file);
+ mContainerActivity.getFileOperationsHelper().syncFile(file);
+
+ } else if (PreviewAudioFragment.canBePreviewed(file)) {
+ // media preview
+ ((FileDisplayActivity) mContainerActivity).startAudioPreview(file, 0);
+ mContainerActivity.getFileOperationsHelper().syncFile(file);
+
+ } else {
+ // sync file content, then open with external apps
+ ((FileDisplayActivity) mContainerActivity).startSyncThenOpen(file);
+ }
+ }
+
/**
* Check if the fragment was created with an empty layout. An empty fragment can't show file details, must be
* replaced.
@@ -424,6 +449,7 @@ private void setFiletype(OCFile file) {
}
ImageView iv = getView().findViewById(R.id.fdIcon);
+ iv.setOnClickListener(this);
if (iv != null) {
Bitmap thumbnail;
diff --git a/owncloudApp/src/main/java/com/owncloud/android/ui/helpers/FileOperationsHelper.java b/owncloudApp/src/main/java/com/owncloud/android/ui/helpers/FileOperationsHelper.java
index 0ccae12d9f0..276e06a9d57 100644
--- a/owncloudApp/src/main/java/com/owncloud/android/ui/helpers/FileOperationsHelper.java
+++ b/owncloudApp/src/main/java/com/owncloud/android/ui/helpers/FileOperationsHelper.java
@@ -224,6 +224,7 @@ public void syncFile(OCFile file) {
intent.setAction(OperationsService.ACTION_SYNC_FILE);
intent.putExtra(OperationsService.EXTRA_ACCOUNT, mFileActivity.getAccount());
intent.putExtra(OperationsService.EXTRA_REMOTE_PATH, file.getRemotePath());
+
mWaitingForOpId = mFileActivity.getOperationsServiceBinder().queueNewOperation(intent);
} else {
diff --git a/owncloudApp/src/main/res/layout/file_details_fragment.xml b/owncloudApp/src/main/res/layout/file_details_fragment.xml
index 275fc2d8cf2..2d170bf6a2d 100644
--- a/owncloudApp/src/main/res/layout/file_details_fragment.xml
+++ b/owncloudApp/src/main/res/layout/file_details_fragment.xml
@@ -45,8 +45,8 @@
android:layout_width="0dp"
android:layout_height="0dp"
android:ellipsize="end"
- android:paddingStart="@dimen/standard_margin"
android:gravity="center_vertical"
+ android:paddingStart="@dimen/standard_margin"
android:text=""
android:textAppearance="?android:attr/textAppearanceLarge"
app:layout_constraintBottom_toBottomOf="@id/fdIcon"
diff --git a/owncloudApp/src/main/res/values/setup.xml b/owncloudApp/src/main/res/values/setup.xml
index 02dc17f0344..4c72ef5b03b 100644
--- a/owncloudApp/src/main/res/values/setup.xml
+++ b/owncloudApp/src/main/res/values/setup.xml
@@ -120,4 +120,8 @@