show/hide auto upload list items

Signed-off-by: Andy Scherzinger <info@andy-scherzinger.de>
This commit is contained in:
Andy Scherzinger 2019-11-01 22:37:55 +01:00
parent 540c649efe
commit 23e44243da
No known key found for this signature in database
GPG key ID: 6CADC7E3523C308B
13 changed files with 528 additions and 214 deletions

View file

@ -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;
}
/**

View file

@ -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;
}
}

View file

@ -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;
}

View file

@ -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";

View file

@ -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);
}
}
}
}

View file

@ -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

View file

@ -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.mainHeaderContainer.setVisibility(View.VISIBLE);
holder.title.setText(filteredSyncFolderItems.get(section).getFolderName());
holder.title.setText(mSyncFolderItems.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);
}
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);
} else {
holder.type.setImageResource(R.drawable.folder_star_32dp);
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.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());
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));
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);
if (item.isHidden()) {
popup.getMenu()
.findItem(R.id.action_auto_upload_folder_toggle_visibility)
.setTitle(R.string.autoupload_show_folder);
} else {
holder.menuButton.setVisibility(View.VISIBLE);
holder.menuButton.setTag(section);
holder.menuButton.setOnClickListener(v -> mListener.onSyncFolderSettingsClick(section,
mSyncFolderItems.get(section)));
popup.getMenu()
.findItem(R.id.action_auto_upload_folder_toggle_visibility)
.setTitle(R.string.autoupload_hide_folder);
}
popup.show();
}
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 {
// 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);
}

View file

@ -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;
}
}

View file

@ -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>

View file

@ -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>

View file

@ -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>

View file

@ -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>

View file

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