Explorar o código

Merge pull request #2533 from nextcloud/fileDetail

Iteration 1 for File detail & new sharing
Andy Scherzinger %!s(int64=7) %!d(string=hai) anos
pai
achega
ad064fdc24
Modificáronse 26 ficheiros con 1333 adicións e 520 borrados
  1. 3 3
      build.gradle
  2. 1 0
      drawable_resources/ic_star.svg
  3. 1 0
      drawable_resources/ic_star_outline.svg
  4. 1 0
      drawable_resources/ic_tag.svg
  5. 1 1
      scripts/lint/lint-results.txt
  6. 10 5
      src/main/java/com/owncloud/android/datamodel/ThumbnailsCacheManager.java
  7. 27 15
      src/main/java/com/owncloud/android/files/FileMenuFilter.java
  8. 62 0
      src/main/java/com/owncloud/android/ui/adapter/FileDetailTabAdapter.java
  9. 34 13
      src/main/java/com/owncloud/android/ui/adapter/ShareUserListAdapter.java
  10. 24 4
      src/main/java/com/owncloud/android/ui/adapter/UserListAdapter.java
  11. 327 0
      src/main/java/com/owncloud/android/ui/fragment/FileDetailActivitiesFragment.java
  12. 280 289
      src/main/java/com/owncloud/android/ui/fragment/FileDetailFragment.java
  13. 177 0
      src/main/java/com/owncloud/android/ui/fragment/FileDetailSharingFragment.java
  14. 1 1
      src/main/java/com/owncloud/android/ui/helpers/FileOperationsHelper.java
  15. 23 0
      src/main/res/drawable/ic_star.xml
  16. 23 0
      src/main/res/drawable/ic_star_outline.xml
  17. 23 0
      src/main/res/drawable/ic_tag.xml
  18. 53 0
      src/main/res/layout/file_details_activities_fragment.xml
  19. 109 155
      src/main/res/layout/file_details_fragment.xml
  20. 12 2
      src/main/res/layout/file_details_share_user_item.xml
  21. 103 0
      src/main/res/layout/file_details_sharing_fragment.xml
  22. 1 1
      src/main/res/layout/log_send_file.xml
  23. 4 6
      src/main/res/layout/share_user_item.xml
  24. 32 23
      src/main/res/layout/toolbar_standard.xml
  25. 0 1
      src/main/res/values/dims.xml
  26. 1 1
      src/main/res/values/strings.xml

+ 3 - 3
build.gradle

@@ -194,9 +194,9 @@ dependencies {
     // dependencies for app building
     implementation 'com.android.support:multidex:1.0.3'
 //    implementation project('nextcloud-android-library')
-    genericImplementation "com.github.nextcloud:android-library:${androidLibraryVersion}"
-    gplayImplementation "com.github.nextcloud:android-library:${androidLibraryVersion}"
-    versionDevImplementation 'com.github.nextcloud:android-library:master-SNAPSHOT' // use always latest master
+    genericImplementation "com.github.nextcloud:android-library:filterActivities-SNAPSHOT"
+    gplayImplementation "com.github.nextcloud:android-library:filterActivities-SNAPSHOT"
+    versionDevImplementation 'com.github.nextcloud:android-library:filterActivities-SNAPSHOT' // use always latest master
     implementation "com.android.support:support-v4:${supportLibraryVersion}"
     implementation "com.android.support:design:${supportLibraryVersion}"
     implementation 'com.jakewharton:disklrucache:2.0.2'

+ 1 - 0
drawable_resources/ic_star.svg

@@ -0,0 +1 @@
+<?xml version="1.0" encoding="UTF-8"?><!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd"><svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" version="1.1" width="24" height="24" viewBox="0 0 24 24"><path d="M12,17.27L18.18,21L16.54,13.97L22,9.24L14.81,8.62L12,2L9.19,8.62L2,9.24L7.45,13.97L5.82,21L12,17.27Z" /></svg>

+ 1 - 0
drawable_resources/ic_star_outline.svg

@@ -0,0 +1 @@
+<?xml version="1.0" encoding="UTF-8"?><!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd"><svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" version="1.1" width="24" height="24" viewBox="0 0 24 24"><path d="M12,15.39L8.24,17.66L9.23,13.38L5.91,10.5L10.29,10.13L12,6.09L13.71,10.13L18.09,10.5L14.77,13.38L15.76,17.66M22,9.24L14.81,8.63L12,2L9.19,8.63L2,9.24L7.45,13.97L5.82,21L12,17.27L18.18,21L16.54,13.97L22,9.24Z" /></svg>

+ 1 - 0
drawable_resources/ic_tag.svg

@@ -0,0 +1 @@
+<?xml version="1.0" encoding="UTF-8"?><!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd"><svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" version="1.1" width="24" height="24" viewBox="0 0 24 24"><path d="M5.5,7A1.5,1.5 0 0,1 4,5.5A1.5,1.5 0 0,1 5.5,4A1.5,1.5 0 0,1 7,5.5A1.5,1.5 0 0,1 5.5,7M21.41,11.58L12.41,2.58C12.05,2.22 11.55,2 11,2H4C2.89,2 2,2.89 2,4V11C2,11.55 2.22,12.05 2.59,12.41L11.58,21.41C11.95,21.77 12.45,22 13,22C13.55,22 14.05,21.77 14.41,21.41L21.41,14.41C21.78,14.05 22,13.55 22,13C22,12.44 21.77,11.94 21.41,11.58Z" /></svg>

+ 1 - 1
scripts/lint/lint-results.txt

@@ -1,2 +1,2 @@
 DO NOT TOUCH; GENERATED BY DRONE
-      <span class="mdl-layout-title">Lint Report: 114 warnings</span>
+      <span class="mdl-layout-title">Lint Report: 113 warnings</span>

+ 10 - 5
src/main/java/com/owncloud/android/datamodel/ThumbnailsCacheManager.java

@@ -56,6 +56,7 @@ import com.owncloud.android.lib.common.utils.Log_OC;
 import com.owncloud.android.lib.resources.status.OwnCloudVersion;
 import com.owncloud.android.ui.TextDrawable;
 import com.owncloud.android.ui.adapter.DiskLruImageCache;
+import com.owncloud.android.ui.fragment.FileFragment;
 import com.owncloud.android.ui.preview.PreviewImageFragment;
 import com.owncloud.android.utils.BitmapUtils;
 import com.owncloud.android.utils.ConnectivityUtils;
@@ -208,17 +209,17 @@ public class ThumbnailsCacheManager {
     }
 
     public static class ResizedImageGenerationTask extends AsyncTask<Object, Void, Bitmap> {
-        private PreviewImageFragment previewImageFragment;
+        private FileFragment fileFragment;
         private FileDataStorageManager storageManager;
         private Account account;
         private WeakReference<ImageView> imageViewReference;
         private OCFile file;
 
 
-        public ResizedImageGenerationTask(PreviewImageFragment previewImageFragment, ImageView imageView,
+        public ResizedImageGenerationTask(FileFragment fileFragment, ImageView imageView,
                                           FileDataStorageManager storageManager, Account account)
                 throws IllegalArgumentException {
-            this.previewImageFragment = previewImageFragment;
+            this.fileFragment = fileFragment;
             imageViewReference = new WeakReference<>(imageView);
             this.storageManager = storageManager;
             this.account = account;
@@ -350,9 +351,13 @@ public class ThumbnailsCacheManager {
                 } else {
                     new Thread(() -> {
                         if (ConnectivityUtils.isInternetWalled(MainApp.getAppContext())) {
-                            previewImageFragment.setNoConnectionErrorMessage();
+                            if (fileFragment instanceof PreviewImageFragment) {
+                                ((PreviewImageFragment) fileFragment).setNoConnectionErrorMessage();
+                            }
                         } else {
-                            previewImageFragment.setErrorPreviewMessage();
+                            if (fileFragment instanceof PreviewImageFragment) {
+                                ((PreviewImageFragment) fileFragment).setErrorPreviewMessage();
+                            }
                         }
                     }).start();
                     

+ 27 - 15
src/main/java/com/owncloud/android/files/FileMenuFilter.java

@@ -105,34 +105,46 @@ public class FileMenuFilter {
 
             filter(toShow, toHide, inSingleFileFragment);
 
-            MenuItem item;
             for (int i : toShow) {
-                item = menu.findItem(i);
-                if (item != null) {
-                    item.setVisible(true);
-                    item.setEnabled(true);
-                }
+                showMenuItem(menu.findItem(i));
             }
 
             for (int i : toHide) {
-                item = menu.findItem(i);
-                if (item != null) {
-                    item.setVisible(false);
-                    item.setEnabled(false);
-                }
+                hideMenuItem(menu.findItem(i));
             }
         }
     }
 
-    private void hideAll(Menu menu) {
-        MenuItem item;
-        for (int i = 0; i < menu.size(); i++) {
-            item = menu.getItem(i);
+    public static void hideAll(Menu menu) {
+        if (menu != null) {
+            for (int i = 0; i < menu.size(); i++) {
+                hideMenuItem(menu.getItem(i));
+            }
+        }
+    }
+
+    private static void hideMenuItem(MenuItem item) {
+        if (item != null) {
             item.setVisible(false);
             item.setEnabled(false);
         }
     }
 
+    private static void showMenuItem(MenuItem item) {
+        if (item != null) {
+            item.setVisible(true);
+            item.setEnabled(true);
+        }
+    }
+
+    public static void hideMenuItems(MenuItem... items) {
+        if (items != null) {
+            for (MenuItem item : items) {
+                hideMenuItem(item);
+            }
+        }
+    }
+
     /**
      * Performs the real filtering, to be applied in the {@link Menu} by the caller methods.
      *

+ 62 - 0
src/main/java/com/owncloud/android/ui/adapter/FileDetailTabAdapter.java

@@ -0,0 +1,62 @@
+/*
+ * Nextcloud Android client application
+ *
+ * @author Andy Scherzinger
+ * Copyright (C) 2018 Andy Scherzinger
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU AFFERO GENERAL PUBLIC LICENSE
+ * License as published by the Free Software Foundation; either
+ * version 3 of the License, or 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 AFFERO GENERAL PUBLIC LICENSE for more details.
+ *
+ * You should have received a copy of the GNU Affero General Public
+ * License along with this program.  If not, see <http://www.gnu.org/licenses/>.
+ */
+
+package com.owncloud.android.ui.adapter;
+
+import android.accounts.Account;
+import android.support.v4.app.Fragment;
+import android.support.v4.app.FragmentManager;
+import android.support.v4.app.FragmentStatePagerAdapter;
+
+import com.owncloud.android.datamodel.OCFile;
+import com.owncloud.android.ui.fragment.FileDetailActivitiesFragment;
+import com.owncloud.android.ui.fragment.FileDetailSharingFragment;
+
+/**
+ * File details pager adapter.
+ */
+public class FileDetailTabAdapter extends FragmentStatePagerAdapter {
+    private OCFile file;
+    private Account account;
+
+    public FileDetailTabAdapter(FragmentManager fm, OCFile file, Account account) {
+        super(fm);
+
+        this.file = file;
+        this.account = account;
+    }
+
+    @Override
+    public Fragment getItem(int position) {
+        switch (position) {
+            case 0:
+                return FileDetailActivitiesFragment.newInstance(file, account);
+            case 1:
+                return FileDetailSharingFragment.newInstance(file, account);
+            default:
+                return null;
+        }
+    }
+
+    @Override
+    public int getCount() {
+        return 2;
+    }
+}

+ 34 - 13
src/main/java/com/owncloud/android/ui/adapter/ShareUserListAdapter.java

@@ -22,6 +22,7 @@ package com.owncloud.android.ui.adapter;
 
 import android.content.Context;
 import android.graphics.drawable.Drawable;
+import android.support.annotation.NonNull;
 import android.view.LayoutInflater;
 import android.view.View;
 import android.view.ViewGroup;
@@ -32,7 +33,10 @@ import android.widget.TextView;
 import com.owncloud.android.R;
 import com.owncloud.android.lib.resources.shares.OCShare;
 import com.owncloud.android.lib.resources.shares.ShareType;
+import com.owncloud.android.ui.TextDrawable;
 
+import java.io.UnsupportedEncodingException;
+import java.security.NoSuchAlgorithmException;
 import java.util.ArrayList;
 
 /**
@@ -43,6 +47,7 @@ public class ShareUserListAdapter extends ArrayAdapter {
     private Context mContext;
     private ArrayList<OCShare> mShares;
     private ShareUserAdapterListener mListener;
+    private float mAvatarRadiusDimension;
 
     public ShareUserListAdapter(Context context, int resource, ArrayList<OCShare>shares,
                                 ShareUserAdapterListener listener) {
@@ -50,6 +55,8 @@ public class ShareUserListAdapter extends ArrayAdapter {
         mContext= context;
         mShares = shares;
         mListener = listener;
+
+        mAvatarRadiusDimension = context.getResources().getDimension(R.dimen.standard_padding);
     }
 
     @Override
@@ -67,32 +74,46 @@ public class ShareUserListAdapter extends ArrayAdapter {
         return 0;
     }
 
+    @NonNull
     @Override
-    public View getView(final int position, View convertView, ViewGroup parent) {
-        LayoutInflater inflator = (LayoutInflater) mContext
-                .getSystemService(Context.LAYOUT_INFLATER_SERVICE);
-        View view = inflator.inflate(R.layout.share_user_item, parent, false);
+    public View getView(final int position, View convertView, @NonNull ViewGroup parent) {
+        View view = convertView;
+        if (view == null) {
+            LayoutInflater inflater = (LayoutInflater) mContext.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
+            view = inflater.inflate(R.layout.share_user_item, parent, false);
+        }
 
         if (mShares != null && mShares.size() > position) {
             OCShare share = mShares.get(position);
 
-            TextView userName = (TextView) view.findViewById(R.id.userOrGroupName);
-            ImageView iconView = (ImageView) view.findViewById(R.id.icon);
-            final ImageView editShareButton = (ImageView) view.findViewById(R.id.editShareButton);
-            final ImageView unshareButton = (ImageView) view.findViewById(R.id.unshareButton);
+            TextView userName = view.findViewById(R.id.userOrGroupName);
+            ImageView icon = view.findViewById(R.id.icon);
+            final ImageView editShareButton = view.findViewById(R.id.editShareButton);
+            final ImageView unshareButton = view.findViewById(R.id.unshareButton);
 
             String name = share.getSharedWithDisplayName();
-            Drawable icon = getContext().getResources().getDrawable(R.drawable.ic_user);
             if (share.getShareType() == ShareType.GROUP) {
                 name = getContext().getString(R.string.share_group_clarification, name);
-                icon = getContext().getResources().getDrawable(R.drawable.ic_group);
+                try {
+                    icon.setImageDrawable(TextDrawable.createNamedAvatar(name, mAvatarRadiusDimension));
+                } catch (UnsupportedEncodingException | NoSuchAlgorithmException e) {
+                    icon.setImageResource(R.drawable.ic_group);
+                }
             } else if (share.getShareType() == ShareType.EMAIL) {
                 name = getContext().getString(R.string.share_email_clarification, name);
-                icon = getContext().getResources().getDrawable(R.drawable.ic_email);
-                editShareButton.setVisibility(View.INVISIBLE);
+                try {
+                    icon.setImageDrawable(TextDrawable.createNamedAvatar(name, mAvatarRadiusDimension));
+                } catch (UnsupportedEncodingException | NoSuchAlgorithmException e) {
+                    icon.setImageResource(R.drawable.ic_email);
+                }
+            } else {
+                try {
+                    icon.setImageDrawable(TextDrawable.createNamedAvatar(name, mAvatarRadiusDimension));
+                } catch (UnsupportedEncodingException | NoSuchAlgorithmException e) {
+                    icon.setImageResource(R.drawable.ic_user);
+                }
             }
             userName.setText(name);
-            iconView.setImageDrawable(icon);
 
             /// bind listener to edit privileges
             editShareButton.setOnClickListener(new View.OnClickListener() {

+ 24 - 4
src/main/java/com/owncloud/android/ui/adapter/UserListAdapter.java

@@ -32,7 +32,10 @@ import android.widget.TextView;
 import com.owncloud.android.R;
 import com.owncloud.android.lib.resources.shares.OCShare;
 import com.owncloud.android.lib.resources.shares.ShareType;
+import com.owncloud.android.ui.TextDrawable;
 
+import java.io.UnsupportedEncodingException;
+import java.security.NoSuchAlgorithmException;
 import java.util.ArrayList;
 
 /**
@@ -42,11 +45,14 @@ public class UserListAdapter extends ArrayAdapter {
 
     private Context mContext;
     private ArrayList<OCShare> mShares;
+    private float mAvatarRadiusDimension;
 
     public UserListAdapter(Context context, int resource, ArrayList<OCShare> shares) {
         super(context, resource);
         mContext = context;
         mShares = shares;
+
+        mAvatarRadiusDimension = context.getResources().getDimension(R.dimen.standard_padding);
     }
 
     @Override
@@ -75,15 +81,29 @@ public class UserListAdapter extends ArrayAdapter {
         if (mShares != null && mShares.size() > position) {
             OCShare share = mShares.get(position);
 
-            TextView userName = (TextView) view.findViewById(R.id.userOrGroupName);
-            ImageView icon = (ImageView) view.findViewById(R.id.userIcon);
+            TextView userName = view.findViewById(R.id.userOrGroupName);
+            ImageView icon = view.findViewById(R.id.userIcon);
             String name = share.getSharedWithDisplayName();
             if (share.getShareType() == ShareType.GROUP) {
                 name = getContext().getString(R.string.share_group_clarification, name);
-                icon.setImageResource(R.drawable.ic_group);
+                try {
+                    icon.setImageDrawable(TextDrawable.createNamedAvatar(name, mAvatarRadiusDimension));
+                } catch (UnsupportedEncodingException | NoSuchAlgorithmException e) {
+                    icon.setImageResource(R.drawable.ic_group);
+                }
             } else if (share.getShareType() == ShareType.EMAIL) {
                 name = getContext().getString(R.string.share_email_clarification, name);
-                icon.setImageResource(R.drawable.ic_email);
+                try {
+                    icon.setImageDrawable(TextDrawable.createNamedAvatar(name, mAvatarRadiusDimension));
+                } catch (UnsupportedEncodingException | NoSuchAlgorithmException e) {
+                    icon.setImageResource(R.drawable.ic_email);
+                }
+            } else {
+                try {
+                    icon.setImageDrawable(TextDrawable.createNamedAvatar(name, mAvatarRadiusDimension));
+                } catch (UnsupportedEncodingException | NoSuchAlgorithmException e) {
+                    icon.setImageResource(R.drawable.ic_user);
+                }
             }
             userName.setText(name);
 

+ 327 - 0
src/main/java/com/owncloud/android/ui/fragment/FileDetailActivitiesFragment.java

@@ -0,0 +1,327 @@
+/*
+ * Nextcloud Android client application
+ *
+ * @author Andy Scherzinger
+ * Copyright (C) 2018 Andy Scherzinger
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU AFFERO GENERAL PUBLIC LICENSE
+ * License as published by the Free Software Foundation; either
+ * version 3 of the License, or 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 AFFERO GENERAL PUBLIC LICENSE for more details.
+ *
+ * You should have received a copy of the GNU Affero General Public
+ * License along with this program.  If not, see <http://www.gnu.org/licenses/>.
+ */
+
+package com.owncloud.android.ui.fragment;
+
+import android.accounts.Account;
+import android.accounts.AuthenticatorException;
+import android.accounts.OperationCanceledException;
+import android.content.Context;
+import android.graphics.PorterDuff;
+import android.os.Bundle;
+import android.support.annotation.NonNull;
+import android.support.v4.app.Fragment;
+import android.support.v4.widget.SwipeRefreshLayout;
+import android.support.v7.widget.LinearLayoutManager;
+import android.support.v7.widget.RecyclerView;
+import android.view.LayoutInflater;
+import android.view.View;
+import android.view.ViewGroup;
+import android.widget.ImageView;
+import android.widget.LinearLayout;
+import android.widget.ProgressBar;
+import android.widget.TextView;
+
+import com.owncloud.android.MainApp;
+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.lib.common.OwnCloudAccount;
+import com.owncloud.android.lib.common.OwnCloudClient;
+import com.owncloud.android.lib.common.OwnCloudClientManagerFactory;
+import com.owncloud.android.lib.common.operations.RemoteOperationResult;
+import com.owncloud.android.lib.common.utils.Log_OC;
+import com.owncloud.android.lib.resources.activities.GetRemoteActivitiesOperation;
+import com.owncloud.android.lib.resources.activities.models.RichObject;
+import com.owncloud.android.ui.activity.FileActivity;
+import com.owncloud.android.ui.adapter.ActivityListAdapter;
+import com.owncloud.android.ui.interfaces.ActivityListInterface;
+import com.owncloud.android.utils.ThemeUtils;
+
+import java.io.IOException;
+import java.util.ArrayList;
+import java.util.List;
+
+import butterknife.BindString;
+import butterknife.BindView;
+import butterknife.ButterKnife;
+import butterknife.Unbinder;
+
+public class FileDetailActivitiesFragment extends Fragment implements ActivityListInterface {
+    private static final String TAG = FileDetailActivitiesFragment.class.getSimpleName();
+
+    private static final String ARG_FILE = "FILE";
+    private static final String ARG_ACCOUNT = "ACCOUNT";
+
+    private ActivityListAdapter adapter;
+    private Unbinder unbinder;
+    private OwnCloudClient ownCloudClient;
+
+    private OCFile file;
+    private Account account;
+
+    private String nextPageUrl;
+    private boolean isLoadingActivities;
+
+    @BindView(R.id.empty_list_view)
+    public LinearLayout emptyContentContainer;
+
+    @BindView(R.id.swipe_containing_list)
+    public SwipeRefreshLayout swipeListRefreshLayout;
+
+    @BindView(R.id.swipe_containing_empty)
+    public SwipeRefreshLayout swipeEmptyListRefreshLayout;
+
+    @BindView(R.id.empty_list_view_text)
+    public TextView emptyContentMessage;
+
+    @BindView(R.id.empty_list_view_headline)
+    public TextView emptyContentHeadline;
+
+    @BindView(R.id.empty_list_icon)
+    public ImageView emptyContentIcon;
+
+    @BindView(R.id.empty_list_progress)
+    public ProgressBar emptyContentProgressBar;
+
+    @BindView(android.R.id.list)
+    public RecyclerView recyclerView;
+
+    @BindString(R.string.activities_no_results_headline)
+    public String noResultsHeadline;
+
+    @BindString(R.string.activities_no_results_message)
+    public String noResultsMessage;
+
+    public static FileDetailActivitiesFragment newInstance(OCFile file, Account account) {
+        FileDetailActivitiesFragment fragment = new FileDetailActivitiesFragment();
+        Bundle args = new Bundle();
+        args.putParcelable(ARG_FILE, file);
+        args.putParcelable(ARG_ACCOUNT, account);
+        fragment.setArguments(args);
+        return fragment;
+    }
+
+    @Override
+    public View onCreateView(@NonNull LayoutInflater inflater,
+                             ViewGroup container,
+                             Bundle savedInstanceState) {
+
+        file = getArguments().getParcelable(ARG_FILE);
+        account = getArguments().getParcelable(ARG_ACCOUNT);
+
+        if (savedInstanceState != null) {
+            file = savedInstanceState.getParcelable(FileActivity.EXTRA_FILE);
+            account = savedInstanceState.getParcelable(FileActivity.EXTRA_ACCOUNT);
+        }
+
+        View view = inflater.inflate(R.layout.file_details_activities_fragment, container, false);
+        unbinder = ButterKnife.bind(this, view);
+
+        setupView();
+
+        onCreateSwipeToRefresh(swipeEmptyListRefreshLayout);
+        onCreateSwipeToRefresh(swipeListRefreshLayout);
+
+        fetchAndSetData(null);
+
+        swipeListRefreshLayout.setOnRefreshListener(() -> {
+                    setLoadingMessage();
+                    if (swipeListRefreshLayout != null && swipeListRefreshLayout.isRefreshing()) {
+                        swipeListRefreshLayout.setRefreshing(false);
+                    }
+                    fetchAndSetData(null);
+                }
+        );
+
+        swipeEmptyListRefreshLayout.setOnRefreshListener(() -> {
+                    setLoadingMessage();
+                    if (swipeEmptyListRefreshLayout != null && swipeEmptyListRefreshLayout.isRefreshing()) {
+                        swipeEmptyListRefreshLayout.setRefreshing(false);
+                    }
+                    fetchAndSetData(null);
+                }
+        );
+
+        return view;
+    }
+
+    private void setLoadingMessage() {
+        emptyContentHeadline.setText(R.string.file_list_loading);
+        emptyContentMessage.setText("");
+
+        emptyContentIcon.setVisibility(View.GONE);
+        emptyContentProgressBar.setVisibility(View.VISIBLE);
+    }
+
+    @Override
+    public void onDestroy() {
+        super.onDestroy();
+        unbinder.unbind();
+    }
+
+    private void setupView() {
+        FileDataStorageManager storageManager = new FileDataStorageManager(account, getActivity().getContentResolver());
+        emptyContentProgressBar.getIndeterminateDrawable().setColorFilter(ThemeUtils.primaryAccentColor(getContext()),
+                PorterDuff.Mode.SRC_IN);
+        emptyContentIcon.setImageDrawable(getResources().getDrawable(R.drawable.ic_activity_light_grey));
+
+        adapter = new ActivityListAdapter(getContext(), this, storageManager);
+        recyclerView.setAdapter(adapter);
+
+        LinearLayoutManager layoutManager = new LinearLayoutManager(getContext());
+
+        recyclerView.setLayoutManager(layoutManager);
+        recyclerView.addOnScrollListener(new RecyclerView.OnScrollListener() {
+
+            @Override
+            public void onScrolled(RecyclerView recyclerView, int dx, int dy) {
+                super.onScrolled(recyclerView, dx, dy);
+
+                int visibleItemCount = recyclerView.getChildCount();
+                int totalItemCount = layoutManager.getItemCount();
+                int firstVisibleItemIndex = layoutManager.findFirstVisibleItemPosition();
+
+                // synchronize loading state when item count changes
+                if (!isLoadingActivities && (totalItemCount - visibleItemCount) <= (firstVisibleItemIndex + 5)
+                        && nextPageUrl != null && !nextPageUrl.isEmpty()) {
+                    // Almost reached the end, continue to load new activities
+                    fetchAndSetData(nextPageUrl);
+                }
+            }
+        });
+    }
+
+    /**
+     * @param pageUrl String
+     */
+    private void fetchAndSetData(String pageUrl) {
+        final Account currentAccount = AccountUtils.getCurrentOwnCloudAccount(MainApp.getAppContext());
+        final Context context = MainApp.getAppContext();
+
+        Thread t = new Thread(() -> {
+            OwnCloudAccount ocAccount;
+            try {
+                ocAccount = new OwnCloudAccount(currentAccount, context);
+                ownCloudClient = OwnCloudClientManagerFactory.getDefaultSingleton().
+                        getClientFor(ocAccount, MainApp.getAppContext());
+                ownCloudClient.setOwnCloudVersion(AccountUtils.getServerVersion(currentAccount));
+                isLoadingActivities = true;
+
+                GetRemoteActivitiesOperation getRemoteNotificationOperation = new GetRemoteActivitiesOperation(
+                        file.getLocalId());
+                
+                if (pageUrl != null) {
+                    getRemoteNotificationOperation.setNextUrl(pageUrl);
+                }
+
+                Log_OC.d(TAG, "BEFORE getRemoteActivitiesOperation.execute");
+                final RemoteOperationResult result = getRemoteNotificationOperation.execute(ownCloudClient);
+
+                if (result.isSuccess() && result.getData() != null) {
+                    final ArrayList<Object> data = result.getData();
+                    final ArrayList<Object> activities = (ArrayList) data.get(0);
+                    nextPageUrl = (String) data.get(1);
+
+                    getActivity().runOnUiThread(() -> {
+                        populateList(activities, ownCloudClient, pageUrl == null);
+                        if (activities.size() > 0) {
+                            swipeEmptyListRefreshLayout.setVisibility(View.GONE);
+                            swipeListRefreshLayout.setVisibility(View.VISIBLE);
+                        } else {
+                            setEmptyContent(noResultsHeadline, noResultsMessage);
+                            swipeListRefreshLayout.setVisibility(View.GONE);
+                            swipeEmptyListRefreshLayout.setVisibility(View.VISIBLE);
+                        }
+                        isLoadingActivities = false;
+                    });
+                } else {
+                    Log_OC.d(TAG, result.getLogMessage());
+                    // show error
+                    String logMessage = result.getLogMessage();
+                    if (result.getHttpCode() == 304) {
+                        logMessage = noResultsMessage;
+                    }
+                    final String finalLogMessage = logMessage;
+                    getActivity().runOnUiThread(() -> {
+                        setEmptyContent(noResultsHeadline, finalLogMessage);
+                        isLoadingActivities = false;
+                        //setIndeterminate(isLoadingActivities);
+                    });
+                }
+
+                hideRefreshLayoutLoader();
+            } catch (com.owncloud.android.lib.common.accounts.AccountUtils.AccountNotFoundException e) {
+                Log_OC.e(TAG, "Account not found", e);
+            } catch (IOException e) {
+                Log_OC.e(TAG, "IO error", e);
+            } catch (OperationCanceledException e) {
+                Log_OC.e(TAG, "Operation has been canceled", e);
+            } catch (AuthenticatorException e) {
+                Log_OC.e(TAG, "Authentication Exception", e);
+            }
+        }
+        );
+
+        t.start();
+    }
+
+    private void populateList(List<Object> activities, OwnCloudClient mClient, boolean clear) {
+        adapter.setActivityItems(activities, mClient, clear);
+    }
+
+    private void setEmptyContent(String headline, String message) {
+        if (emptyContentContainer != null && emptyContentMessage != null) {
+            emptyContentHeadline.setText(headline);
+            emptyContentMessage.setText(message);
+
+            emptyContentProgressBar.setVisibility(View.GONE);
+            emptyContentIcon.setVisibility(View.VISIBLE);
+        }
+    }
+
+    private void hideRefreshLayoutLoader() {
+        getActivity().runOnUiThread(() -> {
+            if (swipeListRefreshLayout != null) {
+                swipeListRefreshLayout.setRefreshing(false);
+            }
+            if (swipeEmptyListRefreshLayout != null) {
+                swipeEmptyListRefreshLayout.setRefreshing(false);
+            }
+            isLoadingActivities = false;
+            //setIndeterminate(isLoadingActivities);
+        });
+    }
+
+    protected void onCreateSwipeToRefresh(SwipeRefreshLayout refreshLayout) {
+        int primaryColor = ThemeUtils.primaryColor(getContext());
+        int darkColor = ThemeUtils.primaryDarkColor(getContext());
+        int accentColor = ThemeUtils.primaryAccentColor(getContext());
+
+        // Colors in animations
+        refreshLayout.setColorSchemeColors(accentColor, primaryColor, darkColor);
+    }
+
+    @Override
+    public void onActivityClicked(RichObject richObject) {
+        // TODO implement activity click
+    }
+}

+ 280 - 289
src/main/java/com/owncloud/android/ui/fragment/FileDetailFragment.java

@@ -23,20 +23,20 @@ package com.owncloud.android.ui.fragment;
 
 import android.accounts.Account;
 import android.graphics.Bitmap;
+import android.os.Build;
 import android.os.Bundle;
+import android.support.annotation.NonNull;
 import android.support.design.widget.Snackbar;
-import android.support.v7.widget.SwitchCompat;
+import android.support.design.widget.TabLayout;
+import android.support.v4.view.ViewPager;
 import android.view.LayoutInflater;
 import android.view.Menu;
-import android.view.MenuInflater;
 import android.view.MenuItem;
 import android.view.View;
 import android.view.View.OnClickListener;
 import android.view.ViewGroup;
-import android.widget.CompoundButton;
 import android.widget.ImageView;
-import android.widget.ListAdapter;
-import android.widget.ListView;
+import android.widget.PopupMenu;
 import android.widget.ProgressBar;
 import android.widget.TextView;
 
@@ -50,10 +50,10 @@ import com.owncloud.android.files.services.FileDownloader.FileDownloaderBinder;
 import com.owncloud.android.files.services.FileUploader.FileUploaderBinder;
 import com.owncloud.android.lib.common.network.OnDatatransferProgressListener;
 import com.owncloud.android.lib.common.utils.Log_OC;
-import com.owncloud.android.lib.resources.shares.OCShare;
 import com.owncloud.android.ui.activity.FileActivity;
 import com.owncloud.android.ui.activity.FileDisplayActivity;
-import com.owncloud.android.ui.adapter.UserListAdapter;
+import com.owncloud.android.ui.activity.ToolbarActivity;
+import com.owncloud.android.ui.adapter.FileDetailTabAdapter;
 import com.owncloud.android.ui.dialog.RemoveFilesDialogFragment;
 import com.owncloud.android.ui.dialog.RenameFileDialogFragment;
 import com.owncloud.android.utils.AnalyticsUtils;
@@ -62,23 +62,21 @@ import com.owncloud.android.utils.MimeTypeUtil;
 import com.owncloud.android.utils.ThemeUtils;
 
 import java.lang.ref.WeakReference;
-import java.util.ArrayList;
 
 
 /**
  * This Fragment is used to display the details about a file.
  */
-public class FileDetailFragment extends FileFragment implements OnClickListener,
-        CompoundButton.OnCheckedChangeListener {
+public class FileDetailFragment extends FileFragment implements OnClickListener {
 
-    private int mLayout;
-    private View mView;
-    private Account mAccount;
+    private int layout;
+    private View view;
+    private ImageView previewImage;
+    private ProgressBar toolbarProgressBar;
+    private boolean previewLoaded;
+    private Account account;
 
-    public ProgressListener mProgressListener;
-
-    // to show share with users/groups info
-    private ArrayList<OCShare> mShares;
+    public ProgressListener progressListener;
 
     private static final String TAG = FileDetailFragment.class.getSimpleName();
     public static final String FTAG_CONFIRMATION = "REMOVE_CONFIRMATION_FRAGMENT";
@@ -115,9 +113,9 @@ public class FileDetailFragment extends FileFragment implements OnClickListener,
      */
     public FileDetailFragment() {
         super();
-        mAccount = null;
-        mLayout = R.layout.file_details_empty;
-        mProgressListener = null;
+        account = null;
+        layout = R.layout.file_details_empty;
+        progressListener = null;
     }
 
     @Override
@@ -126,6 +124,18 @@ public class FileDetailFragment extends FileFragment implements OnClickListener,
         if (getActivity() != null) {
             AnalyticsUtils.setCurrentScreenName(getActivity(), SCREEN_NAME, TAG);
         }
+
+        if (previewImage != null && MimeTypeUtil.isImage(getFile()) && previewLoaded) {
+            activatePreviewImage();
+        }
+    }
+
+    private void activatePreviewImage() {
+        previewImage.setVisibility(View.VISIBLE);
+        toolbarProgressBar.setVisibility(View.GONE);
+        ((ToolbarActivity) getActivity()).getSupportActionBar().setTitle(null);
+        ((ToolbarActivity) getActivity()).getSupportActionBar().setBackgroundDrawable(null);
+        makeStatusBarBlack();
     }
 
     @Override
@@ -135,45 +145,141 @@ public class FileDetailFragment extends FileFragment implements OnClickListener,
     }
 
     @Override
-    public View onCreateView(LayoutInflater inflater, ViewGroup container,
+    public View onCreateView(@NonNull LayoutInflater inflater, ViewGroup container,
             Bundle savedInstanceState) {
 
         setFile(getArguments().getParcelable(ARG_FILE));
-        mAccount = getArguments().getParcelable(ARG_ACCOUNT);
+        account = getArguments().getParcelable(ARG_ACCOUNT);
 
         if (savedInstanceState != null) {
             setFile(savedInstanceState.getParcelable(FileActivity.EXTRA_FILE));
-            mAccount = savedInstanceState.getParcelable(FileActivity.EXTRA_ACCOUNT);
+            account = savedInstanceState.getParcelable(FileActivity.EXTRA_ACCOUNT);
         }
 
-        if (getFile() != null && mAccount != null) {
-            mLayout = R.layout.file_details_fragment;
+        toolbarProgressBar = getActivity().findViewById(R.id.progressBar);
+
+        if (getFile() != null && account != null) {
+            layout = R.layout.file_details_fragment;
         }
 
-        mView = inflater.inflate(mLayout, null);
+        view = inflater.inflate(layout, null);
         
-        if (mLayout == R.layout.file_details_fragment) {
-            int accentColor = ThemeUtils.primaryAccentColor(getContext());
-            SwitchCompat favoriteToggle = mView.findViewById(R.id.fdFavorite);
-            favoriteToggle.setOnCheckedChangeListener(this);
-            ThemeUtils.tintSwitch(favoriteToggle, accentColor, false);
-            ProgressBar progressBar = mView.findViewById(R.id.fdProgressBar);
+        if (layout == R.layout.file_details_fragment) {
+            ProgressBar progressBar = view.findViewById(R.id.fdProgressBar);
             ThemeUtils.colorHorizontalProgressBar(progressBar, ThemeUtils.primaryAccentColor(getContext()));
-            mProgressListener = new ProgressListener(progressBar);
-            mView.findViewById(R.id.fdCancelBtn).setOnClickListener(this);
-            ((TextView)mView.findViewById(R.id.fdShareTitle)).setTextColor(accentColor);
-            ((TextView)mView.findViewById(R.id.fdShareWithUsersTitle)).setTextColor(accentColor);
+            progressListener = new ProgressListener(progressBar);
+            view.findViewById(R.id.fdCancelBtn).setOnClickListener(this);
+            view.findViewById(R.id.fdFavorite).setOnClickListener(this);
+            view.findViewById(R.id.overflow_menu).setOnClickListener(this);
+            previewImage = getActivity().findViewById(R.id.preview_image);
+            // TODO use whenever we switch to use glide for preview images
+            /*
+            if (getFile() != null && account != null && MimeTypeUtil.isImage(getFile())) {
+                setHeaderImage();
+            }
+             */
         }
 
         updateFileDetails(false, false);
-        return mView;
+        return view;
+    }
+    // TODO use whenever we switch to use glide for preview images
+    /*
+    private void setHeaderImage() {
+        if (mContainerActivity.getStorageManager().getCapability(account.name)
+                .getServerBackground() != null && previewImage != null) {
+
+            String background = mContainerActivity.getStorageManager().getCapability(account.name).getServerBackground();
+
+            int primaryColor = ThemeUtils.primaryColor(account, getContext());
+
+            if (URLUtil.isValidUrl(background)) {
+                // background image
+                SimpleTarget target = new SimpleTarget<Drawable>() {
+                    @Override
+                    public void onResourceReady(Drawable resource, GlideAnimation glideAnimation) {
+                        Drawable[] drawables = {new ColorDrawable(primaryColor), resource};
+                        LayerDrawable layerDrawable = new LayerDrawable(drawables);
+                        previewImage.setImageDrawable(layerDrawable);
+                        previewImage.setVisibility(View.VISIBLE);
+                        ((ToolbarActivity) getActivity()).getSupportActionBar().setTitle(null);
+                        ((ToolbarActivity) getActivity()).getSupportActionBar().setBackgroundDrawable(null);
+                        toolbarProgressBar.setVisibility(View.GONE);
+                        previewLoaded = true;
+                    }
+
+                    @Override
+                    public void onLoadFailed(Exception e, Drawable errorDrawable) {
+                        previewImage.setVisibility(View.GONE);
+                        toolbarProgressBar.setVisibility(View.VISIBLE);
+                    }
+                };
+
+                Glide.with(this)
+                        .load(background)
+                        .centerCrop()
+                        .placeholder(R.drawable.background)
+                        .error(R.drawable.background)
+                        .crossFade()
+                        .into(target);
+            } else {
+                // hide image
+                previewImage.setVisibility(View.GONE);
+                toolbarProgressBar.setVisibility(View.VISIBLE);
+            }
+        }
+    }
+    */
+
+    public void onOverflowIconClicked(View view) {
+        PopupMenu popup = new PopupMenu(getActivity(), view);
+        popup.inflate(R.menu.file_actions_menu);
+        prepareOptionsMenu(popup.getMenu());
+
+        popup.setOnMenuItemClickListener(item -> {
+            return optionsItemSelected(item);
+        });
+        popup.show();
+    }
+
+    private void setupViewPager(View view) {
+        TabLayout tabLayout = view.findViewById(R.id.tab_layout);
+        tabLayout.removeAllTabs();
+
+        tabLayout.addTab(tabLayout.newTab().setText(R.string.drawer_item_activities));
+        tabLayout.addTab(tabLayout.newTab().setText(R.string.share_dialog_title));
+
+        tabLayout.setTabGravity(TabLayout.GRAVITY_FILL);
+        tabLayout.setSelectedTabIndicatorColor(ThemeUtils.primaryAccentColor(getContext()));
+
+        final ViewPager viewPager = view.findViewById(R.id.pager);
+        final FileDetailTabAdapter adapter = new FileDetailTabAdapter
+                (getFragmentManager(), getFile(), account);
+        viewPager.setAdapter(adapter);
+        viewPager.addOnPageChangeListener(new TabLayout.TabLayoutOnPageChangeListener(tabLayout));
+        tabLayout.addOnTabSelectedListener(new TabLayout.OnTabSelectedListener() {
+            @Override
+            public void onTabSelected(TabLayout.Tab tab) {
+                viewPager.setCurrentItem(tab.getPosition());
+            }
+
+            @Override
+            public void onTabUnselected(TabLayout.Tab tab) {
+                // unused at the moment
+            }
+
+            @Override
+            public void onTabReselected(TabLayout.Tab tab) {
+                // unused at the moment
+            }
+        });
     }
 
     @Override
-    public void onSaveInstanceState(Bundle outState) {
+    public void onSaveInstanceState(@NonNull Bundle outState) {
         super.onSaveInstanceState(outState);
         outState.putParcelable(FileActivity.EXTRA_FILE, getFile());
-        outState.putParcelable(FileActivity.EXTRA_ACCOUNT, mAccount);
+        outState.putParcelable(FileActivity.EXTRA_ACCOUNT, account);
     }
 
     @Override
@@ -185,33 +291,30 @@ public class FileDetailFragment extends FileFragment implements OnClickListener,
     @Override
     public void onStop() {
         leaveTransferProgress();
+        if (previewImage != null) {
+            previewImage.setVisibility(View.GONE);
+            toolbarProgressBar.setVisibility(View.VISIBLE);
+            if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) {
+                getActivity().getWindow().setStatusBarColor(ThemeUtils.primaryDarkColor(getContext()));
+            }
+        }
+
         super.onStop();
     }
 
-
     @Override
     public View getView() {
-        return super.getView() == null ? mView : super.getView();
-    }
-
-
-    /**
-     * {@inheritDoc}
-     */
-    @Override
-    public void onCreateOptionsMenu(Menu menu, MenuInflater inflater) {
-        super.onCreateOptionsMenu(menu, inflater);
-        inflater.inflate(R.menu.file_actions_menu, menu);
+        return super.getView() == null ? view : super.getView();
     }
 
-
-    /**
-     * {@inheritDoc}
-     */
     @Override
     public void onPrepareOptionsMenu(Menu menu) {
         super.onPrepareOptionsMenu(menu);
 
+        FileMenuFilter.hideAll(menu);
+    }
+
+    private void prepareOptionsMenu(Menu menu) {
         if (mContainerActivity.getStorageManager() != null) {
             FileMenuFilter mf = new FileMenuFilter(
                 getFile(),
@@ -223,94 +326,33 @@ public class FileDetailFragment extends FileFragment implements OnClickListener,
             mf.filter(menu, true);
         }
 
-        // additional restriction for this fragment 
-        MenuItem item = menu.findItem(R.id.action_see_details);
-        if (item != null) {
-            item.setVisible(false);
-            item.setEnabled(false);
-        }
-
-        // additional restriction for this fragment
-        item = menu.findItem(R.id.action_select_all);
-        if (item != null) {
-            item.setVisible(false);
-            item.setEnabled(false);
-        }
-
-        // additional restriction for this fragment
-        item = menu.findItem(R.id.action_move);
-        if (item != null) {
-            item.setVisible(false);
-            item.setEnabled(false);
-        }
-
-        // additional restriction for this fragment
-        item = menu.findItem(R.id.action_copy);
-        if (item != null) {
-            item.setVisible(false);
-            item.setEnabled(false);
-        }
-
-        // additional restriction for this fragment
-        item = menu.findItem(R.id.action_favorite);
-        if (item != null) {
-            item.setVisible(false);
-            item.setEnabled(false);
-        }
-
-        // additional restriction for this fragment
-        item = menu.findItem(R.id.action_unset_favorite);
-        if (item != null) {
-            item.setVisible(false);
-            item.setEnabled(false);
-        }
-
-        // additional restriction for this fragment
-        item = menu.findItem(R.id.action_search);
-        if (item != null) {
-            item.setVisible(false);
-            item.setEnabled(false);
-        }
-
-
-        Boolean dualPane = getResources().getBoolean(R.bool.large_land_layout);
-
-        item = menu.findItem(R.id.action_switch_view);
-        if (item != null && !dualPane){
-            item.setVisible(false);
-            item.setEnabled(false);
-        }
-
-        item = menu.findItem(R.id.action_sync_account);
-        if (item != null && !dualPane) {
-            item.setVisible(false);
-            item.setEnabled(false);
-        }
+        // restriction for this fragment
+        FileMenuFilter.hideMenuItems(
+                menu.findItem(R.id.action_see_details),
+                menu.findItem(R.id.action_select_all),
+                menu.findItem(R.id.action_move),
+                menu.findItem(R.id.action_copy),
+                menu.findItem(R.id.action_favorite),
+                menu.findItem(R.id.action_unset_favorite),
+                menu.findItem(R.id.action_search)
+        );
 
-        item = menu.findItem(R.id.action_sort);
-        if (item != null && !dualPane) {
-            item.setVisible(false);
-            item.setEnabled(false);
+        // dual pane restrictions
+        if (!getResources().getBoolean(R.bool.large_land_layout)){
+            FileMenuFilter.hideMenuItems(
+                    menu.findItem(R.id.action_switch_view),
+                    menu.findItem(R.id.action_sync_account),
+                    menu.findItem(R.id.action_sort)
+            );
         }
 
-        item = menu.findItem(R.id.action_send_share_file);
-        if (item != null) {
-            ThemeUtils.tintDrawable(item.getIcon(), ThemeUtils.fontColor(getContext()));
-            item.setShowAsAction(MenuItem.SHOW_AS_ACTION_IF_ROOM);
-            if (getFile().isSharedWithMe() && !getFile().canReshare()) {
-                // additional restriction for this fragment
-
-                item.setVisible(false);
-                item.setEnabled(false);
-            }
+        // share restrictions
+        if (getFile().isSharedWithMe() && !getFile().canReshare()) {
+            FileMenuFilter.hideMenuItems(menu.findItem(R.id.action_send_share_file));
         }
     }
 
-    /**
-     * {@inheritDoc}
-     */
-    @Override
-    public boolean onOptionsItemSelected(MenuItem item) {
+    public boolean optionsItemSelected(MenuItem item) {
         switch (item.getItemId()) {
             case R.id.action_send_share_file: {
                 if(getFile().isSharedWithMe() && !getFile().canReshare()){
@@ -347,6 +389,14 @@ public class FileDetailFragment extends FileFragment implements OnClickListener,
                 mContainerActivity.getFileOperationsHelper().syncFile(getFile());
                 return true;
             }
+            case R.id.action_keep_files_offline: {
+                mContainerActivity.getFileOperationsHelper().toggleOfflineFile(getFile(), true);
+                return true;
+            }
+            case R.id.action_unset_keep_files_offline: {
+                mContainerActivity.getFileOperationsHelper().toggleOfflineFile(getFile(), false);
+                return true;
+            }
             default:
                 return super.onOptionsItemSelected(item);
         }
@@ -359,28 +409,39 @@ public class FileDetailFragment extends FileFragment implements OnClickListener,
                 ((FileDisplayActivity) mContainerActivity).cancelTransference(getFile());
                 break;
             }
+            case R.id.fdFavorite: {
+                if (getFile().getIsFavorite()) {
+                    ((ImageView)getView().findViewById(R.id.fdFavorite)).
+                            setImageDrawable(getResources()
+                                    .getDrawable(R.drawable.ic_star_outline));
+                    mContainerActivity.getFileOperationsHelper().toggleFavoriteFile(getFile(), false);
+                } else {
+                    ((ImageView)getView().findViewById(R.id.fdFavorite))
+                            .setImageDrawable(getResources()
+                                    .getDrawable(R.drawable.ic_star));
+                    mContainerActivity.getFileOperationsHelper().toggleFavoriteFile(getFile(), true);
+                }
+                break;
+            }
+            case R.id.overflow_menu: {
+                onOverflowIconClicked(v);
+                break;
+            }
             default:
                 Log_OC.e(TAG, "Incorrect view clicked!");
                 break;
         }
     }
 
-    @Override
-    public void onCheckedChanged(CompoundButton buttonView, boolean isChecked) {
-        SwitchCompat favSwitch = getView().findViewById(R.id.fdFavorite);
-        mContainerActivity.getFileOperationsHelper().toggleOfflineFile(getFile(), favSwitch.isChecked());
-    }
-
     /**
      * Check if the fragment was created with an empty layout. An empty fragment can't show file details, must be replaced.
      *
      * @return True when the fragment was created with the empty layout.
      */
     public boolean isEmpty() {
-        return (mLayout == R.layout.file_details_empty || getFile() == null || mAccount == null);
+        return (layout == R.layout.file_details_empty || getFile() == null || account == null);
     }
 
-
     /**
      * Use this method to signal this Activity that it shall update its view.
      *
@@ -388,13 +449,13 @@ public class FileDetailFragment extends FileFragment implements OnClickListener,
      */
     public void updateFileDetails(OCFile file, Account ocAccount) {
         setFile(file);
-        mAccount = ocAccount;
+        account = ocAccount;
         updateFileDetails(false, false);
     }
 
     /**
      * Updates the view with all relevant details about that file.
-     * <p/>
+     *
      * TODO Remove parameter when the transferring state of files is kept in database.
      *
      * @param transferring Flag signaling if the file should be considered as downloading or uploading,
@@ -419,22 +480,20 @@ public class FileDetailFragment extends FileFragment implements OnClickListener,
             setFilename(file.getFileName());
             setFiletype(file);
             setFilesize(file.getFileLength());
-
             setTimeModified(file.getModificationTimestamp());
 
-            SwitchCompat favSwitch = getView().findViewById(R.id.fdFavorite);
-            favSwitch.setChecked(file.isAvailableOffline());
-
-            setShareByLinkInfo(file.isSharedViaLink());
-
-            setShareWithUserInfo();
+            if (file.getIsFavorite()) {
+                ((ImageView)getView().findViewById(R.id.fdFavorite)).setImageDrawable(getResources().getDrawable(R.drawable.ic_star));
+            } else {
+                ((ImageView)getView().findViewById(R.id.fdFavorite)).setImageDrawable(getResources().getDrawable(R.drawable.ic_star_outline));
+            }
 
             // configure UI for depending upon local state of the file
             FileDownloaderBinder downloaderBinder = mContainerActivity.getFileDownloaderBinder();
             FileUploaderBinder uploaderBinder = mContainerActivity.getFileUploaderBinder();
             if (transferring ||
-                    (downloaderBinder != null && downloaderBinder.isDownloading(mAccount, file)) ||
-                    (uploaderBinder != null && uploaderBinder.isUploading(mAccount, file))
+                    (downloaderBinder != null && downloaderBinder.isDownloading(account, file)) ||
+                    (uploaderBinder != null && uploaderBinder.isUploading(account, file))
                     ) {
                 setButtonsForTransferring();
 
@@ -448,6 +507,9 @@ public class FileDetailFragment extends FileFragment implements OnClickListener,
                 setButtonsForRemote();
             }
         }
+
+        setupViewPager(getView());
+
         getView().invalidate();
     }
 
@@ -457,10 +519,9 @@ public class FileDetailFragment extends FileFragment implements OnClickListener,
      * @return 'True' when the fragment is ready to show details of a file
      */
     private boolean readyToShow() {
-        return (getFile() != null && mAccount != null && mLayout == R.layout.file_details_fragment);
+        return (getFile() != null && account != null && layout == R.layout.file_details_fragment);
     }
 
-
     /**
      * Updates the filename in view
      *
@@ -479,48 +540,75 @@ public class FileDetailFragment extends FileFragment implements OnClickListener,
      */
     private void setFiletype(OCFile file) {
         ImageView iv = getView().findViewById(R.id.fdIcon);
+        View v = getView().findViewById(R.id.fdIcon_divider);
 
         if (iv != null) {
             iv.setTag(file.getFileId());
             // Name of the file, to deduce the icon to use in case the MIME type is not precise enough
-            iv.setImageDrawable(MimeTypeUtil.getFileTypeIcon(file.getMimetype(), file.getFileName(), mAccount,
+            iv.setImageDrawable(MimeTypeUtil.getFileTypeIcon(file.getMimetype(), file.getFileName(), account,
                     getContext()));
 
-            Bitmap thumbnail;
+            Bitmap resizedImage;
 
             if (MimeTypeUtil.isImage(file)) {
-                String tagId = String.valueOf(file.getRemoteId());
-                thumbnail = ThumbnailsCacheManager.getBitmapFromDiskCache(tagId);
-
-                if (thumbnail != null && !file.needsUpdateThumbnail()) {
-                    iv.setImageBitmap(thumbnail);
+                String tagId = String.valueOf(ThumbnailsCacheManager.PREFIX_RESIZED_IMAGE + getFile().getRemoteId());
+                resizedImage = ThumbnailsCacheManager.getBitmapFromDiskCache(tagId);
+
+                if (resizedImage != null && !file.needsUpdateThumbnail()) {
+                    iv.setVisibility(View.GONE);
+                    v.setVisibility(View.GONE);
+                    previewImage.setImageBitmap(resizedImage);
+                    activatePreviewImage();
+                    previewLoaded = true;
                 } else {
-                    // generate new Thumbnail
-                    if (ThumbnailsCacheManager.cancelPotentialThumbnailWork(file, iv)) {
-                        final ThumbnailsCacheManager.ThumbnailGenerationTask task =
-                                new ThumbnailsCacheManager.ThumbnailGenerationTask(
-                                        iv, mContainerActivity.getStorageManager(), mAccount
-                                );
-                        if (thumbnail == null) {
-                            thumbnail = ThumbnailsCacheManager.mDefaultImg;
+                    // show thumbnail while loading resized image
+                    Bitmap thumbnail = ThumbnailsCacheManager.getBitmapFromDiskCache(
+                            String.valueOf(ThumbnailsCacheManager.PREFIX_THUMBNAIL + getFile().getRemoteId()));
+
+                    if (thumbnail != null) {
+                        iv.setImageBitmap(thumbnail);
+                    } else {
+                        thumbnail = ThumbnailsCacheManager.mDefaultImg;
+                    }
+
+                    // generate new resized image
+                    if (ThumbnailsCacheManager.cancelPotentialThumbnailWork(getFile(), iv) &&
+                            mContainerActivity.getStorageManager() != null) {
+                        final ThumbnailsCacheManager.ResizedImageGenerationTask task =
+                                new ThumbnailsCacheManager.ResizedImageGenerationTask(FileDetailFragment.this,
+                                        iv,
+                                        mContainerActivity.getStorageManager(),
+                                        mContainerActivity.getStorageManager().getAccount());
+                        if (resizedImage == null) {
+                            resizedImage = thumbnail;
                         }
-                        final ThumbnailsCacheManager.AsyncThumbnailDrawable asyncDrawable =
-                                new ThumbnailsCacheManager.AsyncThumbnailDrawable(
+                        final ThumbnailsCacheManager.AsyncResizedImageDrawable asyncDrawable =
+                                new ThumbnailsCacheManager.AsyncResizedImageDrawable(
                                         MainApp.getAppContext().getResources(),
-                                        thumbnail,
+                                        resizedImage,
                                         task
                                 );
-                        iv.setImageDrawable(asyncDrawable);
-                        task.execute(new ThumbnailsCacheManager.ThumbnailGenerationTaskObject(file, file.getRemoteId()));
+                        iv.setVisibility(View.GONE);
+                        v.setVisibility(View.GONE);
+                        previewImage.setImageDrawable(asyncDrawable);
+                        activatePreviewImage();
+                        previewLoaded = true;
+                        task.execute(getFile());
                     }
                 }
             } else {
-                iv.setImageDrawable(MimeTypeUtil.getFileTypeIcon(file.getMimetype(), file.getFileName(), mAccount,
+                iv.setImageDrawable(MimeTypeUtil.getFileTypeIcon(file.getMimetype(), file.getFileName(), account,
                         getContext()));
             }
         }
     }
 
+    private void makeStatusBarBlack() {
+        if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) {
+            getActivity().getWindow().setStatusBarColor(getResources().getColor(R.color.black));
+        }
+    }
+
     /**
      * Updates the file size in view
      *
@@ -545,98 +633,11 @@ public class FileDetailFragment extends FileFragment implements OnClickListener,
         }
     }
 
-    /**
-     * Updates Share by link data
-     *
-     * @param isShareByLink flag is share by link is enable
-     */
-    private void setShareByLinkInfo(boolean isShareByLink) {
-        TextView tv = getView().findViewById(R.id.fdSharebyLink);
-        if (tv != null) {
-            tv.setText(isShareByLink ? R.string.filedetails_share_link_enable :
-                    R.string.filedetails_share_link_disable);
-        }
-        ImageView linkIcon = getView().findViewById(R.id.fdShareLinkIcon);
-        if (linkIcon != null) {
-            linkIcon.setVisibility(isShareByLink ? View.VISIBLE : View.GONE);
-        }
-    }
-
-    /**
-     * Update Share With data
-     */
-    private void setShareWithUserInfo(){
-        // Get Users and Groups
-        if (((FileActivity) getActivity()).getStorageManager() != null) {
-            FileDataStorageManager fileDataStorageManager = ((FileActivity) getActivity()).getStorageManager();
-            mShares = fileDataStorageManager.getSharesWithForAFile(
-                    getFile().getRemotePath(),mAccount.name
-            );
-
-            // Update list of users/groups
-            updateListOfUserGroups();
-        }
-    }
-
-    private void updateListOfUserGroups() {
-        // Update list of users/groups
-        // TODO Refactoring: create a new {@link ShareUserListAdapter} instance with every call should not be needed
-        UserListAdapter mUserGroupsAdapter = new UserListAdapter(
-                getActivity().getApplicationContext(),
-                R.layout.share_user_item, mShares
-        );
-
-        // Show data
-        ListView usersList = getView().findViewById(R.id.fdshareUsersList);
-
-        // No data
-        TextView noList = getView().findViewById(R.id.fdShareNoUsers);
-
-        if (mShares.size() > 0) {
-            usersList.setVisibility(View.VISIBLE);
-            usersList.setAdapter(mUserGroupsAdapter);
-            noList.setVisibility(View.GONE);
-            setListViewHeightBasedOnChildren(usersList);
-
-        } else {
-            usersList.setVisibility(View.GONE);
-            noList.setVisibility(View.VISIBLE);
-        }
-    }
-
-    /**
-     * Fix scroll in listview when the parent is a ScrollView
-     */
-    private static void setListViewHeightBasedOnChildren(ListView listView) {
-        ListAdapter listAdapter = listView.getAdapter();
-        if (listAdapter == null) {
-            return;
-        }
-        int desiredWidth = View.MeasureSpec.makeMeasureSpec(listView.getWidth(), View.MeasureSpec.AT_MOST);
-        int totalHeight = 0;
-        View view = null;
-        for (int i = 0; i < listAdapter.getCount(); i++) {
-            view = listAdapter.getView(i, view, listView);
-            if (i == 0) {
-                view.setLayoutParams(new ViewGroup.LayoutParams(desiredWidth, ViewGroup.LayoutParams.WRAP_CONTENT));
-            }
-            view.measure(desiredWidth, View.MeasureSpec.UNSPECIFIED);
-            totalHeight += view.getMeasuredHeight();
-        }
-        ViewGroup.LayoutParams params = listView.getLayoutParams();
-        params.height = totalHeight + (listView.getDividerHeight() * (listAdapter.getCount() - 1));
-        listView.setLayoutParams(params);
-        listView.requestLayout();
-    }
-
     /**
      * Enables or disables buttons for a file being downloaded
      */
     private void setButtonsForTransferring() {
         if (!isEmpty()) {
-            // let's protect the user from himself ;)
-            getView().findViewById(R.id.fdFavorite).setEnabled(false);
-            
             // show the progress bar for the transfer
             getView().findViewById(R.id.fdProgressBlock).setVisibility(View.VISIBLE);
             TextView progressText = getView().findViewById(R.id.fdProgressText);
@@ -644,11 +645,11 @@ public class FileDetailFragment extends FileFragment implements OnClickListener,
             FileDownloaderBinder downloaderBinder = mContainerActivity.getFileDownloaderBinder();
             FileUploaderBinder uploaderBinder = mContainerActivity.getFileUploaderBinder();
             //if (getFile().isDownloading()) {
-            if (downloaderBinder != null && downloaderBinder.isDownloading(mAccount, getFile())) {
+            if (downloaderBinder != null && downloaderBinder.isDownloading(account, getFile())) {
                 progressText.setText(R.string.downloader_download_in_progress_ticker);
             }
             else {
-                if (uploaderBinder != null && uploaderBinder.isUploading(mAccount, getFile())) {
+                if (uploaderBinder != null && uploaderBinder.isUploading(account, getFile())) {
                     progressText.setText(R.string.uploader_upload_in_progress_ticker);
                 }
             }
@@ -660,8 +661,6 @@ public class FileDetailFragment extends FileFragment implements OnClickListener,
      */
     private void setButtonsForDown() {
         if (!isEmpty()) {
-            getView().findViewById(R.id.fdFavorite).setEnabled(true);
-            
             // hides the progress bar
             getView().findViewById(R.id.fdProgressBlock).setVisibility(View.GONE);
             TextView progressText = getView().findViewById(R.id.fdProgressText);
@@ -674,8 +673,6 @@ public class FileDetailFragment extends FileFragment implements OnClickListener,
      */
     private void setButtonsForRemote() {
         if (!isEmpty()) {
-            getView().findViewById(R.id.fdFavorite).setEnabled(true);
-            
             // hides the progress bar
             getView().findViewById(R.id.fdProgressBlock).setVisibility(View.GONE);
             TextView progressText = getView().findViewById(R.id.fdProgressText);
@@ -683,47 +680,43 @@ public class FileDetailFragment extends FileFragment implements OnClickListener,
         }
     }
 
-
     public void listenForTransferProgress() {
-        if (mProgressListener != null) {
+        if (progressListener != null) {
             if (mContainerActivity.getFileDownloaderBinder() != null) {
                 mContainerActivity.getFileDownloaderBinder().
-                        addDatatransferProgressListener(mProgressListener, mAccount, getFile());
+                        addDatatransferProgressListener(progressListener, account, getFile());
             }
             if (mContainerActivity.getFileUploaderBinder() != null) {
                 mContainerActivity.getFileUploaderBinder().
-                        addDatatransferProgressListener(mProgressListener, mAccount, getFile());
+                        addDatatransferProgressListener(progressListener, account, getFile());
             }
         } else {
-            Log_OC.d(TAG, "mProgressListener == null");
+            Log_OC.d(TAG, "progressListener == null");
         }
     }
 
-
     public void leaveTransferProgress() {
-        if (mProgressListener != null) {
+        if (progressListener != null) {
             if (mContainerActivity.getFileDownloaderBinder() != null) {
                 mContainerActivity.getFileDownloaderBinder().
-                        removeDatatransferProgressListener(mProgressListener, mAccount, getFile());
+                        removeDatatransferProgressListener(progressListener, account, getFile());
             }
             if (mContainerActivity.getFileUploaderBinder() != null) {
                 mContainerActivity.getFileUploaderBinder().
-                        removeDatatransferProgressListener(mProgressListener, mAccount, getFile());
+                        removeDatatransferProgressListener(progressListener, account, getFile());
             }
         }
     }
 
-
     /**
-     * Helper class responsible for updating the progress bar shown for file uploading or
-     * downloading
+     * Helper class responsible for updating the progress bar shown for file downloading.
      */
     private class ProgressListener implements OnDatatransferProgressListener {
-        int mLastPercent = 0;
-        WeakReference<ProgressBar> mProgressBar = null;
+        private int mLastPercent = 0;
+        private WeakReference<ProgressBar> mProgressBar;
 
         ProgressListener(ProgressBar progressBar) {
-            mProgressBar = new WeakReference<ProgressBar>(progressBar);
+            mProgressBar = new WeakReference<>(progressBar);
         }
 
         @Override
@@ -739,7 +732,5 @@ public class FileDetailFragment extends FileFragment implements OnClickListener,
             }
             mLastPercent = percent;
         }
-
     }
-
 }

+ 177 - 0
src/main/java/com/owncloud/android/ui/fragment/FileDetailSharingFragment.java

@@ -0,0 +1,177 @@
+/*
+ * Nextcloud Android client application
+ *
+ * @author Andy Scherzinger
+ * Copyright (C) 2018 Andy Scherzinger
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU AFFERO GENERAL PUBLIC LICENSE
+ * License as published by the Free Software Foundation; either
+ * version 3 of the License, or 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 AFFERO GENERAL PUBLIC LICENSE for more details.
+ *
+ * You should have received a copy of the GNU Affero General Public
+ * License along with this program.  If not, see <http://www.gnu.org/licenses/>.
+ */
+
+package com.owncloud.android.ui.fragment;
+
+import android.accounts.Account;
+import android.os.Bundle;
+import android.support.annotation.NonNull;
+import android.support.v4.app.Fragment;
+import android.view.LayoutInflater;
+import android.view.View;
+import android.view.ViewGroup;
+import android.widget.ImageView;
+import android.widget.ListAdapter;
+import android.widget.ListView;
+import android.widget.TextView;
+
+import com.owncloud.android.R;
+import com.owncloud.android.datamodel.FileDataStorageManager;
+import com.owncloud.android.datamodel.OCFile;
+import com.owncloud.android.lib.resources.shares.OCShare;
+import com.owncloud.android.ui.activity.FileActivity;
+import com.owncloud.android.ui.adapter.UserListAdapter;
+import com.owncloud.android.utils.ThemeUtils;
+
+import java.util.ArrayList;
+
+public class FileDetailSharingFragment  extends Fragment {
+
+    private static final String ARG_FILE = "FILE";
+    private static final String ARG_ACCOUNT = "ACCOUNT";
+
+    // to show share with users/groups info
+    private ArrayList<OCShare> mShares;
+
+    private OCFile file;
+    private Account account;
+
+    public static FileDetailSharingFragment newInstance(OCFile file, Account account) {
+        FileDetailSharingFragment fragment = new FileDetailSharingFragment();
+        Bundle args = new Bundle();
+        args.putParcelable(ARG_FILE, file);
+        args.putParcelable(ARG_ACCOUNT, account);
+        fragment.setArguments(args);
+        return fragment;
+    }
+
+    @Override
+    public View onCreateView(@NonNull LayoutInflater inflater,
+                             ViewGroup container,
+                             Bundle savedInstanceState) {
+
+        file = getArguments().getParcelable(ARG_FILE);
+        account = getArguments().getParcelable(ARG_ACCOUNT);
+
+        if (savedInstanceState != null) {
+            file = savedInstanceState.getParcelable(FileActivity.EXTRA_FILE);
+            account = savedInstanceState.getParcelable(FileActivity.EXTRA_ACCOUNT);
+        }
+
+        View view = inflater.inflate(R.layout.file_details_sharing_fragment, container, false);
+
+        setupView(view);
+
+        return view;
+    }
+
+    private void setupView(View view) {
+        ((TextView)view.findViewById(R.id.fdShareTitle)).setTextColor(ThemeUtils.primaryAccentColor(getContext()));
+        ((TextView)view.findViewById(R.id.fdShareWithUsersTitle)).setTextColor(ThemeUtils.primaryAccentColor(getContext()));
+
+        setShareByLinkInfo(file.isSharedViaLink(), view);
+
+        setShareWithUserInfo(view);
+    }
+
+    /**
+     * Updates Share by link data
+     *
+     * @param isShareByLink flag is share by link is enable
+     */
+    private void setShareByLinkInfo(boolean isShareByLink, View view) {
+        TextView tv = view.findViewById(R.id.fdSharebyLink);
+        if (tv != null) {
+            tv.setText(isShareByLink ? R.string.filedetails_share_link_enable :
+                    R.string.filedetails_share_link_disable);
+        }
+        ImageView linkIcon = view.findViewById(R.id.fdShareLinkIcon);
+        if (linkIcon != null) {
+            linkIcon.setVisibility(isShareByLink ? View.VISIBLE : View.GONE);
+        }
+    }
+
+    /**
+     * Update Share With data
+     */
+    private void setShareWithUserInfo(View view){
+        // Get Users and Groups
+        if (((FileActivity) getActivity()).getStorageManager() != null) {
+            FileDataStorageManager fileDataStorageManager = ((FileActivity) getActivity()).getStorageManager();
+            mShares = fileDataStorageManager.getSharesWithForAFile(
+                    file.getRemotePath(),account.name
+            );
+
+            // Update list of users/groups
+            updateListOfUserGroups(view);
+        }
+    }
+
+    private void updateListOfUserGroups(View view) {
+        // Update list of users/groups
+        // TODO Refactoring: create a new {@link ShareUserListAdapter} instance with every call should not be needed
+        UserListAdapter mUserGroupsAdapter = new UserListAdapter(
+                getActivity().getApplicationContext(),
+                R.layout.share_user_item, mShares
+        );
+
+        // Show data
+        ListView usersList = view.findViewById(R.id.fdshareUsersList);
+
+        // No data
+        TextView noList = view.findViewById(R.id.fdShareNoUsers);
+
+        if (mShares.size() > 0) {
+            usersList.setVisibility(View.VISIBLE);
+            usersList.setAdapter(mUserGroupsAdapter);
+            noList.setVisibility(View.GONE);
+            setListViewHeightBasedOnChildren(usersList);
+
+        } else {
+            usersList.setVisibility(View.GONE);
+            noList.setVisibility(View.VISIBLE);
+        }
+    }
+
+    /**
+     * Fix scroll in listview when the parent is a ScrollView
+     */
+    private static void setListViewHeightBasedOnChildren(ListView listView) {
+        ListAdapter listAdapter = listView.getAdapter();
+        if (listAdapter == null) {
+            return;
+        }
+        int desiredWidth = View.MeasureSpec.makeMeasureSpec(listView.getWidth(), View.MeasureSpec.AT_MOST);
+        int totalHeight = 0;
+        View view = null;
+        for (int i = 0; i < listAdapter.getCount(); i++) {
+            view = listAdapter.getView(i, view, listView);
+            if (i == 0) {
+                view.setLayoutParams(new ViewGroup.LayoutParams(desiredWidth, ViewGroup.LayoutParams.WRAP_CONTENT));
+            }
+            view.measure(desiredWidth, View.MeasureSpec.UNSPECIFIED);
+            totalHeight += view.getMeasuredHeight();
+        }
+        ViewGroup.LayoutParams params = listView.getLayoutParams();
+        params.height = totalHeight + (listView.getDividerHeight() * (listAdapter.getCount() - 1));
+        listView.setLayoutParams(params);
+        listView.requestLayout();
+    }
+}

+ 1 - 1
src/main/java/com/owncloud/android/ui/helpers/FileOperationsHelper.java

@@ -728,7 +728,7 @@ public class FileOperationsHelper {
         }
     }
 
-    private void toggleFavoriteFile(OCFile file, boolean shouldBeFavorite) {
+    public void toggleFavoriteFile(OCFile file, boolean shouldBeFavorite) {
         if (file.getIsFavorite() != shouldBeFavorite) {
             EventBus.getDefault().post(new FavoriteEvent(file.getRemotePath(), shouldBeFavorite, file.getRemoteId()));
         }

+ 23 - 0
src/main/res/drawable/ic_star.xml

@@ -0,0 +1,23 @@
+<!--
+    @author Google LLC
+    Copyright (C) 2018 Google LLC
+
+    Licensed under the Apache License, Version 2.0 (the "License");
+    you may not use this file except in compliance with the License.
+    You may obtain a copy of the License at
+
+    http://www.apache.org/licenses/LICENSE-2.0
+
+    Unless required by applicable law or agreed to in writing, software
+    distributed under the License is distributed on an "AS IS" BASIS,
+    WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+    See the License for the specific language governing permissions and
+    limitations under the License.
+-->
+<vector xmlns:android="http://schemas.android.com/apk/res/android"
+    android:height="24dp"
+    android:width="24dp"
+    android:viewportWidth="24"
+    android:viewportHeight="24">
+    <path android:fillColor="#757575" android:pathData="M12,17.27L18.18,21L16.54,13.97L22,9.24L14.81,8.62L12,2L9.19,8.62L2,9.24L7.45,13.97L5.82,21L12,17.27Z" />
+</vector>

+ 23 - 0
src/main/res/drawable/ic_star_outline.xml

@@ -0,0 +1,23 @@
+<!--
+    @author Google LLC
+    Copyright (C) 2018 Google LLC
+
+    Licensed under the Apache License, Version 2.0 (the "License");
+    you may not use this file except in compliance with the License.
+    You may obtain a copy of the License at
+
+    http://www.apache.org/licenses/LICENSE-2.0
+
+    Unless required by applicable law or agreed to in writing, software
+    distributed under the License is distributed on an "AS IS" BASIS,
+    WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+    See the License for the specific language governing permissions and
+    limitations under the License.
+-->
+<vector xmlns:android="http://schemas.android.com/apk/res/android"
+    android:height="24dp"
+    android:width="24dp"
+    android:viewportWidth="24"
+    android:viewportHeight="24">
+    <path android:fillColor="#757575" android:pathData="M12,15.39L8.24,17.66L9.23,13.38L5.91,10.5L10.29,10.13L12,6.09L13.71,10.13L18.09,10.5L14.77,13.38L15.76,17.66M22,9.24L14.81,8.63L12,2L9.19,8.63L2,9.24L7.45,13.97L5.82,21L12,17.27L18.18,21L16.54,13.97L22,9.24Z" />
+</vector>

+ 23 - 0
src/main/res/drawable/ic_tag.xml

@@ -0,0 +1,23 @@
+<!--
+    @author Google LLC
+    Copyright (C) 2018 Google LLC
+
+    Licensed under the Apache License, Version 2.0 (the "License");
+    you may not use this file except in compliance with the License.
+    You may obtain a copy of the License at
+
+    http://www.apache.org/licenses/LICENSE-2.0
+
+    Unless required by applicable law or agreed to in writing, software
+    distributed under the License is distributed on an "AS IS" BASIS,
+    WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+    See the License for the specific language governing permissions and
+    limitations under the License.
+-->
+<vector xmlns:android="http://schemas.android.com/apk/res/android"
+    android:height="24dp"
+    android:width="24dp"
+    android:viewportWidth="24"
+    android:viewportHeight="24">
+    <path android:fillColor="#757575" android:pathData="M5.5,7A1.5,1.5 0 0,1 4,5.5A1.5,1.5 0 0,1 5.5,4A1.5,1.5 0 0,1 7,5.5A1.5,1.5 0 0,1 5.5,7M21.41,11.58L12.41,2.58C12.05,2.22 11.55,2 11,2H4C2.89,2 2,2.89 2,4V11C2,11.55 2.22,12.05 2.59,12.41L11.58,21.41C11.95,21.77 12.45,22 13,22C13.55,22 14.05,21.77 14.41,21.41L21.41,14.41C21.78,14.05 22,13.55 22,13C22,12.44 21.77,11.94 21.41,11.58Z" />
+</vector>

+ 53 - 0
src/main/res/layout/file_details_activities_fragment.xml

@@ -0,0 +1,53 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+  Nextcloud Android client application
+
+  Copyright (C) 2018 Andy Scherzinger
+
+  This program is free software; you can redistribute it and/or
+  modify it under the terms of the GNU AFFERO GENERAL PUBLIC LICENSE
+  License as published by the Free Software Foundation; either
+  version 3 of the License, or 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 AFFERO GENERAL PUBLIC LICENSE for more details.
+
+  You should have received a copy of the GNU Affero General Public
+  License along with this program.  If not, see <http://www.gnu.org/licenses/>.
+-->
+
+<FrameLayout xmlns:android="http://schemas.android.com/apk/res/android"
+    android:layout_height="match_parent"
+    android:layout_width="match_parent">
+
+    <android.support.v4.widget.SwipeRefreshLayout
+        android:footerDividersEnabled="false"
+        android:id="@+id/swipe_containing_list"
+        android:layout_height="match_parent"
+        android:layout_width="match_parent"
+        android:visibility="visible">
+
+        <android.support.v7.widget.RecyclerView
+            android:clipToPadding="false"
+            android:id="@android:id/list"
+            android:layout_height="match_parent"
+            android:layout_width="match_parent"
+            android:scrollbarStyle="outsideOverlay"
+            android:scrollbars="vertical"
+            android:visibility="visible" />
+
+    </android.support.v4.widget.SwipeRefreshLayout>
+
+    <android.support.v4.widget.SwipeRefreshLayout
+        android:footerDividersEnabled="false"
+        android:id="@+id/swipe_containing_empty"
+        android:layout_height="match_parent"
+        android:layout_width="match_parent"
+        android:visibility="visible">
+
+        <include layout="@layout/empty_list" />
+    </android.support.v4.widget.SwipeRefreshLayout>
+
+</FrameLayout>

+ 109 - 155
src/main/res/layout/file_details_fragment.xml

@@ -18,7 +18,7 @@
   along with this program.  If not, see <http://www.gnu.org/licenses/>.
 -->
 <ScrollView xmlns:android="http://schemas.android.com/apk/res/android"
-    xmlns:tools="http://schemas.android.com/tools"
+    xmlns:app="http://schemas.android.com/apk/res-auto"
     android:id="@+id/fdScrollView"
     android:layout_width="match_parent"
     android:layout_height="match_parent"
@@ -29,64 +29,81 @@
         android:layout_height="wrap_content"
         android:orientation="vertical">
 
-        <RelativeLayout
-            android:id="@+id/fdFileHeaderContainer"
-            android:layout_width="match_parent"
+        <ImageView
+            android:id="@+id/fdIcon"
+            android:layout_width="wrap_content"
             android:layout_height="wrap_content"
-            android:layout_margin="@dimen/standard_margin">
+            android:layout_margin="@dimen/standard_margin"
+            android:contentDescription="@string/file_icon"
+            android:src="@drawable/file" />
 
-            <ImageView
-                android:id="@+id/fdIcon"
-                android:layout_width="wrap_content"
-                android:layout_height="wrap_content"
-                android:contentDescription="@string/file_icon"
-                android:src="@drawable/file"/>
+        <View
+            android:id="@+id/fdIcon_divider"
+            android:layout_width="match_parent"
+            android:layout_height="1dp"
+            android:background="@color/list_divider_background" />
+
+        <LinearLayout
+            android:layout_width="match_parent"
+            android:layout_height="wrap_content"
+            android:paddingTop="@dimen/standard_padding"
+            android:paddingLeft="@dimen/standard_padding"
+            android:paddingRight="@dimen/standard_padding"
+            android:paddingBottom="@dimen/standard_half_padding"
+            android:orientation="horizontal">
 
             <LinearLayout
-                android:layout_width="wrap_content"
+                android:layout_width="0dp"
                 android:layout_height="wrap_content"
-                android:layout_centerVertical="true"
-                android:layout_toEndOf="@+id/fdIcon"
-                android:layout_toRightOf="@+id/fdIcon"
-                android:paddingLeft="@dimen/standard_padding"
-                android:paddingStart="@dimen/standard_padding"
-                android:paddingEnd="@dimen/zero"
-                android:paddingRight="@dimen/zero"
+                android:layout_weight="1"
                 android:orientation="vertical">
 
                 <TextView
                     android:id="@+id/fdFilename"
                     android:layout_width="wrap_content"
                     android:layout_height="wrap_content"
+                    android:ellipsize="middle"
                     android:text="@string/placeholder_filename"
-                    android:textAppearance="?android:attr/textAppearanceLarge"/>
+                    android:textColor="@color/black"
+                    android:textSize="16sp" />
 
                 <LinearLayout
                     android:id="@+id/fdFiledetails"
                     android:layout_width="wrap_content"
                     android:layout_height="wrap_content"
+                    android:gravity="center"
                     android:orientation="horizontal">
 
+                    <ImageView
+                        android:id="@+id/fdFavorite"
+                        android:layout_width="wrap_content"
+                        android:layout_height="wrap_content"
+                        android:layout_marginEnd="@dimen/standard_eighth_margin"
+                        android:layout_marginLeft="@dimen/zero"
+                        android:layout_marginRight="@dimen/standard_eighth_margin"
+                        android:layout_marginStart="@dimen/zero"
+                        android:contentDescription="@null"
+                        android:src="@drawable/ic_star_outline" />
+
                     <TextView
                         android:id="@+id/fdSize"
                         android:layout_width="wrap_content"
                         android:layout_height="wrap_content"
                         android:text="@string/placeholder_fileSize"
-                        android:textColor="@color/list_item_lastmod_and_filesize_text"
-                        android:textSize="@dimen/two_line_secondary_text_size"/>
+                        android:textSize="16sp" />
 
                     <TextView
                         android:id="@+id/file_separator"
                         android:layout_width="wrap_content"
                         android:layout_height="wrap_content"
-                        android:paddingRight="@dimen/standard_quarter_padding"
+                        android:gravity="end"
                         android:paddingEnd="@dimen/standard_quarter_padding"
-                        android:paddingStart="@dimen/zero"
                         android:paddingLeft="@dimen/zero"
-                        android:gravity="end"
+                        android:paddingRight="@dimen/standard_quarter_padding"
+                        android:paddingStart="@dimen/zero"
                         android:text="@string/info_separator"
                         android:textColor="@color/list_item_lastmod_and_filesize_text"
-                        android:textSize="@dimen/two_line_secondary_text_size"/>
+                        android:textSize="@dimen/two_line_secondary_text_size" />
 
                     <TextView
                         android:id="@+id/fdModified"
@@ -94,163 +111,100 @@
                         android:layout_height="wrap_content"
                         android:gravity="end"
                         android:text="@string/placeholder_media_time"
-                        android:textColor="@color/list_item_lastmod_and_filesize_text"
-                        android:textSize="@dimen/two_line_secondary_text_size"/>
-
-                </LinearLayout>
-
-            </LinearLayout>
-
-        </RelativeLayout>
-
-        <View
-            android:layout_width="match_parent"
-            android:layout_height="1dp"
-            android:background="@color/list_divider_background"/>
-
-        <RelativeLayout
-            android:id="@+id/fdProgressAndControl"
-            android:layout_width="match_parent"
-            android:layout_height="wrap_content"
-            android:layout_marginBottom="@dimen/standard_half_margin"
-            android:layout_marginLeft="@dimen/standard_margin"
-            android:layout_marginRight="@dimen/standard_margin"
-            android:layout_marginTop="@dimen/standard_half_margin"
-            android:gravity="center_horizontal">
-
-            <android.support.v7.widget.SwitchCompat
-                android:id="@+id/fdFavorite"
-                android:layout_width="match_parent"
-                android:layout_height="wrap_content"
-                android:layout_alignParentLeft="true"
-                android:layout_alignParentStart="true"
-                android:layout_alignParentTop="true"
-                android:layout_gravity="start"
-                android:text="@string/favorite_switch"
-                android:textSize="16sp"/>
-
-            <LinearLayout
-                android:layout_width="match_parent"
-                android:layout_height="wrap_content"
-                android:layout_below="@id/fdFavorite"
-                android:orientation="vertical">
-
-                <TextView
-                    android:id="@+id/fdProgressText"
-                    android:layout_width="match_parent"
-                    android:layout_height="wrap_content"
-                    android:layout_marginTop="@dimen/standard_half_margin"
-                    android:text="@string/downloader_download_in_progress_ticker"/>
+                        android:textSize="16sp" />
 
-                <LinearLayout
-                    android:id="@+id/fdProgressBlock"
-                    android:layout_width="match_parent"
-                    android:layout_height="wrap_content"
-                    android:layout_marginBottom="@dimen/standard_quarter_margin"
-                    android:layout_marginTop="@dimen/standard_half_margin"
-                    android:gravity="center"
-                    android:orientation="horizontal">
-
-                    <ProgressBar
-                        android:id="@+id/fdProgressBar"
-                        style="?android:attr/progressBarStyleHorizontal"
-                        android:layout_width="0dp"
+                    <ImageView
+                        android:layout_width="wrap_content"
                         android:layout_height="wrap_content"
-                        android:layout_weight="1"
-                        android:indeterminate="false"
-                        android:indeterminateOnly="false"/>
+                        android:layout_marginEnd="@dimen/standard_eighth_margin"
+                        android:layout_marginLeft="@dimen/standard_margin"
+                        android:layout_marginRight="@dimen/standard_eighth_margin"
+                        android:layout_marginStart="@dimen/standard_margin"
+                        android:contentDescription="@null"
+                        android:src="@drawable/ic_tag"
+                        android:visibility="gone" />
 
-                    <ImageButton
-                        android:id="@+id/fdCancelBtn"
+                    <TextView
                         android:layout_width="wrap_content"
                         android:layout_height="wrap_content"
-                        android:layout_marginLeft="@dimen/standard_half_margin"
-                        android:layout_marginStart="@dimen/standard_half_margin"
-                        android:background="@android:color/transparent"
-                        android:contentDescription="@string/common_cancel"
-                        android:src="@drawable/ic_cancel"/>
+                        android:text="@string/tags"
+                        android:visibility="gone" />
 
                 </LinearLayout>
 
             </LinearLayout>
 
-        </RelativeLayout>
-
-        <View
-            android:layout_width="match_parent"
-            android:layout_height="1dp"
-            android:background="@color/list_divider_background"/>
+            <ImageView
+                android:id="@+id/overflow_menu"
+                android:layout_width="wrap_content"
+                android:layout_height="wrap_content"
+                android:background="@color/white"
+                android:src="@drawable/ic_dots_vertical"
+                android:contentDescription="@string/overflow_menu"/>
+        </LinearLayout>
 
         <LinearLayout
-            android:id="@+id/fdShareContainer"
             android:layout_width="match_parent"
-            android:layout_height="match_parent"
-            android:layout_marginBottom="@dimen/standard_half_margin"
-            android:layout_marginLeft="@dimen/standard_margin"
-            android:layout_marginRight="@dimen/standard_margin"
-            android:layout_marginTop="@dimen/standard_half_margin"
+            android:layout_height="wrap_content"
+            android:paddingLeft="@dimen/standard_padding"
+            android:paddingRight="@dimen/standard_padding"
+            android:paddingBottom="@dimen/standard_half_padding"
             android:orientation="vertical">
 
             <TextView
-                android:id="@+id/fdShareTitle"
-                style="@style/TextAppearance.AppCompat.Body2"
+                android:id="@+id/fdProgressText"
                 android:layout_width="match_parent"
                 android:layout_height="wrap_content"
-                android:layout_marginBottom="@dimen/standard_half_margin"
-                android:text="@string/action_send_share"
-                android:textColor="@color/color_accent"/>
+                android:text="@string/downloader_download_in_progress_ticker" />
 
             <LinearLayout
+                android:id="@+id/fdProgressBlock"
                 android:layout_width="match_parent"
                 android:layout_height="wrap_content"
-                android:orientation="horizontal"
-                tools:ignore="UseCompoundDrawables">
-
-                <ImageView
-                    android:contentDescription="@string/shared_icon"
-                    android:id="@+id/fdShareLinkIcon"
-                    android:layout_width="@dimen/shared_list_icon_width"
-                    android:layout_height="@dimen/shared_list_icon_height"
-                    android:layout_gravity="center_vertical"
-                    android:layout_marginEnd="@dimen/standard_half_margin"
-                    android:layout_marginRight="@dimen/standard_half_margin"
-                    android:src="@drawable/shared_via_link"
-                    android:visibility="gone"/>
+                android:layout_marginBottom="@dimen/standard_quarter_margin"
+                android:gravity="center"
+                android:orientation="horizontal">
+
+                <ProgressBar
+                    android:id="@+id/fdProgressBar"
+                    style="?android:attr/progressBarStyleHorizontal"
+                    android:layout_width="0dp"
+                    android:layout_height="wrap_content"
+                    android:layout_weight="1"
+                    android:indeterminate="false"
+                    android:indeterminateOnly="false" />
 
-                <TextView
-                    android:id="@+id/fdSharebyLink"
-                    android:layout_width="match_parent"
+                <ImageButton
+                    android:id="@+id/fdCancelBtn"
+                    android:layout_width="wrap_content"
                     android:layout_height="wrap_content"
-                    android:layout_gravity="start"
-                    android:text="@string/filedetails_share_link_disable"/>
+                    android:layout_marginLeft="@dimen/standard_half_margin"
+                    android:layout_marginStart="@dimen/standard_half_margin"
+                    android:background="@android:color/transparent"
+                    android:contentDescription="@string/common_cancel"
+                    android:src="@drawable/ic_cancel" />
+
             </LinearLayout>
 
-            <TextView
-                android:id="@+id/fdShareWithUsersTitle"
-                style="@style/TextAppearance.AppCompat.Body2"
-                android:layout_width="match_parent"
-                android:layout_height="wrap_content"
-                android:layout_gravity="start"
-                android:layout_marginBottom="@dimen/standard_half_margin"
-                android:layout_marginTop="@dimen/standard_half_margin"
-                android:text="@string/filedetails_share_users_with_access"
-                android:textColor="@color/color_accent"/>
-
-            <ListView
-                android:id="@+id/fdshareUsersList"
-                android:layout_width="match_parent"
-                android:layout_height="0dip"
-                android:layout_weight="1"
-                android:visibility="gone"/>
+        </LinearLayout>
 
-            <TextView
-                android:id="@+id/fdShareNoUsers"
-                android:layout_width="match_parent"
-                android:layout_height="wrap_content"
-                android:text="@string/share_no_users"
-                android:textSize="@dimen/share_no_users_text_size"/>
+        <View
+            android:layout_width="match_parent"
+            android:layout_height="1dp"
+            android:background="@color/list_divider_background" />
 
-        </LinearLayout>
+        <android.support.design.widget.TabLayout
+            android:id="@+id/tab_layout"
+            android:layout_width="match_parent"
+            android:layout_height="wrap_content"
+            app:tabGravity="center"
+            app:tabMode="fixed"
+            android:background="@color/white" />
+
+        <android.support.v4.view.ViewPager
+            android:id="@+id/pager"
+            android:layout_width="match_parent"
+            android:layout_height="fill_parent"/>
 
     </LinearLayout>
 

+ 12 - 2
src/main/res/layout/file_details_share_user_item.xml

@@ -21,6 +21,8 @@
     android:layout_height="wrap_content"
     android:orientation="horizontal"
     android:weightSum="1"
+    android:paddingTop="@dimen/standard_eigth_padding"
+    android:paddingBottom="@dimen/standard_eigth_padding"
     tools:ignore="UseCompoundDrawables">
 
         <ImageView
@@ -29,16 +31,24 @@
             android:layout_height="@dimen/file_details_user_icon_layout_height"
             android:src="@drawable/ic_user"
             android:layout_gravity="center_vertical"
+            android:layout_marginTop="@dimen/standard_half_margin"
+            android:layout_marginBottom="@dimen/standard_half_margin"
+            android:layout_marginLeft="@dimen/standard_margin"
+            android:layout_marginStart="@dimen/standard_margin"
+            android:layout_marginEnd="@dimen/standard_margin"
+            android:layout_marginRight="@dimen/standard_margin"
             android:contentDescription="@string/user_icon"/>
 
         <TextView
             android:layout_width="match_parent"
-            android:layout_height="wrap_content"
+            android:layout_height="match_parent"
             android:textSize="@dimen/file_details_username_text_size"
             android:text="@string/username"
             android:id="@+id/userOrGroupName"
-            android:layout_margin="@dimen/file_details_username_layout_text_margin"
+            android:layout_marginRight="@dimen/standard_margin"
+            android:layout_marginEnd="@dimen/standard_margin"
             android:singleLine="true"
             android:ellipsize="middle"
+            android:gravity="center_vertical"
             android:textColor="@color/black"/>
 </LinearLayout>

+ 103 - 0
src/main/res/layout/file_details_sharing_fragment.xml

@@ -0,0 +1,103 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+  Nextcloud Android client application
+
+  Copyright (C) 2018 Andy Scherzinger
+
+  This program is free software; you can redistribute it and/or
+  modify it under the terms of the GNU AFFERO GENERAL PUBLIC LICENSE
+  License as published by the Free Software Foundation; either
+  version 3 of the License, or 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 AFFERO GENERAL PUBLIC LICENSE for more details.
+
+  You should have received a copy of the GNU Affero General Public
+  License along with this program.  If not, see <http://www.gnu.org/licenses/>.
+-->
+<ScrollView xmlns:android="http://schemas.android.com/apk/res/android"
+    xmlns:tools="http://schemas.android.com/tools"
+    android:layout_width="match_parent"
+    android:layout_height="match_parent"
+    android:layout_weight="1">
+
+    <LinearLayout
+        android:id="@+id/fdShareContainer"
+        android:layout_width="match_parent"
+        android:layout_height="wrap_content"
+        android:orientation="vertical"
+        android:paddingTop="@dimen/standard_padding">
+
+        <TextView
+            android:id="@+id/fdShareTitle"
+            style="@style/TextAppearance.AppCompat.Body2"
+            android:layout_width="match_parent"
+            android:layout_height="wrap_content"
+            android:layout_marginBottom="@dimen/standard_half_margin"
+            android:paddingLeft="@dimen/standard_padding"
+            android:paddingRight="@dimen/standard_padding"
+            android:text="@string/action_send_share"
+            android:textColor="@color/color_accent" />
+
+        <LinearLayout
+            android:layout_width="match_parent"
+            android:layout_height="wrap_content"
+            android:orientation="horizontal"
+            android:paddingLeft="@dimen/standard_padding"
+            android:paddingRight="@dimen/standard_padding"
+            tools:ignore="UseCompoundDrawables">
+
+            <ImageView
+                android:id="@+id/fdShareLinkIcon"
+                android:layout_width="@dimen/shared_list_icon_width"
+                android:layout_height="@dimen/shared_list_icon_height"
+                android:layout_gravity="center_vertical"
+                android:layout_marginEnd="@dimen/standard_half_margin"
+                android:layout_marginRight="@dimen/standard_half_margin"
+                android:contentDescription="@string/shared_icon"
+                android:src="@drawable/shared_via_link"
+                android:visibility="gone" />
+
+            <TextView
+                android:id="@+id/fdSharebyLink"
+                android:layout_width="match_parent"
+                android:layout_height="wrap_content"
+                android:layout_gravity="start"
+                android:text="@string/filedetails_share_link_disable" />
+        </LinearLayout>
+
+        <TextView
+            android:id="@+id/fdShareWithUsersTitle"
+            style="@style/TextAppearance.AppCompat.Body2"
+            android:layout_width="match_parent"
+            android:layout_height="wrap_content"
+            android:layout_gravity="start"
+            android:layout_marginBottom="@dimen/standard_half_margin"
+            android:layout_marginTop="@dimen/standard_half_margin"
+            android:paddingLeft="@dimen/standard_padding"
+            android:paddingRight="@dimen/standard_padding"
+            android:text="@string/filedetails_share_users_with_access"
+            android:textColor="@color/color_accent" />
+
+        <ListView
+            android:id="@+id/fdshareUsersList"
+            android:layout_width="match_parent"
+            android:layout_height="0dip"
+            android:layout_weight="1"
+            android:visibility="gone" />
+
+        <TextView
+            android:id="@+id/fdShareNoUsers"
+            android:layout_width="match_parent"
+            android:layout_height="wrap_content"
+            android:paddingBottom="@dimen/standard_padding"
+            android:paddingLeft="@dimen/standard_padding"
+            android:paddingRight="@dimen/standard_padding"
+            android:text="@string/share_no_users"
+            android:textSize="@dimen/share_no_users_text_size" />
+
+    </LinearLayout>
+
+</ScrollView>

+ 1 - 1
src/main/res/layout/log_send_file.xml

@@ -28,7 +28,7 @@
     <ScrollView
         android:id="@+id/scrollView1"
         android:layout_width="match_parent"
-        android:layout_height="@dimen/zero"
+        android:layout_height="0dp"
         android:layout_marginBottom="@dimen/standard_margin"
         android:layout_weight="1">
 

+ 4 - 6
src/main/res/layout/share_user_item.xml

@@ -27,8 +27,8 @@
         android:weightSum="1"
         android:longClickable="true">
         <ImageView
-            android:layout_width="wrap_content"
-            android:layout_height="wrap_content"
+            android:layout_width="@dimen/file_details_user_icon_layout_width"
+            android:layout_height="@dimen/file_details_user_icon_layout_height"
             android:id="@+id/icon"
             android:src="@drawable/ic_user"
             android:layout_gravity="center_vertical"
@@ -36,19 +36,17 @@
 
         <TextView
             android:layout_width="0dp"
-            android:layout_height="wrap_content"
+            android:layout_height="match_parent"
             android:layout_weight="1"
             android:textSize="@dimen/two_line_primary_text_size"
             android:text="@string/username"
             android:id="@+id/userOrGroupName"
-            android:layout_marginTop="@dimen/standard_half_margin"
-            android:layout_marginBottom="@dimen/standard_half_margin"
             android:layout_marginLeft="@dimen/standard_half_margin"
             android:layout_marginStart="@dimen/standard_half_margin"
             android:textColor="@color/textColor"
             android:singleLine="true"
             android:ellipsize="middle"
-            android:layout_gravity="center_vertical"/>
+            android:gravity="center_vertical"/>
 
         <ImageView
             android:layout_width="@dimen/unshare_icon_size"

+ 32 - 23
src/main/res/layout/toolbar_standard.xml

@@ -19,32 +19,41 @@
   You should have received a copy of the GNU Affero General Public
   License along with this program.  If not, see <http://www.gnu.org/licenses/>.
 -->
-<android.support.design.widget.AppBarLayout
-    android:id="@+id/appbar"
-    xmlns:android="http://schemas.android.com/apk/res/android"
+<android.support.design.widget.AppBarLayout xmlns:android="http://schemas.android.com/apk/res/android"
     xmlns:app="http://schemas.android.com/apk/res-auto"
+    android:id="@+id/appbar"
     android:layout_width="match_parent"
     android:layout_height="wrap_content"
     android:theme="@style/ThemeOverlay.AppCompat.Dark.ActionBar">
 
-    <android.support.v7.widget.Toolbar
-        android:id="@+id/toolbar"
+    <RelativeLayout
         android:layout_width="match_parent"
-        android:layout_height="?attr/actionBarSize"
-        android:background="?attr/colorPrimary"
-        app:layout_scrollFlags="scroll|enterAlways|snap"
-        app:popupTheme="@style/ThemeOverlay.AppCompat.Light"/>
-
-    <ProgressBar
-        android:id="@+id/progressBar"
-        style="@style/Widget.ownCloud.TopProgressBar"
-        android:layout_width="match_parent"
-        android:layout_height="@dimen/standard_quarter_margin"
-        android:layout_margin="@dimen/zero"
-        android:indeterminate="false"
-        android:indeterminateOnly="false"
-        android:padding="@dimen/zero"
-        android:visibility="visible"
-        />
-
-</android.support.design.widget.AppBarLayout>
+        android:layout_height="wrap_content">
+
+        <ImageView
+            android:id="@+id/preview_image"
+            android:layout_width="match_parent"
+            android:layout_height="@dimen/nav_drawer_header_height"
+            android:scaleType="centerCrop"
+            android:visibility="gone" />
+
+        <android.support.v7.widget.Toolbar
+            android:id="@id/toolbar"
+            android:layout_width="match_parent"
+            android:layout_height="?attr/actionBarSize"
+            app:popupTheme="@style/ThemeOverlay.AppCompat.Light" />
+
+        <ProgressBar
+            android:id="@+id/progressBar"
+            style="@style/Widget.ownCloud.TopProgressBar"
+            android:layout_width="match_parent"
+            android:layout_height="@dimen/standard_quarter_margin"
+            android:layout_below="@+id/toolbar"
+            android:layout_margin="@dimen/zero"
+            android:indeterminate="false"
+            android:indeterminateOnly="false"
+            android:padding="@dimen/zero"
+            android:visibility="visible" />
+    </RelativeLayout>
+
+</android.support.design.widget.AppBarLayout>

+ 0 - 1
src/main/res/values/dims.xml

@@ -107,7 +107,6 @@
     <dimen name="file_details_user_icon_layout_width">32dp</dimen>
     <dimen name="file_details_user_icon_layout_height">32dp</dimen>
     <dimen name="file_details_username_text_size">16sp</dimen>
-    <dimen name="file_details_username_layout_text_margin">12dp</dimen>
     <dimen name="grid_image_shared_icon_layout_top_margin">24dp</dimen>
     <dimen name="grid_image_local_file_indicator_layout_width">16dp</dimen>
     <dimen name="grid_image_local_file_indicator_layout_height">16dp</dimen>

+ 1 - 1
src/main/res/values/strings.xml

@@ -269,7 +269,6 @@
     <string name="unfavorite">Unset as available offline</string>
     <string name="favorite_real">Set as favorite</string>
     <string name="unset_favorite_real">Unset favorite</string>
-    <string name="favorite_switch">Available offline</string>
     <string name="encrypted">Set as encrypted</string>
     <string name="unset_encrypted">Unset encryption</string>
     <string name="common_rename">Rename</string>
@@ -784,4 +783,5 @@
     <string name="upload_content_from_other_apps">Upload content from other apps</string>
     <string name="create_new_folder">Create new folder</string>
     <string name="uploads_view_upload_status_virus_detected">Virus detected. Upload cannot be completed!</string>
+    <string name="tags">Tags</string>
 </resources>