Browse Source

Merge pull request #3472 from nextcloud/revertExpertMode

Upload list activity: integrated overflow menu
Andy Scherzinger 6 years ago
parent
commit
869c4a91e7

+ 1 - 0
drawable_resources/ic_close.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="M19,6.41L17.59,5L12,10.59L6.41,5L5,6.41L10.59,12L5,17.59L6.41,19L12,13.41L17.59,19L19,17.59L13.41,12L19,6.41Z" /></svg>

+ 1 - 0
drawable_resources/ic_sync.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,18A6,6 0 0,1 6,12C6,11 6.25,10.03 6.7,9.2L5.24,7.74C4.46,8.97 4,10.43 4,12A8,8 0 0,0 12,20V23L16,19L12,15M12,4V1L8,5L12,9V6A6,6 0 0,1 18,12C18,13 17.75,13.97 17.3,14.8L18.76,16.26C19.54,15.03 20,13.57 20,12A8,8 0 0,0 12,4Z" /></svg>

+ 38 - 50
src/main/java/com/owncloud/android/ui/activity/UploadListActivity.java

@@ -37,6 +37,8 @@ import android.view.View;
 import android.widget.ImageView;
 import android.widget.TextView;
 
+import com.evernote.android.job.Job;
+import com.evernote.android.job.JobManager;
 import com.evernote.android.job.JobRequest;
 import com.evernote.android.job.util.support.PersistableBundleCompat;
 import com.google.android.material.bottomnavigation.BottomNavigationView;
@@ -56,6 +58,8 @@ import com.owncloud.android.utils.DisplayUtils;
 import com.owncloud.android.utils.FilesSyncHelper;
 import com.owncloud.android.utils.ThemeUtils;
 
+import java.util.Set;
+
 import androidx.recyclerview.widget.GridLayoutManager;
 import androidx.swiperefreshlayout.widget.SwipeRefreshLayout;
 import butterknife.BindString;
@@ -72,14 +76,12 @@ public class UploadListActivity extends FileActivity {
 
     private static final String TAG = UploadListActivity.class.getSimpleName();
 
-    private UploadMessagesReceiver mUploadMessagesReceiver;
+    private UploadsStorageManager uploadStorageManager;
 
-    private Menu menu;
+    private UploadMessagesReceiver uploadMessagesReceiver;
 
     private UploadListAdapter uploadListAdapter;
 
-    private UploadsStorageManager uploadStorageManager;
-
     public SwipeRefreshLayout swipeListRefreshLayout;
 
     @BindView(R.id.empty_list_view_text)
@@ -183,6 +185,25 @@ public class UploadListActivity extends FileActivity {
     }
 
     private void refresh() {
+        // scan for missing auto uploads files
+        Set<Job> jobs = JobManager.instance().getAllJobsForTag(FilesSyncJob.TAG);
+
+        if (jobs.isEmpty()) {
+            PersistableBundleCompat persistableBundleCompat = new PersistableBundleCompat();
+            persistableBundleCompat.putBoolean(FilesSyncJob.OVERRIDE_POWER_SAVING, true);
+            new JobRequest.Builder(FilesSyncJob.TAG)
+                .setExact(1_000L)
+                .setUpdateCurrent(false)
+                .setExtras(persistableBundleCompat)
+                .build()
+                .schedule();
+        }
+
+        // retry failed uploads
+        FileUploader.UploadRequester requester = new FileUploader.UploadRequester();
+        new Thread(() -> requester.retryFailedUploads(this, null, null)).start();
+
+        // update UI
         uploadListAdapter.loadUploadItemsFromDb();
         swipeListRefreshLayout.setRefreshing(false);
     }
@@ -195,12 +216,12 @@ public class UploadListActivity extends FileActivity {
         setDrawerMenuItemChecked(R.id.nav_uploads);
 
         // Listen for upload messages
-        mUploadMessagesReceiver = new UploadMessagesReceiver();
+        uploadMessagesReceiver = new UploadMessagesReceiver();
         IntentFilter uploadIntentFilter = new IntentFilter();
         uploadIntentFilter.addAction(FileUploader.getUploadsAddedMessage());
         uploadIntentFilter.addAction(FileUploader.getUploadStartMessage());
         uploadIntentFilter.addAction(FileUploader.getUploadFinishMessage());
-        registerReceiver(mUploadMessagesReceiver, uploadIntentFilter);
+        registerReceiver(uploadMessagesReceiver, uploadIntentFilter);
 
         Log_OC.v(TAG, "onResume() end");
 
@@ -209,14 +230,22 @@ public class UploadListActivity extends FileActivity {
     @Override
     protected void onPause() {
         Log_OC.v(TAG, "onPause() start");
-        if (mUploadMessagesReceiver != null) {
-            unregisterReceiver(mUploadMessagesReceiver);
-            mUploadMessagesReceiver = null;
+        if (uploadMessagesReceiver != null) {
+            unregisterReceiver(uploadMessagesReceiver);
+            uploadMessagesReceiver = null;
         }
         super.onPause();
         Log_OC.v(TAG, "onPause() end");
     }
 
+    @Override
+    public boolean onCreateOptionsMenu(Menu menu) {
+        MenuInflater inflater = getMenuInflater();
+        inflater.inflate(R.menu.upload_list_menu, menu);
+
+        return true;
+    }
+
     @Override
     public boolean onOptionsItemSelected(MenuItem item) {
         boolean retval = true;
@@ -228,43 +257,11 @@ public class UploadListActivity extends FileActivity {
                     openDrawer();
                 }
                 break;
-
-            case R.id.action_retry_uploads:
-                FileUploader.UploadRequester requester = new FileUploader.UploadRequester();
-
-                new Thread(() -> requester.retryFailedUploads(this, null, null)).start();
-
-                if (menu != null) {
-                    menu.removeItem(R.id.action_retry_uploads);
-                }
-                break;
-
             case R.id.action_clear_failed_uploads:
                 uploadStorageManager.clearFailedButNotDelayedUploads();
                 uploadListAdapter.loadUploadItemsFromDb();
                 break;
 
-            case R.id.action_clear_successfull_uploads:
-                uploadStorageManager.clearSuccessfulUploads();
-                uploadListAdapter.loadUploadItemsFromDb();
-                break;
-
-            case R.id.action_force_rescan:
-                PersistableBundleCompat persistableBundleCompat = new PersistableBundleCompat();
-                persistableBundleCompat.putBoolean(FilesSyncJob.OVERRIDE_POWER_SAVING, true);
-                new JobRequest.Builder(FilesSyncJob.TAG)
-                        .setExact(1_000L)
-                        .setUpdateCurrent(false)
-                        .setExtras(persistableBundleCompat)
-                        .build()
-                        .schedule();
-
-                if (menu != null) {
-                    menu.removeItem(R.id.action_force_rescan);
-                }
-
-                break;
-
             default:
                 retval = super.onOptionsItemSelected(item);
         }
@@ -272,15 +269,6 @@ public class UploadListActivity extends FileActivity {
         return retval;
     }
 
-    @Override
-    public boolean onCreateOptionsMenu(Menu menu) {
-        MenuInflater inflater = getMenuInflater();
-        inflater.inflate(R.menu.upload_list_menu, menu);
-        this.menu = menu;
-
-        return true;
-    }
-
     @Override
     protected void onActivityResult(int requestCode, int resultCode, Intent data) {
         super.onActivityResult(requestCode, resultCode, data);

+ 175 - 115
src/main/java/com/owncloud/android/ui/adapter/UploadListAdapter.java

@@ -58,41 +58,78 @@ import java.util.Arrays;
 import java.util.Comparator;
 
 import androidx.annotation.NonNull;
+import butterknife.BindView;
+import butterknife.ButterKnife;
 
 /**
  * This Adapter populates a ListView with following types of uploads: pending,active, completed. Filtering possible.
  */
 public class UploadListAdapter extends SectionedRecyclerViewAdapter<SectionedViewHolder> {
-
     private static final String TAG = UploadListAdapter.class.getSimpleName();
 
-    private ProgressListener mProgressListener;
-
-    private FileActivity mParentActivity;
-
-    private UploadsStorageManager mUploadsStorageManager;
-
-    private UploadGroup[] mUploadGroups;
+    private ProgressListener progressListener;
+    private FileActivity parentActivity;
+    private UploadsStorageManager uploadsStorageManager;
+    private UploadGroup[] uploadGroups;
 
     @Override
     public int getSectionCount() {
-        return mUploadGroups.length;
+        return uploadGroups.length;
     }
 
     @Override
     public int getItemCount(int section) {
-        return mUploadGroups[section].getItems().length;
+        return uploadGroups[section].getItems().length;
     }
 
     @Override
     public void onBindHeaderViewHolder(SectionedViewHolder holder, int section, boolean expanded) {
         HeaderViewHolder headerViewHolder = (HeaderViewHolder) holder;
 
-        UploadGroup group = mUploadGroups[section];
+        UploadGroup group = uploadGroups[section];
+
+        headerViewHolder.title.setText(String.format(parentActivity.getString(R.string.uploads_view_group_header),
+                                                     group.getGroupName(), group.getGroupItemCount()));
+        headerViewHolder.title.setTextColor(ThemeUtils.primaryAccentColor(parentActivity));
+
+        headerViewHolder.title.setOnClickListener(v -> {
+            toggleSectionExpanded(section);
+        });
+
+        switch (group.type) {
+            case CURRENT:
+                headerViewHolder.action.setImageResource(R.drawable.ic_close);
+                break;
+            case FINISHED:
+                headerViewHolder.action.setImageResource(R.drawable.ic_close);
+                break;
+            case FAILED:
+                headerViewHolder.action.setImageResource(R.drawable.ic_sync);
+                break;
+        }
+
+        headerViewHolder.action.setOnClickListener(v -> {
+            switch (group.type) {
+                case CURRENT:
+                    FileUploader.FileUploaderBinder uploaderBinder = parentActivity.getFileUploaderBinder();
+
+                    if (uploaderBinder != null) {
+                        for (OCUpload upload : group.getItems()) {
+                            uploaderBinder.cancel(upload);
+                        }
+                    }
+                    break;
+                case FINISHED:
+                    uploadsStorageManager.clearSuccessfulUploads();
+                    break;
+                case FAILED:
+                    new Thread(() -> new FileUploader.UploadRequester()
+                        .retryFailedUploads(parentActivity, null, null)).start();
+                    break;
+            }
 
-        headerViewHolder.title.setText(String.format(mParentActivity.getString(R.string.uploads_view_group_header),
-                group.getGroupName(), group.getGroupItemCount()));
-        headerViewHolder.title.setTextColor(ThemeUtils.primaryAccentColor(mParentActivity));
+            loadUploadItemsFromDb();
+        });
     }
 
     @Override
@@ -100,33 +137,36 @@ public class UploadListAdapter extends SectionedRecyclerViewAdapter<SectionedVie
         // not needed
     }
 
-    public UploadListAdapter(FileActivity parentActivity) {
+    public UploadListAdapter(FileActivity fileActivity) {
         Log_OC.d(TAG, "UploadListAdapter");
-        mParentActivity = parentActivity;
-        mUploadsStorageManager = new UploadsStorageManager(mParentActivity.getContentResolver(),
-                parentActivity.getApplicationContext());
-        mUploadGroups = new UploadGroup[3];
+        parentActivity = fileActivity;
+        uploadsStorageManager = new UploadsStorageManager(parentActivity.getContentResolver(),
+                                                          parentActivity.getApplicationContext());
+        uploadGroups = new UploadGroup[3];
 
         shouldShowHeadersForEmptySections(false);
 
-        mUploadGroups[0] = new UploadGroup(mParentActivity.getString(R.string.uploads_view_group_current_uploads)) {
+        uploadGroups[0] = new UploadGroup(Type.CURRENT,
+                                          parentActivity.getString(R.string.uploads_view_group_current_uploads)) {
             @Override
             public void refresh() {
-                fixAndSortItems(mUploadsStorageManager.getCurrentAndPendingUploadsForCurrentAccount());
+                fixAndSortItems(uploadsStorageManager.getCurrentAndPendingUploadsForCurrentAccount());
             }
         };
 
-        mUploadGroups[1] = new UploadGroup(mParentActivity.getString(R.string.uploads_view_group_failed_uploads)) {
+        uploadGroups[1] = new UploadGroup(Type.FAILED,
+                                          parentActivity.getString(R.string.uploads_view_group_failed_uploads)) {
             @Override
             public void refresh() {
-                fixAndSortItems(mUploadsStorageManager.getFailedButNotDelayedUploadsForCurrentAccount());
+                fixAndSortItems(uploadsStorageManager.getFailedButNotDelayedUploadsForCurrentAccount());
             }
         };
 
-        mUploadGroups[2] = new UploadGroup(mParentActivity.getString(R.string.uploads_view_group_finished_uploads)) {
+        uploadGroups[2] = new UploadGroup(Type.FINISHED,
+                                          parentActivity.getString(R.string.uploads_view_group_finished_uploads)) {
             @Override
             public void refresh() {
-                fixAndSortItems(mUploadsStorageManager.getFinishedUploadsForCurrentAccount());
+                fixAndSortItems(uploadsStorageManager.getFinishedUploadsForCurrentAccount());
             }
         };
         loadUploadItemsFromDb();
@@ -136,7 +176,7 @@ public class UploadListAdapter extends SectionedRecyclerViewAdapter<SectionedVie
     public void onBindViewHolder(SectionedViewHolder holder, int section, int relativePosition, int absolutePosition) {
         ItemViewHolder itemViewHolder = (ItemViewHolder) holder;
 
-        OCUpload item = mUploadGroups[section].getItem(relativePosition);
+        OCUpload item = uploadGroups[section].getItem(relativePosition);
 
         itemViewHolder.name.setText(item.getLocalPath());
 
@@ -161,14 +201,14 @@ public class UploadListAdapter extends SectionedRecyclerViewAdapter<SectionedVie
 
         // upload date
         long updateTime = item.getUploadEndTimestamp();
-        CharSequence dateString = DisplayUtils.getRelativeDateTimeString(mParentActivity, updateTime,
-                DateUtils.SECOND_IN_MILLIS, DateUtils.WEEK_IN_MILLIS, 0);
+        CharSequence dateString = DisplayUtils.getRelativeDateTimeString(parentActivity, updateTime,
+                                                                         DateUtils.SECOND_IN_MILLIS, DateUtils.WEEK_IN_MILLIS, 0);
         itemViewHolder.date.setText(dateString);
 
-        Account account = AccountUtils.getOwnCloudAccountByName(mParentActivity, item.getAccountName());
+        Account account = AccountUtils.getOwnCloudAccountByName(parentActivity, item.getAccountName());
         if (account != null) {
-            itemViewHolder.account.setText(DisplayUtils.getAccountNameDisplayText(mParentActivity, account,
-                    account.name, item.getAccountName()));
+            itemViewHolder.account.setText(DisplayUtils.getAccountNameDisplayText(parentActivity, account,
+                                                                                  account.name, item.getAccountName()));
         } else {
             itemViewHolder.account.setText(item.getAccountName());
         }
@@ -187,31 +227,31 @@ public class UploadListAdapter extends SectionedRecyclerViewAdapter<SectionedVie
         switch (item.getUploadStatus()) {
             case UPLOAD_IN_PROGRESS:
                 ThemeUtils.colorHorizontalProgressBar(itemViewHolder.progressBar,
-                        ThemeUtils.primaryAccentColor(mParentActivity));
+                                                      ThemeUtils.primaryAccentColor(parentActivity));
                 itemViewHolder.progressBar.setProgress(0);
                 itemViewHolder.progressBar.setVisibility(View.VISIBLE);
 
-                FileUploader.FileUploaderBinder binder = mParentActivity.getFileUploaderBinder();
+                FileUploader.FileUploaderBinder binder = parentActivity.getFileUploaderBinder();
                 if (binder != null) {
                     if (binder.isUploadingNow(item)) {
                         // really uploading, so...
                         // ... unbind the old progress bar, if any; ...
-                        if (mProgressListener != null) {
+                        if (progressListener != null) {
                             binder.removeDatatransferProgressListener(
-                                    mProgressListener,
-                                    mProgressListener.getUpload()   // the one that was added
+                                progressListener,
+                                progressListener.getUpload()   // the one that was added
                             );
                         }
                         // ... then, bind the current progress bar to listen for updates
-                        mProgressListener = new ProgressListener(item, itemViewHolder.progressBar);
-                        binder.addDatatransferProgressListener(mProgressListener, item);
+                        progressListener = new ProgressListener(item, itemViewHolder.progressBar);
+                        binder.addDatatransferProgressListener(progressListener, item);
                     } else {
                         // not really uploading; stop listening progress if view is reused!
-                        if (mProgressListener != null && mProgressListener.isWrapping(itemViewHolder.progressBar)) {
-                            binder.removeDatatransferProgressListener(mProgressListener,
-                                    mProgressListener.getUpload()   // the one that was added
+                        if (progressListener != null && progressListener.isWrapping(itemViewHolder.progressBar)) {
+                            binder.removeDatatransferProgressListener(progressListener,
+                                                                      progressListener.getUpload()   // the one that was added
                             );
-                            mProgressListener = null;
+                            progressListener = null;
                         }
                     }
                 } else {
@@ -239,7 +279,7 @@ public class UploadListAdapter extends SectionedRecyclerViewAdapter<SectionedVie
             itemViewHolder.button.setImageResource(R.drawable.ic_action_cancel_grey);
             itemViewHolder.button.setVisibility(View.VISIBLE);
             itemViewHolder.button.setOnClickListener(v -> {
-                FileUploader.FileUploaderBinder uploaderBinder = mParentActivity.getFileUploaderBinder();
+                FileUploader.FileUploaderBinder uploaderBinder = parentActivity.getFileUploaderBinder();
                 if (uploaderBinder != null) {
                     uploaderBinder.cancel(item);
                     loadUploadItemsFromDb();
@@ -251,7 +291,7 @@ public class UploadListAdapter extends SectionedRecyclerViewAdapter<SectionedVie
             itemViewHolder.button.setImageResource(R.drawable.ic_action_delete_grey);
             itemViewHolder.button.setVisibility(View.VISIBLE);
             itemViewHolder.button.setOnClickListener(v -> {
-                mUploadsStorageManager.removeUpload(item);
+                uploadsStorageManager.removeUpload(item);
                 loadUploadItemsFromDb();
             });
 
@@ -265,15 +305,15 @@ public class UploadListAdapter extends SectionedRecyclerViewAdapter<SectionedVie
         if (item.getUploadStatus() == UploadStatus.UPLOAD_FAILED) {
             if (UploadResult.CREDENTIAL_ERROR.equals(item.getLastResult())) {
                 itemViewHolder.itemLayout.setOnClickListener(v ->
-                        mParentActivity.getFileOperationsHelper().checkCurrentCredentials(
-                                item.getAccount(mParentActivity)));
+                                                                 parentActivity.getFileOperationsHelper().checkCurrentCredentials(
+                                                                     item.getAccount(parentActivity)));
             } else {
                 // not a credentials error
                 itemViewHolder.itemLayout.setOnClickListener(v -> {
                     File file = new File(item.getLocalPath());
                     if (file.exists()) {
                         FileUploader.UploadRequester requester = new FileUploader.UploadRequester();
-                        requester.retry(mParentActivity, item);
+                        requester.retry(parentActivity, item);
                         loadUploadItemsFromDb();
                     } else {
                         DisplayUtils.showSnackMessage(
@@ -318,7 +358,7 @@ public class UploadListAdapter extends SectionedRecyclerViewAdapter<SectionedVie
                 if (allowedToCreateNewThumbnail) {
                     final ThumbnailsCacheManager.ThumbnailGenerationTask task =
                             new ThumbnailsCacheManager.ThumbnailGenerationTask(
-                                    itemViewHolder.thumbnail, mParentActivity.getStorageManager(), mParentActivity.getAccount()
+                                itemViewHolder.thumbnail, parentActivity.getStorageManager(), parentActivity.getAccount()
                             );
                     if (thumbnail == null) {
                         if (MimeTypeUtil.isVideo(fakeFileToCheatThumbnailsCacheManagerInterface)) {
@@ -329,9 +369,9 @@ public class UploadListAdapter extends SectionedRecyclerViewAdapter<SectionedVie
                     }
                     final ThumbnailsCacheManager.AsyncThumbnailDrawable asyncDrawable =
                             new ThumbnailsCacheManager.AsyncThumbnailDrawable(
-                                    mParentActivity.getResources(),
-                                    thumbnail,
-                                    task
+                                parentActivity.getResources(),
+                                thumbnail,
+                                task
                             );
                     itemViewHolder.thumbnail.setImageDrawable(asyncDrawable);
                     task.execute(new ThumbnailsCacheManager.ThumbnailGenerationTaskObject(
@@ -340,7 +380,7 @@ public class UploadListAdapter extends SectionedRecyclerViewAdapter<SectionedVie
             }
 
             if ("image/png".equals(item.getMimeType())) {
-                itemViewHolder.thumbnail.setBackgroundColor(mParentActivity.getResources()
+                itemViewHolder.thumbnail.setBackgroundColor(parentActivity.getResources()
                         .getColor(R.color.background_color));
             }
 
@@ -365,8 +405,8 @@ public class UploadListAdapter extends SectionedRecyclerViewAdapter<SectionedVie
                     }
 
                     final ThumbnailsCacheManager.AsyncThumbnailDrawable asyncDrawable =
-                            new ThumbnailsCacheManager.AsyncThumbnailDrawable(mParentActivity.getResources(), thumbnail,
-                                    task);
+                        new ThumbnailsCacheManager.AsyncThumbnailDrawable(parentActivity.getResources(), thumbnail,
+                                                                          task);
 
                     itemViewHolder.thumbnail.setImageDrawable(asyncDrawable);
                     task.execute(new ThumbnailsCacheManager.ThumbnailGenerationTaskObject(file, null));
@@ -375,12 +415,12 @@ public class UploadListAdapter extends SectionedRecyclerViewAdapter<SectionedVie
             }
 
             if ("image/png".equalsIgnoreCase(item.getMimeType())) {
-                itemViewHolder.thumbnail.setBackgroundColor(mParentActivity.getResources()
+                itemViewHolder.thumbnail.setBackgroundColor(parentActivity.getResources()
                         .getColor(R.color.background_color));
             }
         } else {
             itemViewHolder.thumbnail.setImageDrawable(MimeTypeUtil.getFileTypeIcon(item.getMimeType(), fileName,
-                    account, mParentActivity));
+                                                                                   account, parentActivity));
         }
     }
 
@@ -397,16 +437,16 @@ public class UploadListAdapter extends SectionedRecyclerViewAdapter<SectionedVie
         switch (upload.getUploadStatus()) {
 
             case UPLOAD_IN_PROGRESS:
-                status = mParentActivity.getString(R.string.uploads_view_later_waiting_to_upload);
-                FileUploader.FileUploaderBinder binder = mParentActivity.getFileUploaderBinder();
+                status = parentActivity.getString(R.string.uploads_view_later_waiting_to_upload);
+                FileUploader.FileUploaderBinder binder = parentActivity.getFileUploaderBinder();
                 if (binder != null && binder.isUploadingNow(upload)) {
                     // really uploading, bind the progress bar to listen for progress updates
-                    status = mParentActivity.getString(R.string.uploader_upload_in_progress_ticker);
+                    status = parentActivity.getString(R.string.uploader_upload_in_progress_ticker);
                 }
                 break;
 
             case UPLOAD_SUCCEEDED:
-                status = mParentActivity.getString(R.string.uploads_view_upload_status_succeeded);
+                status = parentActivity.getString(R.string.uploads_view_upload_status_succeeded);
                 break;
 
             case UPLOAD_FAILED:
@@ -424,81 +464,82 @@ public class UploadListAdapter extends SectionedRecyclerViewAdapter<SectionedVie
         String status;
         switch (result) {
             case CREDENTIAL_ERROR:
-                status = mParentActivity.getString(R.string.uploads_view_upload_status_failed_credentials_error);
+                status = parentActivity.getString(R.string.uploads_view_upload_status_failed_credentials_error);
                 break;
             case FOLDER_ERROR:
-                status = mParentActivity.getString(R.string.uploads_view_upload_status_failed_folder_error);
+                status = parentActivity.getString(R.string.uploads_view_upload_status_failed_folder_error);
                 break;
             case FILE_NOT_FOUND:
-                status = mParentActivity.getString(R.string.uploads_view_upload_status_failed_localfile_error);
+                status = parentActivity.getString(R.string.uploads_view_upload_status_failed_localfile_error);
                 break;
             case FILE_ERROR:
-                status = mParentActivity.getString(R.string.uploads_view_upload_status_failed_file_error);
+                status = parentActivity.getString(R.string.uploads_view_upload_status_failed_file_error);
                 break;
             case PRIVILEGES_ERROR:
-                status = mParentActivity.getString(R.string.uploads_view_upload_status_failed_permission_error);
+                status = parentActivity.getString(R.string.uploads_view_upload_status_failed_permission_error);
                 break;
             case NETWORK_CONNECTION:
-                status = mParentActivity.getString(R.string.uploads_view_upload_status_failed_connection_error);
+                status = parentActivity.getString(R.string.uploads_view_upload_status_failed_connection_error);
                 break;
             case DELAYED_FOR_WIFI:
-                status = mParentActivity.getString(R.string.uploads_view_upload_status_waiting_for_wifi);
+                status = parentActivity.getString(R.string.uploads_view_upload_status_waiting_for_wifi);
                 break;
             case DELAYED_FOR_CHARGING:
-                status = mParentActivity.getString(R.string.uploads_view_upload_status_waiting_for_charging);
+                status = parentActivity.getString(R.string.uploads_view_upload_status_waiting_for_charging);
                 break;
             case CONFLICT_ERROR:
-                status = mParentActivity.getString(R.string.uploads_view_upload_status_conflict);
+                status = parentActivity.getString(R.string.uploads_view_upload_status_conflict);
                 break;
             case SERVICE_INTERRUPTED:
-                status = mParentActivity.getString(R.string.uploads_view_upload_status_service_interrupted);
+                status = parentActivity.getString(R.string.uploads_view_upload_status_service_interrupted);
                 break;
             case CANCELLED:
                 // should not get here ; cancelled uploads should be wiped out
-                status = mParentActivity.getString(R.string.uploads_view_upload_status_cancelled);
+                status = parentActivity.getString(R.string.uploads_view_upload_status_cancelled);
                 break;
             case UPLOADED:
                 // should not get here ; status should be UPLOAD_SUCCESS
-                status = mParentActivity.getString(R.string.uploads_view_upload_status_succeeded);
+                status = parentActivity.getString(R.string.uploads_view_upload_status_succeeded);
                 break;
             case MAINTENANCE_MODE:
-                status = mParentActivity.getString(R.string.maintenance_mode);
+                status = parentActivity.getString(R.string.maintenance_mode);
                 break;
             case SSL_RECOVERABLE_PEER_UNVERIFIED:
-                status = mParentActivity.getString(
+                status =
+                    parentActivity.getString(
                                 R.string.uploads_view_upload_status_failed_ssl_certificate_not_trusted
                         );
                 break;
             case UNKNOWN:
-                status = mParentActivity.getString(R.string.uploads_view_upload_status_unknown_fail);
+                status = parentActivity.getString(R.string.uploads_view_upload_status_unknown_fail);
                 break;
             case LOCK_FAILED:
-                status = mParentActivity.getString(R.string.upload_lock_failed);
+                status = parentActivity.getString(R.string.upload_lock_failed);
                 break;
             case DELAYED_IN_POWER_SAVE_MODE:
-                status = mParentActivity.getString(
+                status = parentActivity.getString(
                         R.string.uploads_view_upload_status_waiting_exit_power_save_mode);
                 break;
             case VIRUS_DETECTED:
-                status = mParentActivity.getString(R.string.uploads_view_upload_status_virus_detected);
+                status = parentActivity.getString(R.string.uploads_view_upload_status_virus_detected);
                 break;
             case LOCAL_STORAGE_FULL:
-                status = mParentActivity.getString(R.string.upload_local_storage_full);
+                status = parentActivity.getString(R.string.upload_local_storage_full);
                 break;
             case OLD_ANDROID_API:
-                status = mParentActivity.getString(R.string.upload_old_android);
+                status = parentActivity.getString(R.string.upload_old_android);
                 break;
             case SYNC_CONFLICT:
-                status = mParentActivity.getString(R.string.upload_sync_conflict);
+                status = parentActivity.getString(R.string.upload_sync_conflict);
                 break;
             case CANNOT_CREATE_FILE:
-                status = mParentActivity.getString(R.string.upload_cannot_create_file);
+                status = parentActivity.getString(R.string.upload_cannot_create_file);
                 break;
             case LOCAL_STORAGE_NOT_COPIED:
-                status = mParentActivity.getString(R.string.upload_local_storage_not_copied);
+                status = parentActivity.getString(R.string.upload_local_storage_not_copied);
                 break;
             default:
-                status = mParentActivity.getString(R.string.upload_unknown_error);
+                status = parentActivity.getString(R.string.upload_unknown_error);
                 break;
         }
 
@@ -523,21 +564,20 @@ public class UploadListAdapter extends SectionedRecyclerViewAdapter<SectionedVie
     public void loadUploadItemsFromDb() {
         Log_OC.d(TAG, "loadUploadItemsFromDb");
 
-        for (UploadGroup group : mUploadGroups) {
+        for (UploadGroup group : uploadGroups) {
             group.refresh();
         }
 
         notifyDataSetChanged();
     }
 
-    private boolean onUploadItemClick(OCUpload file) {
+    private void onUploadItemClick(OCUpload file) {
         File f = new File(file.getLocalPath());
         if (!f.exists()) {
-            DisplayUtils.showSnackMessage(mParentActivity, R.string.local_file_not_found_message);
+            DisplayUtils.showSnackMessage(parentActivity, R.string.local_file_not_found_message);
         } else {
             openFileWithDefault(file.getLocalPath());
         }
-        return true;
     }
 
 
@@ -553,46 +593,60 @@ public class UploadListAdapter extends SectionedRecyclerViewAdapter<SectionedVie
         }
         myIntent.setDataAndType(Uri.fromFile(file), mimetype);
         try {
-            mParentActivity.startActivity(myIntent);
+            parentActivity.startActivity(myIntent);
         } catch (ActivityNotFoundException e) {
-            DisplayUtils.showSnackMessage(mParentActivity, R.string.file_list_no_app_for_file_type);
+            DisplayUtils.showSnackMessage(parentActivity, R.string.file_list_no_app_for_file_type);
             Log_OC.i(TAG, "Could not find app for sending log history.");
         }
     }
 
     static class HeaderViewHolder extends SectionedViewHolder {
-        private final TextView title;
+        @BindView(R.id.upload_list_title)
+        TextView title;
+
+        @BindView(R.id.upload_list_action)
+        ImageView action;
 
         HeaderViewHolder(View itemView) {
             super(itemView);
-            title = itemView.findViewById(R.id.upload_list_title);
+            ButterKnife.bind(this, itemView);
         }
     }
 
     static class ItemViewHolder extends SectionedViewHolder {
-        private TextView name;
-        private ImageView thumbnail;
-        private TextView fileSize;
-        private TextView date;
-        private TextView status;
-        private TextView account;
-        private TextView remotePath;
-        private ProgressBar progressBar;
-        private ImageButton button;
-        private LinearLayout itemLayout;
+        @BindView(R.id.upload_name)
+        TextView name;
+
+        @BindView(R.id.thumbnail)
+        ImageView thumbnail;
+
+        @BindView(R.id.upload_file_size)
+        TextView fileSize;
+
+        @BindView(R.id.upload_date)
+        TextView date;
+
+        @BindView(R.id.upload_status)
+        TextView status;
+
+        @BindView(R.id.upload_account)
+        TextView account;
+
+        @BindView(R.id.upload_remote_path)
+        TextView remotePath;
+
+        @BindView(R.id.upload_progress_bar)
+        ProgressBar progressBar;
+
+        @BindView(R.id.upload_right_button)
+        ImageButton button;
+
+        @BindView(R.id.upload_list_item_layout)
+        LinearLayout itemLayout;
 
         ItemViewHolder(View itemView) {
             super(itemView);
-            name = itemView.findViewById(R.id.upload_name);
-            thumbnail = itemView.findViewById(R.id.thumbnail);
-            fileSize = itemView.findViewById(R.id.upload_file_size);
-            date = itemView.findViewById(R.id.upload_date);
-            status = itemView.findViewById(R.id.upload_status);
-            account = itemView.findViewById(R.id.upload_account);
-            remotePath = itemView.findViewById(R.id.upload_remote_path);
-            progressBar = itemView.findViewById(R.id.upload_progress_bar);
-            button = itemView.findViewById(R.id.upload_right_button);
-            itemLayout = itemView.findViewById(R.id.upload_list_item_layout);
+            ButterKnife.bind(this, itemView);
         }
     }
 
@@ -600,11 +654,17 @@ public class UploadListAdapter extends SectionedRecyclerViewAdapter<SectionedVie
         void refresh();
     }
 
+    enum Type {
+        CURRENT, FINISHED, FAILED
+    }
+
     abstract class UploadGroup implements Refresh {
+        private Type type;
         private OCUpload[] items;
         private String name;
 
-        UploadGroup(String groupName) {
+        UploadGroup(Type type, String groupName) {
+            this.type = type;
             this.name = groupName;
             items = new OCUpload[0];
         }
@@ -626,7 +686,7 @@ public class UploadListAdapter extends SectionedRecyclerViewAdapter<SectionedVie
         }
 
         void fixAndSortItems(OCUpload... array) {
-            FileUploader.FileUploaderBinder binder = mParentActivity.getFileUploaderBinder();
+            FileUploader.FileUploaderBinder binder = parentActivity.getFileUploaderBinder();
 
             for (OCUpload upload : array) {
                 upload.setDataFixed(binder);
@@ -640,7 +700,7 @@ public class UploadListAdapter extends SectionedRecyclerViewAdapter<SectionedVie
             return items == null ? 0 : items.length;
         }
 
-        public Comparator<OCUpload> comparator = new Comparator<OCUpload>() {
+        Comparator<OCUpload> comparator = new Comparator<OCUpload>() {
             @Override
             public int compare(OCUpload upload1, OCUpload upload2) {
                 if (upload1 == null && upload2 == null) {

+ 8 - 0
src/main/res/drawable/ic_close.xml

@@ -0,0 +1,8 @@
+<!-- drawable/close.xml -->
+<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="M19,6.41L17.59,5L12,10.59L6.41,5L5,6.41L10.59,12L5,17.59L6.41,19L12,13.41L17.59,19L19,17.59L13.41,12L19,6.41Z" />
+</vector>

+ 8 - 0
src/main/res/drawable/ic_sync.xml

@@ -0,0 +1,8 @@
+<!-- drawable/sync.xml -->
+<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,18A6,6 0 0,1 6,12C6,11 6.25,10.03 6.7,9.2L5.24,7.74C4.46,8.97 4,10.43 4,12A8,8 0 0,0 12,20V23L16,19L12,15M12,4V1L8,5L12,9V6A6,6 0 0,1 18,12C18,13 17.75,13.97 17.3,14.8L18.76,16.26C19.54,15.03 20,13.57 20,12A8,8 0 0,0 12,4Z" />
+</vector>

+ 22 - 4
src/main/res/layout/upload_list_header.xml

@@ -21,21 +21,39 @@
   License along with this program.  If not, see <http://www.gnu.org/licenses/>.
 -->
 
-<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
+<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
     xmlns:tools="http://schemas.android.com/tools"
     android:id="@+id/ListItemLayout"
     android:layout_width="match_parent"
     android:layout_height="wrap_content"
-    android:orientation="horizontal"
-    android:padding="@dimen/standard_half_padding">
+    android:orientation="horizontal">
 
     <TextView
         android:id="@+id/upload_list_title"
         style="@style/TextAppearance.AppCompat.Body2"
         android:layout_width="wrap_content"
         android:layout_height="wrap_content"
+        android:layout_alignParentStart="true"
+        android:layout_alignParentLeft="true"
+        android:layout_toStartOf="@id/upload_list_action"
+        android:layout_toLeftOf="@id/upload_list_action"
         android:ellipsize="middle"
+        android:padding="@dimen/standard_half_padding"
         android:textColor="@color/color_accent"
         tools:text="Current (2)" />
 
-</LinearLayout>
+    <ImageView
+        android:id="@+id/upload_list_action"
+        android:layout_width="wrap_content"
+        android:layout_height="wrap_content"
+        android:layout_alignParentEnd="true"
+        android:layout_alignParentRight="true"
+        android:contentDescription="@string/delete_entries"
+        android:paddingStart="@dimen/standard_half_padding"
+        android:paddingLeft="@dimen/standard_half_padding"
+        android:paddingTop="@dimen/standard_half_padding"
+        android:paddingEnd="@dimen/zero"
+        android:paddingRight="@dimen/zero"
+        android:paddingBottom="@dimen/standard_half_padding"
+        android:src="@drawable/nav_trashbin" />
+</RelativeLayout>

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

@@ -143,7 +143,7 @@
             android:id="@+id/upload_right_button"
             android:layout_width="@dimen/upload_list_item_image_size"
             android:layout_height="@dimen/upload_list_item_image_size"
-            android:layout_gravity="center"
+            android:layout_gravity="center|end"
             android:background="@android:color/transparent"
             android:contentDescription="@string/upload_item_action_button" />
     </FrameLayout>

+ 4 - 20
src/main/res/menu/upload_list_menu.xml

@@ -1,6 +1,5 @@
-<?xml version="1.0" encoding="utf-8"?>
-<!--
-  ownCloud Android client application
+<?xml version="1.0" encoding="utf-8"?><!--
+  Nextcloud Android client application
 
   Copyright (C) 2012  Bartek Przybylski
   Copyright (C) 2012-2013 ownCloud Inc.
@@ -22,23 +21,8 @@
         android:id="@+id/upload_list_actions"
         android:checkableBehavior="none">
 
-        <item
-            android:id="@+id/action_retry_uploads"
-            android:title="@string/action_retry_uploads"/>
         <item
             android:id="@+id/action_clear_failed_uploads"
-            android:title="@string/action_clear_failed_uploads"/>
-
-        <item
-            android:id="@+id/action_clear_successfull_uploads"
-            android:title="@string/action_clear_successful_uploads"/>
-    </group>
-    <group
-        android:id="@+id/upload_list_force_scan"
-        android:checkableBehavior="none">
-
-        <item
-            android:id="@+id/action_force_rescan"
-            android:title="@string/action_force_rescan"/>
+            android:title="@string/action_clear_failed_uploads" />
     </group>
-</menu>
+</menu>

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

@@ -82,7 +82,7 @@
     <dimen name="scroll_view_height">180dp</dimen>
     <dimen name="upload_list_item_frame_layout_width">60dp</dimen>
     <dimen name="upload_list_item_text_size">12sp</dimen>
-    <dimen name="upload_list_item_image_size">35dp</dimen>
+    <dimen name="upload_list_item_image_size">24dp</dimen>
     <dimen name="uploader_list_item_layout_image_margin">12dp</dimen>
     <dimen name="media_grid_spacing">2dp</dimen>
     <dimen name="account_item_layout_user_image_left_start_margin">12dp</dimen>
@@ -138,7 +138,6 @@
     <dimen name="toolbar_user_information_layout_margin">12dp</dimen>
     <dimen name="bottom_sheet_text_size">16sp</dimen>
     <dimen name="permission_dialog_text_size">18sp</dimen>
-    <dimen name="permission_dialog_text_padding">56dp</dimen>
     <dimen name="button_corner_radius">24dp</dimen>
     <integer name="media_grid_width">4</integer>
 </resources>

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

@@ -513,10 +513,7 @@
     <string name="share_privilege_can_edit_change">can change</string>
     <string name="share_privilege_can_edit_delete">can delete</string>
 
-    <string name="action_retry_uploads">Retry failed uploads</string>
     <string name="action_clear_failed_uploads">Clear failed uploads</string>
-    <string name="action_clear_successful_uploads">Clear successful uploads</string>
-    <string name="action_force_rescan">Force rescan</string>
 
     <string name="action_switch_grid_view">Grid view</string>
     <string name="action_switch_list_view">List view</string>
@@ -857,4 +854,5 @@
     <string name="upload_sync_conflict">Sync conflict, please resolve manually</string>
     <string name="upload_cannot_create_file">Cannot create local file</string>
     <string name="upload_local_storage_not_copied">File could not be copied to local storage</string>
+    <string name="delete_entries">Delete entries</string>
 </resources>