Эх сурвалжийг харах

show/hide auto upload list items

Signed-off-by: Andy Scherzinger <info@andy-scherzinger.de>
Andy Scherzinger 5 жил өмнө
parent
commit
23e44243da

+ 14 - 13
src/main/java/com/owncloud/android/datamodel/SyncedFolder.java

@@ -23,14 +23,12 @@ package com.owncloud.android.datamodel;
 
 import java.io.Serializable;
 
-import lombok.AllArgsConstructor;
 import lombok.Getter;
 import lombok.Setter;
 
 /**
  * Synced folder entity containing all information per synced folder.
  */
-@AllArgsConstructor
 public class SyncedFolder implements Serializable, Cloneable {
     public static final long UNPERSISTED_ID = Long.MIN_VALUE;
     public static final long EMPTY_ENABLED_TIMESTAMP_MS = -1;
@@ -39,14 +37,15 @@ public class SyncedFolder implements Serializable, Cloneable {
     @Getter @Setter private long id;
     @Getter @Setter private String localPath;
     @Getter @Setter private String remotePath;
-    @Getter @Setter private Boolean wifiOnly;
-    @Getter @Setter private Boolean chargingOnly;
-    @Getter @Setter private Boolean subfolderByDate;
+    @Getter @Setter private boolean wifiOnly;
+    @Getter @Setter private boolean chargingOnly;
+    @Getter @Setter private boolean subfolderByDate;
     @Getter @Setter private String account;
-    @Getter @Setter private Integer uploadAction;
+    @Getter @Setter private int uploadAction;
     @Getter private boolean enabled;
     @Getter private long enabledTimestampMs;
     @Getter @Setter private MediaFolderType type;
+    @Getter @Setter private boolean hidden;
 
     /**
      * constructor for new, to be persisted entity.
@@ -61,12 +60,13 @@ public class SyncedFolder implements Serializable, Cloneable {
      * @param enabled         flag if synced folder config is active
      * @param timestampMs     the current timestamp in milliseconds
      * @param type            the type of the folder
+     * @param hidden          hide item flag
      */
-    public SyncedFolder(String localPath, String remotePath, Boolean wifiOnly, Boolean chargingOnly,
-                        Boolean subfolderByDate, String account, Integer uploadAction, Boolean enabled,
-                        long timestampMs, MediaFolderType type) {
+    public SyncedFolder(String localPath, String remotePath, boolean wifiOnly, boolean chargingOnly,
+                        boolean subfolderByDate, String account, int uploadAction, boolean enabled,
+                        long timestampMs, MediaFolderType type, boolean hidden) {
         this(UNPERSISTED_ID, localPath, remotePath, wifiOnly, chargingOnly, subfolderByDate, account, uploadAction,
-             enabled, timestampMs, type);
+             enabled, timestampMs, type, hidden);
     }
 
     /**
@@ -74,9 +74,9 @@ public class SyncedFolder implements Serializable, Cloneable {
      *
      * @param id id
      */
-    protected SyncedFolder(long id, String localPath, String remotePath, Boolean wifiOnly, Boolean chargingOnly,
-                           Boolean subfolderByDate, String account, Integer uploadAction, Boolean enabled,
-                           long timestampMs, MediaFolderType type) {
+    protected SyncedFolder(long id, String localPath, String remotePath, boolean wifiOnly, boolean chargingOnly,
+                           boolean subfolderByDate, String account, int uploadAction, boolean enabled,
+                           long timestampMs, MediaFolderType type, boolean hidden) {
         this.id = id;
         this.localPath = localPath;
         this.remotePath = remotePath;
@@ -87,6 +87,7 @@ public class SyncedFolder implements Serializable, Cloneable {
         this.uploadAction = uploadAction;
         this.setEnabled(enabled, timestampMs);
         this.type = type;
+        this.hidden = hidden;
     }
 
     /**

+ 9 - 8
src/main/java/com/owncloud/android/datamodel/SyncedFolderDisplayItem.java

@@ -53,24 +53,25 @@ public class SyncedFolderDisplayItem extends SyncedFolder {
      * @param folderName      the UI info for the folder's name
      * @param numberOfFiles   the UI info for number of files within the folder
      * @param type            the type of the folder
+     * @param hidden          hide item flag
      */
-    public SyncedFolderDisplayItem(long id, String localPath, String remotePath, Boolean wifiOnly, Boolean chargingOnly,
-                                   Boolean subfolderByDate, String account, Integer uploadAction, Boolean enabled,
+    public SyncedFolderDisplayItem(long id, String localPath, String remotePath, boolean wifiOnly, boolean chargingOnly,
+                                   boolean subfolderByDate, String account, int uploadAction, boolean enabled,
                                    long timestampMs, List<String> filePaths, String folderName, long numberOfFiles,
-                                   MediaFolderType type)
+                                   MediaFolderType type, boolean hidden)
     {
         super(id, localPath, remotePath, wifiOnly, chargingOnly, subfolderByDate, account, uploadAction, enabled,
-              timestampMs, type);
+              timestampMs, type, hidden);
         this.filePaths = filePaths;
         this.folderName = folderName;
         this.numberOfFiles = numberOfFiles;
     }
 
-    public SyncedFolderDisplayItem(long id, String localPath, String remotePath, Boolean wifiOnly, Boolean chargingOnly,
-                                   Boolean subfolderByDate, String account, Integer uploadAction, Boolean enabled,
-                                   long timestampMs, String folderName, MediaFolderType type) {
+    public SyncedFolderDisplayItem(long id, String localPath, String remotePath, boolean wifiOnly, boolean chargingOnly,
+                                   boolean subfolderByDate, String account, int uploadAction, boolean enabled,
+                                   long timestampMs, String folderName, MediaFolderType type, boolean hidden) {
         super(id, localPath, remotePath, wifiOnly, chargingOnly, subfolderByDate, account, uploadAction, enabled,
-              timestampMs, type);
+              timestampMs, type, hidden);
         this.folderName = folderName;
     }
 }

+ 4 - 1
src/main/java/com/owncloud/android/datamodel/SyncedFolderProvider.java

@@ -354,9 +354,11 @@ public class SyncedFolderProvider extends Observable {
                     ProviderMeta.ProviderTableMeta.SYNCED_FOLDER_ENABLED_TIMESTAMP_MS));
             MediaFolderType type = MediaFolderType.getById(cursor.getInt(cursor.getColumnIndex(
                     ProviderMeta.ProviderTableMeta.SYNCED_FOLDER_TYPE)));
+            Boolean hidden = cursor.getInt(cursor.getColumnIndex(
+                ProviderMeta.ProviderTableMeta.SYNCED_FOLDER_HIDDEN)) == 1;
 
             syncedFolder = new SyncedFolder(id, localPath, remotePath, wifiOnly, chargingOnly, subfolderByDate,
-                    accountName, uploadAction, enabled, enabledTimestampMs, type);
+                    accountName, uploadAction, enabled, enabledTimestampMs, type, hidden);
         }
         return syncedFolder;
     }
@@ -380,6 +382,7 @@ public class SyncedFolderProvider extends Observable {
         cv.put(ProviderMeta.ProviderTableMeta.SYNCED_FOLDER_ACCOUNT, syncedFolder.getAccount());
         cv.put(ProviderMeta.ProviderTableMeta.SYNCED_FOLDER_UPLOAD_ACTION, syncedFolder.getUploadAction());
         cv.put(ProviderMeta.ProviderTableMeta.SYNCED_FOLDER_TYPE, syncedFolder.getType().getId());
+        cv.put(ProviderMeta.ProviderTableMeta.SYNCED_FOLDER_HIDDEN, syncedFolder.getHidden());
 
         return cv;
     }

+ 2 - 1
src/main/java/com/owncloud/android/db/ProviderMeta.java

@@ -31,7 +31,7 @@ import com.owncloud.android.MainApp;
  */
 public class ProviderMeta {
     public static final String DB_NAME = "filelist";
-    public static final int DB_VERSION = 50;
+    public static final int DB_VERSION = 51;
 
     private ProviderMeta() {
         // No instance
@@ -225,6 +225,7 @@ public class ProviderMeta {
         public static final String SYNCED_FOLDER_SUBFOLDER_BY_DATE = "subfolder_by_date";
         public static final String SYNCED_FOLDER_ACCOUNT = "account";
         public static final String SYNCED_FOLDER_UPLOAD_ACTION = "upload_option";
+        public static final String SYNCED_FOLDER_HIDDEN = "hidden";
 
         // Columns of external links table
         public static final String EXTERNAL_LINKS_ICON_URL = "icon_url";

+ 26 - 1
src/main/java/com/owncloud/android/providers/FileContentProvider.java

@@ -833,7 +833,8 @@ public class FileContentProvider extends ContentProvider {
                        + ProviderTableMeta.SYNCED_FOLDER_SUBFOLDER_BY_DATE + " INTEGER, " // subfolder by date
                        + ProviderTableMeta.SYNCED_FOLDER_ACCOUNT + "  TEXT, "             // account
                        + ProviderTableMeta.SYNCED_FOLDER_UPLOAD_ACTION + " INTEGER, "     // upload action
-                       + ProviderTableMeta.SYNCED_FOLDER_TYPE + " INTEGER );"             // type
+                       + ProviderTableMeta.SYNCED_FOLDER_TYPE + " INTEGER, "              // type
+                       + ProviderTableMeta.SYNCED_FOLDER_HIDDEN + " INTEGER );"           // hidden
         );
     }
 
@@ -2045,6 +2046,24 @@ public class FileContentProvider extends ContentProvider {
             if (!upgraded) {
                 Log_OC.i(SQL, String.format(Locale.ENGLISH, UPGRADE_VERSION_MSG, oldVersion, newVersion));
             }
+
+            if (oldVersion < 51 && newVersion >= 51) {
+                Log_OC.i(SQL, "Entering in the #51 add show/hide to folderSync table");
+                db.beginTransaction();
+                try {
+                    db.execSQL(ALTER_TABLE + ProviderTableMeta.SYNCED_FOLDERS_TABLE_NAME +
+                                   ADD_COLUMN + ProviderTableMeta.SYNCED_FOLDER_HIDDEN + " INTEGER ");
+
+                    upgraded = true;
+                    db.setTransactionSuccessful();
+                } finally {
+                    db.endTransaction();
+                }
+            }
+
+            if (!upgraded) {
+                Log_OC.i(SQL, String.format(Locale.ENGLISH, UPGRADE_VERSION_MSG, oldVersion, newVersion));
+            }
         }
 
         @Override
@@ -2057,6 +2076,12 @@ public class FileContentProvider extends ContentProvider {
                 db.execSQL(ALTER_TABLE + ProviderTableMeta.CAPABILITIES_TABLE_NAME +
                                REMOVE_COLUMN + ProviderTableMeta.CAPABILITIES_END_TO_END_ENCRYPTION);
             }
+
+            if(oldVersion == 50 && newVersion < 50) {
+                db.execSQL(ALTER_TABLE + ProviderTableMeta.SYNCED_FOLDERS_TABLE_NAME +
+                               REMOVE_COLUMN + ProviderTableMeta.SYNCED_FOLDER_HIDDEN);
+
+            }
         }
     }
 }

+ 68 - 40
src/main/java/com/owncloud/android/ui/activity/SyncedFoldersActivity.java

@@ -50,6 +50,7 @@ import com.nextcloud.java.util.Optional;
 import com.owncloud.android.BuildConfig;
 import com.owncloud.android.MainApp;
 import com.owncloud.android.R;
+import com.owncloud.android.datamodel.ArbitraryDataProvider;
 import com.owncloud.android.datamodel.MediaFolder;
 import com.owncloud.android.datamodel.MediaFolderType;
 import com.owncloud.android.datamodel.MediaProvider;
@@ -382,9 +383,9 @@ public class SyncedFoldersActivity extends FileActivity implements SyncedFolderA
                 syncedFolder.getId(),
                 syncedFolder.getLocalPath(),
                 syncedFolder.getRemotePath(),
-                syncedFolder.getWifiOnly(),
-                syncedFolder.getChargingOnly(),
-                syncedFolder.getSubfolderByDate(),
+                syncedFolder.isWifiOnly(),
+                syncedFolder.isChargingOnly(),
+                syncedFolder.isSubfolderByDate(),
                 syncedFolder.getAccount(),
                 syncedFolder.getUploadAction(),
                 syncedFolder.isEnabled(),
@@ -392,7 +393,8 @@ public class SyncedFoldersActivity extends FileActivity implements SyncedFolderA
                 filePaths,
                 localFolder.getName(),
                 files.length,
-                syncedFolder.getType());
+                syncedFolder.getType(),
+                syncedFolder.isHidden());
     }
 
     /**
@@ -408,9 +410,9 @@ public class SyncedFoldersActivity extends FileActivity implements SyncedFolderA
                 syncedFolder.getId(),
                 syncedFolder.getLocalPath(),
                 syncedFolder.getRemotePath(),
-                syncedFolder.getWifiOnly(),
-                syncedFolder.getChargingOnly(),
-                syncedFolder.getSubfolderByDate(),
+                syncedFolder.isWifiOnly(),
+                syncedFolder.isChargingOnly(),
+                syncedFolder.isSubfolderByDate(),
                 syncedFolder.getAccount(),
                 syncedFolder.getUploadAction(),
                 syncedFolder.isEnabled(),
@@ -418,7 +420,8 @@ public class SyncedFoldersActivity extends FileActivity implements SyncedFolderA
                 mediaFolder.filePaths,
                 mediaFolder.folderName,
                 mediaFolder.numberOfFiles,
-                mediaFolder.type);
+                mediaFolder.type,
+                syncedFolder.isHidden());
     }
 
     /**
@@ -443,7 +446,8 @@ public class SyncedFoldersActivity extends FileActivity implements SyncedFolderA
                 mediaFolder.filePaths,
                 mediaFolder.folderName,
                 mediaFolder.numberOfFiles,
-                mediaFolder.type);
+                mediaFolder.type,
+                false);
     }
 
     private File[] getFileList(File localFolder) {
@@ -523,8 +527,8 @@ public class SyncedFoldersActivity extends FileActivity implements SyncedFolderA
                 Log.d(TAG, "Show custom folder dialog");
                 SyncedFolderDisplayItem emptyCustomFolder = new SyncedFolderDisplayItem(
                     SyncedFolder.UNPERSISTED_ID, null, null, true, false,
-                    false, getAccount().name,
-                    FileUploader.LOCAL_BEHAVIOUR_FORGET, false, clock.getCurrentTime(), null, MediaFolderType.CUSTOM);
+                    false, getAccount().name, FileUploader.LOCAL_BEHAVIOUR_FORGET, false,
+                    clock.getCurrentTime(), null, MediaFolderType.CUSTOM, false);
                 onSyncFolderSettingsClick(0, emptyCustomFolder);
             }
 
@@ -581,6 +585,14 @@ public class SyncedFoldersActivity extends FileActivity implements SyncedFolderA
         mSyncedFolderPreferencesDialogFragment.show(ft, SYNCED_FOLDER_PREFERENCES_DIALOG_TAG);
     }
 
+    @Override
+    public void onVisibilityToggleClick(int section, SyncedFolderDisplayItem syncedFolder) {
+        syncedFolder.setHidden(!syncedFolder.isHidden());
+
+        saveOrUpdateSyncedFolder(syncedFolder);
+        mAdapter.setSyncFolderItem(section, syncedFolder);
+    }
+
     @Override
     protected void onActivityResult(int requestCode, int resultCode, Intent data) {
         if (requestCode == SyncedFolderPreferencesDialogFragment.REQUEST_CODE__SELECT_REMOTE_FOLDER
@@ -606,39 +618,21 @@ public class SyncedFoldersActivity extends FileActivity implements SyncedFolderA
                     SyncedFolder.UNPERSISTED_ID, syncedFolder.getLocalPath(), syncedFolder.getRemotePath(),
                     syncedFolder.getWifiOnly(), syncedFolder.getChargingOnly(), syncedFolder.getSubfolderByDate(),
                     syncedFolder.getAccount(), syncedFolder.getUploadAction(), syncedFolder.getEnabled(),
-                    clock.getCurrentTime(), new File(syncedFolder.getLocalPath()).getName(), syncedFolder.getType());
-            long storedId = mSyncedFolderProvider.storeSyncedFolder(newCustomFolder);
-            if (storedId != -1) {
-                newCustomFolder.setId(storedId);
-                if (newCustomFolder.isEnabled()) {
-                    FilesSyncHelper.insertAllDBEntriesForSyncedFolder(newCustomFolder);
-                }
-            }
+                    clock.getCurrentTime(), new File(syncedFolder.getLocalPath()).getName(), syncedFolder.getType(), syncedFolder.getHidden());
+
+            saveOrUpdateSyncedFolder(newCustomFolder);
             mAdapter.addSyncFolderItem(newCustomFolder);
         } else {
             SyncedFolderDisplayItem item = mAdapter.get(syncedFolder.getSection());
-            item = updateSyncedFolderItem(item, syncedFolder.getLocalPath(), syncedFolder.getRemotePath(), syncedFolder
+            updateSyncedFolderItem(item, syncedFolder.getId(), syncedFolder.getLocalPath(),
+                                   syncedFolder.getRemotePath(), syncedFolder
                     .getWifiOnly(), syncedFolder.getChargingOnly(), syncedFolder.getSubfolderByDate(), syncedFolder
                     .getUploadAction(), syncedFolder.getEnabled());
 
-            if (syncedFolder.getId() == UNPERSISTED_ID) {
-                // newly set up folder sync config
-                long storedId = mSyncedFolderProvider.storeSyncedFolder(item);
-                if (storedId != -1) {
-                    item.setId(storedId);
-                    if (item.isEnabled()) {
-                        FilesSyncHelper.insertAllDBEntriesForSyncedFolder(item);
-                    }
-                }
-            } else {
-                // existing synced folder setup to be updated
-                mSyncedFolderProvider.updateSyncFolder(item);
-                if (item.isEnabled()) {
-                    FilesSyncHelper.insertAllDBEntriesForSyncedFolder(item);
-                }
-            }
+            saveOrUpdateSyncedFolder(item);
 
-            mAdapter.setSyncFolderItem(syncedFolder.getSection(), item);
+            // TODO test if notifiyItemChanged is suffiecient (should improve performance)
+            mAdapter.notifyDataSetChanged();
         }
 
         mSyncedFolderPreferencesDialogFragment = null;
@@ -648,6 +642,40 @@ public class SyncedFoldersActivity extends FileActivity implements SyncedFolderA
         }
     }
 
+    private void saveOrUpdateSyncedFolder(SyncedFolderDisplayItem item) {
+        if (item.getId() == UNPERSISTED_ID) {
+            // newly set up folder sync config
+            storeSyncedFolder(item);
+        } else {
+            // existing synced folder setup to be updated
+            mSyncedFolderProvider.updateSyncFolder(item);
+            if (item.isEnabled()) {
+                FilesSyncHelper.insertAllDBEntriesForSyncedFolder(item);
+            } else {
+                String syncedFolderInitiatedKey = "syncedFolderIntitiated_" + item.getId();
+
+                ArbitraryDataProvider arbitraryDataProvider = new ArbitraryDataProvider(MainApp.getAppContext().
+                    getContentResolver());
+                arbitraryDataProvider.deleteKeyForAccount("global", syncedFolderInitiatedKey);
+            }
+        }
+    }
+
+    private void storeSyncedFolder(SyncedFolderDisplayItem item) {
+        ArbitraryDataProvider arbitraryDataProvider = new ArbitraryDataProvider(MainApp.getAppContext().
+            getContentResolver());
+        long storedId = mSyncedFolderProvider.storeSyncedFolder(item);
+        if (storedId != -1) {
+            item.setId(storedId);
+            if (item.isEnabled()) {
+                FilesSyncHelper.insertAllDBEntriesForSyncedFolder(item);
+            } else {
+                String syncedFolderInitiatedKey = "syncedFolderIntitiated_" + item.getId();
+                arbitraryDataProvider.deleteKeyForAccount("global", syncedFolderInitiatedKey);
+            }
+        }
+    }
+
     @Override
     public void onCancelSyncedFolderPreference() {
         mSyncedFolderPreferencesDialogFragment = null;
@@ -670,9 +698,9 @@ public class SyncedFoldersActivity extends FileActivity implements SyncedFolderA
      * @param subfolderByDate created sub folders
      * @param uploadAction    upload action
      * @param enabled         is sync enabled
-     * @return the updated item
      */
-    private SyncedFolderDisplayItem updateSyncedFolderItem(SyncedFolderDisplayItem item,
+    private void updateSyncedFolderItem(SyncedFolderDisplayItem item,
+                                                           long id,
                                                            String localPath,
                                                            String remotePath,
                                                            Boolean wifiOnly,
@@ -680,6 +708,7 @@ public class SyncedFoldersActivity extends FileActivity implements SyncedFolderA
                                                            Boolean subfolderByDate,
                                                            Integer uploadAction,
                                                            Boolean enabled) {
+        item.setId(id);
         item.setLocalPath(localPath);
         item.setRemotePath(remotePath);
         item.setWifiOnly(wifiOnly);
@@ -687,7 +716,6 @@ public class SyncedFoldersActivity extends FileActivity implements SyncedFolderA
         item.setSubfolderByDate(subfolderByDate);
         item.setUploadAction(uploadAction);
         item.setEnabled(enabled, clock.getCurrentTime());
-        return item;
     }
 
     @Override

+ 235 - 71
src/main/java/com/owncloud/android/ui/adapter/SyncedFolderAdapter.java

@@ -23,11 +23,14 @@ package com.owncloud.android.ui.adapter;
 
 import android.content.Context;
 import android.view.LayoutInflater;
+import android.view.MenuItem;
 import android.view.View;
 import android.view.ViewGroup;
+import android.widget.FrameLayout;
 import android.widget.ImageButton;
 import android.widget.ImageView;
 import android.widget.LinearLayout;
+import android.widget.PopupMenu;
 import android.widget.RelativeLayout;
 import android.widget.TextView;
 
@@ -54,64 +57,167 @@ import butterknife.ButterKnife;
  */
 public class SyncedFolderAdapter extends SectionedRecyclerViewAdapter<SectionedViewHolder> {
 
-    private final Context mContext;
+    private final Context context;
     private final Clock clock;
-    private final int mGridWidth;
-    private final int mGridTotal;
-    private final ClickListener mListener;
-    private final List<SyncedFolderDisplayItem> mSyncFolderItems;
-    private final boolean mLight;
+    private final int gridWidth;
+    private final int gridTotal;
+    private final ClickListener clickListener;
+    private final List<SyncedFolderDisplayItem> syncFolderItems;
+    private final List<SyncedFolderDisplayItem> filteredSyncFolderItems;
+    private final boolean light;
+    private final int VIEW_TYPE_EMPTY = Integer.MAX_VALUE;
+    private boolean hideItems;
 
     public SyncedFolderAdapter(Context context, Clock clock, int gridWidth, ClickListener listener, boolean light) {
-        mContext = context;
+        this.context = context;
         this.clock = clock;
-        mGridWidth = gridWidth;
-        mGridTotal = gridWidth * 2;
-        mListener = listener;
-        mSyncFolderItems = new ArrayList<>();
-        mLight = light;
+        this.gridWidth = gridWidth;
+        gridTotal = gridWidth * 2;
+        clickListener = listener;
+        syncFolderItems = new ArrayList<>();
+        filteredSyncFolderItems = new ArrayList<>();
+        this.light = light;
+        this.hideItems = true;
 
         shouldShowHeadersForEmptySections(true);
+        shouldShowFooters(true);
+    }
+
+    private void toggleHiddenItemsVisibility() {
+        hideItems = !hideItems;
+        filteredSyncFolderItems.clear();
+        filteredSyncFolderItems.addAll(filterHiddenItems(syncFolderItems, hideItems));
+        notifyDataSetChanged();
     }
 
     public void setSyncFolderItems(List<SyncedFolderDisplayItem> syncFolderItems) {
-        mSyncFolderItems.clear();
-        mSyncFolderItems.addAll(syncFolderItems);
+        this.syncFolderItems.clear();
+        this.syncFolderItems.addAll(syncFolderItems);
+
+        this.filteredSyncFolderItems.clear();
+        this.filteredSyncFolderItems.addAll(filterHiddenItems(this.syncFolderItems, hideItems));
     }
 
     public void setSyncFolderItem(int location, SyncedFolderDisplayItem syncFolderItem) {
-        mSyncFolderItems.set(location, syncFolderItem);
+        // show all items OR
+        if (hideItems && syncFolderItem.isHidden() && filteredSyncFolderItems.contains(syncFolderItem)) {
+            filteredSyncFolderItems.remove(location);
+        } else {
+            if (filteredSyncFolderItems.contains(syncFolderItem)) {
+                filteredSyncFolderItems.set(filteredSyncFolderItems.indexOf(syncFolderItem), syncFolderItem);
+            } else {
+                filteredSyncFolderItems.add(syncFolderItem);
+            }
+        }
+
+        if (syncFolderItems.contains(syncFolderItem)) {
+            syncFolderItems.set(syncFolderItems.indexOf(syncFolderItem), syncFolderItem);
+        } else {
+            syncFolderItems.add(syncFolderItem);
+        }
+
         notifyDataSetChanged();
     }
 
     public void addSyncFolderItem(SyncedFolderDisplayItem syncFolderItem) {
-        mSyncFolderItems.add(syncFolderItem);
-        notifyDataSetChanged();
+        syncFolderItems.add(syncFolderItem);
+
+        // add item for display when either all items should be shown (!hideItems)
+        // or if items should be hi
+        if (!hideItems || !syncFolderItem.isHidden()) {
+            filteredSyncFolderItems.add(syncFolderItem);
+            notifyDataSetChanged();
+        }
     }
 
     public void removeItem(int section) {
-        mSyncFolderItems.remove(section);
-        notifyDataSetChanged();
+        if (filteredSyncFolderItems.contains(syncFolderItems.get(section))) {
+            filteredSyncFolderItems.remove(syncFolderItems.get(section));
+            notifyDataSetChanged();
+        }
+        syncFolderItems.remove(section);
+    }
+
+    /**
+     * Filter for hidden items
+     *
+     * @param items Collection of items to filter
+     * @return Non-hidden items
+     */
+    private List<SyncedFolderDisplayItem> filterHiddenItems(List<SyncedFolderDisplayItem> items, boolean hide) {
+        if (hide) {
+            List<SyncedFolderDisplayItem> ret = new ArrayList<>();
+
+            for (SyncedFolderDisplayItem item : items) {
+                if (!item.isHidden() && !ret.contains(item)) {
+                    ret.add(item);
+                }
+            }
+
+            return ret;
+        } else {
+            return items;
+        }
     }
 
     @Override
     public int getSectionCount() {
-        return mSyncFolderItems.size();
+        if (filteredSyncFolderItems.size() > 0) {
+            return filteredSyncFolderItems.size() + 1;
+        } else {
+            return 0;
+        }
     }
 
     @Override
     public int getItemCount(int section) {
-        List<String> filePaths = mSyncFolderItems.get(section).getFilePaths();
+        if (section < filteredSyncFolderItems.size()) {
+            List<String> filePaths = filteredSyncFolderItems.get(section).getFilePaths();
 
-        if (filePaths != null) {
-            return mSyncFolderItems.get(section).getFilePaths().size();
+            if (filePaths != null) {
+                return filteredSyncFolderItems.get(section).getFilePaths().size();
+            } else {
+                return 1;
+            }
         } else {
             return 1;
         }
     }
 
     public SyncedFolderDisplayItem get(int section) {
-        return mSyncFolderItems.get(section);
+        return filteredSyncFolderItems.get(section);
+    }
+
+    @Override
+    public int getItemViewType(int section, int relativePosition, int absolutePosition) {
+        if (isLastSection(section)) {
+            return VIEW_TYPE_EMPTY;
+        } else {
+            return VIEW_TYPE_ITEM;
+        }
+    }
+
+    @Override
+    public int getHeaderViewType(int section) {
+        if (isLastSection(section)) {
+            return VIEW_TYPE_EMPTY;
+        } else {
+            return VIEW_TYPE_HEADER;
+        }
+    }
+
+    @Override
+    public int getFooterViewType(int section) {
+        if (isLastSection(section) && showFooter()) {
+            return VIEW_TYPE_FOOTER;
+        } else {
+            // only show footer after last item and only if folders have been hidden
+            return VIEW_TYPE_EMPTY;
+        }
+    }
+
+    private boolean showFooter() {
+        return syncFolderItems.size() > filteredSyncFolderItems.size();
     }
 
     /**
@@ -122,9 +228,9 @@ public class SyncedFolderAdapter extends SectionedRecyclerViewAdapter<SectionedV
      * @return the section index of the looked up synced folder, <code>-1</code> if not present
      */
     public int getSectionByLocalPathAndType(String localPath, int type) {
-        for (int i = 0; i < mSyncFolderItems.size(); i++) {
-            if (mSyncFolderItems.get(i).getLocalPath().equalsIgnoreCase(localPath) &&
-                    mSyncFolderItems.get(i).getType().getId().equals(type)) {
+        for (int i = 0; i < filteredSyncFolderItems.size(); i++) {
+            if (filteredSyncFolderItems.get(i).getLocalPath().equalsIgnoreCase(localPath) &&
+                filteredSyncFolderItems.get(i).getType().getId().equals(type)) {
                 return i;
             }
         }
@@ -134,70 +240,95 @@ public class SyncedFolderAdapter extends SectionedRecyclerViewAdapter<SectionedV
 
     @Override
     public void onBindHeaderViewHolder(SectionedViewHolder commonHolder, final int section, boolean expanded) {
-        HeaderViewHolder holder = (HeaderViewHolder) commonHolder;
+        if (section < filteredSyncFolderItems.size()) {
+            HeaderViewHolder holder = (HeaderViewHolder) commonHolder;
+            holder.mainHeaderContainer.setVisibility(View.VISIBLE);
+
+            holder.title.setText(filteredSyncFolderItems.get(section).getFolderName());
+
+            if (MediaFolderType.VIDEO == filteredSyncFolderItems.get(section).getType()) {
+                holder.type.setImageResource(R.drawable.video_32dp);
+            } else if (MediaFolderType.IMAGE == filteredSyncFolderItems.get(section).getType()) {
+                holder.type.setImageResource(R.drawable.image_32dp);
+            } else {
+                holder.type.setImageResource(R.drawable.folder_star_32dp);
+            }
 
-        holder.mainHeaderContainer.setVisibility(View.VISIBLE);
+            holder.syncStatusButton.setVisibility(View.VISIBLE);
+            holder.syncStatusButton.setTag(section);
+            holder.syncStatusButton.setOnClickListener(v -> {
+                filteredSyncFolderItems.get(section).setEnabled(
+                    !filteredSyncFolderItems.get(section).isEnabled(),
+                    clock.getCurrentTime()
+                );
+                setSyncButtonActiveIcon(holder.syncStatusButton, filteredSyncFolderItems.get(section).isEnabled());
+                clickListener.onSyncStatusToggleClick(section, filteredSyncFolderItems.get(section));
+            });
+            setSyncButtonActiveIcon(holder.syncStatusButton, filteredSyncFolderItems.get(section).isEnabled());
+
+            if (light) {
+                holder.menuButton.setVisibility(View.GONE);
+            } else {
+                holder.menuButton.setVisibility(View.VISIBLE);
+                holder.menuButton.setTag(section);
+                holder.menuButton.setOnClickListener(v -> onOverflowIconClicked(section,
+                                                                                filteredSyncFolderItems.get(section),
+                                                                                v));
+            }
+        }
+    }
 
-        holder.title.setText(mSyncFolderItems.get(section).getFolderName());
+    private void onOverflowIconClicked(int section, SyncedFolderDisplayItem item, View view) {
+        PopupMenu popup = new PopupMenu(context, view);
+        popup.inflate(R.menu.synced_folders_adapter);
+        popup.setOnMenuItemClickListener(i -> optionsItemSelected(i,section,item));
 
-        if (MediaFolderType.VIDEO == mSyncFolderItems.get(section).getType()) {
-            holder.type.setImageResource(R.drawable.video_32dp);
-        } else if (MediaFolderType.IMAGE == mSyncFolderItems.get(section).getType()) {
-            holder.type.setImageResource(R.drawable.image_32dp);
+        if (item.isHidden()) {
+            popup.getMenu()
+                .findItem(R.id.action_auto_upload_folder_toggle_visibility)
+                .setTitle(R.string.autoupload_show_folder);
         } else {
-            holder.type.setImageResource(R.drawable.folder_star_32dp);
+            popup.getMenu()
+                .findItem(R.id.action_auto_upload_folder_toggle_visibility)
+                .setTitle(R.string.autoupload_hide_folder);
         }
+        popup.show();
+    }
 
-        holder.syncStatusButton.setVisibility(View.VISIBLE);
-        holder.syncStatusButton.setTag(section);
-        holder.syncStatusButton.setOnClickListener(v -> {
-            mSyncFolderItems.get(section).setEnabled(!mSyncFolderItems.get(section).isEnabled(), clock.getCurrentTime());
-            setSyncButtonActiveIcon(holder.syncStatusButton, mSyncFolderItems.get(section).isEnabled());
-            mListener.onSyncStatusToggleClick(section, mSyncFolderItems.get(section));
-        });
-        setSyncButtonActiveIcon(holder.syncStatusButton, mSyncFolderItems.get(section).isEnabled());
-
-        holder.syncStatusButton.setVisibility(View.VISIBLE);
-        holder.syncStatusButton.setTag(section);
-        holder.syncStatusButton.setOnClickListener(v -> {
-            mSyncFolderItems.get(section).setEnabled(!mSyncFolderItems.get(section).isEnabled(), clock.getCurrentTime());
-            setSyncButtonActiveIcon(holder.syncStatusButton, mSyncFolderItems.get(section).isEnabled());
-            mListener.onSyncStatusToggleClick(section, mSyncFolderItems.get(section));
-        });
-        setSyncButtonActiveIcon(holder.syncStatusButton, mSyncFolderItems.get(section).isEnabled());
-
-        if (mLight) {
-            holder.menuButton.setVisibility(View.GONE);
+    private boolean optionsItemSelected(MenuItem menuItem, int section, SyncedFolderDisplayItem item) {
+        if (menuItem.getItemId() == R.id.action_auto_upload_folder_toggle_visibility) {
+            clickListener.onVisibilityToggleClick(section, item);
         } else {
-            holder.menuButton.setVisibility(View.VISIBLE);
-            holder.menuButton.setTag(section);
-            holder.menuButton.setOnClickListener(v -> mListener.onSyncFolderSettingsClick(section,
-                    mSyncFolderItems.get(section)));
+            // default: R.id.action_create_custom_folder
+            clickListener.onSyncFolderSettingsClick(section, item);
         }
+        return true;
     }
 
     @Override
     public void onBindFooterViewHolder(SectionedViewHolder holder, int section) {
-        // not needed
+        if (isLastSection(section) && showFooter()) {
+            FooterViewHolder footerHolder = (FooterViewHolder) holder;
+            footerHolder.title.setOnClickListener(v -> toggleHiddenItemsVisibility());
+        }
     }
 
-
     @Override
     public void onBindViewHolder(SectionedViewHolder commonHolder, int section, int relativePosition,
                                  int absolutePosition) {
-        if (mSyncFolderItems.get(section).getFilePaths() != null) {
+        if (section < filteredSyncFolderItems.size() && filteredSyncFolderItems.get(section).getFilePaths() != null) {
             MainViewHolder holder = (MainViewHolder) commonHolder;
 
-            File file = new File(mSyncFolderItems.get(section).getFilePaths().get(relativePosition));
+            File file = new File(filteredSyncFolderItems.get(section).getFilePaths().get(relativePosition));
 
             ThumbnailsCacheManager.MediaThumbnailGenerationTask task =
-                    new ThumbnailsCacheManager.MediaThumbnailGenerationTask(holder.image, mContext);
+                    new ThumbnailsCacheManager.MediaThumbnailGenerationTask(holder.image, context);
 
             ThumbnailsCacheManager.AsyncMediaThumbnailDrawable asyncDrawable =
                     new ThumbnailsCacheManager.AsyncMediaThumbnailDrawable(
-                            mContext.getResources(),
-                            ThumbnailsCacheManager.mDefaultImg,
-                            task
+                        context.getResources(),
+                        ThumbnailsCacheManager.mDefaultImg,
+                        task
                     );
             holder.image.setImageDrawable(asyncDrawable);
 
@@ -206,11 +337,11 @@ public class SyncedFolderAdapter extends SectionedRecyclerViewAdapter<SectionedV
             // set proper tag
             holder.image.setTag(file.hashCode());
 
-            holder.itemView.setTag(relativePosition % mGridWidth);
+            holder.itemView.setTag(relativePosition % gridWidth);
 
-            if (mSyncFolderItems.get(section).getNumberOfFiles() > mGridTotal && relativePosition >= mGridTotal - 1) {
+            if (filteredSyncFolderItems.get(section).getNumberOfFiles() > gridTotal && relativePosition >= gridTotal - 1) {
                 holder.counterValue.setText(String.format(Locale.US, "%d",
-                    mSyncFolderItems.get(section).getNumberOfFiles() - mGridTotal));
+                                                          filteredSyncFolderItems.get(section).getNumberOfFiles() - gridTotal));
                 holder.counterBar.setVisibility(View.VISIBLE);
                 holder.thumbnailDarkener.setVisibility(View.VISIBLE);
             } else {
@@ -226,15 +357,26 @@ public class SyncedFolderAdapter extends SectionedRecyclerViewAdapter<SectionedV
         if (viewType == VIEW_TYPE_HEADER) {
             View v = LayoutInflater.from(parent.getContext()).inflate(R.layout.synced_folders_item_header, parent, false);
             return new HeaderViewHolder(v);
+        } else if (viewType == VIEW_TYPE_FOOTER) {
+            View v = LayoutInflater.from(parent.getContext()).inflate(R.layout.synced_folders_footer, parent, false);
+            return new FooterViewHolder(v);
+        } else if (viewType == VIEW_TYPE_EMPTY) {
+            View v = LayoutInflater.from(parent.getContext()).inflate(R.layout.synced_folders_empty, parent, false);
+            return new EmptyViewHolder(v);
         } else {
             View v = LayoutInflater.from(parent.getContext()).inflate(R.layout.grid_sync_item, parent, false);
             return new MainViewHolder(v);
         }
     }
 
+    private boolean isLastSection(int section) {
+        return section >= getSectionCount() - 1;
+    }
+
     public interface ClickListener {
         void onSyncStatusToggleClick(int section, SyncedFolderDisplayItem syncedFolderDisplayItem);
         void onSyncFolderSettingsClick(int section, SyncedFolderDisplayItem syncedFolderDisplayItem);
+        void onVisibilityToggleClick(int section, SyncedFolderDisplayItem item);
     }
 
     static class HeaderViewHolder extends SectionedViewHolder {
@@ -259,7 +401,29 @@ public class SyncedFolderAdapter extends SectionedRecyclerViewAdapter<SectionedV
         }
     }
 
+    static class FooterViewHolder extends SectionedViewHolder {
+        @BindView(R.id.footer_container)
+        public LinearLayout mainFooterContainer;
+
+        @BindView(R.id.footer_text)
+        public TextView title;
+
+        private FooterViewHolder(View itemView) {
+            super(itemView);
+            ButterKnife.bind(this, itemView);
+        }
+    }
+
+    static class EmptyViewHolder extends SectionedViewHolder {
+        private EmptyViewHolder(View itemView) {
+            super(itemView);
+        }
+    }
+
     static class MainViewHolder extends SectionedViewHolder {
+        @BindView(R.id.grid_item_container)
+        public FrameLayout item_container;
+
         @BindView(R.id.thumbnail)
         public ImageView image;
 
@@ -281,7 +445,7 @@ public class SyncedFolderAdapter extends SectionedRecyclerViewAdapter<SectionedV
     private void setSyncButtonActiveIcon(ImageButton syncStatusButton, boolean enabled) {
         if (enabled) {
             syncStatusButton.setImageDrawable(ThemeUtils.tintDrawable(R.drawable.ic_cloud_sync_on,
-                    ThemeUtils.primaryColor(mContext)));
+                    ThemeUtils.primaryColor(context)));
         } else {
             syncStatusButton.setImageResource(R.drawable.ic_cloud_sync_off);
         }

+ 90 - 78
src/main/java/com/owncloud/android/ui/dialog/parcel/SyncedFolderParcelable.java

@@ -34,63 +34,67 @@ import lombok.NoArgsConstructor;
  */
 @NoArgsConstructor
 public class SyncedFolderParcelable implements Parcelable {
-    private String mFolderName;
-    private String mLocalPath;
-    private String mRemotePath;
-    private Boolean mWifiOnly = false;
-    private Boolean mChargingOnly = false;
-    private Boolean mEnabled = false;
-    private Boolean mSubfolderByDate = false;
-    private Integer mUploadAction;
-    private MediaFolderType mType;
-    private long mId;
-    private String mAccount;
-    private int mSection;
+    private String folderName;
+    private String localPath;
+    private String remotePath;
+    private Boolean wifiOnly = false;
+    private Boolean chargingOnly = false;
+    private Boolean enabled = false;
+    private Boolean subfolderByDate = false;
+    private Integer uploadAction;
+    private MediaFolderType type;
+    private Boolean hidden = false;
+    private long id;
+    private String account;
+    private int section;
 
     public SyncedFolderParcelable(SyncedFolderDisplayItem syncedFolderDisplayItem, int section) {
-        mId = syncedFolderDisplayItem.getId();
-        mFolderName = syncedFolderDisplayItem.getFolderName();
-        mLocalPath = syncedFolderDisplayItem.getLocalPath();
-        mRemotePath = syncedFolderDisplayItem.getRemotePath();
-        mWifiOnly = syncedFolderDisplayItem.getWifiOnly();
-        mChargingOnly = syncedFolderDisplayItem.getChargingOnly();
-        mEnabled = syncedFolderDisplayItem.isEnabled();
-        mSubfolderByDate = syncedFolderDisplayItem.getSubfolderByDate();
-        mType = syncedFolderDisplayItem.getType();
-        mAccount = syncedFolderDisplayItem.getAccount();
-        mUploadAction = syncedFolderDisplayItem.getUploadAction();
-        mSection = section;
+        id = syncedFolderDisplayItem.getId();
+        folderName = syncedFolderDisplayItem.getFolderName();
+        localPath = syncedFolderDisplayItem.getLocalPath();
+        remotePath = syncedFolderDisplayItem.getRemotePath();
+        wifiOnly = syncedFolderDisplayItem.getWifiOnly();
+        chargingOnly = syncedFolderDisplayItem.getChargingOnly();
+        enabled = syncedFolderDisplayItem.isEnabled();
+        subfolderByDate = syncedFolderDisplayItem.getSubfolderByDate();
+        type = syncedFolderDisplayItem.getType();
+        account = syncedFolderDisplayItem.getAccount();
+        uploadAction = syncedFolderDisplayItem.getUploadAction();
+        this.section = section;
+        hidden = syncedFolderDisplayItem.getHidden();
     }
 
     private SyncedFolderParcelable(Parcel read) {
-        mId = read.readLong();
-        mFolderName = read.readString();
-        mLocalPath = read.readString();
-        mRemotePath = read.readString();
-        mWifiOnly = read.readInt()!= 0;
-        mChargingOnly = read.readInt() != 0;
-        mEnabled = read.readInt() != 0;
-        mSubfolderByDate = read.readInt() != 0;
-        mType = MediaFolderType.getById(read.readInt());
-        mAccount = read.readString();
-        mUploadAction = read.readInt();
-        mSection = read.readInt();
+        id = read.readLong();
+        folderName = read.readString();
+        localPath = read.readString();
+        remotePath = read.readString();
+        wifiOnly = read.readInt()!= 0;
+        chargingOnly = read.readInt() != 0;
+        enabled = read.readInt() != 0;
+        subfolderByDate = read.readInt() != 0;
+        type = MediaFolderType.getById(read.readInt());
+        account = read.readString();
+        uploadAction = read.readInt();
+        section = read.readInt();
+        hidden = read.readInt() != 0;
     }
 
     @Override
     public void writeToParcel(Parcel dest, int flags) {
-        dest.writeLong(mId);
-        dest.writeString(mFolderName);
-        dest.writeString(mLocalPath);
-        dest.writeString(mRemotePath);
-        dest.writeInt(mWifiOnly ? 1 : 0);
-        dest.writeInt(mChargingOnly ? 1 : 0);
-        dest.writeInt(mEnabled ? 1 : 0);
-        dest.writeInt(mSubfolderByDate ? 1 : 0);
-        dest.writeInt(mType.getId());
-        dest.writeString(mAccount);
-        dest.writeInt(mUploadAction);
-        dest.writeInt(mSection);
+        dest.writeLong(id);
+        dest.writeString(folderName);
+        dest.writeString(localPath);
+        dest.writeString(remotePath);
+        dest.writeInt(wifiOnly ? 1 : 0);
+        dest.writeInt(chargingOnly ? 1 : 0);
+        dest.writeInt(enabled ? 1 : 0);
+        dest.writeInt(subfolderByDate ? 1 : 0);
+        dest.writeInt(type.getId());
+        dest.writeString(account);
+        dest.writeInt(uploadAction);
+        dest.writeInt(section);
+        dest.writeInt(hidden ? 1 : 0);
     }
 
     public static final Creator<SyncedFolderParcelable> CREATOR =
@@ -113,75 +117,83 @@ public class SyncedFolderParcelable implements Parcelable {
     }
 
     public String getFolderName() {
-        return mFolderName;
+        return folderName;
     }
 
     public void setFolderName(String mFolderName) {
-        this.mFolderName = mFolderName;
+        this.folderName = mFolderName;
     }
 
     public String getLocalPath() {
-        return mLocalPath;
+        return localPath;
     }
 
     public void setLocalPath(String mLocalPath) {
-        this.mLocalPath = mLocalPath;
+        this.localPath = mLocalPath;
     }
 
     public String getRemotePath() {
-        return mRemotePath;
+        return remotePath;
     }
 
     public void setRemotePath(String mRemotePath) {
-        this.mRemotePath = mRemotePath;
+        this.remotePath = mRemotePath;
     }
 
     public Boolean getWifiOnly() {
-        return mWifiOnly;
+        return wifiOnly;
     }
 
     public void setWifiOnly(Boolean mWifiOnly) {
-        this.mWifiOnly = mWifiOnly;
+        this.wifiOnly = mWifiOnly;
     }
 
     public Boolean getChargingOnly() {
-        return mChargingOnly;
+        return chargingOnly;
     }
 
     public void setChargingOnly(Boolean mChargingOnly) {
-        this.mChargingOnly = mChargingOnly;
+        this.chargingOnly = mChargingOnly;
     }
 
     public Boolean getEnabled() {
-        return mEnabled;
+        return enabled;
     }
 
     public void setEnabled(boolean mEnabled) {
-        this.mEnabled = mEnabled;
+        this.enabled = mEnabled;
     }
 
     public Boolean getSubfolderByDate() {
-        return mSubfolderByDate;
+        return subfolderByDate;
     }
 
     public void setSubfolderByDate(Boolean mSubfolderByDate) {
-        this.mSubfolderByDate = mSubfolderByDate;
+        this.subfolderByDate = mSubfolderByDate;
     }
 
     public MediaFolderType getType() {
-        return mType;
+        return type;
     }
 
     public void setType(MediaFolderType mType) {
-        this.mType = mType;
+        this.type = mType;
+    }
+
+    public Boolean getHidden() {
+        return hidden;
+    }
+
+    public void setHidden(boolean mHidden) {
+        this.hidden = mHidden;
     }
 
     public Integer getUploadAction() {
-        return mUploadAction;
+        return uploadAction;
     }
 
     public Integer getUploadActionInteger() {
-        switch (mUploadAction) {
+        switch (uploadAction) {
             case FileUploader.LOCAL_BEHAVIOUR_FORGET:
                 return 0;
             case FileUploader.LOCAL_BEHAVIOUR_MOVE:
@@ -195,38 +207,38 @@ public class SyncedFolderParcelable implements Parcelable {
     public void setUploadAction(String mUploadAction) {
         switch (mUploadAction) {
             case "LOCAL_BEHAVIOUR_FORGET":
-                this.mUploadAction = FileUploader.LOCAL_BEHAVIOUR_FORGET;
+                this.uploadAction = FileUploader.LOCAL_BEHAVIOUR_FORGET;
                 break;
             case "LOCAL_BEHAVIOUR_MOVE":
-                this.mUploadAction = FileUploader.LOCAL_BEHAVIOUR_MOVE;
+                this.uploadAction = FileUploader.LOCAL_BEHAVIOUR_MOVE;
                 break;
             case "LOCAL_BEHAVIOUR_DELETE":
-                this.mUploadAction = FileUploader.LOCAL_BEHAVIOUR_DELETE;
+                this.uploadAction = FileUploader.LOCAL_BEHAVIOUR_DELETE;
                 break;
         }
     }
 
     public long getId() {
-        return mId;
+        return id;
     }
 
-    public void setId(long mId) {
-        this.mId = mId;
+    public void setId(long id) {
+        this.id = id;
     }
 
     public String getAccount() {
-        return mAccount;
+        return account;
     }
 
-    public void setAccount(String mAccount) {
-        this.mAccount = mAccount;
+    public void setAccount(String account) {
+        this.account = account;
     }
 
     public int getSection() {
-        return mSection;
+        return section;
     }
 
-    public void setSection(int mSection) {
-        this.mSection = mSection;
+    public void setSection(int section) {
+        this.section = section;
     }
 }

+ 6 - 0
src/main/res/layout/synced_folders_empty.xml

@@ -0,0 +1,6 @@
+<?xml version="1.0" encoding="utf-8"?>
+<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
+    android:layout_width="@dimen/zero"
+    android:layout_height="@dimen/zero">
+
+</LinearLayout>

+ 38 - 0
src/main/res/layout/synced_folders_footer.xml

@@ -0,0 +1,38 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+  Nextcloud Android client application
+
+  Copyright (C) 2019 Andy Scherzinger
+
+  This program is free software; you can redistribute it and/or
+  modify it under the terms of the GNU AFFERO GENERAL PUBLIC LICENSE
+  License as published by the Free Software Foundation; either
+  version 3 of the License, or any later version.
+
+  This program is distributed in the hope that it will be useful,
+  but WITHOUT ANY WARRANTY; without even the implied warranty of
+  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+  GNU AFFERO GENERAL PUBLIC LICENSE for more details.
+
+  You should have received a copy of the GNU Affero General Public
+  License along with this program. If not, see <http://www.gnu.org/licenses/>.
+-->
+<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
+    android:id="@+id/footer_container"
+    android:layout_width="match_parent"
+    android:layout_height="wrap_content"
+    android:orientation="vertical"
+    android:showDividers="none">
+
+    <TextView
+        android:id="@+id/footer_text"
+        android:layout_width="match_parent"
+        android:layout_height="wrap_content"
+        android:layout_marginTop="@dimen/standard_double_margin"
+        android:layout_marginBottom="@dimen/min_list_item_size"
+        android:gravity="center"
+        android:padding="@dimen/standard_padding"
+        android:text="@string/show_hidden_folders"
+        android:textColor="@color/secondary_text_color" />
+
+</LinearLayout>

+ 28 - 0
src/main/res/menu/synced_folders_adapter.xml

@@ -0,0 +1,28 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+  Nextcloud Android client application
+
+  Copyright (C) 2019 Andy Scherzinger
+
+  This program is free software: you can redistribute it and/or modify
+  it under the terms of the GNU General Public License as published by
+  the Free Software Foundation, either version 3 of the License, or
+  (at your option) 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 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 <https://www.gnu.org/licenses/>.
+-->
+<menu xmlns:android="http://schemas.android.com/apk/res/android">
+    <item
+        android:id="@+id/action_auto_upload_folder_toggle_visibility"
+        android:title="@string/autoupload_hide_item" />
+
+    <item
+        android:id="@+id/action_auto_upload_folder_settings"
+        android:title="@string/autoupload_configure" />
+</menu>

+ 6 - 0
src/main/res/values/strings.xml

@@ -627,6 +627,9 @@
     <!-- Auto upload -->
     <string name="autoupload_custom_folder">Set up a custom folder</string>
     <string name="autoupload_create_new_custom_folder">Create new custom folder setup</string>
+    <string name="autoupload_show_folder">Show folder</string>
+    <string name="autoupload_hide_folder">Hide folder</string>
+    <string name="autoupload_configure">Configure</string>
     <string name="synced_folders_configure_folders">Configure folders</string>
 
     <string name="empty" translatable="false" />
@@ -901,4 +904,7 @@
     <string name="folder">folder</string>
     <string name="file">file</string>
     <string name="share_internal_link">Share internal link</string>
+    <string name="prefs_instant_upload_hide_item_summary">Hide folder in auto upload list</string>
+    <string name="prefs_instant_upload_hide_item_title">Hide folder</string>
+    <string name="show_hidden_folders">Show hidden folders</string>
 </resources>

+ 2 - 1
src/test/java/com/owncloud/android/ui/activity/SyncedFoldersActivityTest.java

@@ -181,6 +181,7 @@ public class SyncedFoldersActivityTest {
                                            new ArrayList<String>(),
                                            folderName,
                                            2,
-                                           MediaFolderType.IMAGE);
+                                           MediaFolderType.IMAGE,
+                                           false);
     }
 }