Pārlūkot izejas kodu

introduce divisions in upload list view

Luke Owncloud 10 gadi atpakaļ
vecāks
revīzija
eaab185720

BIN
res/drawable/upload_failed.png


BIN
res/drawable/upload_finished.png


BIN
res/drawable/upload_in_progress.png


+ 28 - 0
res/layout/upload_list_group.xml

@@ -0,0 +1,28 @@
+<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
+    android:id="@+id/LinearLayout01"
+    android:layout_width="fill_parent"
+    android:layout_height="45dip"
+    android:background="@drawable/abs__ab_bottom_solid_light_holo" >
+
+    <ImageView
+        android:id="@+id/uploadListGroupIcon"
+        android:layout_width="20dip"
+        android:layout_height="20dip"
+        android:layout_marginLeft="10dip"
+        android:layout_marginStart="10dip"
+        android:layout_marginTop="2dip" >
+    </ImageView>
+
+    <TextView
+        android:id="@+id/uploadListGroupName"
+        android:layout_width="fill_parent"
+        android:layout_height="25dip"
+        android:gravity="center_vertical|end"
+        android:paddingLeft="5dip"
+        android:paddingRight="5dip"
+        android:textColor="#ffffffff"
+        android:textSize="17sp"
+        android:textStyle="bold" >
+    </TextView>
+
+</LinearLayout>

+ 38 - 7
src/com/owncloud/android/db/UploadDbHandler.java

@@ -273,13 +273,13 @@ public class UploadDbHandler extends Observable {
         return result != 0;
     }
 
-    public List<UploadDbObject> getAllStoredUploads() {
+    public UploadDbObject[] getAllStoredUploads() {
         return getUploads(null, null);
     }
 
-    private List<UploadDbObject> getUploads(String selection, String[] selectionArgs) {
+    private UploadDbObject[] getUploads(String selection, String[] selectionArgs) {
         Cursor c = getDB().query(TABLE_UPLOAD, null, selection, selectionArgs, null, null, null);
-        List<UploadDbObject> list = new ArrayList<UploadDbObject>();
+        UploadDbObject[] list = new UploadDbObject[c.getCount()];
         if (c.moveToFirst()) {
             do {
                 String uploadObjectString = c.getString(c.getColumnIndex("uploadObject"));
@@ -287,20 +287,51 @@ public class UploadDbHandler extends Observable {
                 if (uploadObject == null) {
                     Log_OC.e(TAG, "Could not deserialize UploadDbObject " + uploadObjectString);
                 } else {
-                    list.add(uploadObject);
+                    list[c.getPosition()] = uploadObject;
                 }
             } while (c.moveToNext());
         }
         return list;
     }
 
-    public List<UploadDbObject> getAllPendingUploads() {
+    /**
+     * Get all uploads which are pending, i.e., queued for upload but not currently being uploaded
+     * @return
+     */
+    public UploadDbObject[] getPendingUploads() {
         return getUploads("uploadStatus==" + UploadStatus.UPLOAD_LATER.value + " OR uploadStatus=="
-                + UploadStatus.UPLOAD_FAILED_RETRY.value, null);
+                + UploadStatus.UPLOAD_FAILED_RETRY.value+ " OR uploadStatus=="
+                        + UploadStatus.UPLOAD_PAUSED.value, null);
     }
-    public List<UploadDbObject> getCurrentUpload() {
+    /**
+     * Get all uploads which are currently being uploaded. There should only be one. No guarantee though.
+     */
+    public UploadDbObject[] getCurrentUpload() {
         return getUploads("uploadStatus==" + UploadStatus.UPLOAD_IN_PROGRESS.value, null);
     }
+    
+    /**
+     * Get all current and pending uploads.
+     */
+    public UploadDbObject[] getCurrentAndPendingUploads() {
+        return getUploads("uploadStatus==" + UploadStatus.UPLOAD_IN_PROGRESS.value + " OR uploadStatus==" + UploadStatus.UPLOAD_LATER.value + " OR uploadStatus=="
+                + UploadStatus.UPLOAD_FAILED_RETRY.value+ " OR uploadStatus=="
+                        + UploadStatus.UPLOAD_PAUSED.value, null);
+    }
+    
+    /**
+     * Get all unrecoverably failed. Upload of these should/must/will not be retried.
+     */
+    public UploadDbObject[] getFailedUploads() {
+        return getUploads("uploadStatus==" + UploadStatus.UPLOAD_FAILED_GIVE_UP.value + " OR uploadStatus=="
+                + UploadStatus.UPLOAD_CANCELLED.value, null);
+    }    
+    /**
+     * Get all uploads which where successfully completed.
+     */
+    public UploadDbObject[] getFinishedUploads() {
+        return getUploads("uploadStatus==" + UploadStatus.UPLOAD_SUCCEEDED.value, null);
+    }
 
     private SQLiteDatabase getDB() {
         if (mDB == null) {

+ 2 - 2
src/com/owncloud/android/files/services/FileUploadService.java

@@ -276,7 +276,7 @@ public class FileUploadService extends IntentService {
         mDb.recreateDb(); //for testing only
         
         //when this service starts there is no upload in progress. if db says so, app probably crashed before.
-        List<UploadDbObject> current = mDb.getCurrentUpload();
+        UploadDbObject[] current = mDb.getCurrentUpload();
         for (UploadDbObject uploadDbObject : current) {
             uploadDbObject.setUploadStatus(UploadStatus.UPLOAD_LATER);
             mDb.updateUpload(uploadDbObject);   
@@ -320,7 +320,7 @@ public class FileUploadService extends IntentService {
             // retry of pending upload was requested. 
             // ==> First check persistent uploads, then perform upload.
             int countAddedEntries = 0;
-            List<UploadDbObject> list = mDb.getAllPendingUploads();
+            UploadDbObject[] list = mDb.getPendingUploads();
             for (UploadDbObject uploadDbObject : list) {
                 // store locally.
                 String uploadKey = buildRemoteName(uploadDbObject);

+ 147 - 73
src/com/owncloud/android/ui/adapter/UploadListAdapter.java → src/com/owncloud/android/ui/adapter/ExpandableUploadListAdapter.java

@@ -2,23 +2,24 @@ package com.owncloud.android.ui.adapter;
 
 import java.util.Arrays;
 import java.util.Comparator;
-import java.util.List;
 import java.util.Observable;
 import java.util.Observer;
 
 import android.app.Activity;
 import android.content.Context;
 import android.database.DataSetObserver;
+import android.graphics.Bitmap;
 import android.text.format.DateUtils;
 import android.view.LayoutInflater;
 import android.view.View;
 import android.view.ViewGroup;
-import android.widget.BaseAdapter;
+import android.widget.BaseExpandableListAdapter;
+import android.widget.ExpandableListView;
 import android.widget.ImageView;
-import android.widget.ListAdapter;
 import android.widget.TextView;
 
 import com.owncloud.android.R;
+import com.owncloud.android.datamodel.ThumbnailsCacheManager;
 import com.owncloud.android.db.UploadDbHandler;
 import com.owncloud.android.db.UploadDbObject;
 import com.owncloud.android.lib.common.utils.Log_OC;
@@ -29,17 +30,78 @@ import com.owncloud.android.utils.DisplayUtils;
  * active, completed. Filtering possible.
  * 
  */
-public class UploadListAdapter extends BaseAdapter implements ListAdapter, Observer {
+public class ExpandableUploadListAdapter extends BaseExpandableListAdapter implements Observer {
 
-    private static final String TAG = "UploadListAdapter";
+    private static final String TAG = "ExpandableUploadListAdapter";
     private Activity mActivity;
-    private UploadDbObject[] mUploads = null;
+    
+    interface Refresh {
+        public void refresh();
+    }
+    abstract class UploadGroup implements Refresh {
+        UploadDbObject[] items;
+        String name;
+        public UploadGroup(String groupName) {
+            this.name = groupName;            
+            items = new UploadDbObject[0];
+        }        
+        public String getGroupName() {
+            return name;
+        }
+        public Comparator<UploadDbObject> comparator = new Comparator<UploadDbObject>() {
+            @Override
+            public int compare(UploadDbObject lhs, UploadDbObject rhs) {
+                return compareUploadTime(lhs, rhs);
+            }
+            private int compareUploadTime(UploadDbObject lhs, UploadDbObject rhs) {
+                return rhs.getUploadTime().compareTo(lhs.getUploadTime());
+            }
+        };
+        abstract public int getGroupIcon();
+    }
+    private UploadGroup[] mUploadGroups = null;
     UploadDbHandler mDb;
 
-    public UploadListAdapter(Activity context) {
+    public ExpandableUploadListAdapter(Activity context) {
         Log_OC.d(TAG, "UploadListAdapter");
         mActivity = context;
         mDb = UploadDbHandler.getInstance(mActivity);
+        mUploadGroups = new UploadGroup[3];
+        mUploadGroups[0] = new UploadGroup("Current Uploads") {
+            @Override
+            public void refresh() {
+                items = mDb.getCurrentAndPendingUploads();
+                Arrays.sort(items, comparator);
+            }
+            @Override
+            public int getGroupIcon() {
+                return R.drawable.upload_in_progress;
+            }
+        };
+        mUploadGroups[1] = new UploadGroup("Failed Uploads"){
+            @Override
+            public void refresh() {
+                items = mDb.getFailedUploads();
+                Arrays.sort(items, comparator);
+            }
+            @Override
+            public int getGroupIcon() {
+                return R.drawable.upload_failed;
+            }
+
+        };
+        mUploadGroups[2] = new UploadGroup("Finished Uploads"){
+            @Override
+            public void refresh() {
+                items = mDb.getFinishedUploads();
+                Arrays.sort(items, comparator);
+            }
+            @Override
+            public int getGroupIcon() {
+                return R.drawable.upload_finished;
+            }
+
+        };
         loadUploadItemsFromDb();
     }
 
@@ -62,42 +124,14 @@ public class UploadListAdapter extends BaseAdapter implements ListAdapter, Obser
         return true;
     }
 
-    @Override
-    public boolean isEnabled(int position) {
-        return true;
-    }
-
-    @Override
-    public int getCount() {
-        return mUploads != null ? mUploads.length : 0;
-    }
-
-    @Override
-    public Object getItem(int position) {
-        if (mUploads == null || mUploads.length <= position)
-            return null;
-        return mUploads[position];
-    }
-
-    @Override
-    public long getItemId(int position) {
-        return mUploads != null && mUploads.length <= position ? position : -1;
-    }
-
-    @Override
-    public int getItemViewType(int position) {
-        return 0;
-    }
-
-    @Override
-    public View getView(int position, View convertView, ViewGroup parent) {
+    private View getView(UploadDbObject[] uploadsItems, int position, View convertView, ViewGroup parent) {
         View view = convertView;
         if (view == null) {
             LayoutInflater inflator = (LayoutInflater) mActivity.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
             view = inflator.inflate(R.layout.upload_list_item, null);
         }
-        if (mUploads != null && mUploads.length > position) {
-            UploadDbObject uploadObject = mUploads[position];
+        if (uploadsItems != null && uploadsItems.length > position) {
+            UploadDbObject uploadObject = uploadsItems[position];
 
             TextView fileName = (TextView) view.findViewById(R.id.upload_name);
             fileName.setText(uploadObject.getLocalPath());
@@ -110,11 +144,15 @@ public class UploadListAdapter extends BaseAdapter implements ListAdapter, Obser
             statusView.setText(status);
 
             ImageView fileIcon = (ImageView) view.findViewById(R.id.imageView1);
-            // if (!file.isDirectory()) {
             fileIcon.setImageResource(R.drawable.file);
-            // } else {
-            // fileIcon.setImageResource(R.drawable.ic_menu_archive);
-            // }
+            try {
+                //?? TODO RemoteID is not set yet. How to get thumbnail?
+                Bitmap b = ThumbnailsCacheManager.getBitmapFromDiskCache(uploadObject.getOCFile().getRemoteId());
+                if (b != null) {
+                    fileIcon.setImageBitmap(b);
+                }
+            } catch (NullPointerException e) {
+            }            
 
             TextView fileSizeV = (TextView) view.findViewById(R.id.file_size);
             CharSequence dateString = DisplayUtils.getRelativeDateTimeString(mActivity, uploadObject.getUploadTime()
@@ -161,49 +199,23 @@ public class UploadListAdapter extends BaseAdapter implements ListAdapter, Obser
         return view;
     }
 
-    @Override
-    public int getViewTypeCount() {
-        return 1;
-    }
+    
 
     @Override
     public boolean hasStableIds() {
         return false;
     }
 
-    @Override
-    public boolean isEmpty() {
-        return (mUploads == null || mUploads.length == 0);
-    }
+    
 
     /**
      * Load upload items from {@link UploadDbHandler}.
      */
     private void loadUploadItemsFromDb() {
         Log_OC.d(TAG, "loadUploadItemsFromDb");
-        List<UploadDbObject> list = mDb.getAllStoredUploads();
-        mUploads = list.toArray(new UploadDbObject[list.size()]);
-        if (mUploads != null) {
-            Arrays.sort(mUploads, new Comparator<UploadDbObject>() {
-                @Override
-                public int compare(UploadDbObject lhs, UploadDbObject rhs) {
-                    // if (lhs.isDirectory() && !rhs.isDirectory()) {
-                    // return -1;
-                    // } else if (!lhs.isDirectory() && rhs.isDirectory()) {
-                    // return 1;
-                    // }
-                    return compareUploadTime(lhs, rhs);
-                }
-
-                private int compareNames(UploadDbObject lhs, UploadDbObject rhs) {
-                    return lhs.getLocalPath().toLowerCase().compareTo(rhs.getLocalPath().toLowerCase());
-                }
-
-                private int compareUploadTime(UploadDbObject lhs, UploadDbObject rhs) {
-                    return rhs.getUploadTime().compareTo(lhs.getUploadTime());
-                }
-
-            });
+        
+        for (UploadGroup group : mUploadGroups) {
+            group.refresh();
         }
         mActivity.runOnUiThread(new Runnable() {
             @Override
@@ -219,4 +231,66 @@ public class UploadListAdapter extends BaseAdapter implements ListAdapter, Obser
         Log_OC.d(TAG, "update");
         loadUploadItemsFromDb();
     }
+
+    @Override
+    public Object getChild(int groupPosition, int childPosition) {
+        return mUploadGroups[groupPosition].items[childPosition];
+    }
+
+    @Override
+    public long getChildId(int groupPosition, int childPosition) {
+        return groupPosition * 1000l + childPosition;
+    }
+
+    @Override
+    public View getChildView(int groupPosition, int childPosition, boolean isLastChild, View convertView,
+            ViewGroup parent) {
+        return getView(mUploadGroups[groupPosition].items, childPosition, convertView, parent);
+    }
+
+    @Override
+    public int getChildrenCount(int groupPosition) {
+        return mUploadGroups[groupPosition].items.length;
+    }
+
+    @Override
+    public Object getGroup(int groupPosition) {
+        return mUploadGroups[groupPosition];
+    }
+
+    @Override
+    public int getGroupCount() {
+        return mUploadGroups.length;
+    }
+
+    @Override
+    public long getGroupId(int groupPosition) {
+        return groupPosition;
+    }
+
+    @Override
+    public View getGroupView(int groupPosition, boolean isExpanded, View convertView, ViewGroup parent) {
+        //force group to stay unfolded
+        ExpandableListView listView = (ExpandableListView) parent;
+        listView.expandGroup(groupPosition);
+        
+        listView.setGroupIndicator(null);
+        
+        UploadGroup group = (UploadGroup) getGroup(groupPosition);
+        if (convertView == null) {
+            LayoutInflater infalInflater = (LayoutInflater) mActivity
+                    .getSystemService(Context.LAYOUT_INFLATER_SERVICE);
+            convertView = infalInflater.inflate(R.layout.upload_list_group, null);
+        }
+        TextView tv = (TextView) convertView.findViewById(R.id.uploadListGroupName);
+        tv.setText(group.getGroupName());
+        ImageView icon = (ImageView) convertView.findViewById(R.id.uploadListGroupIcon);
+        icon.setImageResource(group.getGroupIcon());
+        return convertView;
+    }
+
+    @Override
+    public boolean isChildSelectable(int groupPosition, int childPosition) {
+        return false;
+    }
 }

+ 0 - 190
src/com/owncloud/android/ui/fragment/UploadListFragment.java

@@ -1,190 +0,0 @@
-/* ownCloud Android client application
- *   Copyright (C) 2011  Bartek Przybylski
- *   Copyright (C) 2012-2013 ownCloud Inc.
- *
- *   This program is free software: you can redistribute it and/or modify
- *   it under the terms of the GNU General Public License version 2,
- *   as published by the Free Software Foundation.
- *
- *   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 General Public License for more details.
- *
- *   You should have received a copy of the GNU General Public License
- *   along with this program.  If not, see <http://www.gnu.org/licenses/>.
- *
- */
-package com.owncloud.android.ui.fragment;
-
-import java.io.File;
-import java.util.ArrayList;
-
-import android.app.Activity;
-import android.os.Bundle;
-import android.util.SparseBooleanArray;
-import android.view.LayoutInflater;
-import android.view.View;
-import android.view.ViewGroup;
-import android.widget.AdapterView;
-import android.widget.ImageView;
-import android.widget.ListView;
-
-import com.owncloud.android.R;
-import com.owncloud.android.db.UploadDbObject;
-import com.owncloud.android.lib.common.utils.Log_OC;
-import com.owncloud.android.ui.adapter.UploadListAdapter;
-
-/**
- * A Fragment that lists all files and folders in a given LOCAL path.
- *
- * @author LukeOwncloud
- *
- */
-public class UploadListFragment extends ExtendedListFragment {
-    private static final String TAG = "UploadListFragment";
-
-    /**
-     * Reference to the Activity which this fragment is attached to. For
-     * callbacks
-     */
-    private UploadListFragment.ContainerActivity mContainerActivity;
-
-    /** Adapter to connect the data from the directory with the View object */
-    private UploadListAdapter mAdapter = null;
-
-    /**
-     * {@inheritDoc}
-     */
-    @Override
-    public void onAttach(Activity activity) {
-        super.onAttach(activity);
-        try {
-            mContainerActivity = (ContainerActivity) activity;
-        } catch (ClassCastException e) {
-            throw new ClassCastException(activity.toString() + " must implement "
-                    + UploadListFragment.ContainerActivity.class.getSimpleName());
-        }
-    }
-
-    /**
-     * {@inheritDoc}
-     */
-    @Override
-    public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
-        Log_OC.i(TAG, "onCreateView() start");
-        View v = super.onCreateView(inflater, container, savedInstanceState);
-        getListView().setChoiceMode(ListView.CHOICE_MODE_MULTIPLE);
-        disableSwipe(); // Disable pull refresh
-//        setMessageForEmptyList(getString(R.string.local_file_list_empty));
-        setMessageForEmptyList("No uploads available.");
-        Log_OC.i(TAG, "onCreateView() end");
-        return v;
-    }
-
-    /**
-     * {@inheritDoc}
-     */
-    @Override
-    public void onActivityCreated(Bundle savedInstanceState) {
-        Log_OC.i(TAG, "onActivityCreated() start");
-
-        super.onActivityCreated(savedInstanceState);
-        mAdapter = new UploadListAdapter(getActivity());
-        setListAdapter(mAdapter);
-
-    }
-    
-    public void selectAll() {
-        int numberOfFiles = mAdapter.getCount();
-        for (int i = 0; i < numberOfFiles; i++) {
-            UploadDbObject file = (UploadDbObject) mAdapter.getItem(i);
-            if (file != null) {
-                // / Click on a file
-                getListView().setItemChecked(i, true);
-                // notify the change to the container Activity
-                mContainerActivity.onUploadItemClick(file);
-            }
-        }
-    }
-
-    public void deselectAll() {
-        mAdapter = new UploadListAdapter(getActivity());
-        setListAdapter(mAdapter);
-    }
-
-    /**
-     * Checks the file clicked over. Browses inside if it is a directory.
-     * Notifies the container activity in any case.
-     */
-    @Override
-    public void onItemClick(AdapterView<?> l, View v, int position, long id) {
-        UploadDbObject uploadDbObject = (UploadDbObject) mAdapter.getItem(position);
-
-        if (uploadDbObject != null) {
-
-            // notify the click to container Activity
-            mContainerActivity.onUploadItemClick(uploadDbObject);
-
-            ImageView checkBoxV = (ImageView) v.findViewById(R.id.custom_checkbox);
-            if (checkBoxV != null) {
-                if (getListView().isItemChecked(position)) {
-                    checkBoxV.setImageResource(android.R.drawable.checkbox_on_background);
-                } else {
-                    checkBoxV.setImageResource(android.R.drawable.checkbox_off_background);
-                }
-            }
-
-        } else {
-            Log_OC.w(TAG, "Null object in ListAdapter!!");
-        }
-    }
-
-    /**
-     * Returns the fule paths to the files checked by the user
-     *
-     * @return File paths to the files checked by the user.
-     */
-    public String[] getCheckedFilePaths() {
-        ArrayList<String> result = new ArrayList<String>();
-        SparseBooleanArray positions = mList.getCheckedItemPositions();
-        if (positions.size() > 0) {
-            for (int i = 0; i < positions.size(); i++) {
-                if (positions.get(positions.keyAt(i)) == true) {
-                    result.add(((File) mList.getItemAtPosition(positions.keyAt(i))).getAbsolutePath());
-                }
-            }
-
-            Log_OC.d(TAG, "Returning " + result.size() + " selected files");
-        }
-        return result.toArray(new String[result.size()]);
-    }
-
-    /**
-     * Interface to implement by any Activity that includes some instance of
-     * UploadListFragment
-     *
-     * @author LukeOwncloud
-     */
-    public interface ContainerActivity {
-
-        /**
-         * Callback method invoked when an upload item is clicked by the user on
-         * the upload list
-         *
-         * @param file
-         */
-        public void onUploadItemClick(UploadDbObject file);
-
-        /**
-         * Callback method invoked when the parent activity is fully created to
-         * get the filter which is to be applied to the upload list.
-         *
-         * @return Filter to be applied. Can be null, then all uploads are
-         *         shown.
-         */
-        public File getInitialFilter();
-
-    }
-
-}