Merge pull request #3320 from nextcloud/showSharedUser

Show shared user
This commit is contained in:
Andy Scherzinger 2019-02-27 11:59:55 +01:00 committed by GitHub
commit 5b0a35204f
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
14 changed files with 339 additions and 115 deletions

View file

@ -1 +1 @@
481 483

View file

@ -25,9 +25,11 @@ import android.content.Context;
import android.content.SharedPreferences; import android.content.SharedPreferences;
import android.net.Uri; import android.net.Uri;
import android.preference.PreferenceManager; import android.preference.PreferenceManager;
import android.text.TextUtils;
import com.owncloud.android.MainApp; import com.owncloud.android.MainApp;
import com.owncloud.android.datamodel.ArbitraryDataProvider; 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.OwnCloudAccount;
import com.owncloud.android.lib.common.OwnCloudClient; import com.owncloud.android.lib.common.OwnCloudClient;
import com.owncloud.android.lib.common.OwnCloudClientManagerFactory; import com.owncloud.android.lib.common.OwnCloudClientManagerFactory;
@ -344,4 +346,14 @@ public final class AccountUtils {
// will assume it succeeds, not a big deal otherwise // will assume it succeeds, not a big deal otherwise
return newAccount; 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());
}
} }

View file

@ -205,6 +205,8 @@ public class FileDataStorageManager {
cv.put(ProviderTableMeta.FILE_IS_DOWNLOADING, file.isDownloading()); cv.put(ProviderTableMeta.FILE_IS_DOWNLOADING, file.isDownloading());
cv.put(ProviderTableMeta.FILE_ETAG_IN_CONFLICT, file.getEtagInConflict()); cv.put(ProviderTableMeta.FILE_ETAG_IN_CONFLICT, file.getEtagInConflict());
cv.put(ProviderTableMeta.FILE_UNREAD_COMMENTS_COUNT, file.getUnreadCommentsCount()); 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()); boolean sameRemotePath = fileExists(file.getRemotePath());
if (sameRemotePath || if (sameRemotePath ||
@ -443,6 +445,8 @@ public class FileDataStorageManager {
cv.put(ProviderTableMeta.FILE_FAVORITE, folder.isFavorite()); cv.put(ProviderTableMeta.FILE_FAVORITE, folder.isFavorite());
cv.put(ProviderTableMeta.FILE_IS_ENCRYPTED, folder.isEncrypted()); cv.put(ProviderTableMeta.FILE_IS_ENCRYPTED, folder.isEncrypted());
cv.put(ProviderTableMeta.FILE_UNREAD_COMMENTS_COUNT, folder.getUnreadCommentsCount()); 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; return cv;
} }
@ -479,6 +483,8 @@ public class FileDataStorageManager {
cv.put(ProviderTableMeta.FILE_MOUNT_TYPE, file.getMountType().ordinal()); cv.put(ProviderTableMeta.FILE_MOUNT_TYPE, file.getMountType().ordinal());
cv.put(ProviderTableMeta.FILE_HAS_PREVIEW, file.isPreviewAvailable() ? 1 : 0); cv.put(ProviderTableMeta.FILE_HAS_PREVIEW, file.isPreviewAvailable() ? 1 : 0);
cv.put(ProviderTableMeta.FILE_UNREAD_COMMENTS_COUNT, file.getUnreadCommentsCount()); 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; return cv;
} }
@ -975,6 +981,8 @@ public class FileDataStorageManager {
c.getColumnIndex(ProviderTableMeta.FILE_MOUNT_TYPE))]); c.getColumnIndex(ProviderTableMeta.FILE_MOUNT_TYPE))]);
file.setPreviewAvailable(c.getInt(c.getColumnIndex(ProviderTableMeta.FILE_HAS_PREVIEW)) == 1); file.setPreviewAvailable(c.getInt(c.getColumnIndex(ProviderTableMeta.FILE_HAS_PREVIEW)) == 1);
file.setUnreadCommentsCount(c.getInt(c.getColumnIndex(ProviderTableMeta.FILE_UNREAD_COMMENTS_COUNT))); 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; return file;

View file

@ -84,9 +84,9 @@ public class OCFile implements Parcelable, Comparable<OCFile>, ServerFileInterfa
@Getter @Setter private boolean favorite; @Getter @Setter private boolean favorite;
@Getter @Setter private boolean encrypted; @Getter @Setter private boolean encrypted;
@Getter @Setter private WebdavEntry.MountType mountType; @Getter @Setter private WebdavEntry.MountType mountType;
@Getter @Getter @Setter private int unreadCommentsCount;
@Setter @Getter @Setter private String ownerId;
private int unreadCommentsCount; @Getter @Setter private String ownerDisplayName;
/** /**
* URI to the local path of the file contents, if stored in the device; cached after first call * URI to the local path of the file contents, if stored in the device; cached after first call

View file

@ -64,6 +64,7 @@ import com.owncloud.android.utils.MimeTypeUtil;
import org.apache.commons.httpclient.HttpStatus; import org.apache.commons.httpclient.HttpStatus;
import org.apache.commons.httpclient.methods.GetMethod; import org.apache.commons.httpclient.methods.GetMethod;
import org.jetbrains.annotations.NotNull;
import java.io.File; import java.io.File;
import java.io.FileNotFoundException; import java.io.FileNotFoundException;
@ -858,7 +859,7 @@ public final class ThumbnailsCacheManager {
return Math.round(r.getDimension(R.dimen.file_avatar_size)); return Math.round(r.getDimension(R.dimen.file_avatar_size));
} }
private @Nullable private @NotNull
Drawable doAvatarInBackground() { Drawable doAvatarInBackground() {
Bitmap avatar = null; Bitmap avatar = null;
@ -923,7 +924,6 @@ public final class ThumbnailsCacheManager {
// everything else // everything else
mClient.exhaustResponse(get.getResponseBodyAsStream()); mClient.exhaustResponse(get.getResponseBodyAsStream());
break; break;
} }
} catch (Exception e) { } catch (Exception e) {
try { try {
@ -936,15 +936,17 @@ public final class ThumbnailsCacheManager {
get.releaseConnection(); 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);
}
} }
} }

View file

@ -32,7 +32,7 @@ import com.owncloud.android.MainApp;
public class ProviderMeta { public class ProviderMeta {
public static final String DB_NAME = "filelist"; public static final String DB_NAME = "filelist";
public static final int DB_VERSION = 42; public static final int DB_VERSION = 43;
private ProviderMeta() { private ProviderMeta() {
} }
@ -106,6 +106,8 @@ public class ProviderMeta {
public static final String FILE_MOUNT_TYPE = "mount_type"; public static final String FILE_MOUNT_TYPE = "mount_type";
public static final String FILE_HAS_PREVIEW = "has_preview"; 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_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 = { public static final String[] FILE_ALL_COLUMNS = {
_ID, FILE_PARENT, FILE_NAME, FILE_CREATION, FILE_MODIFIED, _ID, FILE_PARENT, FILE_NAME, FILE_CREATION, FILE_MODIFIED,

View file

@ -698,7 +698,9 @@ public class FileContentProvider extends ContentProvider {
+ ProviderTableMeta.FILE_SHARED_WITH_SHAREE + INTEGER + ProviderTableMeta.FILE_SHARED_WITH_SHAREE + INTEGER
+ ProviderTableMeta.FILE_MOUNT_TYPE + INTEGER + ProviderTableMeta.FILE_MOUNT_TYPE + INTEGER
+ ProviderTableMeta.FILE_HAS_PREVIEW + 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) { if (!upgraded) {
Log_OC.i(SQL, String.format(Locale.ENGLISH, UPGRADE_VERSION_MSG, oldVersion, newVersion)); 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 @Override

View file

@ -22,67 +22,76 @@
package com.owncloud.android.ui.adapter; package com.owncloud.android.ui.adapter;
import android.accounts.Account; import android.accounts.Account;
import android.content.ContentValues; import android.content.ContentValues;
import android.content.Context; import android.content.Context;
import android.content.res.Resources; import android.content.res.Resources;
import android.graphics.Bitmap; import android.graphics.Bitmap;
import android.graphics.Color; import android.graphics.Color;
import android.os.Handler; import android.graphics.drawable.Drawable;
import android.os.Looper; import android.os.Handler;
import android.text.TextUtils; import android.os.Looper;
import android.view.LayoutInflater; import android.text.TextUtils;
import android.view.View; import android.view.LayoutInflater;
import android.view.ViewGroup; import android.view.View;
import android.widget.Filter; import android.view.ViewGroup;
import android.widget.ImageView; import android.widget.Filter;
import android.widget.LinearLayout; import android.widget.ImageView;
import android.widget.TextView; import android.widget.LinearLayout;
import android.widget.TextView;
import com.owncloud.android.R; import com.bumptech.glide.Glide;
import com.owncloud.android.authentication.AccountUtils; import com.bumptech.glide.request.target.BitmapImageViewTarget;
import com.owncloud.android.datamodel.FileDataStorageManager; import com.owncloud.android.R;
import com.owncloud.android.datamodel.OCFile; import com.owncloud.android.authentication.AccountUtils;
import com.owncloud.android.datamodel.ThumbnailsCacheManager; import com.owncloud.android.datamodel.FileDataStorageManager;
import com.owncloud.android.datamodel.VirtualFolderType; import com.owncloud.android.datamodel.OCFile;
import com.owncloud.android.db.PreferenceManager; import com.owncloud.android.datamodel.ThumbnailsCacheManager;
import com.owncloud.android.db.ProviderMeta; import com.owncloud.android.datamodel.VirtualFolderType;
import com.owncloud.android.files.services.FileDownloader; import com.owncloud.android.db.PreferenceManager;
import com.owncloud.android.files.services.FileUploader; import com.owncloud.android.db.ProviderMeta;
import com.owncloud.android.lib.common.operations.RemoteOperation; import com.owncloud.android.files.services.FileDownloader;
import com.owncloud.android.lib.common.operations.RemoteOperationResult; import com.owncloud.android.files.services.FileUploader;
import com.owncloud.android.lib.common.utils.Log_OC; import com.owncloud.android.lib.common.operations.RemoteOperation;
import com.owncloud.android.lib.resources.files.ReadFileRemoteOperation; import com.owncloud.android.lib.common.operations.RemoteOperationResult;
import com.owncloud.android.lib.resources.files.model.RemoteFile; import com.owncloud.android.lib.common.utils.Log_OC;
import com.owncloud.android.lib.resources.shares.OCShare; import com.owncloud.android.lib.resources.files.ReadFileRemoteOperation;
import com.owncloud.android.lib.resources.shares.ShareType; import com.owncloud.android.lib.resources.files.model.RemoteFile;
import com.owncloud.android.operations.RefreshFolderOperation; import com.owncloud.android.lib.resources.shares.OCShare;
import com.owncloud.android.operations.RemoteOperationFailedException; import com.owncloud.android.lib.resources.shares.ShareType;
import com.owncloud.android.services.OperationsService; import com.owncloud.android.operations.RefreshFolderOperation;
import com.owncloud.android.ui.activity.ComponentsGetter; import com.owncloud.android.operations.RemoteOperationFailedException;
import com.owncloud.android.ui.fragment.ExtendedListFragment; import com.owncloud.android.services.OperationsService;
import com.owncloud.android.ui.interfaces.OCFileListFragmentInterface; import com.owncloud.android.ui.TextDrawable;
import com.owncloud.android.utils.DisplayUtils; import com.owncloud.android.ui.activity.ComponentsGetter;
import com.owncloud.android.utils.FileSortOrder; import com.owncloud.android.ui.fragment.ExtendedListFragment;
import com.owncloud.android.utils.FileStorageUtils; import com.owncloud.android.ui.interfaces.OCFileListFragmentInterface;
import com.owncloud.android.utils.MimeTypeUtil; import com.owncloud.android.utils.DisplayUtils;
import com.owncloud.android.utils.ThemeUtils; 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.io.File;
import java.util.ArrayList; import java.util.ArrayList;
import java.util.HashSet; import java.util.HashSet;
import java.util.List; import java.util.List;
import java.util.Locale; import java.util.Locale;
import java.util.Set; import java.util.Set;
import java.util.Vector; import java.util.Vector;
import androidx.annotation.NonNull; import androidx.annotation.NonNull;
import androidx.recyclerview.widget.RecyclerView; 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. * This Adapter populates a RecyclerView with all files and folders in a Nextcloud instance.
*/ */
public class OCFileListAdapter extends RecyclerView.Adapter<RecyclerView.ViewHolder> { public class OCFileListAdapter extends RecyclerView.Adapter<RecyclerView.ViewHolder>
implements DisplayUtils.AvatarGenerationListener {
private static final int showFilenameColumnThreshold = 4; private static final int showFilenameColumnThreshold = 4;
private final FileDownloader.FileDownloaderBinder downloaderBinder; private final FileDownloader.FileDownloaderBinder downloaderBinder;
@ -308,6 +317,27 @@ public class OCFileListAdapter extends RecyclerView.Adapter<RecyclerView.ViewHol
if (holder instanceof OCFileListItemViewHolder) { if (holder instanceof OCFileListItemViewHolder) {
OCFileListItemViewHolder itemViewHolder = (OCFileListItemViewHolder) holder; OCFileListItemViewHolder itemViewHolder = (OCFileListItemViewHolder) holder;
if (file.isSharedWithMe() && !multiSelect && !gridView && !mHideItemOptions) {
itemViewHolder.sharedAvatar.setVisibility(View.VISIBLE);
Resources resources = mContext.getResources();
float avatarRadius = resources.getDimension(R.dimen.list_item_avatar_icon_radius);
if (file.getOwnerId().contains("@")) {
showFederatedShareAvatar(file, avatarRadius, resources, itemViewHolder);
} else {
itemViewHolder.sharedAvatar.setTag(file.getOwnerId());
DisplayUtils.setAvatar(mAccount, file.getOwnerId(), this, avatarRadius, resources,
itemViewHolder.sharedAvatar, mContext);
}
itemViewHolder.sharedAvatar.setOnClickListener(view ->
ocFileListFragmentInterface.showShareDetailView(file));
} else {
itemViewHolder.sharedAvatar.setVisibility(View.GONE);
}
if (onlyOnDevice) { if (onlyOnDevice) {
File localFile = new File(file.getStoragePath()); File localFile = new File(file.getStoragePath());
@ -393,6 +423,39 @@ public class OCFileListAdapter extends RecyclerView.Adapter<RecyclerView.ViewHol
} }
} }
private void showFederatedShareAvatar(OCFile file, float avatarRadius, Resources resources,
OCFileListItemViewHolder itemViewHolder) {
// maybe federated share
String userId = file.getOwnerId().split("@")[0];
String server = file.getOwnerId().split("@")[1];
String url = "https://" + server + "/avatar/" + userId + "/" +
DisplayUtils.convertDpToPixel(avatarRadius, mContext);
Drawable placeholder;
try {
placeholder = TextDrawable.createAvatarByUserId(userId, avatarRadius);
} catch (Exception e) {
Log_OC.e(TAG, "Error calculating RGB value for active account icon.", e);
placeholder = resources.getDrawable(R.drawable.account_circle_white);
}
itemViewHolder.sharedAvatar.setTag(null);
Glide.with(mContext).load(url)
.asBitmap()
.placeholder(placeholder)
.error(placeholder)
.into(new BitmapImageViewTarget(itemViewHolder.sharedAvatar) {
@Override
protected void setResource(Bitmap resource) {
RoundedBitmapDrawable circularBitmapDrawable =
RoundedBitmapDrawableFactory.create(mContext.getResources(), resource);
circularBitmapDrawable.setCircular(true);
itemViewHolder.sharedAvatar.setImageDrawable(circularBitmapDrawable);
}
});
}
private void setThumbnail(OCFile file, ImageView thumbnailView) { private void setThumbnail(OCFile file, ImageView thumbnailView) {
if (file.isFolder()) { if (file.isFolder()) {
thumbnailView.setImageDrawable(MimeTypeUtil.getFolderTypeIcon(file.isSharedWithMe() || thumbnailView.setImageDrawable(MimeTypeUtil.getFolderTypeIcon(file.isSharedWithMe() ||
@ -513,9 +576,11 @@ public class OCFileListAdapter extends RecyclerView.Adapter<RecyclerView.ViewHol
if (gridViewHolder instanceof OCFileListItemViewHolder || file.getUnreadCommentsCount() == 0) { if (gridViewHolder instanceof OCFileListItemViewHolder || file.getUnreadCommentsCount() == 0) {
sharedIconView.setVisibility(View.VISIBLE); sharedIconView.setVisibility(View.VISIBLE);
if (file.isSharedWithSharee() || file.isSharedWithMe()) { if (file.isSharedWithSharee()) {
sharedIconView.setImageResource(R.drawable.shared_via_users); sharedIconView.setImageResource(R.drawable.shared_via_users);
sharedIconView.setContentDescription(mContext.getString(R.string.shared_icon_shared)); sharedIconView.setContentDescription(mContext.getString(R.string.shared_icon_shared));
} else if (file.isSharedWithMe()) {
sharedIconView.setVisibility(View.GONE);
} else if (file.isSharedViaLink()) { } else if (file.isSharedViaLink()) {
sharedIconView.setImageResource(R.drawable.shared_via_link); sharedIconView.setImageResource(R.drawable.shared_via_link);
sharedIconView.setContentDescription(mContext.getString(R.string.shared_icon_shared_via_link)); sharedIconView.setContentDescription(mContext.getString(R.string.shared_icon_shared_via_link));
@ -523,7 +588,11 @@ public class OCFileListAdapter extends RecyclerView.Adapter<RecyclerView.ViewHol
sharedIconView.setImageResource(R.drawable.ic_unshared); sharedIconView.setImageResource(R.drawable.ic_unshared);
sharedIconView.setContentDescription(mContext.getString(R.string.shared_icon_share)); sharedIconView.setContentDescription(mContext.getString(R.string.shared_icon_share));
} }
sharedIconView.setOnClickListener(view -> ocFileListFragmentInterface.onShareIconClick(file)); if (AccountUtils.accountOwnsFile(file, mAccount)) {
sharedIconView.setOnClickListener(view -> ocFileListFragmentInterface.onShareIconClick(file));
} else {
sharedIconView.setOnClickListener(view -> ocFileListFragmentInterface.showShareDetailView(file));
}
} else { } else {
sharedIconView.setVisibility(View.GONE); sharedIconView.setVisibility(View.GONE);
} }
@ -732,6 +801,16 @@ public class OCFileListAdapter extends RecyclerView.Adapter<RecyclerView.ViewHol
return mFilesFilter; return mFilesFilter;
} }
@Override
public void avatarGenerated(Drawable avatarDrawable, Object callContext) {
((ImageView) callContext).setImageDrawable(avatarDrawable);
}
@Override
public boolean shouldCallGeneratedCallback(String tag, Object callContext) {
return ((ImageView) callContext).getTag().equals(tag);
}
private class FilesFilter extends Filter { private class FilesFilter extends Filter {
@Override @Override
@ -825,59 +904,69 @@ public class OCFileListAdapter extends RecyclerView.Adapter<RecyclerView.ViewHol
gridView = bool; gridView = bool;
} }
private static class OCFileListItemViewHolder extends OCFileListGridItemViewHolder { static class OCFileListItemViewHolder extends OCFileListGridItemViewHolder {
private final TextView fileSize; @BindView(R.id.file_size)
private final TextView lastModification; public TextView fileSize;
private final ImageView overflowMenu;
@BindView(R.id.last_mod)
public TextView lastModification;
@BindView(R.id.overflow_menu)
public ImageView overflowMenu;
@BindView(R.id.sharedAvatar)
public ImageView sharedAvatar;
private OCFileListItemViewHolder(View itemView) { private OCFileListItemViewHolder(View itemView) {
super(itemView); super(itemView);
ButterKnife.bind(this, itemView);
fileSize = itemView.findViewById(R.id.file_size);
lastModification = itemView.findViewById(R.id.last_mod);
overflowMenu = itemView.findViewById(R.id.overflow_menu);
} }
} }
static class OCFileListGridItemViewHolder extends OCFileListGridImageViewHolder { static class OCFileListGridItemViewHolder extends OCFileListGridImageViewHolder {
private final TextView fileName; @BindView(R.id.Filename) public TextView fileName;
private OCFileListGridItemViewHolder(View itemView) { private OCFileListGridItemViewHolder(View itemView) {
super(itemView); super(itemView);
ButterKnife.bind(this, itemView);
fileName = itemView.findViewById(R.id.Filename);
} }
} }
static class OCFileListGridImageViewHolder extends RecyclerView.ViewHolder { static class OCFileListGridImageViewHolder extends RecyclerView.ViewHolder {
private final ImageView thumbnail; @BindView(R.id.thumbnail)
private final ImageView favorite; public ImageView thumbnail;
private final ImageView localFileIndicator;
private final ImageView shared; @BindView(R.id.favorite_action)
private final ImageView checkbox; public ImageView favorite;
final ImageView unreadComments;
private final LinearLayout itemLayout; @BindView(R.id.localFileIndicator)
public ImageView localFileIndicator;
@BindView(R.id.sharedIcon)
public ImageView shared;
@BindView(R.id.custom_checkbox)
public ImageView checkbox;
@BindView(R.id.ListItemLayout)
public LinearLayout itemLayout;
@BindView(R.id.unreadComments)
public ImageView unreadComments;
private OCFileListGridImageViewHolder(View itemView) { private OCFileListGridImageViewHolder(View itemView) {
super(itemView); super(itemView);
ButterKnife.bind(this, itemView);
thumbnail = itemView.findViewById(R.id.thumbnail);
favorite = itemView.findViewById(R.id.favorite_action);
localFileIndicator = itemView.findViewById(R.id.localFileIndicator);
shared = itemView.findViewById(R.id.sharedIcon);
checkbox = itemView.findViewById(R.id.custom_checkbox);
unreadComments = itemView.findViewById(R.id.unreadComments);
itemLayout = itemView.findViewById(R.id.ListItemLayout);
} }
} }
private static class OCFileListFooterViewHolder extends RecyclerView.ViewHolder { static class OCFileListFooterViewHolder extends RecyclerView.ViewHolder {
private final TextView footerText; @BindView(R.id.footerText)
public TextView footerText;
private OCFileListFooterViewHolder(View itemView) { private OCFileListFooterViewHolder(View itemView) {
super(itemView); super(itemView);
ButterKnife.bind(this, itemView);
footerText = itemView.findViewById(R.id.footerText);
} }
} }
} }

View file

@ -24,6 +24,7 @@ import android.accounts.Account;
import android.app.SearchManager; import android.app.SearchManager;
import android.content.Context; import android.content.Context;
import android.content.res.Resources; import android.content.res.Resources;
import android.graphics.drawable.Drawable;
import android.os.Bundle; import android.os.Bundle;
import android.text.TextUtils; import android.text.TextUtils;
import android.view.LayoutInflater; import android.view.LayoutInflater;
@ -38,6 +39,7 @@ import android.widget.TextView;
import com.google.android.material.snackbar.Snackbar; import com.google.android.material.snackbar.Snackbar;
import com.owncloud.android.R; import com.owncloud.android.R;
import com.owncloud.android.authentication.AccountUtils;
import com.owncloud.android.datamodel.FileDataStorageManager; import com.owncloud.android.datamodel.FileDataStorageManager;
import com.owncloud.android.datamodel.OCFile; import com.owncloud.android.datamodel.OCFile;
import com.owncloud.android.lib.common.operations.RemoteOperationResult; import com.owncloud.android.lib.common.operations.RemoteOperationResult;
@ -73,7 +75,8 @@ import butterknife.ButterKnife;
import butterknife.OnClick; import butterknife.OnClick;
import butterknife.Unbinder; import butterknife.Unbinder;
public class FileDetailSharingFragment extends Fragment implements UserListAdapter.ShareeListAdapterListener { public class FileDetailSharingFragment extends Fragment implements UserListAdapter.ShareeListAdapterListener,
DisplayUtils.AvatarGenerationListener {
private static final String ARG_FILE = "FILE"; private static final String ARG_FILE = "FILE";
private static final String ARG_ACCOUNT = "ACCOUNT"; private static final String ARG_ACCOUNT = "ACCOUNT";
@ -86,6 +89,10 @@ public class FileDetailSharingFragment extends Fragment implements UserListAdapt
private OCCapability capabilities; private OCCapability capabilities;
private OCShare publicShare; private OCShare publicShare;
private FileOperationsHelper fileOperationsHelper;
private FileDisplayActivity fileDisplayActivity;
private FileDataStorageManager fileDataStorageManager;
private Unbinder unbinder; private Unbinder unbinder;
@BindView(R.id.searchView) @BindView(R.id.searchView)
@ -112,9 +119,14 @@ public class FileDetailSharingFragment extends Fragment implements UserListAdapt
@BindView(R.id.share_by_link_container) @BindView(R.id.share_by_link_container)
LinearLayout shareByLinkContainer; LinearLayout shareByLinkContainer;
private FileOperationsHelper fileOperationsHelper; @BindView(R.id.shared_with_you_container)
private FileDisplayActivity fileDisplayActivity; LinearLayout sharedWithYouContainer;
private FileDataStorageManager fileDataStorageManager;
@BindView(R.id.shared_with_you_avatar)
ImageView sharedWithYouAvatar;
@BindView(R.id.shared_with_you_username)
TextView sharedWithYouUsername;
public static FileDetailSharingFragment newInstance(OCFile file, Account account) { public static FileDetailSharingFragment newInstance(OCFile file, Account account) {
FileDetailSharingFragment fragment = new FileDetailSharingFragment(); FileDetailSharingFragment fragment = new FileDetailSharingFragment();
@ -198,6 +210,7 @@ public class FileDetailSharingFragment extends Fragment implements UserListAdapt
private void setupView() { private void setupView() {
setShareByLinkInfo(file.isSharedViaLink()); setShareByLinkInfo(file.isSharedViaLink());
setShareWithUserInfo(); setShareWithUserInfo();
setShareWithYou();
FileDetailSharingFragmentHelper.setupSearchView( FileDetailSharingFragmentHelper.setupSearchView(
(SearchManager) fileDisplayActivity.getSystemService(Context.SEARCH_SERVICE), searchView, (SearchManager) fileDisplayActivity.getSystemService(Context.SEARCH_SERVICE), searchView,
fileDisplayActivity.getComponentName()); fileDisplayActivity.getComponentName());
@ -246,6 +259,20 @@ public class FileDetailSharingFragment extends Fragment implements UserListAdapt
updateListOfUserGroups(); updateListOfUserGroups();
} }
private void setShareWithYou() {
if (AccountUtils.accountOwnsFile(file, account)) {
sharedWithYouContainer.setVisibility(View.GONE);
} else {
sharedWithYouUsername.setText(
String.format(getString(R.string.shared_with_you_by), file.getOwnerDisplayName()));
DisplayUtils.setAvatar(account, file.getOwnerId(), this, getResources().getDimension(
R.dimen.file_list_item_avatar_icon_radius), getResources(), sharedWithYouAvatar,
getContext());
sharedWithYouAvatar.setVisibility(View.VISIBLE);
}
}
private void updateListOfUserGroups() { private void updateListOfUserGroups() {
// TODO Refactoring: create a new {@link ShareUserListAdapter} instance with every call should not be needed // TODO Refactoring: create a new {@link ShareUserListAdapter} instance with every call should not be needed
@ -546,4 +573,14 @@ public class FileDetailSharingFragment extends Fragment implements UserListAdapt
outState.putParcelable(FileActivity.EXTRA_FILE, file); outState.putParcelable(FileActivity.EXTRA_FILE, file);
outState.putParcelable(FileActivity.EXTRA_ACCOUNT, account); outState.putParcelable(FileActivity.EXTRA_ACCOUNT, account);
} }
@Override
public void avatarGenerated(Drawable avatarDrawable, Object callContext) {
sharedWithYouAvatar.setImageDrawable(avatarDrawable);
}
@Override
public boolean shouldCallGeneratedCallback(String tag, Object callContext) {
return false;
}
} }

View file

@ -207,6 +207,8 @@ public final class FileStorageUtils {
file.setMountType(remote.getMountType()); file.setMountType(remote.getMountType());
file.setPreviewAvailable(remote.isHasPreview()); file.setPreviewAvailable(remote.isHasPreview());
file.setUnreadCommentsCount(remote.getUnreadCommentsCount()); file.setUnreadCommentsCount(remote.getUnreadCommentsCount());
file.setOwnerId(remote.getOwnerId());
file.setOwnerDisplayName(remote.getOwnerDisplayName());
return file; return file;
} }

View file

@ -34,12 +34,46 @@
android:layout_width="match_parent" android:layout_width="match_parent"
android:layout_height="wrap_content" android:layout_height="wrap_content"
android:id="@+id/searchView" android:id="@+id/searchView"
android:hint="@string/share_search"
android:layout_marginStart="@dimen/standard_eighth_margin" android:layout_marginStart="@dimen/standard_eighth_margin"
android:layout_marginLeft="@dimen/standard_eighth_margin" android:layout_marginLeft="@dimen/standard_eighth_margin"
android:layout_marginEnd="@dimen/standard_margin" android:layout_marginEnd="@dimen/standard_margin"
android:layout_marginRight="@dimen/standard_margin" android:layout_marginRight="@dimen/standard_margin"
style="@style/ownCloud.SearchView" /> style="@style/ownCloud.SearchView"
android:hint="@string/share_search"/>
<LinearLayout
android:id="@+id/shared_with_you_container"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginBottom="@dimen/standard_half_margin"
android:orientation="horizontal"
android:paddingLeft="@dimen/standard_padding"
android:paddingTop="@dimen/standard_padding"
android:paddingRight="@dimen/standard_padding">
<ImageView
android:id="@+id/shared_with_you_avatar"
android:layout_width="40dp"
android:layout_height="40dp"
android:contentDescription="@string/avatar"
app:srcCompat="@drawable/ic_user"/>
<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:orientation="vertical">
<TextView
android:id="@+id/shared_with_you_username"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:paddingLeft="@dimen/standard_padding"
android:paddingTop="@dimen/standard_half_padding"
android:paddingRight="@dimen/standard_padding"
android:text="@string/shared_with_you_by"
android:textSize="16sp"/>
</LinearLayout>
</LinearLayout>
<LinearLayout <LinearLayout
android:id="@+id/share_by_link_container" android:id="@+id/share_by_link_container"
@ -106,7 +140,7 @@
android:paddingLeft="@dimen/standard_half_padding" android:paddingLeft="@dimen/standard_half_padding"
android:paddingEnd="@dimen/zero" android:paddingEnd="@dimen/zero"
android:paddingRight="@dimen/zero" android:paddingRight="@dimen/zero"
android:src="@drawable/ic_dots_vertical" /> android:src="@drawable/ic_dots_vertical"/>
</LinearLayout> </LinearLayout>
<androidx.recyclerview.widget.RecyclerView <androidx.recyclerview.widget.RecyclerView
@ -121,11 +155,11 @@
android:id="@+id/shareNoUsers" android:id="@+id/shareNoUsers"
android:layout_width="match_parent" android:layout_width="match_parent"
android:layout_height="wrap_content" android:layout_height="wrap_content"
android:paddingTop="@dimen/standard_half_padding"
android:paddingLeft="@dimen/standard_padding" android:paddingLeft="@dimen/standard_padding"
android:paddingTop="@dimen/standard_half_padding"
android:paddingRight="@dimen/standard_padding" android:paddingRight="@dimen/standard_padding"
android:text="@string/share_no_users" android:text="@string/share_no_users"
android:textSize="16sp" /> android:textSize="16sp"/>
</LinearLayout> </LinearLayout>

View file

@ -171,13 +171,26 @@
android:paddingStart="@dimen/standard_half_padding" android:paddingStart="@dimen/standard_half_padding"
android:src="@drawable/ic_unshared" /> android:src="@drawable/ic_unshared" />
<ImageView
android:id="@+id/sharedAvatar"
android:layout_width="@dimen/file_icon_size"
android:layout_height="@dimen/file_icon_size"
android:layout_centerVertical="true"
android:layout_toEndOf="@id/sharedIcon"
android:layout_toRightOf="@id/sharedIcon"
android:contentDescription="@string/shared_avatar_desc"
android:clickable="true"
android:focusable="true"
android:src="@drawable/ic_user"
android:visibility="gone" />
<ImageView <ImageView
android:id="@+id/custom_checkbox" android:id="@+id/custom_checkbox"
android:layout_width="wrap_content" android:layout_width="wrap_content"
android:layout_height="match_parent" android:layout_height="match_parent"
android:layout_centerVertical="true" android:layout_centerVertical="true"
android:layout_toEndOf="@id/sharedIcon" android:layout_toEndOf="@id/sharedAvatar"
android:layout_toRightOf="@id/sharedIcon" android:layout_toRightOf="@id/sharedAvatar"
android:clickable="false" android:clickable="false"
android:contentDescription="@string/checkbox" android:contentDescription="@string/checkbox"
android:focusable="false" android:focusable="false"

View file

@ -49,6 +49,7 @@
<dimen name="list_item_avatar_icon_margin">20dp</dimen> <dimen name="list_item_avatar_icon_margin">20dp</dimen>
<dimen name="list_item_avatar_text_margin">20dp</dimen> <dimen name="list_item_avatar_text_margin">20dp</dimen>
<dimen name="list_item_share_right_margin">12dp</dimen> <dimen name="list_item_share_right_margin">12dp</dimen>
<dimen name="file_list_item_avatar_icon_radius">10dp</dimen>
<dimen name="account_action_layout_height">72dp</dimen> <dimen name="account_action_layout_height">72dp</dimen>
<dimen name="zero">0dp</dimen> <dimen name="zero">0dp</dimen>
<dimen name="account_item_layout_height">72dp</dimen> <dimen name="account_item_layout_height">72dp</dimen>

View file

@ -873,4 +873,6 @@
<string name="io_error">IO error</string> <string name="io_error">IO error</string>
<string name="operation_canceled">Operation has been canceled</string> <string name="operation_canceled">Operation has been canceled</string>
<string name="authentication_exception">Authentication Exception</string> <string name="authentication_exception">Authentication Exception</string>
<string name="shared_avatar_desc">Avatar from shared user</string>
<string name="shared_with_you_by">Shared with you by %1$s</string>
</resources> </resources>