From 3bfc373e5007b70f6b114c02818996399ec43ab3 Mon Sep 17 00:00:00 2001 From: tobiasKaminsky Date: Mon, 31 Jan 2022 11:28:02 +0100 Subject: [PATCH] Enhance media tab Signed-off-by: tobiasKaminsky --- build.gradle | 2 +- .../android/ui/adapter/OCFileListAdapterIT.kt | 79 ++++++++ .../datamodel/FileDataStorageManager.java | 104 +++++++++++ .../owncloud/android/datamodel/OCFile.java | 3 + .../com/owncloud/android/db/ProviderMeta.java | 3 +- .../providers/FileContentProvider.java | 24 ++- .../android/ui/adapter/OCFileListAdapter.java | 31 +++- .../ui/asynctasks/GallerySearchTask.java | 175 +++++++++++++----- .../android/ui/fragment/GalleryFragment.java | 131 ++++++------- .../ui/fragment/OCFileListFragment.java | 12 +- .../OCFileListFragmentInterface.java | 2 + 11 files changed, 445 insertions(+), 121 deletions(-) create mode 100644 src/androidTest/java/com/owncloud/android/ui/adapter/OCFileListAdapterIT.kt diff --git a/build.gradle b/build.gradle index 5432255b8d..de5c3e80fd 100644 --- a/build.gradle +++ b/build.gradle @@ -64,7 +64,7 @@ ext { daggerVersion = "2.40.5" markwonVersion = "4.6.2" prismVersion = "2.0.0" - androidLibraryVersion = "master-SNAPSHOT" + androidLibraryVersion = "limitDates-SNAPSHOT" mockitoVersion = "4.3.1" mockkVersion = "1.12.2" powermockVersion = "2.0.9" diff --git a/src/androidTest/java/com/owncloud/android/ui/adapter/OCFileListAdapterIT.kt b/src/androidTest/java/com/owncloud/android/ui/adapter/OCFileListAdapterIT.kt new file mode 100644 index 0000000000..e40e7d1b2f --- /dev/null +++ b/src/androidTest/java/com/owncloud/android/ui/adapter/OCFileListAdapterIT.kt @@ -0,0 +1,79 @@ +/* + * + * Nextcloud Android client application + * + * @author Tobias Kaminsky + * Copyright (C) 2022 Tobias Kaminsky + * Copyright (C) 2022 Nextcloud GmbH + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU Affero 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 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 . + */ +package com.owncloud.android.ui.adapter + +import com.owncloud.android.AbstractIT +import com.owncloud.android.datamodel.OCFile +import org.junit.Assert.assertEquals +import org.junit.Test + +class OCFileListAdapterIT : AbstractIT() { + @Test + fun testParseMedia() { + // empty start + storageManager.deleteAllFiles() + + val startDate: Long = 0 + val endDate: Long = 3642752043 + assertEquals(0, storageManager.getGalleryItems(startDate, endDate).size) + + // create dummy files + OCFile("/test.txt", "01").apply { + mimeType = "text/plain" + }.let { + storageManager.saveFile(it) + } + + OCFile("/image.png", "02").apply { + mimeType = "image/png" + modificationTimestamp = 1000000 + }.let { + storageManager.saveFile(it) + } + + OCFile("/image2.png", "03").apply { + mimeType = "image/png" + modificationTimestamp = 1000050 + }.let { + storageManager.saveFile(it) + } + + OCFile("/video.mpg", "04").apply { + mimeType = "video/mpg" + modificationTimestamp = 1000045 + }.let { + storageManager.saveFile(it) + } + + OCFile("/video2.avi", "05").apply { + mimeType = "video/avi" + modificationTimestamp = endDate + 10 + }.let { + storageManager.saveFile(it) + } + + // list of remoteFiles + assertEquals(5, storageManager.allFiles.size) + assertEquals(3, storageManager.getGalleryItems(startDate, endDate).size) + assertEquals(4, storageManager.allGalleryItems.size) + } +} diff --git a/src/main/java/com/owncloud/android/datamodel/FileDataStorageManager.java b/src/main/java/com/owncloud/android/datamodel/FileDataStorageManager.java index 50e75d18b6..3463decd2e 100644 --- a/src/main/java/com/owncloud/android/datamodel/FileDataStorageManager.java +++ b/src/main/java/com/owncloud/android/datamodel/FileDataStorageManager.java @@ -2274,6 +2274,110 @@ public class FileDataStorageManager { } } + public boolean virtualExists(VirtualFolderType type, OCFile file) { + Cursor cursor; + + if (getContentProviderClient() != null) { + try { + cursor = getContentProviderClient().query( + ProviderTableMeta.CONTENT_URI_VIRTUAL, + null, + ProviderTableMeta.VIRTUAL_TYPE + AND + ProviderTableMeta.VIRTUAL_OCFILE_REMOTE_ID + " =?", + new String[]{String.valueOf(type), file.getRemoteId()}, + null + ); + } catch (RemoteException e) { + Log_OC.e(TAG, e.getMessage(), e); + return false; + } + } else { + cursor = getContentResolver().query( + ProviderTableMeta.CONTENT_URI_VIRTUAL, + null, + ProviderTableMeta.VIRTUAL_TYPE + AND + ProviderTableMeta.VIRTUAL_OCFILE_REMOTE_ID + " =?", + new String[]{String.valueOf(type), file.getRemoteId()}, + null + ); + } + + if (cursor == null) { + Log_OC.e(TAG, "Couldn't determine file existence, assuming non existence"); + + return false; + } else { + boolean exists = cursor.moveToFirst(); + cursor.close(); + + return exists; + } + } + + public List getAllGalleryItems() { + return getGalleryItems(0, Long.MAX_VALUE); + } + + public List getGalleryItems(long startDate, long endDate) { + List files = new ArrayList<>(); + + Uri requestURI = ProviderTableMeta.CONTENT_URI; + Cursor cursor; + + if (getContentProviderClient() != null) { + try { + cursor = getContentProviderClient().query( + requestURI, + null, + ProviderTableMeta.FILE_ACCOUNT_OWNER + AND + + ProviderTableMeta.FILE_MODIFIED + ">=? AND " + + ProviderTableMeta.FILE_MODIFIED + "=? AND " + + ProviderTableMeta.FILE_MODIFIED + " getVirtualFolderContent(VirtualFolderType type, boolean onlyImages) { List ocFiles = new ArrayList<>(); Uri req_uri = ProviderTableMeta.CONTENT_URI_VIRTUAL; diff --git a/src/main/java/com/owncloud/android/datamodel/OCFile.java b/src/main/java/com/owncloud/android/datamodel/OCFile.java index 0f38e7d9f7..08c8f1264c 100644 --- a/src/main/java/com/owncloud/android/datamodel/OCFile.java +++ b/src/main/java/com/owncloud/android/datamodel/OCFile.java @@ -603,6 +603,9 @@ public class OCFile implements Parcelable, Comparable, ServerFileInterfa return this.creationTimestamp; } + /** + * @return unix timestamp in milliseconds + */ public long getModificationTimestamp() { return this.modificationTimestamp; } diff --git a/src/main/java/com/owncloud/android/db/ProviderMeta.java b/src/main/java/com/owncloud/android/db/ProviderMeta.java index 7657fb40c9..723676fb28 100644 --- a/src/main/java/com/owncloud/android/db/ProviderMeta.java +++ b/src/main/java/com/owncloud/android/db/ProviderMeta.java @@ -35,7 +35,7 @@ import java.util.List; */ public class ProviderMeta { public static final String DB_NAME = "filelist"; - public static final int DB_VERSION = 62; + public static final int DB_VERSION = 63; private ProviderMeta() { // No instance @@ -286,6 +286,7 @@ public class ProviderMeta { // Columns of virtual public static final String VIRTUAL_TYPE = "type"; public static final String VIRTUAL_OCFILE_ID = "ocfile_id"; + public static final String VIRTUAL_OCFILE_REMOTE_ID = "ocfile_remote_id"; // Columns of filesystem data table public static final String FILESYSTEM_FILE_LOCAL_PATH = "local_path"; diff --git a/src/main/java/com/owncloud/android/providers/FileContentProvider.java b/src/main/java/com/owncloud/android/providers/FileContentProvider.java index a125ee02c0..babe439511 100644 --- a/src/main/java/com/owncloud/android/providers/FileContentProvider.java +++ b/src/main/java/com/owncloud/android/providers/FileContentProvider.java @@ -916,7 +916,8 @@ public class FileContentProvider extends ContentProvider { + ProviderTableMeta._ID + " INTEGER PRIMARY KEY, " // id + ProviderTableMeta.VIRTUAL_TYPE + " TEXT, " // type + ProviderTableMeta.VIRTUAL_OCFILE_ID + " INTEGER )" // file id - ); + + ProviderTableMeta.VIRTUAL_OCFILE_REMOTE_ID + " STRNING )" // remote id + ); } private void createFileSystemTable(SQLiteDatabase db) { @@ -2467,6 +2468,27 @@ public class FileContentProvider extends ContentProvider { if (!upgraded) { Log_OC.i(SQL, String.format(Locale.ENGLISH, UPGRADE_VERSION_MSG, oldVersion, newVersion)); } + + if (oldVersion < 63 && newVersion >= 63) { + Log_OC.i(SQL, "Entering in the #63 add remote_id to virtuals"); + db.beginTransaction(); + try { + db.execSQL(ALTER_TABLE + ProviderTableMeta.VIRTUAL_TABLE_NAME + + ADD_COLUMN + ProviderTableMeta.VIRTUAL_OCFILE_REMOTE_ID + " TEXT "); + + // delete all virtual + db.execSQL("DELETE FROM `virtual`"); + + upgraded = true; + db.setTransactionSuccessful(); + } finally { + db.endTransaction(); + } + } + + if (!upgraded) { + Log_OC.i(SQL, String.format(Locale.ENGLISH, UPGRADE_VERSION_MSG, oldVersion, newVersion)); + } } } } diff --git a/src/main/java/com/owncloud/android/ui/adapter/OCFileListAdapter.java b/src/main/java/com/owncloud/android/ui/adapter/OCFileListAdapter.java index 27c1fcbb98..2292df2007 100644 --- a/src/main/java/com/owncloud/android/ui/adapter/OCFileListAdapter.java +++ b/src/main/java/com/owncloud/android/ui/adapter/OCFileListAdapter.java @@ -753,7 +753,7 @@ public class OCFileListAdapter extends RecyclerView.Adapter objects, ExtendedListFragment.SearchType searchType, FileDataStorageManager storageManager, @Nullable OCFile folder, - boolean clear) { + boolean clear, + long startDate, + long endDate) { if (storageManager != null && mStorageManager == null) { mStorageManager = storageManager; showShareAvatar = mStorageManager.getCapability(user.getAccountName()).getVersion().isShareesOnDavSupported(); @@ -891,7 +892,9 @@ public class OCFileListAdapter extends RecyclerView.Adapter { - private int columnCount; - private User user; - private WeakReference photoFragmentWeakReference; - private SearchRemoteOperation searchRemoteOperation; - private FileDataStorageManager storageManager; - private int limit; + private final User user; + private final WeakReference photoFragmentWeakReference; + private final FileDataStorageManager storageManager; + private final int limit; + private final long startDate; + private final long endDate; - public GallerySearchTask(int columnsCount, - GalleryFragment photoFragment, + public GallerySearchTask(GalleryFragment photoFragment, User user, - SearchRemoteOperation searchRemoteOperation, - FileDataStorageManager storageManager) { - this.columnCount = columnsCount; + FileDataStorageManager storageManager, + long startDate, + long endDate, + int limit) { this.user = user; this.photoFragmentWeakReference = new WeakReference<>(photoFragment); - this.searchRemoteOperation = searchRemoteOperation; this.storageManager = storageManager; + this.startDate = startDate; + this.endDate = endDate; + this.limit = limit; } - @Override - protected void onPreExecute() { - super.onPreExecute(); - - if (photoFragmentWeakReference.get() == null) { - return; - } - GalleryFragment photoFragment = photoFragmentWeakReference.get(); - photoFragment.setPhotoSearchQueryRunning(true); - } +// @Override +// protected void onPreExecute() { +// super.onPreExecute(); +// +// if (photoFragmentWeakReference.get() == null) { +// return; +// } +// GalleryFragment photoFragment = photoFragmentWeakReference.get(); +// // photoFragment.searchCompleted(true, lastTimeStamp); +// } @Override protected RemoteOperationResult doInBackground(Void... voids) { +// try { +// Thread.sleep(5 * 1000); +// } catch (InterruptedException e) { +// e.printStackTrace(); +// } + if (photoFragmentWeakReference.get() == null) { return new RemoteOperationResult(new Exception("Photo fragment is null")); } GalleryFragment photoFragment = photoFragmentWeakReference.get(); - OCFileListAdapter adapter = photoFragment.getAdapter(); if (isCancelled()) { return new RemoteOperationResult(new Exception("Cancelled")); } else { - limit = 15 * columnCount; + OCCapability ocCapability = storageManager.getCapability(user.getAccountName()); + + SearchRemoteOperation searchRemoteOperation = new SearchRemoteOperation("", + SearchRemoteOperation.SearchType.GALLERY_SEARCH, + false, + ocCapability); - long timestamp = -1; - if (adapter.getLastTimestamp() > 0) { - timestamp = adapter.getLastTimestamp(); - } searchRemoteOperation.setLimit(limit); - searchRemoteOperation.setTimestamp(timestamp); + searchRemoteOperation.setStartDate(startDate); + searchRemoteOperation.setEndDate(endDate); if (photoFragment.getContext() != null) { + Log_OC.d(this, + "Start gallery search with " + new Date(startDate * 1000L) + + " - " + new Date(endDate * 1000L) + + " with limit: " + limit); return searchRemoteOperation.execute(user.toPlatformAccount(), photoFragment.getContext()); } else { return new RemoteOperationResult(new IllegalStateException("No context available")); @@ -100,35 +123,91 @@ public class GallerySearchTask extends AsyncTask remoteFiles) { + int lastPosition = remoteFiles.size() - 1; + + if (lastPosition < 0) { + return -1; + } + + RemoteFile lastFile = remoteFiles.get(lastPosition); + return lastFile.getModifiedTimestamp() / 1000; + } + + private boolean parseMedia(long startDate, long endDate, List remoteFiles) { + // retrieve all between startDate and endDate + Map localFilesMap = RefreshFolderOperation.prefillLocalFilesMap(null, + storageManager.getGalleryItems(startDate * 1000L, + endDate * 1000L)); + List filesToAdd = new ArrayList<>(); + List filesToUpdate = new ArrayList<>(); + + OCFile localFile; + for (Object file : remoteFiles) { + OCFile ocFile = FileStorageUtils.fillOCFile((RemoteFile) file); + + localFile = localFilesMap.remove(ocFile.getRemotePath()); + + if (localFile == null) { + // add new file + filesToAdd.add(ocFile); + } else if (!localFile.getEtag().equals(ocFile.getEtag())) { + // update file + ocFile.setLastSyncDateForData(System.currentTimeMillis()); + filesToUpdate.add(ocFile); + } + } + + // add new files + for (OCFile file : filesToAdd) { + storageManager.saveFile(file); + } + + // update existing files + for (OCFile file : filesToUpdate) { + storageManager.saveFile(file); + } + + // existing files to remove + for (OCFile file : localFilesMap.values()) { + storageManager.removeFile(file, true, true); + } + + Log_OC.d(this, "Gallery search result:" + + " new: " + filesToAdd.size() + + " updated: " + filesToUpdate.size() + + " deleted: " + localFilesMap.values().size()); + + return didNotFindNewResults(filesToAdd, filesToUpdate, localFilesMap.values()); + } + + private boolean didNotFindNewResults(List filesToAdd, + List filesToUpdate, + Collection filesToRemove) { + return filesToAdd.isEmpty() && filesToUpdate.isEmpty() && filesToRemove.isEmpty(); + } } diff --git a/src/main/java/com/owncloud/android/ui/fragment/GalleryFragment.java b/src/main/java/com/owncloud/android/ui/fragment/GalleryFragment.java index 3e595cba2c..7b59ff6732 100644 --- a/src/main/java/com/owncloud/android/ui/fragment/GalleryFragment.java +++ b/src/main/java/com/owncloud/android/ui/fragment/GalleryFragment.java @@ -27,52 +27,32 @@ import android.view.LayoutInflater; import android.view.View; import android.view.ViewGroup; -import com.owncloud.android.datamodel.VirtualFolderType; +import com.owncloud.android.datamodel.OCFile; +import com.owncloud.android.lib.common.operations.RemoteOperationResult; import com.owncloud.android.lib.common.utils.Log_OC; -import com.owncloud.android.lib.resources.files.SearchRemoteOperation; -import com.owncloud.android.lib.resources.status.OCCapability; import com.owncloud.android.ui.asynctasks.GallerySearchTask; import com.owncloud.android.ui.events.ChangeMenuEvent; -import com.owncloud.android.ui.events.SearchEvent; - -import java.util.ArrayList; import androidx.annotation.NonNull; import androidx.recyclerview.widget.GridLayoutManager; import androidx.recyclerview.widget.RecyclerView; /** - * A Fragment that lists all files and folders in a given path. TODO refactor to get rid of direct dependency on - * FileDisplayActivity + * A Fragment that lists all files and folders in a given path */ public class GalleryFragment extends OCFileListFragment { private static final int MAX_ITEMS_PER_ROW = 10; private boolean photoSearchQueryRunning = false; - private boolean photoSearchNoNew = false; - private SearchRemoteOperation searchRemoteOperation; - private AsyncTask photoSearchTask; - private SearchEvent searchEvent; - private boolean refresh; - - private void createOperation() { - if(searchEvent == null) { - searchEvent = new SearchEvent("", SearchRemoteOperation.SearchType.GALLERY_SEARCH); - } - if(searchRemoteOperation == null) { - OCCapability ocCapability = mContainerActivity.getStorageManager() - .getCapability(accountManager.getUser().getAccountName()); - - searchRemoteOperation = new SearchRemoteOperation(searchEvent.getSearchQuery(), - searchEvent.getSearchType(), - false, - ocCapability); - } - } + private AsyncTask photoSearchTask; + private long startDate; + private long endDate; + private long daySpan = 30; + private int limit = 300; @Override public void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); - refresh = true; + searchFragment = true; } @Override @@ -89,7 +69,6 @@ public class GalleryFragment extends OCFileListFragment { */ @Override public View onCreateView(@NonNull LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) { - createOperation(); View v = super.onCreateView(inflater, container, savedInstanceState); getRecyclerView().addOnScrollListener(new RecyclerView.OnScrollListener() { @@ -121,7 +100,6 @@ public class GalleryFragment extends OCFileListFragment { public void onRefresh() { super.onRefresh(); - refresh = true; handleSearchEvent(); } @@ -138,25 +116,10 @@ public class GalleryFragment extends OCFileListFragment { private void handleSearchEvent() { prepareCurrentSearch(searchEvent); - searchFragment = true; setEmptyListLoadingMessage(); - if (refresh || preferences.getPhotoSearchTimestamp() == 0 || - System.currentTimeMillis() - preferences.getPhotoSearchTimestamp() >= 30 * 1000) { - mAdapter.setData( - new ArrayList<>(), - SearchType.GALLERY_SEARCH, - mContainerActivity.getStorageManager(), - mFile, - true); - photoSearchNoNew = false; - refresh = false; - } else { - mAdapter.showVirtuals(VirtualFolderType.GALLERY, true, mContainerActivity.getStorageManager()); - preferences.setPhotoSearchTimestamp(System.currentTimeMillis()); - - return; - } + // always show first stored items + mAdapter.showAllGalleryItems(mContainerActivity.getStorageManager()); setFabVisible(false); @@ -164,27 +127,59 @@ public class GalleryFragment extends OCFileListFragment { } private void searchAndDisplay() { - if (!photoSearchQueryRunning && !photoSearchNoNew) { - photoSearchTask = new GallerySearchTask(getColumnsCount(), - this, + // first: always search from now to -30 days + + if (!photoSearchQueryRunning) { + photoSearchQueryRunning = true; + + startDate = (System.currentTimeMillis() / 1000) - 30 * 24 * 60 * 60; + endDate = System.currentTimeMillis() / 1000; + + photoSearchTask = new GallerySearchTask(this, accountManager.getUser(), - searchRemoteOperation, - mContainerActivity.getStorageManager()) + mContainerActivity.getStorageManager(), + startDate, + endDate, + limit) .execute(); } } - public void setPhotoSearchQueryRunning(boolean bool) { - photoSearchQueryRunning = bool; - } + public void searchCompleted(boolean emptySearch, long lastTimeStamp) { + photoSearchQueryRunning = false; - public void setSearchDidNotFindNewPhotos(boolean noNewPhotos) { - photoSearchNoNew = noNewPhotos; + if (emptySearch) { + Log_OC.d(this, "End gallery search"); + return; + } + if (daySpan == 30) { + daySpan = 90; + } else if (daySpan == 90) { + daySpan = 180; + } else if (daySpan == 180) { + daySpan = 999; + } else if (daySpan == 999 && limit > 0) { + limit = -1; // no limit + } else { + Log_OC.d(this, "End gallery search"); + return; + } + + endDate = lastTimeStamp; + startDate = endDate - (daySpan * 24 * 60 * 60); + + photoSearchTask = new GallerySearchTask(this, + accountManager.getUser(), + mContainerActivity.getStorageManager(), + startDate, + endDate, + limit) + .execute(); } @Override public boolean isLoading() { - return !photoSearchNoNew; + return photoSearchQueryRunning; } private void loadMoreWhenEndReached(@NonNull RecyclerView recyclerView, int dy) { @@ -195,12 +190,24 @@ public class GalleryFragment extends OCFileListFragment { if (dy > 0 && !photoSearchQueryRunning) { int visibleItemCount = gridLayoutManager.getChildCount(); int totalItemCount = gridLayoutManager.getItemCount(); - int firstVisibleItem = gridLayoutManager.findFirstCompletelyVisibleItemPosition(); + int lastVisibleItem = gridLayoutManager.findLastCompletelyVisibleItemPosition(); - if ((totalItemCount - visibleItemCount) <= (firstVisibleItem + MAX_ITEMS_PER_ROW) + if ((totalItemCount - visibleItemCount) <= (lastVisibleItem + MAX_ITEMS_PER_ROW) && (totalItemCount - visibleItemCount) > 0) { // Almost reached the end, continue to load new photos - searchAndDisplay(); + OCFile lastFile = mAdapter.getItem(lastVisibleItem - 1); + + daySpan = 30; + endDate = lastFile.getModificationTimestamp() / 1000; + startDate = endDate - (daySpan * 24 * 60 * 60); + + photoSearchTask = new GallerySearchTask(this, + accountManager.getUser(), + mContainerActivity.getStorageManager(), + startDate, + endDate, + limit) + .execute(); } } } diff --git a/src/main/java/com/owncloud/android/ui/fragment/OCFileListFragment.java b/src/main/java/com/owncloud/android/ui/fragment/OCFileListFragment.java index 554cd01f04..79246f61bc 100644 --- a/src/main/java/com/owncloud/android/ui/fragment/OCFileListFragment.java +++ b/src/main/java/com/owncloud/android/ui/fragment/OCFileListFragment.java @@ -1499,7 +1499,13 @@ public class OCFileListFragment extends ExtendedListFragment implements prepareCurrentSearch(event); searchFragment = true; setEmptyListLoadingMessage(); - mAdapter.setData(new ArrayList<>(), SearchType.NO_SEARCH, mContainerActivity.getStorageManager(), mFile, true); + mAdapter.setData(new ArrayList<>(), + SearchType.NO_SEARCH, + mContainerActivity.getStorageManager(), + mFile, + true, + -1, + -1); setFabVisible(false); @@ -1557,7 +1563,9 @@ public class OCFileListFragment extends ExtendedListFragment implements currentSearchType, storageManager, mFile, - true); + true, + -1, + -1); } final ToolbarActivity fileDisplayActivity = (ToolbarActivity) getActivity(); diff --git a/src/main/java/com/owncloud/android/ui/interfaces/OCFileListFragmentInterface.java b/src/main/java/com/owncloud/android/ui/interfaces/OCFileListFragmentInterface.java index 5b2fd546d5..0925623ef0 100644 --- a/src/main/java/com/owncloud/android/ui/interfaces/OCFileListFragmentInterface.java +++ b/src/main/java/com/owncloud/android/ui/interfaces/OCFileListFragmentInterface.java @@ -48,4 +48,6 @@ public interface OCFileListFragmentInterface { boolean isLoading(); void onHeaderClicked(); + + boolean isSearchFragment(); }