add exclude hidden file or folder option when create custom media folder type

Signed-off-by: JinWeiyang <jwy8645@163.com>
This commit is contained in:
JinWeiyang 2023-12-15 23:24:48 +08:00 committed by Andy Scherzinger
parent f7502cead3
commit 82fc3cf217
15 changed files with 182 additions and 31 deletions

View file

@ -74,7 +74,8 @@ public class SyncedFoldersActivityIT extends AbstractIT {
"Name", "Name",
MediaFolderType.IMAGE, MediaFolderType.IMAGE,
false, false,
SubFolderRule.YEAR_MONTH); SubFolderRule.YEAR_MONTH,
false);
SyncedFolderPreferencesDialogFragment sut = SyncedFolderPreferencesDialogFragment.newInstance(item, 0); SyncedFolderPreferencesDialogFragment sut = SyncedFolderPreferencesDialogFragment.newInstance(item, 0);
Intent intent = new Intent(targetContext, SyncedFoldersActivity.class); Intent intent = new Intent(targetContext, SyncedFoldersActivity.class);

View file

@ -187,7 +187,8 @@ class SyncedFolderUtilsTest : AbstractIT() {
0L, 0L,
MediaFolderType.IMAGE, MediaFolderType.IMAGE,
false, false,
SubFolderRule.YEAR_MONTH SubFolderRule.YEAR_MONTH,
false
) )
Assert.assertFalse(SyncedFolderUtils.isQualifyingMediaFolder(folder)) Assert.assertFalse(SyncedFolderUtils.isQualifyingMediaFolder(folder))
} }
@ -210,7 +211,8 @@ class SyncedFolderUtilsTest : AbstractIT() {
0L, 0L,
MediaFolderType.IMAGE, MediaFolderType.IMAGE,
false, false,
SubFolderRule.YEAR_MONTH SubFolderRule.YEAR_MONTH,
false
) )
Assert.assertFalse(SyncedFolderUtils.isQualifyingMediaFolder(folder)) Assert.assertFalse(SyncedFolderUtils.isQualifyingMediaFolder(folder))
} }

View file

@ -59,5 +59,7 @@ data class SyncedFolderEntity(
@ColumnInfo(name = ProviderTableMeta.SYNCED_FOLDER_HIDDEN) @ColumnInfo(name = ProviderTableMeta.SYNCED_FOLDER_HIDDEN)
val hidden: Int?, val hidden: Int?,
@ColumnInfo(name = ProviderTableMeta.SYNCED_FOLDER_SUBFOLDER_RULE) @ColumnInfo(name = ProviderTableMeta.SYNCED_FOLDER_SUBFOLDER_RULE)
val subFolderRule: Int? val subFolderRule: Int?,
@ColumnInfo(name = ProviderTableMeta.SYNCED_EXCLUDE_HIDDEN)
val excludeHidden: Int?
) )

View file

@ -51,6 +51,7 @@ public class SyncedFolder implements Serializable, Cloneable {
private MediaFolderType type; private MediaFolderType type;
private boolean hidden; private boolean hidden;
private SubFolderRule subfolderRule; private SubFolderRule subfolderRule;
private boolean excludeHidden;
/** /**
* constructor for new, to be persisted entity. * constructor for new, to be persisted entity.
@ -68,6 +69,8 @@ public class SyncedFolder implements Serializable, Cloneable {
* @param timestampMs the current timestamp in milliseconds * @param timestampMs the current timestamp in milliseconds
* @param type the type of the folder * @param type the type of the folder
* @param hidden hide item flag * @param hidden hide item flag
* @param subFolderRule whether to filter subFolder by year/month/day
* @param excludeHidden exclude hidden file or folder, for {@link MediaFolderType#CUSTOM} only
*/ */
public SyncedFolder(String localPath, public SyncedFolder(String localPath,
String remotePath, String remotePath,
@ -82,7 +85,8 @@ public class SyncedFolder implements Serializable, Cloneable {
long timestampMs, long timestampMs,
MediaFolderType type, MediaFolderType type,
boolean hidden, boolean hidden,
SubFolderRule subFolderRule) { SubFolderRule subFolderRule,
boolean excludeHidden) {
this(UNPERSISTED_ID, this(UNPERSISTED_ID,
localPath, localPath,
remotePath, remotePath,
@ -97,7 +101,8 @@ public class SyncedFolder implements Serializable, Cloneable {
timestampMs, timestampMs,
type, type,
hidden, hidden,
subFolderRule); subFolderRule,
excludeHidden);
} }
/** /**
@ -119,7 +124,8 @@ public class SyncedFolder implements Serializable, Cloneable {
long timestampMs, long timestampMs,
MediaFolderType type, MediaFolderType type,
boolean hidden, boolean hidden,
SubFolderRule subFolderRule) { SubFolderRule subFolderRule,
boolean excludeHidden) {
this.id = id; this.id = id;
this.localPath = localPath; this.localPath = localPath;
this.remotePath = remotePath; this.remotePath = remotePath;
@ -134,6 +140,7 @@ public class SyncedFolder implements Serializable, Cloneable {
this.type = type; this.type = type;
this.hidden = hidden; this.hidden = hidden;
this.subfolderRule = subFolderRule; this.subfolderRule = subFolderRule;
this.excludeHidden = excludeHidden;
} }
/** /**
@ -263,4 +270,12 @@ public class SyncedFolder implements Serializable, Cloneable {
} }
public void setSubFolderRule(SubFolderRule subFolderRule) { this.subfolderRule = subFolderRule; } public void setSubFolderRule(SubFolderRule subFolderRule) { this.subfolderRule = subFolderRule; }
public boolean isExcludeHidden() {
return excludeHidden;
}
public void setExcludeHidden(boolean excludeHidden) {
this.excludeHidden = excludeHidden;
}
} }

View file

@ -54,6 +54,7 @@ public class SyncedFolderDisplayItem extends SyncedFolder {
* @param type the type of the folder * @param type the type of the folder
* @param hidden hide item flag * @param hidden hide item flag
* @param subFolderRule whether to filter subFolder by year/month/day * @param subFolderRule whether to filter subFolder by year/month/day
* @param excludeHidden exclude hidden file or folder, for {@link MediaFolderType#CUSTOM} only
*/ */
public SyncedFolderDisplayItem(long id, public SyncedFolderDisplayItem(long id,
String localPath, String localPath,
@ -72,7 +73,8 @@ public class SyncedFolderDisplayItem extends SyncedFolder {
long numberOfFiles, long numberOfFiles,
MediaFolderType type, MediaFolderType type,
boolean hidden, boolean hidden,
SubFolderRule subFolderRule) { SubFolderRule subFolderRule,
boolean excludeHidden) {
super(id, super(id,
localPath, localPath,
remotePath, remotePath,
@ -87,7 +89,8 @@ public class SyncedFolderDisplayItem extends SyncedFolder {
timestampMs, timestampMs,
type, type,
hidden, hidden,
subFolderRule); subFolderRule,
excludeHidden);
this.filePaths = filePaths; this.filePaths = filePaths;
this.folderName = folderName; this.folderName = folderName;
this.numberOfFiles = numberOfFiles; this.numberOfFiles = numberOfFiles;
@ -108,7 +111,8 @@ public class SyncedFolderDisplayItem extends SyncedFolder {
String folderName, String folderName,
MediaFolderType type, MediaFolderType type,
boolean hidden, boolean hidden,
SubFolderRule subFolderRule) { SubFolderRule subFolderRule,
boolean excludeHidden) {
super(id, super(id,
localPath, localPath,
remotePath, remotePath,
@ -123,7 +127,8 @@ public class SyncedFolderDisplayItem extends SyncedFolder {
timestampMs, timestampMs,
type, type,
hidden, hidden,
subFolderRule); subFolderRule,
excludeHidden);
this.folderName = folderName; this.folderName = folderName;
} }

View file

@ -372,6 +372,8 @@ public class SyncedFolderProvider extends Observable {
ProviderMeta.ProviderTableMeta.SYNCED_FOLDER_HIDDEN)) == 1; ProviderMeta.ProviderTableMeta.SYNCED_FOLDER_HIDDEN)) == 1;
SubFolderRule subFolderRule = SubFolderRule.values()[cursor.getInt( SubFolderRule subFolderRule = SubFolderRule.values()[cursor.getInt(
cursor.getColumnIndexOrThrow(ProviderMeta.ProviderTableMeta.SYNCED_FOLDER_SUBFOLDER_RULE))]; cursor.getColumnIndexOrThrow(ProviderMeta.ProviderTableMeta.SYNCED_FOLDER_SUBFOLDER_RULE))];
boolean excludeHidden = cursor.getInt(cursor.getColumnIndexOrThrow(
ProviderMeta.ProviderTableMeta.SYNCED_EXCLUDE_HIDDEN)) == 1;
syncedFolder = new SyncedFolder(id, syncedFolder = new SyncedFolder(id,
@ -388,7 +390,8 @@ public class SyncedFolderProvider extends Observable {
enabledTimestampMs, enabledTimestampMs,
type, type,
hidden, hidden,
subFolderRule); subFolderRule,
excludeHidden);
} }
return syncedFolder; return syncedFolder;
} }
@ -417,6 +420,7 @@ public class SyncedFolderProvider extends Observable {
cv.put(ProviderMeta.ProviderTableMeta.SYNCED_FOLDER_TYPE, syncedFolder.getType().id); cv.put(ProviderMeta.ProviderTableMeta.SYNCED_FOLDER_TYPE, syncedFolder.getType().id);
cv.put(ProviderMeta.ProviderTableMeta.SYNCED_FOLDER_HIDDEN, syncedFolder.isHidden()); cv.put(ProviderMeta.ProviderTableMeta.SYNCED_FOLDER_HIDDEN, syncedFolder.isHidden());
cv.put(ProviderMeta.ProviderTableMeta.SYNCED_FOLDER_SUBFOLDER_RULE, syncedFolder.getSubfolderRule().ordinal()); cv.put(ProviderMeta.ProviderTableMeta.SYNCED_FOLDER_SUBFOLDER_RULE, syncedFolder.getSubfolderRule().ordinal());
cv.put(ProviderMeta.ProviderTableMeta.SYNCED_EXCLUDE_HIDDEN, syncedFolder.isExcludeHidden());
return cv; return cv;
} }

View file

@ -302,6 +302,7 @@ public class ProviderMeta {
public static final String SYNCED_FOLDER_NAME_COLLISION_POLICY = "name_collision_policy"; public static final String SYNCED_FOLDER_NAME_COLLISION_POLICY = "name_collision_policy";
public static final String SYNCED_FOLDER_HIDDEN = "hidden"; public static final String SYNCED_FOLDER_HIDDEN = "hidden";
public static final String SYNCED_FOLDER_SUBFOLDER_RULE = "sub_folder_rule"; public static final String SYNCED_FOLDER_SUBFOLDER_RULE = "sub_folder_rule";
public static final String SYNCED_EXCLUDE_HIDDEN = "exclude_hidden";
// Columns of external links table // Columns of external links table
public static final String EXTERNAL_LINKS_ICON_URL = "icon_url"; public static final String EXTERNAL_LINKS_ICON_URL = "icon_url";

View file

@ -403,7 +403,8 @@ class SyncedFoldersActivity :
files.size.toLong(), files.size.toLong(),
syncedFolder.type, syncedFolder.type,
syncedFolder.isHidden, syncedFolder.isHidden,
syncedFolder.subfolderRule syncedFolder.subfolderRule,
syncedFolder.isExcludeHidden
) )
} }
@ -433,7 +434,8 @@ class SyncedFoldersActivity :
mediaFolder.numberOfFiles, mediaFolder.numberOfFiles,
mediaFolder.type, mediaFolder.type,
syncedFolder.isHidden, syncedFolder.isHidden,
syncedFolder.subfolderRule syncedFolder.subfolderRule,
syncedFolder.isExcludeHidden
) )
} }
@ -462,7 +464,8 @@ class SyncedFoldersActivity :
mediaFolder.numberOfFiles, mediaFolder.numberOfFiles,
mediaFolder.type, mediaFolder.type,
false, false,
SubFolderRule.YEAR_MONTH SubFolderRule.YEAR_MONTH,
false
) )
} }
@ -554,7 +557,8 @@ class SyncedFoldersActivity :
null, null,
MediaFolderType.CUSTOM, MediaFolderType.CUSTOM,
false, false,
SubFolderRule.YEAR_MONTH SubFolderRule.YEAR_MONTH,
false
) )
onSyncFolderSettingsClick(0, emptyCustomFolder) onSyncFolderSettingsClick(0, emptyCustomFolder)
} else { } else {
@ -670,7 +674,8 @@ class SyncedFoldersActivity :
File(syncedFolder.localPath).name, File(syncedFolder.localPath).name,
syncedFolder.type, syncedFolder.type,
syncedFolder.isHidden, syncedFolder.isHidden,
syncedFolder.subFolderRule syncedFolder.subFolderRule,
syncedFolder.isExcludeHidden
) )
saveOrUpdateSyncedFolder(newCustomFolder) saveOrUpdateSyncedFolder(newCustomFolder)
adapter.addSyncFolderItem(newCustomFolder) adapter.addSyncFolderItem(newCustomFolder)
@ -688,7 +693,8 @@ class SyncedFoldersActivity :
syncedFolder.uploadAction, syncedFolder.uploadAction,
syncedFolder.nameCollisionPolicy.serialize(), syncedFolder.nameCollisionPolicy.serialize(),
syncedFolder.isEnabled, syncedFolder.isEnabled,
syncedFolder.subFolderRule syncedFolder.subFolderRule,
syncedFolder.isExcludeHidden
) )
saveOrUpdateSyncedFolder(item) saveOrUpdateSyncedFolder(item)
@ -759,6 +765,7 @@ class SyncedFoldersActivity :
* @param uploadAction upload action * @param uploadAction upload action
* @param nameCollisionPolicy what to do on name collision * @param nameCollisionPolicy what to do on name collision
* @param enabled is sync enabled * @param enabled is sync enabled
* @param excludeHidden exclude hidden file or folder, for {@link MediaFolderType#CUSTOM} only
*/ */
@Suppress("LongParameterList") @Suppress("LongParameterList")
private fun updateSyncedFolderItem( private fun updateSyncedFolderItem(
@ -773,7 +780,8 @@ class SyncedFoldersActivity :
uploadAction: Int, uploadAction: Int,
nameCollisionPolicy: Int, nameCollisionPolicy: Int,
enabled: Boolean, enabled: Boolean,
subFolderRule: SubFolderRule subFolderRule: SubFolderRule,
excludeHidden: Boolean
) { ) {
item.id = id item.id = id
item.localPath = localPath item.localPath = localPath
@ -786,6 +794,7 @@ class SyncedFoldersActivity :
item.setNameCollisionPolicy(nameCollisionPolicy) item.setNameCollisionPolicy(nameCollisionPolicy)
item.setEnabled(enabled, clock.currentTime) item.setEnabled(enabled, clock.currentTime)
item.setSubFolderRule(subFolderRule) item.setSubFolderRule(subFolderRule)
item.setExcludeHidden(excludeHidden)
} }
override fun onRequestPermissionsResult( override fun onRequestPermissionsResult(

View file

@ -130,12 +130,16 @@ class SyncedFolderPreferencesDialogFragment : DialogFragment(), Injectable {
// hide local folder chooser and delete for non-custom folders // hide local folder chooser and delete for non-custom folders
binding.localFolderContainer.visibility = View.GONE binding.localFolderContainer.visibility = View.GONE
isNeutralButtonActive = false isNeutralButtonActive = false
binding.settingInstantUploadExcludeHiddenContainer.visibility = View.GONE
} else if (syncedFolder!!.id <= SyncedFolder.UNPERSISTED_ID) { } else if (syncedFolder!!.id <= SyncedFolder.UNPERSISTED_ID) {
isNeutralButtonActive = false isNeutralButtonActive = false
// Hide delete/enabled for unpersisted custom folders // Hide delete/enabled for unpersisted custom folders
binding.syncEnabled.visibility = View.GONE binding.syncEnabled.visibility = View.GONE
// Show exclude hidden checkbox when {@link MediaFolderType#CUSTOM}
binding.settingInstantUploadExcludeHiddenContainer.visibility = View.VISIBLE
// auto set custom folder to enabled // auto set custom folder to enabled
syncedFolder?.isEnabled = true syncedFolder?.isEnabled = true
@ -146,6 +150,10 @@ class SyncedFolderPreferencesDialogFragment : DialogFragment(), Injectable {
binding.btnPositive.isEnabled = false binding.btnPositive.isEnabled = false
} else { } else {
binding.localFolderContainer.visibility = View.GONE binding.localFolderContainer.visibility = View.GONE
if (MediaFolderType.CUSTOM.id == syncedFolder!!.type.id) {
// Show exclude hidden checkbox when {@link MediaFolderType#CUSTOM}
binding.settingInstantUploadExcludeHiddenContainer.visibility = View.VISIBLE
}
} }
} }
@ -156,7 +164,8 @@ class SyncedFolderPreferencesDialogFragment : DialogFragment(), Injectable {
binding.settingInstantUploadOnWifiCheckbox, binding.settingInstantUploadOnWifiCheckbox,
binding.settingInstantUploadOnChargingCheckbox, binding.settingInstantUploadOnChargingCheckbox,
binding.settingInstantUploadExistingCheckbox, binding.settingInstantUploadExistingCheckbox,
binding.settingInstantUploadPathUseSubfoldersCheckbox binding.settingInstantUploadPathUseSubfoldersCheckbox,
binding.settingInstantUploadExcludeHiddenCheckbox
) )
viewThemeUtils?.material?.colorMaterialButtonPrimaryTonal(binding.btnPositive) viewThemeUtils?.material?.colorMaterialButtonPrimaryTonal(binding.btnPositive)
@ -209,6 +218,7 @@ class SyncedFolderPreferencesDialogFragment : DialogFragment(), Injectable {
binding.settingInstantUploadOnChargingCheckbox.isChecked = it.isChargingOnly binding.settingInstantUploadOnChargingCheckbox.isChecked = it.isChargingOnly
binding.settingInstantUploadExistingCheckbox.isChecked = it.isExisting binding.settingInstantUploadExistingCheckbox.isChecked = it.isExisting
binding.settingInstantUploadPathUseSubfoldersCheckbox.isChecked = it.isSubfolderByDate binding.settingInstantUploadPathUseSubfoldersCheckbox.isChecked = it.isSubfolderByDate
binding.settingInstantUploadExcludeHiddenCheckbox.isChecked = it.isExcludeHidden
binding.settingInstantUploadSubfolderRuleSpinner.setSelection(it.subFolderRule.ordinal) binding.settingInstantUploadSubfolderRuleSpinner.setSelection(it.subFolderRule.ordinal)
@ -311,6 +321,8 @@ class SyncedFolderPreferencesDialogFragment : DialogFragment(), Injectable {
binding.settingInstantUploadExistingContainer.alpha = alpha binding.settingInstantUploadExistingContainer.alpha = alpha
binding.settingInstantUploadPathUseSubfoldersContainer.isEnabled = enable binding.settingInstantUploadPathUseSubfoldersContainer.isEnabled = enable
binding.settingInstantUploadPathUseSubfoldersContainer.alpha = alpha binding.settingInstantUploadPathUseSubfoldersContainer.alpha = alpha
binding.settingInstantUploadExcludeHiddenContainer.isEnabled = enable
binding.settingInstantUploadExcludeHiddenContainer.alpha = alpha
binding.remoteFolderContainer.isEnabled = enable binding.remoteFolderContainer.isEnabled = enable
binding.remoteFolderContainer.alpha = alpha binding.remoteFolderContainer.alpha = alpha
binding.localFolderContainer.isEnabled = enable binding.localFolderContainer.isEnabled = enable
@ -321,6 +333,7 @@ class SyncedFolderPreferencesDialogFragment : DialogFragment(), Injectable {
binding.settingInstantUploadOnChargingCheckbox.isEnabled = enable binding.settingInstantUploadOnChargingCheckbox.isEnabled = enable
binding.settingInstantUploadExistingCheckbox.isEnabled = enable binding.settingInstantUploadExistingCheckbox.isEnabled = enable
binding.settingInstantUploadPathUseSubfoldersCheckbox.isEnabled = enable binding.settingInstantUploadPathUseSubfoldersCheckbox.isEnabled = enable
binding.settingInstantUploadExcludeHiddenCheckbox.isEnabled = enable
} }
checkWritableFolder() checkWritableFolder()
@ -364,6 +377,10 @@ class SyncedFolderPreferencesDialogFragment : DialogFragment(), Injectable {
binding.settingInstantUploadSubfolderRuleContainer.visibility = View.GONE binding.settingInstantUploadSubfolderRuleContainer.visibility = View.GONE
} }
} }
binding.settingInstantUploadExcludeHiddenContainer.setOnClickListener {
syncedFolder.isExcludeHidden = !syncedFolder.isExcludeHidden
binding.settingInstantUploadExcludeHiddenCheckbox.toggle()
}
binding.settingInstantUploadSubfolderRuleSpinner.onItemSelectedListener = binding.settingInstantUploadSubfolderRuleSpinner.onItemSelectedListener =
object : AdapterView.OnItemSelectedListener { object : AdapterView.OnItemSelectedListener {
override fun onItemSelected(adapterView: AdapterView<*>?, view: View, i: Int, l: Long) { override fun onItemSelected(adapterView: AdapterView<*>?, view: View, i: Int, l: Long) {

View file

@ -49,6 +49,7 @@ public class SyncedFolderParcelable implements Parcelable {
private String account; private String account;
private int section; private int section;
private SubFolderRule subFolderRule; private SubFolderRule subFolderRule;
private boolean excludeHidden;
public SyncedFolderParcelable(SyncedFolderDisplayItem syncedFolderDisplayItem, int section) { public SyncedFolderParcelable(SyncedFolderDisplayItem syncedFolderDisplayItem, int section) {
id = syncedFolderDisplayItem.getId(); id = syncedFolderDisplayItem.getId();
@ -68,6 +69,7 @@ public class SyncedFolderParcelable implements Parcelable {
this.section = section; this.section = section;
hidden = syncedFolderDisplayItem.isHidden(); hidden = syncedFolderDisplayItem.isHidden();
subFolderRule = syncedFolderDisplayItem.getSubfolderRule(); subFolderRule = syncedFolderDisplayItem.getSubfolderRule();
excludeHidden = syncedFolderDisplayItem.isExcludeHidden();
} }
private SyncedFolderParcelable(Parcel read) { private SyncedFolderParcelable(Parcel read) {
@ -87,6 +89,7 @@ public class SyncedFolderParcelable implements Parcelable {
section = read.readInt(); section = read.readInt();
hidden = read.readInt() != 0; hidden = read.readInt() != 0;
subFolderRule = SubFolderRule.values()[read.readInt()]; subFolderRule = SubFolderRule.values()[read.readInt()];
excludeHidden = read.readInt() != 0;
} }
public SyncedFolderParcelable() { public SyncedFolderParcelable() {
@ -111,6 +114,7 @@ public class SyncedFolderParcelable implements Parcelable {
dest.writeInt(section); dest.writeInt(section);
dest.writeInt(hidden ? 1 : 0); dest.writeInt(hidden ? 1 : 0);
dest.writeInt(subFolderRule.ordinal()); dest.writeInt(subFolderRule.ordinal());
dest.writeInt(excludeHidden ? 1 : 0);
} }
public static final Creator<SyncedFolderParcelable> CREATOR = public static final Creator<SyncedFolderParcelable> CREATOR =
@ -279,4 +283,12 @@ public class SyncedFolderParcelable implements Parcelable {
this.section = section; this.section = section;
} }
public void setSubFolderRule(SubFolderRule subFolderRule) { this.subFolderRule = subFolderRule; } public void setSubFolderRule(SubFolderRule subFolderRule) { this.subFolderRule = subFolderRule; }
public boolean isExcludeHidden() {
return excludeHidden;
}
public void setExcludeHidden(boolean excludeHidden) {
this.excludeHidden = excludeHidden;
}
} }

View file

@ -26,6 +26,11 @@ import android.text.TextUtils;
import com.owncloud.android.lib.common.utils.Log_OC; import com.owncloud.android.lib.common.utils.Log_OC;
import com.owncloud.android.lib.resources.files.UploadFileRemoteOperation; import com.owncloud.android.lib.resources.files.UploadFileRemoteOperation;
import org.lukhnos.nnio.file.FileVisitResult;
import org.lukhnos.nnio.file.FileVisitor;
import org.lukhnos.nnio.file.Path;
import org.lukhnos.nnio.file.impl.FileBasedPathImpl;
import java.io.File; import java.io.File;
import java.io.IOException; import java.io.IOException;
import java.nio.file.Files; import java.nio.file.Files;
@ -77,4 +82,19 @@ public final class FileUtil {
return null; return null;
} }
} }
public static Path walkFileTree(Path start, FileVisitor<? super Path> visitor) throws IOException {
if (org.lukhnos.nnio.file.Files.isDirectory(start)) {
org.lukhnos.nnio.file.FileVisitResult preVisitDirectoryResult = visitor.preVisitDirectory(start, null);
if (preVisitDirectoryResult == FileVisitResult.CONTINUE) {
for (File child : start.toFile().listFiles()) {
walkFileTree(FileBasedPathImpl.get(child), visitor);
}
}
visitor.postVisitDirectory(start, null);
} else {
visitor.visitFile(start, new org.lukhnos.nnio.file.attribute.BasicFileAttributes(start.toFile()));
}
return start;
}
} }

View file

@ -48,7 +48,6 @@ import com.owncloud.android.db.UploadResult;
import com.owncloud.android.lib.common.utils.Log_OC; import com.owncloud.android.lib.common.utils.Log_OC;
import org.lukhnos.nnio.file.FileVisitResult; import org.lukhnos.nnio.file.FileVisitResult;
import org.lukhnos.nnio.file.Files;
import org.lukhnos.nnio.file.Path; import org.lukhnos.nnio.file.Path;
import org.lukhnos.nnio.file.Paths; import org.lukhnos.nnio.file.Paths;
import org.lukhnos.nnio.file.SimpleFileVisitor; import org.lukhnos.nnio.file.SimpleFileVisitor;
@ -94,10 +93,14 @@ public final class FilesSyncHelper {
FilesystemDataProvider filesystemDataProvider = new FilesystemDataProvider(contentResolver); FilesystemDataProvider filesystemDataProvider = new FilesystemDataProvider(contentResolver);
Path path = Paths.get(syncedFolder.getLocalPath()); Path path = Paths.get(syncedFolder.getLocalPath());
Files.walkFileTree(path, new SimpleFileVisitor<Path>() { FileUtil.walkFileTree(path, new SimpleFileVisitor<Path>() {
@Override @Override
public FileVisitResult visitFile(Path path, BasicFileAttributes attrs) { public FileVisitResult visitFile(Path path, BasicFileAttributes attrs) {
File file = path.toFile(); File file = path.toFile();
if (syncedFolder.isExcludeHidden() && file.isHidden()) {
// exclude hidden file or folder
return FileVisitResult.CONTINUE;
}
if (syncedFolder.isExisting() || attrs.lastModifiedTime().toMillis() >= enabledTimestampMs) { if (syncedFolder.isExisting() || attrs.lastModifiedTime().toMillis() >= enabledTimestampMs) {
filesystemDataProvider.storeOrUpdateFileValue(path.toAbsolutePath().toString(), filesystemDataProvider.storeOrUpdateFileValue(path.toAbsolutePath().toString(),
attrs.lastModifiedTime().toMillis(), attrs.lastModifiedTime().toMillis(),
@ -107,6 +110,14 @@ public final class FilesSyncHelper {
return FileVisitResult.CONTINUE; return FileVisitResult.CONTINUE;
} }
@Override
public FileVisitResult preVisitDirectory(Path dir, BasicFileAttributes attrs) throws IOException {
if (syncedFolder.isExcludeHidden() && dir.compareTo(Paths.get(syncedFolder.getLocalPath())) != 0 && dir.toFile().isHidden()) {
return null;
}
return FileVisitResult.CONTINUE;
}
@Override @Override
public FileVisitResult visitFileFailed(Path file, IOException exc) { public FileVisitResult visitFileFailed(Path file, IOException exc) {
return FileVisitResult.CONTINUE; return FileVisitResult.CONTINUE;
@ -186,11 +197,10 @@ public final class FilesSyncHelper {
for (OCUpload failedUpload : failedUploads) { for (OCUpload failedUpload : failedUploads) {
accountExists = false; accountExists = false;
if(!failedUpload.isWhileChargingOnly()){ if (!failedUpload.isWhileChargingOnly()) {
whileChargingOnly = false; whileChargingOnly = false;
} }
if(!failedUpload.isUseWifiOnly()) if (!failedUpload.isUseWifiOnly()) {
{
useWifiOnly = false; useWifiOnly = false;
} }
@ -208,22 +218,21 @@ public final class FilesSyncHelper {
} }
failedUploads = uploadsStorageManager.getFailedUploads(); failedUploads = uploadsStorageManager.getFailedUploads();
if(failedUploads.length == 0) if (failedUploads.length == 0) {
{
//nothing to do //nothing to do
return; return;
} }
if(whileChargingOnly){ if (whileChargingOnly) {
final BatteryStatus batteryStatus = powerManagementService.getBattery(); final BatteryStatus batteryStatus = powerManagementService.getBattery();
final boolean charging = batteryStatus.isCharging() || batteryStatus.isFull(); final boolean charging = batteryStatus.isCharging() || batteryStatus.isFull();
if(!charging){ if (!charging) {
//all uploads requires charging //all uploads requires charging
return; return;
} }
} }
if (useWifiOnly && !connectivityService.getConnectivity().isWifi()){ if (useWifiOnly && !connectivityService.getConnectivity().isWifi()) {
//all uploads requires wifi //all uploads requires wifi
return; return;
} }

View file

@ -305,6 +305,57 @@
</LinearLayout> </LinearLayout>
</LinearLayout> </LinearLayout>
<LinearLayout
android:id="@+id/setting_instant_upload_exclude_hidden_container"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:baselineAligned="false">
<RelativeLayout
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_weight="1"
android:padding="@dimen/standard_padding">
<TextView
android:id="@+id/setting_instant_upload_exclude_hidden_label"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:ellipsize="marquee"
android:maxLines="2"
android:text="@string/prefs_instant_upload_exclude_hidden_title"
android:textAppearance="?attr/textAppearanceListItem" />
<TextView
android:id="@+id/setting_instant_upload_exclude_hidden_summary"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_below="@id/setting_instant_upload_exclude_hidden_label"
android:layout_alignStart="@id/setting_instant_upload_exclude_hidden_label"
android:ellipsize="end"
android:maxLines="2"
android:text="@string/prefs_instant_upload_exclude_hidden_summary"
android:textColor="?android:attr/textColorSecondary" />
</RelativeLayout>
<!-- Preference should place its actual preference widget here. -->
<LinearLayout
android:id="@+id/setting_instant_upload_exclude_hidden_frame"
android:layout_width="@dimen/synced_folders_control_width"
android:layout_height="match_parent"
android:gravity="center"
android:padding="@dimen/standard_padding">
<androidx.appcompat.widget.AppCompatCheckBox
android:id="@+id/setting_instant_upload_exclude_hidden_checkbox"
android:layout_width="32dp"
android:layout_height="wrap_content"
android:background="@null"
android:clickable="false"
android:focusable="false" />
</LinearLayout>
</LinearLayout>
<LinearLayout <LinearLayout
android:id="@+id/setting_instant_upload_subfolder_rule_container" android:id="@+id/setting_instant_upload_subfolder_rule_container"
android:layout_width="match_parent" android:layout_width="match_parent"

View file

@ -368,6 +368,8 @@
<string name="prefs_synced_folders_remote_path_title">Remote folder</string> <string name="prefs_synced_folders_remote_path_title">Remote folder</string>
<string name="prefs_instant_upload_path_use_subfolders_title">Use subfolders</string> <string name="prefs_instant_upload_path_use_subfolders_title">Use subfolders</string>
<string name="prefs_instant_upload_path_use_date_subfolders_summary">Store in subfolders based on date</string> <string name="prefs_instant_upload_path_use_date_subfolders_summary">Store in subfolders based on date</string>
<string name="prefs_instant_upload_exclude_hidden_title">Exclude hidden</string>
<string name="prefs_instant_upload_exclude_hidden_summary">Exclude hidden file or folder</string>
<string name="prefs_instant_upload_subfolder_rule_title">Subfolder options</string> <string name="prefs_instant_upload_subfolder_rule_title">Subfolder options</string>

View file

@ -178,6 +178,7 @@ public class SyncedFoldersActivityTest {
2, 2,
MediaFolderType.IMAGE, MediaFolderType.IMAGE,
false, false,
SubFolderRule.YEAR_MONTH); SubFolderRule.YEAR_MONTH,
true);
} }
} }