瀏覽代碼

Merge pull request #1012 from nextcloud/activitiesImprovement

Activities improvement
Andy Scherzinger 8 年之前
父節點
當前提交
ce3a8bf3d7

+ 1 - 1
build.gradle

@@ -13,7 +13,7 @@ buildscript {
         }
     }
     dependencies {
-        classpath 'com.android.tools.build:gradle:2.3.1'
+        classpath 'com.android.tools.build:gradle:2.3.2'
         classpath 'com.google.gms:google-services:3.0.0'
     }
 }

+ 31 - 13
src/main/java/com/owncloud/android/ui/activity/ActivitiesListActivity.java

@@ -19,7 +19,6 @@
  * 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.activity;
 
 import android.accounts.Account;
@@ -30,7 +29,6 @@ import android.content.Intent;
 import android.os.Bundle;
 import android.support.design.widget.BottomNavigationView;
 import android.support.v4.widget.SwipeRefreshLayout;
-import android.support.v7.widget.DividerItemDecoration;
 import android.support.v7.widget.LinearLayoutManager;
 import android.support.v7.widget.RecyclerView;
 import android.view.MenuItem;
@@ -43,6 +41,7 @@ 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.OCFile;
 import com.owncloud.android.lib.common.OwnCloudAccount;
 import com.owncloud.android.lib.common.OwnCloudClient;
 import com.owncloud.android.lib.common.OwnCloudClientManagerFactory;
@@ -50,7 +49,12 @@ import com.owncloud.android.lib.common.operations.RemoteOperation;
 import com.owncloud.android.lib.common.operations.RemoteOperationResult;
 import com.owncloud.android.lib.common.utils.Log_OC;
 import com.owncloud.android.lib.resources.activities.GetRemoteActivitiesOperation;
+import com.owncloud.android.lib.resources.activities.models.RichObject;
+import com.owncloud.android.lib.resources.files.FileUtils;
 import com.owncloud.android.ui.adapter.ActivityListAdapter;
+import com.owncloud.android.ui.interfaces.ActivityListInterface;
+import com.owncloud.android.ui.preview.PreviewImageActivity;
+import com.owncloud.android.ui.preview.PreviewImageFragment;
 import com.owncloud.android.utils.AnalyticsUtils;
 import com.owncloud.android.utils.DisplayUtils;
 
@@ -66,7 +70,7 @@ import butterknife.Unbinder;
 /**
  * Activity displaying all server side stored activity items.
  */
-public class ActivitiesListActivity extends FileActivity {
+public class ActivitiesListActivity extends FileActivity implements ActivityListInterface {
 
     private static final String TAG = ActivitiesListActivity.class.getSimpleName();
     private static final String SCREEN_NAME = "Activities";
@@ -102,6 +106,7 @@ public class ActivitiesListActivity extends FileActivity {
     private ActivityListAdapter adapter;
     private Unbinder unbinder;
 
+
     @Override
     protected void onCreate(Bundle savedInstanceState) {
         Log_OC.v(TAG, "onCreate() start");
@@ -133,9 +138,9 @@ public class ActivitiesListActivity extends FileActivity {
             public void onRefresh() {
                 setLoadingMessage();
                 fetchAndSetData();
-
             }
         });
+
         setupContent();
     }
 
@@ -156,18 +161,16 @@ public class ActivitiesListActivity extends FileActivity {
      * sets up the UI elements and loads all activity items.
      */
     private void setupContent() {
+
         emptyContentIcon.setImageResource(R.drawable.ic_activity_light_grey);
         setLoadingMessage();
 
-        adapter = new ActivityListAdapter(this);
+        adapter = new ActivityListAdapter(this, this);
         recyclerView.setAdapter(adapter);
 
         LinearLayoutManager layoutManager = new LinearLayoutManager(this);
-        DividerItemDecoration dividerItemDecoration = new DividerItemDecoration(recyclerView.getContext(),
-                layoutManager.getOrientation());
 
         recyclerView.setLayoutManager(layoutManager);
-        recyclerView.addItemDecoration(dividerItemDecoration);
 
         BottomNavigationView bottomNavigationView = (BottomNavigationView) findViewById(R.id.bottom_navigation_view);
 
@@ -192,8 +195,8 @@ public class ActivitiesListActivity extends FileActivity {
                     ocAccount = new OwnCloudAccount(
                             currentAccount,
                             context
-                            );
-                    OwnCloudClient mClient = OwnCloudClientManagerFactory.getDefaultSingleton().
+                    );
+                    final OwnCloudClient mClient = OwnCloudClientManagerFactory.getDefaultSingleton().
                             getClientFor(ocAccount, MainApp.getAppContext());
                     mClient.setOwnCloudVersion(AccountUtils.getServerVersion(currentAccount));
 
@@ -208,7 +211,7 @@ public class ActivitiesListActivity extends FileActivity {
                             @Override
                             public void run() {
                                 if (activities.size() > 0) {
-                                    populateList(activities);
+                                    populateList(activities, mClient);
                                     swipeEmptyListRefreshLayout.setVisibility(View.GONE);
                                     swipeListRefreshLayout.setVisibility(View.VISIBLE);
                                 } else {
@@ -258,9 +261,9 @@ public class ActivitiesListActivity extends FileActivity {
         });
     }
 
-    private void populateList(List<Object> activities) {
+    private void populateList(List<Object> activities, OwnCloudClient mClient) {
 
-        adapter.setActivityItems(activities);
+        adapter.setActivityItems(activities, mClient);
     }
 
     @Override
@@ -308,4 +311,19 @@ public class ActivitiesListActivity extends FileActivity {
 
         AnalyticsUtils.setCurrentScreenName(this, SCREEN_NAME, TAG);
     }
+
+
+    @Override
+    public void onActivityClicked(RichObject richObject) {
+        Intent showDetailsIntent;
+        OCFile ocFile = new OCFile(FileUtils.PATH_SEPARATOR + richObject.getPath());
+        if (PreviewImageFragment.canBePreviewed(ocFile)) {
+            showDetailsIntent = new Intent(this, PreviewImageActivity.class);
+        } else {
+            showDetailsIntent = new Intent(this, FileDisplayActivity.class);
+        }
+        showDetailsIntent.putExtra(EXTRA_FILE, ocFile);
+        showDetailsIntent.putExtra(EXTRA_ACCOUNT, getAccount());
+        startActivity(showDetailsIntent);
+    }
 }

+ 241 - 29
src/main/java/com/owncloud/android/ui/adapter/ActivityListAdapter.java

@@ -20,14 +20,21 @@
 package com.owncloud.android.ui.adapter;
 
 import android.content.Context;
+import android.content.res.Resources;
 import android.graphics.drawable.PictureDrawable;
 import android.net.Uri;
 import android.support.v7.widget.RecyclerView;
+import android.text.SpannableStringBuilder;
 import android.text.TextUtils;
+import android.text.method.LinkMovementMethod;
+import android.text.style.ClickableSpan;
+import android.text.style.StyleSpan;
 import android.view.LayoutInflater;
 import android.view.View;
 import android.view.ViewGroup;
+import android.widget.GridLayout;
 import android.widget.ImageView;
+import android.widget.LinearLayout;
 import android.widget.TextView;
 
 import com.bumptech.glide.GenericRequestBuilder;
@@ -36,70 +43,203 @@ import com.bumptech.glide.load.engine.DiskCacheStrategy;
 import com.bumptech.glide.load.model.StreamEncoder;
 import com.bumptech.glide.load.resource.file.FileToStreamDecoder;
 import com.caverock.androidsvg.SVG;
+import com.owncloud.android.MainApp;
 import com.owncloud.android.R;
+import com.owncloud.android.datamodel.OCFile;
+import com.owncloud.android.lib.common.OwnCloudClient;
 import com.owncloud.android.lib.resources.activities.models.Activity;
+import com.owncloud.android.lib.resources.activities.models.RichElement;
+import com.owncloud.android.lib.resources.activities.models.RichObject;
+import com.owncloud.android.ui.interfaces.ActivityListInterface;
 import com.owncloud.android.utils.DisplayUtils;
+import com.owncloud.android.utils.MimeTypeUtil;
+import com.owncloud.android.utils.glide.CustomGlideStreamLoader;
 import com.owncloud.android.utils.svg.SvgDecoder;
 import com.owncloud.android.utils.svg.SvgDrawableTranscoder;
 import com.owncloud.android.utils.svg.SvgSoftwareLayerSetter;
 
 import java.io.InputStream;
 import java.util.ArrayList;
+import java.util.Date;
 import java.util.List;
 
 /**
  * Adapter for the activity view
  */
 
-public class ActivityListAdapter extends RecyclerView.Adapter<ActivityListAdapter.ActivityViewHolder> {
+public class ActivityListAdapter extends RecyclerView.Adapter<RecyclerView.ViewHolder> {
+
+    public static final int HEADER_TYPE = 100;
+    public static final int ACTIVITY_TYPE = 101;
+    private final ActivityListInterface activityListInterface;
+    private final int px;
+    private OwnCloudClient mClient;
 
     private Context context;
     private List<Object> mValues;
 
-    public ActivityListAdapter(Context context) {
+    public ActivityListAdapter(Context context, ActivityListInterface activityListInterface) {
         this.mValues = new ArrayList<>();
         this.context = context;
+        this.activityListInterface = activityListInterface;
+        px = getThumbnailDimension();
     }
 
-    public void setActivityItems(List<Object> activityItems) {
+    public void setActivityItems(List<Object> activityItems, OwnCloudClient client) {
+        this.mClient = client;
         mValues.clear();
-        mValues.addAll(activityItems);
+        String sTime = "";
+        for (Object o : activityItems) {
+            Activity activity = (Activity) o;
+            String time = null;
+            if (activity.getDatetime() != null) {
+                time = DisplayUtils.getRelativeTimestamp(context,
+                        activity.getDatetime().getTime()).toString();
+            } else if (activity.getDate() != null) {
+                time = DisplayUtils.getRelativeTimestamp(context,
+                        activity.getDate().getTime()).toString();
+            } else {
+                time = "Unknown";
+            }
+
+            if (sTime.equalsIgnoreCase(time)) {
+                mValues.add(activity);
+            } else {
+
+                sTime = time;
+                mValues.add(sTime);
+                mValues.add(activity);
+            }
+        }
         notifyDataSetChanged();
-    }
 
-    @Override
-    public ActivityViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {
-        View v = LayoutInflater.from(parent.getContext()).inflate(R.layout.activity_list_item, parent, false);
-        return new ActivityViewHolder(v);
     }
 
     @Override
-    public void onBindViewHolder(ActivityViewHolder holder, int position) {
-        Activity activity = (Activity) mValues.get(position);
-        if (activity.getDatetime() != null) {
-            holder.dateTime.setText(DisplayUtils.getRelativeTimestamp(context,
-                    activity.getDatetime().getTime()));
+    public RecyclerView.ViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {
+        if (viewType == ACTIVITY_TYPE) {
+            View v = LayoutInflater.from(parent.getContext()).inflate(R.layout.activity_list_item, parent, false);
+            return new ActivityViewHolder(v);
         } else {
-            holder.dateTime.setText(DisplayUtils.getRelativeTimestamp(context,
-                    activity.getDate().getTime()));
+            View v = LayoutInflater.from(parent.getContext()).inflate(R.layout.activity_list_item_header, parent, false);
+            return new ActivityViewHeaderHolder(v);
         }
 
-        if (!TextUtils.isEmpty(activity.getSubject())) {
-            holder.subject.setText(activity.getSubject());
-            holder.subject.setVisibility(View.VISIBLE);
-        } else {
-            holder.subject.setVisibility(View.GONE);
-        }
+    }
+
+    @Override
+    public void onBindViewHolder(RecyclerView.ViewHolder holder, int position) {
+
+        if (holder instanceof ActivityViewHolder) {
+            final ActivityViewHolder activityViewHolder = (ActivityViewHolder) holder;
+            Activity activity = (Activity) mValues.get(position);
+            if (activity.getDatetime() != null) {
+                activityViewHolder.dateTime.setText(DisplayUtils.getRelativeTimestamp(context,
+                        activity.getDatetime().getTime()));
+            } else {
+                activityViewHolder.dateTime.setText(DisplayUtils.getRelativeTimestamp(context,
+                        new Date().getTime()));
+            }
+
+            if (activity.getRichSubjectElement() != null &&
+                    !TextUtils.isEmpty(activity.getRichSubjectElement().getRichSubject())) {
+                activityViewHolder.subject.setVisibility(View.VISIBLE);
+                activityViewHolder.subject.setMovementMethod(LinkMovementMethod.getInstance());
+                activityViewHolder.subject.setText(addClickablePart(activity.getRichSubjectElement()),
+                        TextView.BufferType.SPANNABLE);
+                activityViewHolder.subject.setVisibility(View.VISIBLE);
+            } else if (!TextUtils.isEmpty(activity.getSubject())) {
+                activityViewHolder.subject.setVisibility(View.VISIBLE);
+                activityViewHolder.subject.setText(activity.getSubject());
+            } else {
+                activityViewHolder.subject.setVisibility(View.GONE);
+            }
 
-        if (!TextUtils.isEmpty(activity.getMessage())) {
-            holder.message.setText(activity.getMessage());
-            holder.message.setVisibility(View.VISIBLE);
+            if (!TextUtils.isEmpty(activity.getMessage())) {
+                activityViewHolder.message.setText(activity.getMessage());
+                activityViewHolder.message.setVisibility(View.VISIBLE);
+            } else {
+                activityViewHolder.message.setVisibility(View.GONE);
+            }
+
+            if (!TextUtils.isEmpty(activity.getIcon())) {
+                downloadIcon(activity.getIcon(), activityViewHolder.activityIcon);
+            }
+
+            if (activity.getRichSubjectElement() != null &&
+                    activity.getRichSubjectElement().getRichObjectList().size() > 0) {
+
+                activityViewHolder.list.setVisibility(View.VISIBLE);
+                activityViewHolder.list.removeAllViews();
+
+                activityViewHolder.list.post(new Runnable() {
+                    @Override
+                    public void run() {
+                        int w = activityViewHolder.list.getMeasuredWidth();
+
+                        int elPxSize = px + 20;
+                        int totalColumnCount = (int) Math.floor(w / elPxSize);
+                        activityViewHolder.list.setColumnCount(totalColumnCount);
+                    }
+                });
+
+
+                for (RichObject richObject : activity.getRichSubjectElement().getRichObjectList()) {
+                    ImageView imageView = createThumbnail(richObject);
+                    activityViewHolder.list.addView(imageView);
+                }
+
+            } else {
+                activityViewHolder.list.removeAllViews();
+                activityViewHolder.list.setVisibility(View.GONE);
+            }
         } else {
-            holder.message.setVisibility(View.GONE);
+            ActivityViewHeaderHolder activityViewHeaderHolder = (ActivityViewHeaderHolder) holder;
+            activityViewHeaderHolder.title.setText((String) mValues.get(position));
         }
+    }
+
+    private ImageView createThumbnail(final RichObject richObject) {
+        OCFile file = new OCFile("/" + richObject.getPath());
+        file.setRemoteId(richObject.getId());
+
+        LinearLayout.LayoutParams params = new LinearLayout.LayoutParams(px, px);
+        params.setMargins(10, 10, 10, 10);
+        ImageView imageView = new ImageView(context);
+        imageView.setLayoutParams(params);
+        imageView.setOnClickListener(new View.OnClickListener() {
+            @Override
+            public void onClick(View v) {
+                activityListInterface.onActivityClicked(richObject);
+            }
+        });
+        setBitmap(file, imageView);
+
+        return imageView;
+    }
 
-        if (!TextUtils.isEmpty(activity.getIcon())) {
-            downloadIcon(activity.getIcon(), holder.activityIcon);
+    private void setBitmap(OCFile file, ImageView fileIcon) {
+        // No Folder
+        if (!file.isFolder()) {
+            if ((MimeTypeUtil.isImage(file) || MimeTypeUtil.isVideo(file))) {
+                String uri = mClient.getBaseUri() + "" +
+                        "/index.php/apps/files/api/v1/thumbnail/" +
+                        px + "/" + px + Uri.encode(file.getRemotePath(), "/");
+
+                Glide.with(context).using(new CustomGlideStreamLoader()).load(uri).into(fileIcon); //Using custom fetcher
+
+            } else {
+                fileIcon.setImageResource(MimeTypeUtil.getFileTypeIconId(file.getMimetype(),
+                        file.getFileName()));
+            }
+        } else {
+            // Folder
+            fileIcon.setImageDrawable(
+                    MimeTypeUtil.getFolderTypeIcon(
+                            file.isSharedWithMe() || file.isSharedWithSharee(),
+                            file.isSharedViaLink()
+                    )
+            );
         }
     }
 
@@ -125,17 +265,76 @@ public class ActivityListAdapter extends RecyclerView.Adapter<ActivityListAdapte
                 .into(itemViewType);
     }
 
+    private SpannableStringBuilder addClickablePart(RichElement richElement) {
+        String text = richElement.getRichSubject();
+        SpannableStringBuilder ssb = new SpannableStringBuilder(text);
+
+        int idx1 = text.indexOf("{");
+        int idx2;
+        while (idx1 != -1) {
+            idx2 = text.indexOf("}", idx1) + 1;
+            final String clickString = text.substring(idx1 + 1, idx2 - 1);
+            final RichObject richObject = searchObjectByName(richElement.getRichObjectList(), clickString);
+            if (richObject != null) {
+                String name = richObject.getName();
+                ssb.replace(idx1, idx2, name);
+                text = ssb.toString();
+                idx2 = idx1 + name.length();
+                ssb.setSpan(new ClickableSpan() {
+                    @Override
+                    public void onClick(View widget) {
+                        activityListInterface.onActivityClicked(richObject);
+                    }
+                }, idx1, idx2, 0);
+                ssb.setSpan(new StyleSpan(android.graphics.Typeface.BOLD), idx1, idx2, 0);
+            }
+            idx1 = text.indexOf("{", idx2);
+        }
+
+        return ssb;
+    }
+
+    public RichObject searchObjectByName(ArrayList<RichObject> richObjectList, String name) {
+        for (RichObject richObject : richObjectList) {
+            if (richObject.getTag().equalsIgnoreCase(name))
+                return richObject;
+        }
+        return null;
+    }
+
+
+    @Override
+    public int getItemViewType(int position) {
+        if (mValues.get(position) instanceof Activity)
+            return ACTIVITY_TYPE;
+        else
+            return HEADER_TYPE;
+    }
+
     @Override
     public int getItemCount() {
         return mValues.size();
     }
 
-    class ActivityViewHolder extends RecyclerView.ViewHolder {
+    /**
+     * Converts size of file icon from dp to pixel
+     *
+     * @return int
+     */
+    private int getThumbnailDimension() {
+        // Converts dp to pixel
+        Resources r = MainApp.getAppContext().getResources();
+        Double d = Math.pow(2, Math.floor(Math.log(r.getDimension(R.dimen.file_icon_size_grid)) / Math.log(2))) / 2;
+        return d.intValue();
+    }
+
+    private class ActivityViewHolder extends RecyclerView.ViewHolder {
 
         private final ImageView activityIcon;
         private final TextView subject;
         private final TextView message;
         private final TextView dateTime;
+        private final GridLayout list;
 
         private ActivityViewHolder(View itemView) {
             super(itemView);
@@ -143,6 +342,19 @@ public class ActivityListAdapter extends RecyclerView.Adapter<ActivityListAdapte
             subject = (TextView) itemView.findViewById(R.id.activity_subject);
             message = (TextView) itemView.findViewById(R.id.activity_message);
             dateTime = (TextView) itemView.findViewById(R.id.activity_datetime);
+            list = (GridLayout) itemView.findViewById(R.id.list);
+        }
+    }
+
+    private class ActivityViewHeaderHolder extends RecyclerView.ViewHolder {
+
+        private final TextView title;
+
+        private ActivityViewHeaderHolder(View itemView) {
+            super(itemView);
+            title = (TextView) itemView.findViewById(R.id.title_header);
+
         }
     }
+
 }

+ 13 - 0
src/main/java/com/owncloud/android/ui/interfaces/ActivityListInterface.java

@@ -0,0 +1,13 @@
+package com.owncloud.android.ui.interfaces;
+
+import com.owncloud.android.lib.resources.activities.models.RichObject;
+
+/**
+ * Created by alejandro on 12/05/17.
+ */
+
+public interface ActivityListInterface {
+
+    void onActivityClicked(RichObject richObject);
+
+}

+ 36 - 0
src/main/java/com/owncloud/android/utils/glide/CustomGlideStreamLoader.java

@@ -0,0 +1,36 @@
+/**
+ * Nextcloud Android client application
+ *
+ * @author Alejandro Bautista
+ * Copyright (C) 2017 Alejandro Bautista
+ *
+ * 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.utils.glide;
+
+import com.bumptech.glide.load.data.DataFetcher;
+import com.bumptech.glide.load.model.stream.StreamModelLoader;
+
+import java.io.InputStream;
+
+/**
+ * Custom Model for OwnCloudClient
+ */
+
+public class CustomGlideStreamLoader implements StreamModelLoader<String> {
+    @Override
+    public DataFetcher<InputStream> getResourceFetcher(String url, int width, int height) {
+        return new HttpStreamFetcher(url);
+    }
+}

+ 101 - 0
src/main/java/com/owncloud/android/utils/glide/HttpStreamFetcher.java

@@ -0,0 +1,101 @@
+/**
+ * Nextcloud Android client application
+ *
+ * @author Alejandro Bautista
+ * Copyright (C) 2017 Alejandro Bautista
+ *
+ * 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.utils.glide;
+
+import android.accounts.Account;
+
+import com.bumptech.glide.Priority;
+import com.bumptech.glide.load.data.DataFetcher;
+import com.owncloud.android.MainApp;
+import com.owncloud.android.authentication.AccountUtils;
+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.utils.Log_OC;
+import com.owncloud.android.lib.resources.status.OwnCloudVersion;
+
+import org.apache.commons.httpclient.HttpStatus;
+import org.apache.commons.httpclient.methods.GetMethod;
+
+import java.io.InputStream;
+
+/**
+ * Fetcher with OwnCloudClient
+ */
+
+public class HttpStreamFetcher implements DataFetcher<InputStream> {
+
+    private static final String TAG = HttpStreamFetcher.class.getName();
+    private final String mURL;
+
+    public HttpStreamFetcher(String url) {
+        this.mURL = url;
+
+    }
+
+    @Override
+    public InputStream loadData(Priority priority) throws Exception {
+
+        Account mAccount = AccountUtils.getCurrentOwnCloudAccount(MainApp.getAppContext());
+        OwnCloudAccount ocAccount = new OwnCloudAccount(mAccount,
+                MainApp.getAppContext());
+        OwnCloudClient mClient = OwnCloudClientManagerFactory.getDefaultSingleton().
+                getClientFor(ocAccount, MainApp.getAppContext());
+
+        OwnCloudVersion serverOCVersion = AccountUtils.getServerVersion(mAccount);
+        if (mClient != null && serverOCVersion != null) {
+            if (serverOCVersion.supportsRemoteThumbnails()) {
+                GetMethod get = null;
+                try {
+                    get = new GetMethod(mURL);
+                    get.setRequestHeader("Cookie",
+                            "nc_sameSiteCookielax=true;nc_sameSiteCookiestrict=true");
+                    int status = mClient.executeMethod(get);
+                    if (status == HttpStatus.SC_OK) {
+                        InputStream inputStream = get.getResponseBodyAsStream();
+                        return inputStream;
+                    } else {
+                        mClient.exhaustResponse(get.getResponseBodyAsStream());
+                    }
+                } catch (Exception e) {
+                    Log_OC.d(TAG, e.getMessage(), e);
+                }
+            } else {
+                Log_OC.d(TAG, "Server too old");
+            }
+        }
+        return null;
+    }
+
+    @Override
+    public void cleanup() {
+        Log_OC.i(TAG,"Cleanup");
+    }
+
+    @Override
+    public String getId() {
+        return mURL;
+    }
+
+    @Override
+    public void cancel() {
+        Log_OC.i(TAG,"Cancel");
+    }
+}

+ 9 - 3
src/main/res/layout/activity_list_item.xml

@@ -30,8 +30,8 @@
 
     <ImageView
         android:id="@+id/activity_icon"
-        android:layout_width="@dimen/user_icon_size"
-        android:layout_height="@dimen/user_icon_size"
+        android:layout_width="@dimen/file_icon_size"
+        android:layout_height="@dimen/file_icon_size"
         android:layout_alignParentTop="true"
         android:layout_marginRight="24dp"
         android:src="@drawable/ic_activity"/>
@@ -48,7 +48,6 @@
             android:layout_width="match_parent"
             android:layout_height="wrap_content"
             android:ellipsize="end"
-            android:maxLines="2"
             android:text="@string/placeholder_filename"
             android:textAppearance="?android:attr/textAppearanceListItem"/>
 
@@ -61,6 +60,13 @@
             android:text="@string/placeholder_sentence"
             android:textColor="?android:attr/textColorSecondary"/>
 
+        <GridLayout
+            android:id="@+id/list"
+            android:layout_width="match_parent"
+            android:layout_height="wrap_content"
+            android:layout_marginTop="5dp"
+            android:columnCount="3" />
+
         <TextView
             android:id="@+id/activity_datetime"
             android:layout_width="wrap_content"

+ 17 - 0
src/main/res/layout/activity_list_item_header.xml

@@ -0,0 +1,17 @@
+<?xml version="1.0" encoding="utf-8"?>
+<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
+    android:orientation="vertical" android:layout_width="match_parent"
+    android:layout_height="wrap_content">
+
+    <TextView
+        android:id="@+id/title_header"
+        android:layout_width="match_parent"
+        android:layout_height="wrap_content"
+        android:textSize="20sp"
+        android:layout_marginLeft="10dp"
+        android:layout_marginTop="10dp"
+        android:text="Header"
+
+        />
+
+</LinearLayout>