From a0d80c2760a5f9aff87f78580d6b78001ee1a7fa Mon Sep 17 00:00:00 2001 From: alperozturk96 Date: Tue, 14 Apr 2026 15:31:26 +0200 Subject: [PATCH 1/6] fix(file-list): browse up Signed-off-by: alperozturk96 --- .../ui/fragment/OCFileListFragment.java | 62 ++----- .../ui/fragment/helper/ParentFolderFinder.kt | 113 ++++++++++++ .../android/ui/db/ParentFolderFinderTest.kt | 168 ++++++++++++++++++ 3 files changed, 294 insertions(+), 49 deletions(-) create mode 100644 app/src/main/java/com/owncloud/android/ui/fragment/helper/ParentFolderFinder.kt create mode 100644 app/src/test/java/com/owncloud/android/ui/db/ParentFolderFinderTest.kt diff --git a/app/src/main/java/com/owncloud/android/ui/fragment/OCFileListFragment.java b/app/src/main/java/com/owncloud/android/ui/fragment/OCFileListFragment.java index ae434dbebba3..5ebb9109969b 100644 --- a/app/src/main/java/com/owncloud/android/ui/fragment/OCFileListFragment.java +++ b/app/src/main/java/com/owncloud/android/ui/fragment/OCFileListFragment.java @@ -80,7 +80,6 @@ import com.owncloud.android.lib.resources.e2ee.ToggleEncryptionRemoteOperation; import com.owncloud.android.lib.resources.files.SearchRemoteOperation; import com.owncloud.android.lib.resources.files.ToggleFavoriteRemoteOperation; -import com.owncloud.android.lib.resources.files.model.RemoteFile; import com.owncloud.android.lib.resources.status.E2EVersion; import com.owncloud.android.lib.resources.status.OCCapability; import com.owncloud.android.lib.resources.status.Type; @@ -106,6 +105,7 @@ import com.owncloud.android.ui.events.FavoriteEvent; import com.owncloud.android.ui.events.FileLockEvent; import com.owncloud.android.ui.events.SearchEvent; +import com.owncloud.android.ui.fragment.helper.ParentFolderFinder; import com.owncloud.android.ui.helpers.FileOperationsHelper; import com.owncloud.android.ui.interfaces.OCFileListFragmentInterface; import com.owncloud.android.ui.preview.PreviewImageFragment; @@ -124,7 +124,6 @@ import org.greenrobot.eventbus.Subscribe; import org.greenrobot.eventbus.ThreadMode; -import java.io.File; import java.util.ArrayList; import java.util.Collection; import java.util.HashSet; @@ -228,6 +227,7 @@ public class OCFileListFragment extends ExtendedListFragment implements protected String mLimitToMimeType; private FloatingActionButton mFabMain; public static boolean isMultipleFileSelectedForCopyOrMove = false; + private final ParentFolderFinder parentFolderFinder = new ParentFolderFinder(); private static final Intent scanIntentExternalApp = new Intent("org.fairscan.app.action.SCAN_TO_PDF"); @@ -1019,7 +1019,6 @@ private void updateSortAndGridMenuItems() { } } - /** * Call this, when the user presses the up button. *

@@ -1029,62 +1028,27 @@ private void updateSortAndGridMenuItems() { * return Count of folder levels browsed up. */ public int onBrowseUp() { - if (mFile == null) { + if (mFile == null || mFile.isRootDirectory()) { + return 0; + } + + final var result = parentFolderFinder.getParent(mFile, mContainerActivity.getStorageManager()); + OCFile target = result.getSecond(); + + if (target == null) { + Log_OC.e(TAG, "onBrowseUp: could not resolve parent, staying put"); return 0; } - Pair result = getPreviousFile(); - mFile = result.second; + mFile = target; setFileDepth(mFile); - // since on browse down sets it to the false, browse up should set back to true if current search type is not NO_SEARCH if (mFile.isRootDirectory() && currentSearchType != NO_SEARCH) { searchFragment = true; } updateFileList(); - return result.first; - } - - private Pair getPreviousFile() { - if (mFile == null) { - return new Pair<>(0, null); - } - - FileDataStorageManager storageManager = mContainerActivity.getStorageManager(); - int moveCount = 0; - String parentPath; - OCFile parentDir; - - if (mFile.getParentId() != FileDataStorageManager.ROOT_PARENT_ID) { - parentPath = new File(mFile.getRemotePath()).getParent(); - parentPath = ensureTrailingSeparator(parentPath); - parentDir = storageManager.getFileByPath(parentPath); - moveCount++; - } else { - parentDir = storageManager.getFileByPath(ROOT_PATH); - parentPath = ROOT_PATH; - } - - // Keep going up until we find a valid folder - while (parentDir == null && !ROOT_PATH.equals(parentPath)) { - parentPath = new File(parentPath).getParent(); - if (parentPath == null) { - parentPath = ROOT_PATH; // fallback to root - } - parentPath = ensureTrailingSeparator(parentPath); - parentDir = storageManager.getFileByPath(parentPath); - moveCount++; - } - - return new Pair<>(moveCount, parentDir); - } - - private String ensureTrailingSeparator(String path) { - if (path == null) { - return ROOT_PATH; - } - return path.endsWith(OCFile.PATH_SEPARATOR) ? path : path + OCFile.PATH_SEPARATOR; + return result.getFirst(); } private void updateFileList() { diff --git a/app/src/main/java/com/owncloud/android/ui/fragment/helper/ParentFolderFinder.kt b/app/src/main/java/com/owncloud/android/ui/fragment/helper/ParentFolderFinder.kt new file mode 100644 index 000000000000..c39902692032 --- /dev/null +++ b/app/src/main/java/com/owncloud/android/ui/fragment/helper/ParentFolderFinder.kt @@ -0,0 +1,113 @@ +/* + * Nextcloud - Android Client + * + * SPDX-FileCopyrightText: 2026 Alper Ozturk + * SPDX-License-Identifier: AGPL-3.0-or-later + */ + +package com.owncloud.android.ui.fragment.helper + +import com.owncloud.android.datamodel.FileDataStorageManager +import com.owncloud.android.datamodel.OCFile +import com.owncloud.android.lib.common.utils.Log_OC + +class ParentFolderFinder { + companion object { + private const val TAG = "ParentFolderFinder" + } + + fun getParent(file: OCFile?, storageManager: FileDataStorageManager?): Pair { + if (file == null || file.isRootDirectory) { + Log_OC.e(TAG, "File is null or already at root") + return 0 to file + } + + if (storageManager == null) { + Log_OC.e(TAG, "StorageManager is null") + return 0 to file + } + + // id based lookup + val parentId = file.parentId + if (parentId > FileDataStorageManager.ROOT_PARENT_ID && parentId != file.fileId) { + storageManager.getFileById(parentId)?.let { parentById -> + if (parentById.isFolder) { + return 1 to parentById + } + } + + Log_OC.w(TAG, "ID lookup missed for parentId=$parentId, falling back to path walk") + } + + // path-based walk up + return walkUpByPath(file.remotePath, storageManager) + } + + /** + * Walks the remote path upward one segment at a time until a valid folder + * is found in the DB, or we reach root. + */ + private fun walkUpByPath(initialPath: String?, storageManager: FileDataStorageManager): Pair { + var path = initialPath + var moveCount = 0 + + while (!path.isNullOrEmpty() && path != OCFile.ROOT_PATH) { + val parentPath = resolveParentPath(path) + moveCount++ + + if (parentPath == null) { + Log_OC.w(TAG, "Failed to resolve parent path for $path, fallback to root") + break + } + + // Check if this resolved parent exists in DB + storageManager.getFileByEncryptedRemotePath(parentPath)?.let { candidate -> + if (candidate.isFolder) { + return moveCount to candidate + } + } + + if (parentPath == OCFile.ROOT_PATH) { + Log_OC.w(TAG, "Root path reached but not found in DB loop, forcing fallback") + break + } + + // Move up one more level for the next iteration + path = parentPath + } + + // fallback to root + val root = storageManager.getFileByEncryptedRemotePath(OCFile.ROOT_PATH) + return moveCount to root + } + + /** + * Returns the parent path of `path` with a guaranteed trailing "/", + * or `null` if `path` is already root or invalid. + * + * + * Correctly handles paths with or without a trailing separator, so both + * "/Foo/Bar" and "/Foo/Bar/" return "/Foo/". + */ + private fun resolveParentPath(path: String?): String? { + if (path.isNullOrEmpty() || path == OCFile.ROOT_PATH) { + return null + } + + // Strip trailing "/" before computing parent + val normalized = if (path.endsWith(OCFile.PATH_SEPARATOR)) { + path.substring(0, path.length - 1) + } else { + path + } + + val lastSep = normalized.lastIndexOf(OCFile.PATH_SEPARATOR) + if (lastSep <= 0) { + Log_OC.w(TAG, "No separator found, or only one at the start") + return OCFile.ROOT_PATH + } + + // e.g. "/Foo/Bar" → "/Foo/" + return normalized.substring(0, lastSep + 1) + } +} diff --git a/app/src/test/java/com/owncloud/android/ui/db/ParentFolderFinderTest.kt b/app/src/test/java/com/owncloud/android/ui/db/ParentFolderFinderTest.kt new file mode 100644 index 000000000000..c3ddfd17b62d --- /dev/null +++ b/app/src/test/java/com/owncloud/android/ui/db/ParentFolderFinderTest.kt @@ -0,0 +1,168 @@ +/* + * Nextcloud - Android Client + * + * SPDX-FileCopyrightText: 2026 Alper Ozturk + * SPDX-License-Identifier: AGPL-3.0-or-later + */ + +package com.owncloud.android.ui.db + +import com.owncloud.android.datamodel.FileDataStorageManager +import com.owncloud.android.datamodel.OCFile +import com.owncloud.android.ui.fragment.helper.ParentFolderFinder +import com.owncloud.android.utils.MimeType +import io.mockk.every +import io.mockk.mockk +import junit.framework.TestCase.assertEquals +import junit.framework.TestCase.assertNull +import org.junit.Before +import org.junit.Test + +@Suppress("TooManyFunctions", "MagicNumber") +class ParentFolderFinderTest { + + private lateinit var storageManager: FileDataStorageManager + private lateinit var finder: ParentFolderFinder + + @Before + fun setup() { + storageManager = mockk(relaxed = true) + finder = ParentFolderFinder() + } + + @Test + fun getParentWithNullFileReturnsZeroAndNull() { + val result = finder.getParent(null, storageManager) + + assertEquals(0, result.first) + assertNull(result.second) + } + + @Test + fun getParentWithRootFileReturnsZeroAndFile() { + val rootFile = OCFile(OCFile.ROOT_PATH).apply { + parentId = 0 + } + + val result = finder.getParent(rootFile, storageManager) + + assertEquals(0, result.first) + assertEquals(rootFile, result.second) + } + + @Test + fun getParentWithNullStorageManagerReturnsZeroAndFile() { + val file = OCFile("/test.txt") + + val result = finder.getParent(file, null) + + assertEquals(0, result.first) + assertEquals(file, result.second) + } + + @Test + fun getParentWithValidParentIdReturnsOneAndParentFile() { + val parentFolder = OCFile("/parent/").apply { + fileId = 10 + mimeType = MimeType.DIRECTORY + } + val childFile = OCFile("/parent/child.txt").apply { + fileId = 11 + parentId = 10 + } + + every { storageManager.getFileById(10L) } returns parentFolder + + val result = finder.getParent(childFile, storageManager) + + assertEquals(1, result.first) + assertEquals(parentFolder, result.second) + } + + @Test + fun getParentWithInvalidParentIdWalksUpPath() { + val parentFolder = OCFile("/parent/").apply { + fileId = 10 + mimeType = MimeType.DIRECTORY + } + val childFile = OCFile("/parent/child.txt").apply { + fileId = 11 + parentId = 99 + remotePath = "/parent/child.txt" + } + + every { storageManager.getFileById(99L) } returns null + every { storageManager.getFileByEncryptedRemotePath("/parent/") } returns parentFolder + + val result = finder.getParent(childFile, storageManager) + + assertEquals(1, result.first) + assertEquals(parentFolder, result.second) + } + + @Test + fun getParentWalksMultipleLevelsUp() { + val grandParentFolder = OCFile("/parent/").apply { + fileId = 10 + mimeType = MimeType.DIRECTORY + } + val childFile = OCFile("/parent/sub/child.txt").apply { + fileId = 12 + parentId = 11 + remotePath = "/parent/sub/child.txt" + } + + every { storageManager.getFileById(11L) } returns null + every { storageManager.getFileByEncryptedRemotePath("/parent/sub/") } returns null + every { storageManager.getFileByEncryptedRemotePath("/parent/") } returns grandParentFolder + + val result = finder.getParent(childFile, storageManager) + + assertEquals(2, result.first) + assertEquals(grandParentFolder, result.second) + } + + @Test + fun getParentWalksUpToRootAndReturnsRootFallback() { + val rootFolder = OCFile(OCFile.ROOT_PATH).apply { + fileId = 1 + mimeType = MimeType.DIRECTORY + } + val childFile = OCFile("/a/b/c.txt").apply { + fileId = 12 + parentId = 11 + remotePath = "/a/b/c.txt" + } + + every { storageManager.getFileById(11L) } returns null + every { storageManager.getFileByEncryptedRemotePath("/a/b/") } returns null + every { storageManager.getFileByEncryptedRemotePath("/a/") } returns null + every { storageManager.getFileByEncryptedRemotePath(OCFile.ROOT_PATH) } returns rootFolder + + val result = finder.getParent(childFile, storageManager) + + assertEquals(3, result.first) + assertEquals(rootFolder, result.second) + } + + @Test + fun getParentWalksUpToRootWithTrailingSlash() { + val rootFolder = OCFile(OCFile.ROOT_PATH).apply { + fileId = 1 + mimeType = MimeType.DIRECTORY + } + val childFolder = OCFile("/folder/").apply { + fileId = 2 + parentId = 99 + remotePath = "/folder/" + } + + every { storageManager.getFileById(99L) } returns null + every { storageManager.getFileByEncryptedRemotePath(OCFile.ROOT_PATH) } returns rootFolder + + val result = finder.getParent(childFolder, storageManager) + + assertEquals(1, result.first) + assertEquals(rootFolder, result.second) + } +} From cb908e7710d916cef82aa9d25a07957ccfd2e178 Mon Sep 17 00:00:00 2001 From: alperozturk96 Date: Tue, 14 Apr 2026 15:40:44 +0200 Subject: [PATCH 2/6] fix(file-list): browse up Signed-off-by: alperozturk96 --- .../owncloud/android/ui/db/ParentFolderFinderTest.kt | 12 ------------ 1 file changed, 12 deletions(-) diff --git a/app/src/test/java/com/owncloud/android/ui/db/ParentFolderFinderTest.kt b/app/src/test/java/com/owncloud/android/ui/db/ParentFolderFinderTest.kt index c3ddfd17b62d..4e7e40e6a9d2 100644 --- a/app/src/test/java/com/owncloud/android/ui/db/ParentFolderFinderTest.kt +++ b/app/src/test/java/com/owncloud/android/ui/db/ParentFolderFinderTest.kt @@ -38,18 +38,6 @@ class ParentFolderFinderTest { assertNull(result.second) } - @Test - fun getParentWithRootFileReturnsZeroAndFile() { - val rootFile = OCFile(OCFile.ROOT_PATH).apply { - parentId = 0 - } - - val result = finder.getParent(rootFile, storageManager) - - assertEquals(0, result.first) - assertEquals(rootFile, result.second) - } - @Test fun getParentWithNullStorageManagerReturnsZeroAndFile() { val file = OCFile("/test.txt") From d797835c290eaaf92d70abe958e2f00133ce60a0 Mon Sep 17 00:00:00 2001 From: alperozturk96 Date: Tue, 14 Apr 2026 15:50:26 +0200 Subject: [PATCH 3/6] fix(file-list): browse up Signed-off-by: alperozturk96 --- .../owncloud/android/ui/fragment/helper/ParentFolderFinder.kt | 1 + 1 file changed, 1 insertion(+) diff --git a/app/src/main/java/com/owncloud/android/ui/fragment/helper/ParentFolderFinder.kt b/app/src/main/java/com/owncloud/android/ui/fragment/helper/ParentFolderFinder.kt index c39902692032..859a40c79267 100644 --- a/app/src/main/java/com/owncloud/android/ui/fragment/helper/ParentFolderFinder.kt +++ b/app/src/main/java/com/owncloud/android/ui/fragment/helper/ParentFolderFinder.kt @@ -11,6 +11,7 @@ import com.owncloud.android.datamodel.FileDataStorageManager import com.owncloud.android.datamodel.OCFile import com.owncloud.android.lib.common.utils.Log_OC +@Suppress("ReturnCount") class ParentFolderFinder { companion object { private const val TAG = "ParentFolderFinder" From cf5746a02b748f86e0f3090ebbf92063f0716ccc Mon Sep 17 00:00:00 2001 From: alperozturk96 Date: Wed, 15 Apr 2026 14:11:16 +0200 Subject: [PATCH 4/6] add tests Signed-off-by: alperozturk96 --- .../android/ui/db/ParentFolderFinderTest.kt | 49 +++++++++++++++++++ 1 file changed, 49 insertions(+) diff --git a/app/src/test/java/com/owncloud/android/ui/db/ParentFolderFinderTest.kt b/app/src/test/java/com/owncloud/android/ui/db/ParentFolderFinderTest.kt index 4e7e40e6a9d2..1128c7a6b751 100644 --- a/app/src/test/java/com/owncloud/android/ui/db/ParentFolderFinderTest.kt +++ b/app/src/test/java/com/owncloud/android/ui/db/ParentFolderFinderTest.kt @@ -153,4 +153,53 @@ class ParentFolderFinderTest { assertEquals(1, result.first) assertEquals(rootFolder, result.second) } + + @Test + fun getParentWhenInFolderCAndCIsRemovedRemotelyShouldReturnFolderB() { + val folderB = OCFile("/A/B/").apply { + fileId = 20 + mimeType = MimeType.DIRECTORY + } + val folderC = OCFile("/A/B/C/").apply { + fileId = 30 + parentId = 20 + remotePath = "/A/B/C/" + } + + // Even if C is deleted remotely, we still have its object in memory, + // and its parentId still correctly maps to B in the local database. + every { storageManager.getFileById(20L) } returns folderB + + val result = finder.getParent(folderC, storageManager) + + assertEquals(1, result.first) + assertEquals(folderB, result.second) + } + + @Test + fun getParentWhenInFolderCAndBIsRemovedRemotelyShouldReturnFolderA() { + val folderA = OCFile("/A/").apply { + fileId = 10 + mimeType = MimeType.DIRECTORY + } + val folderC = OCFile("/A/B/C/").apply { + fileId = 30 + parentId = 20 // Points to B + remotePath = "/A/B/C/" + } + + // ID lookup for B fails because it was removed + every { storageManager.getFileById(20L) } returns null + + // Iteration 1: Tries to find /A/B/ -> also fails + every { storageManager.getFileByEncryptedRemotePath("/A/B/") } returns null + + // Iteration 2: Tries to find /A/ -> Succeeds! + every { storageManager.getFileByEncryptedRemotePath("/A/") } returns folderA + + val result = finder.getParent(folderC, storageManager) + + assertEquals(2, result.first) + assertEquals(folderA, result.second) + } } From 27b324607b9895bcb5a67651aa5e625ba0a8eeb9 Mon Sep 17 00:00:00 2001 From: alperozturk96 Date: Wed, 15 Apr 2026 14:32:20 +0200 Subject: [PATCH 5/6] browse up if parent deleted instead all the time root Signed-off-by: alperozturk96 --- .../android/ui/activity/FileDisplayActivity.kt | 15 ++++++++++----- .../ui/fragment/OCFileListFragment.java | 2 +- .../ui/fragment/helper/ParentFolderFinder.kt | 18 ++++++++++++++++++ 3 files changed, 29 insertions(+), 6 deletions(-) diff --git a/app/src/main/java/com/owncloud/android/ui/activity/FileDisplayActivity.kt b/app/src/main/java/com/owncloud/android/ui/activity/FileDisplayActivity.kt index f4c9becd00b6..bf97b3796e12 100644 --- a/app/src/main/java/com/owncloud/android/ui/activity/FileDisplayActivity.kt +++ b/app/src/main/java/com/owncloud/android/ui/activity/FileDisplayActivity.kt @@ -1572,7 +1572,12 @@ class FileDisplayActivity : private fun handleRemovedFolder(syncFolderRemotePath: String?) { DisplayUtils.showSnackMessage(this, R.string.sync_current_folder_was_removed, syncFolderRemotePath) - browseToRoot() + fileListFragment?.let { + it.parentFolderFinder.getParentOnFirstParentRemoved(syncFolderRemotePath, storageManager)?.let { target -> + it.listDirectory(target, MainApp.isOnlyOnDevice()) + updateActionBarTitleAndHomeButton(target) + } + } } private fun updateFileList( @@ -1896,13 +1901,13 @@ class FileDisplayActivity : // endregion fun browseToRoot() { - val listOfFiles = this.listOfFilesFragment - if (listOfFiles != null) { // should never be null, indeed + listOfFilesFragment?.let { val root = storageManager.getFileByPath(OCFile.ROOT_PATH) - listOfFiles.resetSearchAttributes() - file = listOfFiles.currentFile + it.resetSearchAttributes() + file = it.currentFile startSyncFolderOperation(root, false) } + binding.fabMain.setImageResource(R.drawable.ic_plus) resetScrollingAndUpdateActionBar() } diff --git a/app/src/main/java/com/owncloud/android/ui/fragment/OCFileListFragment.java b/app/src/main/java/com/owncloud/android/ui/fragment/OCFileListFragment.java index 5ebb9109969b..9a1d35e2dfb7 100644 --- a/app/src/main/java/com/owncloud/android/ui/fragment/OCFileListFragment.java +++ b/app/src/main/java/com/owncloud/android/ui/fragment/OCFileListFragment.java @@ -227,7 +227,7 @@ public class OCFileListFragment extends ExtendedListFragment implements protected String mLimitToMimeType; private FloatingActionButton mFabMain; public static boolean isMultipleFileSelectedForCopyOrMove = false; - private final ParentFolderFinder parentFolderFinder = new ParentFolderFinder(); + public final ParentFolderFinder parentFolderFinder = new ParentFolderFinder(); private static final Intent scanIntentExternalApp = new Intent("org.fairscan.app.action.SCAN_TO_PDF"); diff --git a/app/src/main/java/com/owncloud/android/ui/fragment/helper/ParentFolderFinder.kt b/app/src/main/java/com/owncloud/android/ui/fragment/helper/ParentFolderFinder.kt index 859a40c79267..30bd4c4c49e3 100644 --- a/app/src/main/java/com/owncloud/android/ui/fragment/helper/ParentFolderFinder.kt +++ b/app/src/main/java/com/owncloud/android/ui/fragment/helper/ParentFolderFinder.kt @@ -17,6 +17,24 @@ class ParentFolderFinder { private const val TAG = "ParentFolderFinder" } + /** + * User tries to move up but parent folder was deleted thus parent of parent + * will be used as destination else ROOT directory + */ + fun getParentOnFirstParentRemoved(path: String?, storageManager: FileDataStorageManager?): OCFile? { + if (storageManager == null) { + Log_OC.e(TAG, "StorageManager is null") + return null + } + + if (path.isNullOrEmpty() || path == OCFile.ROOT_PATH) { + Log_OC.w(TAG, "Path is null, empty, or already at root. Falling back to ROOT.") + return storageManager.getFileByEncryptedRemotePath(OCFile.ROOT_PATH) + } + + return walkUpByPath(path, storageManager).second + } + fun getParent(file: OCFile?, storageManager: FileDataStorageManager?): Pair { if (file == null || file.isRootDirectory) { Log_OC.e(TAG, "File is null or already at root") From 9f68089658bb99a35f3da6eb51299f1bae2f6545 Mon Sep 17 00:00:00 2001 From: alperozturk96 Date: Wed, 15 Apr 2026 14:37:04 +0200 Subject: [PATCH 6/6] browse up if parent deleted instead all the time root Signed-off-by: alperozturk96 --- .../java/com/owncloud/android/ui/activity/FileDisplayActivity.kt | 1 + 1 file changed, 1 insertion(+) diff --git a/app/src/main/java/com/owncloud/android/ui/activity/FileDisplayActivity.kt b/app/src/main/java/com/owncloud/android/ui/activity/FileDisplayActivity.kt index bf97b3796e12..05ed6933bed0 100644 --- a/app/src/main/java/com/owncloud/android/ui/activity/FileDisplayActivity.kt +++ b/app/src/main/java/com/owncloud/android/ui/activity/FileDisplayActivity.kt @@ -1576,6 +1576,7 @@ class FileDisplayActivity : it.parentFolderFinder.getParentOnFirstParentRemoved(syncFolderRemotePath, storageManager)?.let { target -> it.listDirectory(target, MainApp.isOnlyOnDevice()) updateActionBarTitleAndHomeButton(target) + file = target } } }