Skip to content

Commit

Permalink
Add setting for enabling subfolders
Browse files Browse the repository at this point in the history
The feature is disabled by default. In the long run, we will probably
want to enable it by default, and finally remove it. But I'm not yet
sure how to do that without disrupting the user experience.
  • Loading branch information
amberin committed Oct 4, 2024
1 parent f0cccf2 commit 70b7952
Show file tree
Hide file tree
Showing 14 changed files with 268 additions and 38 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -51,8 +51,13 @@ class DocumentRepoTest : SyncRepoTest, OrgzlyTest() {
}

@Test
override fun testGetBooks_singleFileInSubfolder() {
SyncRepoTest.testGetBooks_singleFileInSubfolder(repoDirectory, syncRepo)
override fun testGetBooks_singleFileInSubfolderWhenEnabled() {
SyncRepoTest.testGetBooks_singleFileInSubfolderWhenEnabled(repoDirectory, syncRepo)
}

@Test
override fun testGetBooks_singleFileInSubfolderWhenDisabled() {
SyncRepoTest.testGetBooks_singleFileInSubfolderWhenDisabled(repoDirectory, syncRepo)
}

@Test
Expand Down Expand Up @@ -81,8 +86,13 @@ class DocumentRepoTest : SyncRepoTest, OrgzlyTest() {
}

@Test
override fun testStoreBook_producesSameUriAsRetrieveBook() {
SyncRepoTest.testStoreBook_producesSameUriAsRetrieveBook(syncRepo)
override fun testStoreBook_producesSameUriAsRetrieveBookWithSubfolder() {
SyncRepoTest.testStoreBook_producesSameUriAsRetrieveBookWithSubfolder(syncRepo)
}

@Test
override fun testStoreBook_producesSameUriAsRetrieveBookWithoutSubfolder() {
SyncRepoTest.testStoreBook_producesSameUriAsRetrieveBookWithoutSubfolder(syncRepo)
}

@Test
Expand All @@ -95,6 +105,11 @@ class DocumentRepoTest : SyncRepoTest, OrgzlyTest() {
SyncRepoTest.testStoreBook_inSubfolder(repoDirectory, syncRepo)
}

@Test(expected = IOException::class)
override fun testStoreBook_inSubfolderWhenDisabled() {
SyncRepoTest.testStoreBook_inSubfolderWhenDisabled(syncRepo)
}

@Test
override fun testRenameBook_expectedUri() {
SyncRepoTest.testRenameBook_expectedUri(syncRepo)
Expand All @@ -106,8 +121,13 @@ class DocumentRepoTest : SyncRepoTest, OrgzlyTest() {
}

@Test
override fun testRenameBook_fromRootToSubfolder() {
SyncRepoTest.testRenameBook_fromRootToSubfolder(syncRepo)
override fun testRenameBook_fromRootToSubfolderWhenEnabled() {
SyncRepoTest.testRenameBook_fromRootToSubfolderWhenEnabled(syncRepo)
}

@Test(expected = IOException::class)
override fun testRenameBook_fromRootToSubfolderWhenDisabled() {
SyncRepoTest.testRenameBook_fromRootToSubfolderWhenDisabled(syncRepo)
}

@Test
Expand Down
13 changes: 13 additions & 0 deletions app/src/main/java/com/orgzly/android/prefs/AppPreferences.java
Original file line number Diff line number Diff line change
Expand Up @@ -1106,6 +1106,19 @@ public static void refileLastLocation(Context context, String value) {
getStateSharedPreferences(context).edit().putString(key, value).apply();
}

/*
* Subfolder support
*/
public static boolean subfolderSupport(Context context) {
String key = context.getResources().getString(R.string.pref_key_enable_repo_subfolders);
return getStateSharedPreferences(context).getBoolean(key, false);
}

public static void subfolderSupport(Context context, boolean value) {
String key = context.getResources().getString(R.string.pref_key_enable_repo_subfolders);
getStateSharedPreferences(context).edit().putBoolean(key, value).apply();
}

/*
* Repository properties map
*/
Expand Down
21 changes: 16 additions & 5 deletions app/src/main/java/com/orgzly/android/repos/DocumentRepo.java
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@
import com.orgzly.R;
import com.orgzly.android.BookName;
import com.orgzly.android.db.entity.Repo;
import com.orgzly.android.prefs.AppPreferences;
import com.orgzly.android.util.LogUtils;
import com.orgzly.android.util.MiscUtils;

Expand Down Expand Up @@ -117,6 +118,8 @@ private List<DocumentFile> walkFileTree() {
for (DocumentFile node : currentDir.listFiles()) {
String repoRelativePath = BookName.getRepoRelativePath(repoUri, node.getUri());
if (node.isDirectory()) {
if (!AppPreferences.subfolderSupport(context))
continue;
if (Build.VERSION.SDK_INT >= 26) {
if (ignores.isPathIgnored(repoRelativePath, true)) {
continue;
Expand Down Expand Up @@ -176,10 +179,14 @@ public VersionedRook storeBook(File file, String repoRelativePath) throws IOExce
}
DocumentFile destinationFile = getDocumentFileFromPath(repoRelativePath);
if (repoRelativePath.contains("/")) {
DocumentFile destinationDir = ensureDirectoryHierarchy(repoRelativePath);
String fileName = Uri.parse(repoRelativePath).getLastPathSegment();
if (destinationDir.findFile(fileName) == null) {
destinationFile = destinationDir.createFile("text/*", fileName);
if (AppPreferences.subfolderSupport(context)) {
DocumentFile destinationDir = ensureDirectoryHierarchy(repoRelativePath);
String fileName = Uri.parse(repoRelativePath).getLastPathSegment();
if (destinationDir.findFile(fileName) == null) {
destinationFile = destinationDir.createFile("text/*", fileName);
}
} else {
throw new IOException(context.getString(R.string.subfolder_support_disabled));
}
} else {
if (!destinationFile.exists()) {
Expand Down Expand Up @@ -246,7 +253,11 @@ public VersionedRook renameBook(Uri oldFullUri, String newName) throws IOExcepti
Uri newUri = oldFullUri;

if (newName.contains("/")) {
newDir = ensureDirectoryHierarchy(newName);
if (AppPreferences.subfolderSupport(context)) {
newDir = ensureDirectoryHierarchy(newName);
} else {
throw new IOException(context.getString(R.string.subfolder_support_disabled));
}
} else {
newDir = repoDocumentFile;
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -180,7 +180,7 @@ public List<VersionedRook> getBooks(Uri repoUri, RepoIgnoreNode ignores) throws
list.add(book);
}
}
if (metadata instanceof FolderMetadata) {
if (metadata instanceof FolderMetadata && AppPreferences.subfolderSupport(mContext)) {
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
if (ignores.isPathIgnored(pathRelativeToRepoRoot, true)) {
continue;
Expand Down Expand Up @@ -385,6 +385,8 @@ public void deleteFolder(String path) throws IOException {
} else {
throw new IOException("Not a directory: " + path);
}
} catch (GetMetadataErrorException e) {
// Do nothing; the folder does not exist.
} catch (DbxException e) {
e.printStackTrace();
if (e.getMessage() != null) {
Expand Down
9 changes: 9 additions & 0 deletions app/src/main/java/com/orgzly/android/repos/DropboxRepo.java
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,10 @@

import androidx.annotation.NonNull;

import com.orgzly.R;
import com.orgzly.android.App;
import com.orgzly.android.BookName;
import com.orgzly.android.prefs.AppPreferences;

import java.io.File;
import java.io.IOException;
Expand Down Expand Up @@ -56,11 +59,17 @@ public InputStream openRepoFileInputStream(String repoRelativePath) throws IOExc

@Override
public VersionedRook storeBook(File file, String repoRelativePath) throws IOException {
Context context = App.getAppContext();
if (repoRelativePath.contains("/") && !AppPreferences.subfolderSupport(context))
throw new IOException(context.getString(R.string.subfolder_support_disabled));
return client.upload(file, repoUri, repoRelativePath);
}

@Override
public VersionedRook renameBook(Uri oldFullUri, String newName) throws IOException {
Context context = App.getAppContext();
if (newName.contains("/") && !AppPreferences.subfolderSupport(context))
throw new IOException(context.getString(R.string.subfolder_support_disabled));
BookName oldBookName = BookName.fromRepoRelativePath(BookName.getRepoRelativePath(repoUri, oldFullUri));
String newRelativePath = BookName.repoRelativePath(newName, oldBookName.getFormat());
String newEncodedRelativePath = Uri.encode(newRelativePath, "/");
Expand Down
10 changes: 9 additions & 1 deletion app/src/main/java/com/orgzly/android/repos/GitRepo.java
Original file line number Diff line number Diff line change
Expand Up @@ -7,13 +7,16 @@
import android.util.Log;

import com.orgzly.BuildConfig;
import com.orgzly.R;
import com.orgzly.android.App;
import com.orgzly.android.BookFormat;
import com.orgzly.android.BookName;
import com.orgzly.android.db.entity.Repo;
import com.orgzly.android.git.GitFileSynchronizer;
import com.orgzly.android.git.GitPreferences;
import com.orgzly.android.git.GitPreferencesFromRepoPrefs;
import com.orgzly.android.git.GitTransportSetter;
import com.orgzly.android.prefs.AppPreferences;
import com.orgzly.android.prefs.RepoPreferences;
import com.orgzly.android.util.LogUtils;

Expand Down Expand Up @@ -260,6 +263,7 @@ public List<VersionedRook> getBooks() throws IOException {
walk.setRecursive(true);
walk.addTree(synchronizer.currentHead().getTree());
final RepoIgnoreNode ignores = new RepoIgnoreNode(this);
boolean supportsSubFolders = AppPreferences.subfolderSupport(App.getAppContext());
walk.setFilter(new TreeFilter() {
@Override
public boolean include(TreeWalk walker) {
Expand All @@ -269,7 +273,7 @@ public boolean include(TreeWalk walker) {
if (ignores.isIgnored(repoRelativePath, isDirectory) == IgnoreNode.MatchResult.IGNORED)
return false;
if (isDirectory)
return true;
return supportsSubFolders;
return BookName.isSupportedFormatFileName(repoRelativePath);
}

Expand Down Expand Up @@ -298,6 +302,10 @@ public void delete(Uri uri) throws IOException {
}

public VersionedRook renameBook(Uri oldFullUri, String newName) throws IOException {
Context context = App.getAppContext();
if (newName.contains("/") && !AppPreferences.subfolderSupport(context)) {
throw new IOException(context.getString(R.string.subfolder_support_disabled));
}
String oldPath = oldFullUri.toString().replaceFirst("^/", "");
String newPath = BookName.repoRelativePath(newName, BookFormat.ORG);
if (synchronizer.renameFileInRepo(oldPath, newPath)) {
Expand Down
17 changes: 16 additions & 1 deletion app/src/main/java/com/orgzly/android/repos/WebdavRepo.kt
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,10 @@ import com.burgstaller.okhttp.basic.BasicAuthenticator
import com.burgstaller.okhttp.digest.CachingAuthenticator
import com.burgstaller.okhttp.digest.Credentials
import com.burgstaller.okhttp.digest.DigestAuthenticator
import com.orgzly.R
import com.orgzly.android.App
import com.orgzly.android.BookName
import com.orgzly.android.prefs.AppPreferences
import com.thegrizzlylabs.sardineandroid.DavResource
import com.thegrizzlylabs.sardineandroid.impl.OkHttpSardine
import okhttp3.OkHttpClient
Expand Down Expand Up @@ -166,8 +169,14 @@ class WebdavRepo(

val ignores = RepoIgnoreNode(this)

val listDepth = if (AppPreferences.subfolderSupport(App.getAppContext())) {
-1
} else {
1
}

return sardine
.list(url, -1)
.list(url, listDepth)
.mapNotNull {
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
if (!BookName.isSupportedFormatFileName(it.name) || ignores.isPathIgnored(it.getRelativePath(), it.isDirectory)) {
Expand Down Expand Up @@ -222,6 +231,9 @@ class WebdavRepo(
val encodedRepoPath = Uri.encode(repoRelativePath, "/")
if (encodedRepoPath != null) {
if (encodedRepoPath.contains("/")) {
val context = App.getAppContext()
if (!AppPreferences.subfolderSupport(context))
throw IOException(context.getString(R.string.subfolder_support_disabled))
ensureDirectoryHierarchy(encodedRepoPath)
}
}
Expand All @@ -244,6 +256,9 @@ class WebdavRepo(
}

if (newName.contains("/")) {
val context = App.getAppContext()
if (!AppPreferences.subfolderSupport(context))
throw IOException(context.getString(R.string.subfolder_support_disabled))
ensureDirectoryHierarchy(newEncodedRelativePath)
}

Expand Down
4 changes: 4 additions & 0 deletions app/src/main/res/values/prefs_keys.xml
Original file line number Diff line number Diff line change
Expand Up @@ -561,6 +561,10 @@
<string name="pref_key_highlight_edited_rich_text" translatable="false">pref_key_highlight_edited_rich_text</string>
<bool name="pref_default_highlight_edited_rich_text" translatable="false">false</bool>

<!-- Subfolder support -->
<string name="pref_key_enable_repo_subfolders" translatable="false">pref_key_enable_repo_subfolders</string>
<bool name="pref_default_enable_repo_subfolders" translatable="false">false</bool>

<!-- Git preferences -->
<string name="pref_key_git_ssh_key_type" translatable="false">pref_key_git_ssh_key_type</string>
<string name="pref_key_git_author" traslatable="false">pref_key_git_author</string>
Expand Down
4 changes: 4 additions & 0 deletions app/src/main/res/values/strings.xml
Original file line number Diff line number Diff line change
Expand Up @@ -87,6 +87,8 @@
<!-- Preferences (Settings). -->
<string name="repos_preference_title">Repositories</string>
<string name="repos_preference_summary">Location to synchronize your notebooks with</string>
<string name="enable_repo_subfolders_preferences_title">Support repository subfolders</string>
<string name="enable_repo_subfolders_preferences_summary">Load from and write to subfolders</string>
<string name="ssh_keygen_preference_title">SSH key generation</string>
<string name="ssh_keygen_preference_summary">Generate key pair for Git repo sync</string>
<string name="ssh_show_public_key_preference_title">View generated SSH public key</string>
Expand Down Expand Up @@ -784,4 +786,6 @@
<string name="sync_status_saved">Saved to %s</string>

<string name="moving_between_subdirectories_requires_api_24">Renaming notebook to a different subdirectory requires Android 7 or higher</string>

<string name="subfolder_support_disabled">Support for subfolders is disabled</string>
</resources>
6 changes: 6 additions & 0 deletions app/src/main/res/xml/prefs_screen_sync.xml
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,12 @@
android:targetClass="com.orgzly.android.ui.repos.ReposActivity"/>
</Preference>

<SwitchPreference
android:key="@string/pref_key_enable_repo_subfolders"
android:title="@string/enable_repo_subfolders_preferences_title"
android:summary="@string/enable_repo_subfolders_preferences_summary"
android:defaultValue="@bool/pref_default_enable_repo_subfolders"/>

<androidx.preference.PreferenceScreen
android:key="prefs_screen_auto_sync"
android:title="@string/auto_sync"
Expand Down
32 changes: 26 additions & 6 deletions app/src/test/java/com/orgzly/android/repos/DropboxRepoTest.kt
Original file line number Diff line number Diff line change
Expand Up @@ -54,8 +54,13 @@ class DropboxRepoTest : SyncRepoTest {
}

@Test
override fun testGetBooks_singleFileInSubfolder() {
SyncRepoTest.testGetBooks_singleFileInSubfolder(client, syncRepo)
override fun testGetBooks_singleFileInSubfolderWhenEnabled() {
SyncRepoTest.testGetBooks_singleFileInSubfolderWhenEnabled(client, syncRepo)
}

@Test
override fun testGetBooks_singleFileInSubfolderWhenDisabled() {
SyncRepoTest.testGetBooks_singleFileInSubfolderWhenDisabled(client, syncRepo)
}

@Test
Expand Down Expand Up @@ -84,8 +89,13 @@ class DropboxRepoTest : SyncRepoTest {
}

@Test
override fun testStoreBook_producesSameUriAsRetrieveBook() {
SyncRepoTest.testStoreBook_producesSameUriAsRetrieveBook(syncRepo)
override fun testStoreBook_producesSameUriAsRetrieveBookWithSubfolder() {
SyncRepoTest.testStoreBook_producesSameUriAsRetrieveBookWithSubfolder(syncRepo)
}

@Test
override fun testStoreBook_producesSameUriAsRetrieveBookWithoutSubfolder() {
SyncRepoTest.testStoreBook_producesSameUriAsRetrieveBookWithoutSubfolder(syncRepo)
}

@Test
Expand All @@ -98,6 +108,11 @@ class DropboxRepoTest : SyncRepoTest {
SyncRepoTest.testStoreBook_inSubfolder(client, syncRepo)
}

@Test(expected = IOException::class)
override fun testStoreBook_inSubfolderWhenDisabled() {
SyncRepoTest.testStoreBook_inSubfolderWhenDisabled(syncRepo)
}

@Test
override fun testRenameBook_expectedUri() {
SyncRepoTest.testRenameBook_expectedUri(syncRepo)
Expand All @@ -109,8 +124,13 @@ class DropboxRepoTest : SyncRepoTest {
}

@Test
override fun testRenameBook_fromRootToSubfolder() {
SyncRepoTest.testRenameBook_fromRootToSubfolder(syncRepo)
override fun testRenameBook_fromRootToSubfolderWhenEnabled() {
SyncRepoTest.testRenameBook_fromRootToSubfolderWhenEnabled(syncRepo)
}

@Test(expected = IOException::class)
override fun testRenameBook_fromRootToSubfolderWhenDisabled() {
SyncRepoTest.testRenameBook_fromRootToSubfolderWhenDisabled(syncRepo)
}

@Test
Expand Down
Loading

0 comments on commit 70b7952

Please sign in to comment.