diff --git a/scripts/analysis/findbugs-results.txt b/scripts/analysis/findbugs-results.txt index 6efca19ea0..1448fd8565 100644 --- a/scripts/analysis/findbugs-results.txt +++ b/scripts/analysis/findbugs-results.txt @@ -1 +1 @@ -481 \ No newline at end of file +483 diff --git a/src/main/java/com/owncloud/android/authentication/AccountUtils.java b/src/main/java/com/owncloud/android/authentication/AccountUtils.java index 138492656f..5ffb8ec759 100644 --- a/src/main/java/com/owncloud/android/authentication/AccountUtils.java +++ b/src/main/java/com/owncloud/android/authentication/AccountUtils.java @@ -25,9 +25,11 @@ import android.content.Context; import android.content.SharedPreferences; import android.net.Uri; import android.preference.PreferenceManager; +import android.text.TextUtils; import com.owncloud.android.MainApp; import com.owncloud.android.datamodel.ArbitraryDataProvider; +import com.owncloud.android.datamodel.OCFile; import com.owncloud.android.lib.common.OwnCloudAccount; import com.owncloud.android.lib.common.OwnCloudClient; import com.owncloud.android.lib.common.OwnCloudClientManagerFactory; @@ -344,4 +346,14 @@ public final class AccountUtils { // will assume it succeeds, not a big deal otherwise return newAccount; } + + /** + * Checks if an account owns the file (file's ownerId is the same as account name) + * @param file File to check + * @param account account to compare + * @return false if ownerId is not set or owner is a different account + */ + public static boolean accountOwnsFile(OCFile file, Account account) { + return !TextUtils.isEmpty(file.getOwnerId()) && account.name.split("@")[0].equals(file.getOwnerId()); + } } diff --git a/src/main/java/com/owncloud/android/datamodel/FileDataStorageManager.java b/src/main/java/com/owncloud/android/datamodel/FileDataStorageManager.java index be03b333c8..0c4148b846 100644 --- a/src/main/java/com/owncloud/android/datamodel/FileDataStorageManager.java +++ b/src/main/java/com/owncloud/android/datamodel/FileDataStorageManager.java @@ -205,6 +205,8 @@ public class FileDataStorageManager { cv.put(ProviderTableMeta.FILE_IS_DOWNLOADING, file.isDownloading()); cv.put(ProviderTableMeta.FILE_ETAG_IN_CONFLICT, file.getEtagInConflict()); cv.put(ProviderTableMeta.FILE_UNREAD_COMMENTS_COUNT, file.getUnreadCommentsCount()); + cv.put(ProviderTableMeta.FILE_OWNER_ID, file.getOwnerId()); + cv.put(ProviderTableMeta.FILE_OWNER_DISPLAY_NAME, file.getOwnerDisplayName()); boolean sameRemotePath = fileExists(file.getRemotePath()); if (sameRemotePath || @@ -443,6 +445,8 @@ public class FileDataStorageManager { cv.put(ProviderTableMeta.FILE_FAVORITE, folder.isFavorite()); cv.put(ProviderTableMeta.FILE_IS_ENCRYPTED, folder.isEncrypted()); cv.put(ProviderTableMeta.FILE_UNREAD_COMMENTS_COUNT, folder.getUnreadCommentsCount()); + cv.put(ProviderTableMeta.FILE_OWNER_ID, folder.getOwnerId()); + cv.put(ProviderTableMeta.FILE_OWNER_DISPLAY_NAME, folder.getOwnerDisplayName()); return cv; } @@ -479,6 +483,8 @@ public class FileDataStorageManager { cv.put(ProviderTableMeta.FILE_MOUNT_TYPE, file.getMountType().ordinal()); cv.put(ProviderTableMeta.FILE_HAS_PREVIEW, file.isPreviewAvailable() ? 1 : 0); cv.put(ProviderTableMeta.FILE_UNREAD_COMMENTS_COUNT, file.getUnreadCommentsCount()); + cv.put(ProviderTableMeta.FILE_OWNER_ID, file.getOwnerId()); + cv.put(ProviderTableMeta.FILE_OWNER_DISPLAY_NAME, file.getOwnerDisplayName()); return cv; } @@ -975,6 +981,8 @@ public class FileDataStorageManager { c.getColumnIndex(ProviderTableMeta.FILE_MOUNT_TYPE))]); file.setPreviewAvailable(c.getInt(c.getColumnIndex(ProviderTableMeta.FILE_HAS_PREVIEW)) == 1); file.setUnreadCommentsCount(c.getInt(c.getColumnIndex(ProviderTableMeta.FILE_UNREAD_COMMENTS_COUNT))); + file.setOwnerId(c.getString(c.getColumnIndex(ProviderTableMeta.FILE_OWNER_ID))); + file.setOwnerDisplayName(c.getString(c.getColumnIndex(ProviderTableMeta.FILE_OWNER_DISPLAY_NAME))); } return file; diff --git a/src/main/java/com/owncloud/android/datamodel/OCFile.java b/src/main/java/com/owncloud/android/datamodel/OCFile.java index 512fe5350e..8edaa7c305 100644 --- a/src/main/java/com/owncloud/android/datamodel/OCFile.java +++ b/src/main/java/com/owncloud/android/datamodel/OCFile.java @@ -84,9 +84,9 @@ public class OCFile implements Parcelable, Comparable, ServerFileInterfa @Getter @Setter private boolean favorite; @Getter @Setter private boolean encrypted; @Getter @Setter private WebdavEntry.MountType mountType; - @Getter - @Setter - private int unreadCommentsCount; + @Getter @Setter private int unreadCommentsCount; + @Getter @Setter private String ownerId; + @Getter @Setter private String ownerDisplayName; /** * URI to the local path of the file contents, if stored in the device; cached after first call diff --git a/src/main/java/com/owncloud/android/datamodel/ThumbnailsCacheManager.java b/src/main/java/com/owncloud/android/datamodel/ThumbnailsCacheManager.java index f76b6208ed..d6fc8585c2 100644 --- a/src/main/java/com/owncloud/android/datamodel/ThumbnailsCacheManager.java +++ b/src/main/java/com/owncloud/android/datamodel/ThumbnailsCacheManager.java @@ -64,6 +64,7 @@ import com.owncloud.android.utils.MimeTypeUtil; import org.apache.commons.httpclient.HttpStatus; import org.apache.commons.httpclient.methods.GetMethod; +import org.jetbrains.annotations.NotNull; import java.io.File; import java.io.FileNotFoundException; @@ -858,7 +859,7 @@ public final class ThumbnailsCacheManager { return Math.round(r.getDimension(R.dimen.file_avatar_size)); } - private @Nullable + private @NotNull Drawable doAvatarInBackground() { Bitmap avatar = null; @@ -923,7 +924,6 @@ public final class ThumbnailsCacheManager { // everything else mClient.exhaustResponse(get.getResponseBodyAsStream()); break; - } } catch (Exception e) { try { @@ -936,15 +936,17 @@ public final class ThumbnailsCacheManager { get.releaseConnection(); } } - - try { - return TextDrawable.createAvatar(mAccount.name, mAvatarRadius); - } catch (Exception e) { - Log_OC.e(TAG, "Error generating fallback avatar"); - } } - return BitmapUtils.bitmapToCircularBitmapDrawable(mResources, avatar); + if (avatar == null) { + try { + return TextDrawable.createAvatar(mAccount.name, mAvatarRadius); + } catch (Exception e1) { + return mResources.getDrawable(R.drawable.ic_user); + } + } else { + return BitmapUtils.bitmapToCircularBitmapDrawable(mResources, avatar); + } } } diff --git a/src/main/java/com/owncloud/android/db/ProviderMeta.java b/src/main/java/com/owncloud/android/db/ProviderMeta.java index 0b7e4c8406..b19caa4b2d 100644 --- a/src/main/java/com/owncloud/android/db/ProviderMeta.java +++ b/src/main/java/com/owncloud/android/db/ProviderMeta.java @@ -32,7 +32,7 @@ import com.owncloud.android.MainApp; public class ProviderMeta { public static final String DB_NAME = "filelist"; - public static final int DB_VERSION = 42; + public static final int DB_VERSION = 43; private ProviderMeta() { } @@ -106,6 +106,8 @@ public class ProviderMeta { public static final String FILE_MOUNT_TYPE = "mount_type"; public static final String FILE_HAS_PREVIEW = "has_preview"; public static final String FILE_UNREAD_COMMENTS_COUNT = "unread_comments_count"; + public static final String FILE_OWNER_ID = "owner_id"; + public static final String FILE_OWNER_DISPLAY_NAME = "owner_display_name"; public static final String[] FILE_ALL_COLUMNS = { _ID, FILE_PARENT, FILE_NAME, FILE_CREATION, FILE_MODIFIED, diff --git a/src/main/java/com/owncloud/android/providers/FileContentProvider.java b/src/main/java/com/owncloud/android/providers/FileContentProvider.java index 450edb203a..9e40cdd84c 100644 --- a/src/main/java/com/owncloud/android/providers/FileContentProvider.java +++ b/src/main/java/com/owncloud/android/providers/FileContentProvider.java @@ -698,7 +698,9 @@ public class FileContentProvider extends ContentProvider { + ProviderTableMeta.FILE_SHARED_WITH_SHAREE + INTEGER + ProviderTableMeta.FILE_MOUNT_TYPE + INTEGER + ProviderTableMeta.FILE_HAS_PREVIEW + INTEGER - + ProviderTableMeta.FILE_UNREAD_COMMENTS_COUNT + " INTEGER);" + + ProviderTableMeta.FILE_UNREAD_COMMENTS_COUNT + INTEGER + + ProviderTableMeta.FILE_OWNER_ID + TEXT + + ProviderTableMeta.FILE_OWNER_DISPLAY_NAME + " TEXT);" ); } @@ -1860,6 +1862,26 @@ public class FileContentProvider extends ContentProvider { if (!upgraded) { Log_OC.i(SQL, String.format(Locale.ENGLISH, UPGRADE_VERSION_MSG, oldVersion, newVersion)); } + + if (oldVersion < 43 && newVersion >= 43) { + Log_OC.i(SQL, "Entering in the #43 add ownerId and owner display name to file table"); + db.beginTransaction(); + try { + db.execSQL(ALTER_TABLE + ProviderTableMeta.FILE_TABLE_NAME + + ADD_COLUMN + ProviderTableMeta.FILE_OWNER_ID + " TEXT "); + db.execSQL(ALTER_TABLE + ProviderTableMeta.FILE_TABLE_NAME + + ADD_COLUMN + ProviderTableMeta.FILE_OWNER_DISPLAY_NAME + " TEXT "); + + upgraded = true; + db.setTransactionSuccessful(); + } finally { + db.endTransaction(); + } + } + + if (!upgraded) { + Log_OC.i(SQL, String.format(Locale.ENGLISH, UPGRADE_VERSION_MSG, oldVersion, newVersion)); + } } @Override diff --git a/src/main/java/com/owncloud/android/ui/adapter/OCFileListAdapter.java b/src/main/java/com/owncloud/android/ui/adapter/OCFileListAdapter.java index a4bd548601..e84282a4f4 100644 --- a/src/main/java/com/owncloud/android/ui/adapter/OCFileListAdapter.java +++ b/src/main/java/com/owncloud/android/ui/adapter/OCFileListAdapter.java @@ -22,67 +22,76 @@ package com.owncloud.android.ui.adapter; -import android.accounts.Account; -import android.content.ContentValues; -import android.content.Context; -import android.content.res.Resources; -import android.graphics.Bitmap; -import android.graphics.Color; -import android.os.Handler; -import android.os.Looper; -import android.text.TextUtils; -import android.view.LayoutInflater; -import android.view.View; -import android.view.ViewGroup; -import android.widget.Filter; -import android.widget.ImageView; -import android.widget.LinearLayout; -import android.widget.TextView; + import android.accounts.Account; + import android.content.ContentValues; + import android.content.Context; + import android.content.res.Resources; + import android.graphics.Bitmap; + import android.graphics.Color; + import android.graphics.drawable.Drawable; + import android.os.Handler; + import android.os.Looper; + import android.text.TextUtils; + import android.view.LayoutInflater; + import android.view.View; + import android.view.ViewGroup; + import android.widget.Filter; + import android.widget.ImageView; + import android.widget.LinearLayout; + import android.widget.TextView; -import com.owncloud.android.R; -import com.owncloud.android.authentication.AccountUtils; -import com.owncloud.android.datamodel.FileDataStorageManager; -import com.owncloud.android.datamodel.OCFile; -import com.owncloud.android.datamodel.ThumbnailsCacheManager; -import com.owncloud.android.datamodel.VirtualFolderType; -import com.owncloud.android.db.PreferenceManager; -import com.owncloud.android.db.ProviderMeta; -import com.owncloud.android.files.services.FileDownloader; -import com.owncloud.android.files.services.FileUploader; -import com.owncloud.android.lib.common.operations.RemoteOperation; -import com.owncloud.android.lib.common.operations.RemoteOperationResult; -import com.owncloud.android.lib.common.utils.Log_OC; -import com.owncloud.android.lib.resources.files.ReadFileRemoteOperation; -import com.owncloud.android.lib.resources.files.model.RemoteFile; -import com.owncloud.android.lib.resources.shares.OCShare; -import com.owncloud.android.lib.resources.shares.ShareType; -import com.owncloud.android.operations.RefreshFolderOperation; -import com.owncloud.android.operations.RemoteOperationFailedException; -import com.owncloud.android.services.OperationsService; -import com.owncloud.android.ui.activity.ComponentsGetter; -import com.owncloud.android.ui.fragment.ExtendedListFragment; -import com.owncloud.android.ui.interfaces.OCFileListFragmentInterface; -import com.owncloud.android.utils.DisplayUtils; -import com.owncloud.android.utils.FileSortOrder; -import com.owncloud.android.utils.FileStorageUtils; -import com.owncloud.android.utils.MimeTypeUtil; -import com.owncloud.android.utils.ThemeUtils; + import com.bumptech.glide.Glide; + import com.bumptech.glide.request.target.BitmapImageViewTarget; + import com.owncloud.android.R; + import com.owncloud.android.authentication.AccountUtils; + import com.owncloud.android.datamodel.FileDataStorageManager; + import com.owncloud.android.datamodel.OCFile; + import com.owncloud.android.datamodel.ThumbnailsCacheManager; + import com.owncloud.android.datamodel.VirtualFolderType; + import com.owncloud.android.db.PreferenceManager; + import com.owncloud.android.db.ProviderMeta; + import com.owncloud.android.files.services.FileDownloader; + import com.owncloud.android.files.services.FileUploader; + import com.owncloud.android.lib.common.operations.RemoteOperation; + import com.owncloud.android.lib.common.operations.RemoteOperationResult; + import com.owncloud.android.lib.common.utils.Log_OC; + import com.owncloud.android.lib.resources.files.ReadFileRemoteOperation; + import com.owncloud.android.lib.resources.files.model.RemoteFile; + import com.owncloud.android.lib.resources.shares.OCShare; + import com.owncloud.android.lib.resources.shares.ShareType; + import com.owncloud.android.operations.RefreshFolderOperation; + import com.owncloud.android.operations.RemoteOperationFailedException; + import com.owncloud.android.services.OperationsService; + import com.owncloud.android.ui.TextDrawable; + import com.owncloud.android.ui.activity.ComponentsGetter; + import com.owncloud.android.ui.fragment.ExtendedListFragment; + import com.owncloud.android.ui.interfaces.OCFileListFragmentInterface; + import com.owncloud.android.utils.DisplayUtils; + import com.owncloud.android.utils.FileSortOrder; + import com.owncloud.android.utils.FileStorageUtils; + import com.owncloud.android.utils.MimeTypeUtil; + import com.owncloud.android.utils.ThemeUtils; -import java.io.File; -import java.util.ArrayList; -import java.util.HashSet; -import java.util.List; -import java.util.Locale; -import java.util.Set; -import java.util.Vector; + import java.io.File; + import java.util.ArrayList; + import java.util.HashSet; + import java.util.List; + import java.util.Locale; + import java.util.Set; + import java.util.Vector; -import androidx.annotation.NonNull; -import androidx.recyclerview.widget.RecyclerView; + import androidx.annotation.NonNull; + import androidx.core.graphics.drawable.RoundedBitmapDrawable; + import androidx.core.graphics.drawable.RoundedBitmapDrawableFactory; + import androidx.recyclerview.widget.RecyclerView; + import butterknife.BindView; + import butterknife.ButterKnife; -/** + /** * This Adapter populates a RecyclerView with all files and folders in a Nextcloud instance. */ -public class OCFileListAdapter extends RecyclerView.Adapter { +public class OCFileListAdapter extends RecyclerView.Adapter + implements DisplayUtils.AvatarGenerationListener { private static final int showFilenameColumnThreshold = 4; private final FileDownloader.FileDownloaderBinder downloaderBinder; @@ -308,6 +317,27 @@ public class OCFileListAdapter extends RecyclerView.Adapter + ocFileListFragmentInterface.showShareDetailView(file)); + } else { + itemViewHolder.sharedAvatar.setVisibility(View.GONE); + } + if (onlyOnDevice) { File localFile = new File(file.getStoragePath()); @@ -393,6 +423,39 @@ public class OCFileListAdapter extends RecyclerView.Adapter ocFileListFragmentInterface.onShareIconClick(file)); + if (AccountUtils.accountOwnsFile(file, mAccount)) { + sharedIconView.setOnClickListener(view -> ocFileListFragmentInterface.onShareIconClick(file)); + } else { + sharedIconView.setOnClickListener(view -> ocFileListFragmentInterface.showShareDetailView(file)); + } } else { sharedIconView.setVisibility(View.GONE); } @@ -732,6 +801,16 @@ public class OCFileListAdapter extends RecyclerView.Adapter + style="@style/ownCloud.SearchView" + android:hint="@string/share_search"/> + + + + + + + + + + + android:src="@drawable/ic_dots_vertical"/> + android:textSize="16sp"/> diff --git a/src/main/res/layout/list_item.xml b/src/main/res/layout/list_item.xml index 04fd0c82d5..551355e347 100644 --- a/src/main/res/layout/list_item.xml +++ b/src/main/res/layout/list_item.xml @@ -171,13 +171,26 @@ android:paddingStart="@dimen/standard_half_padding" android:src="@drawable/ic_unshared" /> + + 20dp 20dp 12dp + 10dp 72dp 0dp 72dp diff --git a/src/main/res/values/strings.xml b/src/main/res/values/strings.xml index 7aa662fff3..d314196a05 100644 --- a/src/main/res/values/strings.xml +++ b/src/main/res/values/strings.xml @@ -873,4 +873,6 @@ IO error Operation has been canceled Authentication Exception + Avatar from shared user + Shared with you by %1$s