Эх сурвалжийг харах

Merge pull request #661 from nextcloud/new-filtering-magic

New filtering magic
Mario Đanić 8 жил өмнө
parent
commit
095067383b

+ 58 - 0
drawable_resources/ic_search_light_blue.svg

@@ -0,0 +1,58 @@
+<?xml version="1.0" encoding="UTF-8" standalone="no"?>
+<svg
+   xmlns:dc="http://purl.org/dc/elements/1.1/"
+   xmlns:cc="http://creativecommons.org/ns#"
+   xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
+   xmlns:svg="http://www.w3.org/2000/svg"
+   xmlns="http://www.w3.org/2000/svg"
+   xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
+   xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
+   version="1.1"
+   width="24"
+   height="24"
+   viewBox="0 0 24 24"
+   id="svg4"
+   sodipodi:docname="ic_search_light_blue.svg"
+   inkscape:export-filename="C:\DEV\src\Android\Nextcloud\filtering-improvements\res\drawable-xxxhdpi\ic_search_light_blue.png"
+   inkscape:export-xdpi="1152"
+   inkscape:export-ydpi="1152"
+   inkscape:version="0.92.0 r15299">
+  <metadata
+     id="metadata10">
+    <rdf:RDF>
+      <cc:Work
+         rdf:about="">
+        <dc:format>image/svg+xml</dc:format>
+        <dc:type
+           rdf:resource="http://purl.org/dc/dcmitype/StillImage" />
+        <dc:title></dc:title>
+      </cc:Work>
+    </rdf:RDF>
+  </metadata>
+  <defs
+     id="defs8" />
+  <sodipodi:namedview
+     pagecolor="#ffffff"
+     bordercolor="#666666"
+     borderopacity="1"
+     objecttolerance="10"
+     gridtolerance="10"
+     guidetolerance="10"
+     inkscape:pageopacity="0"
+     inkscape:pageshadow="2"
+     inkscape:window-width="1920"
+     inkscape:window-height="1005"
+     id="namedview6"
+     showgrid="false"
+     inkscape:zoom="9.8333333"
+     inkscape:cx="12"
+     inkscape:cy="12"
+     inkscape:window-x="-9"
+     inkscape:window-y="-9"
+     inkscape:window-maximized="1"
+     inkscape:current-layer="svg4" />
+  <path
+     d="M9.5,3A6.5,6.5 0 0,1 16,9.5C16,11.11 15.41,12.59 14.44,13.73L14.71,14H15.5L20.5,19L19,20.5L14,15.5V14.71L13.73,14.44C12.59,15.41 11.11,16 9.5,16A6.5,6.5 0 0,1 3,9.5A6.5,6.5 0 0,1 9.5,3M9.5,5C7,5 5,7 5,9.5C5,12 7,14 9.5,14C12,14 14,12 14,9.5C14,7 12,5 9.5,5Z"
+     id="path2"
+     style="fill:#99cde9;fill-opacity:1" />
+</svg>

+ 58 - 0
drawable_resources/ic_search_light_grey.svg

@@ -0,0 +1,58 @@
+<?xml version="1.0" encoding="UTF-8" standalone="no"?>
+<svg
+   xmlns:dc="http://purl.org/dc/elements/1.1/"
+   xmlns:cc="http://creativecommons.org/ns#"
+   xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
+   xmlns:svg="http://www.w3.org/2000/svg"
+   xmlns="http://www.w3.org/2000/svg"
+   xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
+   xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
+   version="1.1"
+   width="24"
+   height="24"
+   viewBox="0 0 24 24"
+   id="svg4"
+   sodipodi:docname="ic_search_light_grey.svg"
+   inkscape:export-filename="C:\DEV\src\Android\Nextcloud\new-filtering-magic\res\drawable-xxxhdpi\ic_search_light_grey.png"
+   inkscape:export-xdpi="1152"
+   inkscape:export-ydpi="1152"
+   inkscape:version="0.92.0 r15299">
+  <metadata
+     id="metadata10">
+    <rdf:RDF>
+      <cc:Work
+         rdf:about="">
+        <dc:format>image/svg+xml</dc:format>
+        <dc:type
+           rdf:resource="http://purl.org/dc/dcmitype/StillImage" />
+        <dc:title />
+      </cc:Work>
+    </rdf:RDF>
+  </metadata>
+  <defs
+     id="defs8" />
+  <sodipodi:namedview
+     pagecolor="#ffffff"
+     bordercolor="#666666"
+     borderopacity="1"
+     objecttolerance="10"
+     gridtolerance="10"
+     guidetolerance="10"
+     inkscape:pageopacity="0"
+     inkscape:pageshadow="2"
+     inkscape:window-width="1920"
+     inkscape:window-height="1005"
+     id="namedview6"
+     showgrid="false"
+     inkscape:zoom="9.8333333"
+     inkscape:cx="-15.305085"
+     inkscape:cy="12"
+     inkscape:window-x="-9"
+     inkscape:window-y="-9"
+     inkscape:window-maximized="1"
+     inkscape:current-layer="svg4" />
+  <path
+     d="M9.5,3A6.5,6.5 0 0,1 16,9.5C16,11.11 15.41,12.59 14.44,13.73L14.71,14H15.5L20.5,19L19,20.5L14,15.5V14.71L13.73,14.44C12.59,15.41 11.11,16 9.5,16A6.5,6.5 0 0,1 3,9.5A6.5,6.5 0 0,1 9.5,3M9.5,5C7,5 5,7 5,9.5C5,12 7,14 9.5,14C12,14 14,12 14,9.5C14,7 12,5 9.5,5Z"
+     id="path2"
+     style="fill:#000000;fill-opacity:1;opacity:0.5" />
+</svg>

BIN
res/drawable-hdpi/ic_search_light_grey.png


BIN
res/drawable-mdpi/ic_search_light_grey.png


BIN
res/drawable-xhdpi/ic_search_light_grey.png


BIN
res/drawable-xxhdpi/ic_search_light_grey.png


BIN
res/drawable-xxxhdpi/ic_search_light_grey.png


+ 1 - 1
res/menu/main_menu.xml

@@ -25,7 +25,7 @@
           android:title="@string/actionbar_search"
           android:contentDescription="@string/actionbar_search"
           app:actionViewClass="android.support.v7.widget.SearchView"
-          app:showAsAction="ifRoom|collapseActionView"/>
+          app:showAsAction="always"/>
     <item
         android:id="@+id/action_create_dir"
         android:icon="@drawable/ic_action_create_dir"

+ 2 - 0
res/values/strings.xml

@@ -83,6 +83,8 @@
     <string name="file_list_loading">Loading&#8230;</string>
     <string name="file_list_no_app_for_file_type">No app found for file type!</string>
     <string name="local_file_list_empty">There are no files in this folder.</string>
+    <string name="file_list_empty_headline_search">No results in this folder</string>
+    <string name="file_list_empty_search">Try looking in another folder?</string>
     <string name="upload_list_empty_headline">No uploads available</string>
     <string name="upload_list_empty_text">Upload some content or activate instant upload!</string>
     <string name="file_list_folder">folder</string>

+ 4 - 2
src/com/owncloud/android/ui/activity/DrawerActivity.java

@@ -92,7 +92,7 @@ public abstract class DrawerActivity extends ToolbarActivity implements DisplayU
     /**
      * Reference to the drawer toggle.
      */
-    private ActionBarDrawerToggle mDrawerToggle;
+    protected ActionBarDrawerToggle mDrawerToggle;
 
     /**
      * Reference to the navigation view.
@@ -507,8 +507,10 @@ public abstract class DrawerActivity extends ToolbarActivity implements DisplayU
         super.updateActionBarTitleAndHomeButton(chosenFile);
 
         /// set home button properties
-        if (mDrawerToggle != null) {
+        if (mDrawerToggle != null && chosenFile != null) {
             mDrawerToggle.setDrawerIndicatorEnabled(isRoot(chosenFile));
+        } else {
+            mDrawerToggle.setDrawerIndicatorEnabled(false);
         }
     }
 

+ 154 - 61
src/com/owncloud/android/ui/activity/FileDisplayActivity.java

@@ -46,11 +46,15 @@ import android.support.v4.app.Fragment;
 import android.support.v4.app.FragmentManager;
 import android.support.v4.app.FragmentTransaction;
 import android.support.v4.content.ContextCompat;
+import android.support.v4.view.MenuItemCompat;
 import android.support.v7.app.AlertDialog;
+import android.support.v7.widget.SearchView;
+import android.text.TextUtils;
 import android.view.Menu;
 import android.view.MenuInflater;
 import android.view.MenuItem;
 import android.view.View;
+import android.view.ViewTreeObserver;
 import android.widget.Toast;
 
 import com.owncloud.android.MainApp;
@@ -116,6 +120,7 @@ public class FileDisplayActivity extends HookActivity
     private static final String KEY_WAITING_TO_PREVIEW = "WAITING_TO_PREVIEW";
     private static final String KEY_SYNC_IN_PROGRESS = "SYNC_IN_PROGRESS";
     private static final String KEY_WAITING_TO_SEND = "WAITING_TO_SEND";
+    private static final String KEY_SEARCH_QUERY = "KEY_SEARCH_QUERY";
 
     public static final String ACTION_DETAILS = "com.owncloud.android.ui.activity.action.DETAILS";
 
@@ -138,7 +143,9 @@ public class FileDisplayActivity extends HookActivity
     private OCFile mWaitingToSend;
 
     private Collection<MenuItem> mDrawerMenuItemstoShowHideList;
+    private String searchQuery;
 
+    private SearchView searchView;
 
     @Override
     protected void onCreate(Bundle savedInstanceState) {
@@ -160,6 +167,7 @@ public class FileDisplayActivity extends HookActivity
             mSyncInProgress = savedInstanceState.getBoolean(KEY_SYNC_IN_PROGRESS);
             mWaitingToSend = (OCFile) savedInstanceState.getParcelable(
                     FileDisplayActivity.KEY_WAITING_TO_SEND);
+            searchQuery = savedInstanceState.getString(KEY_SEARCH_QUERY);
         } else {
             mWaitingToPreview = null;
             mSyncInProgress = false;
@@ -369,7 +377,7 @@ public class FileDisplayActivity extends HookActivity
             if (!stateWasRecovered) {
                 Log_OC.d(TAG, "Initializing Fragments in onAccountChanged..");
                 initFragmentsWithFile();
-                if (file.isFolder()) {
+                if (file.isFolder() && TextUtils.isEmpty(searchQuery)) {
                     startSyncFolderOperation(file, false);
                 }
 
@@ -394,8 +402,8 @@ public class FileDisplayActivity extends HookActivity
         if (getAccount() != null && getFile() != null) {
             /// First fragment
             OCFileListFragment listOfFiles = getListOfFilesFragment();
-            if (listOfFiles != null) {
-                listOfFiles.listDirectory(getCurrentDir(), MainApp.isOnlyOnDevice());
+            if (listOfFiles != null && TextUtils.isEmpty(searchQuery)) {
+                listOfFiles.listDirectory(getCurrentDir(), MainApp.isOnlyOnDevice(), false);
             } else {
                 Log_OC.e(TAG, "Still have a chance to lose the initializacion of list fragment >(");
             }
@@ -457,6 +465,13 @@ public class FileDisplayActivity extends HookActivity
      * @param fragment New second Fragment to set.
      */
     private void setSecondFragment(Fragment fragment) {
+        searchView.post(new Runnable() {
+            @Override
+            public void run() {
+                searchView.setQuery("", true);
+            }
+        });
+        setDrawerIndicatorEnabled(false);
         FragmentTransaction transaction = getSupportFragmentManager().beginTransaction();
         transaction.replace(R.id.right_fragment_container, fragment, TAG_SECOND_FRAGMENT);
         transaction.commit();
@@ -521,10 +536,10 @@ public class FileDisplayActivity extends HookActivity
         updateActionBarTitleAndHomeButton(null);
     }
 
-    protected void refreshListOfFilesFragment() {
+    public void refreshListOfFilesFragment(boolean fromSearch) {
         OCFileListFragment fileListFragment = getListOfFilesFragment();
         if (fileListFragment != null) {
-            fileListFragment.listDirectory(MainApp.isOnlyOnDevice());
+            fileListFragment.listDirectory(MainApp.isOnlyOnDevice(), fromSearch);
         }
     }
 
@@ -590,6 +605,9 @@ public class FileDisplayActivity extends HookActivity
         inflater.inflate(R.menu.main_menu, menu);
         menu.findItem(R.id.action_create_dir).setVisible(false);
 
+        final MenuItem item = menu.findItem(R.id.action_search);
+        searchView = (SearchView) MenuItemCompat.getActionView(item);
+
         // populate list of menu items to show/hide when drawer is opened/closed
         mDrawerMenuItemstoShowHideList = new ArrayList<>(4);
         mDrawerMenuItemstoShowHideList.add(menu.findItem(R.id.action_sort));
@@ -597,6 +615,61 @@ public class FileDisplayActivity extends HookActivity
         mDrawerMenuItemstoShowHideList.add(menu.findItem(R.id.action_switch_view));
         mDrawerMenuItemstoShowHideList.add(menu.findItem(R.id.action_search));
 
+        //focus the SearchView
+        if (!TextUtils.isEmpty(searchQuery)) {
+            searchView.post(new Runnable() {
+                @Override
+                public void run() {
+                    searchView.setIconified(false);
+                    searchView.setQuery(searchQuery, true);
+                    searchView.clearFocus();
+                }
+            });
+        }
+
+        final View mSearchEditFrame = searchView
+                .findViewById(android.support.v7.appcompat.R.id.search_edit_frame);
+
+        searchView.setOnCloseListener(new SearchView.OnCloseListener() {
+            @Override
+            public boolean onClose() {
+                if (TextUtils.isEmpty(searchView.getQuery().toString())) {
+                    searchView.onActionViewCollapsed();
+                    setDrawerIndicatorEnabled(isDrawerIndicatorAvailable()); // order matters
+                    getSupportActionBar().setDisplayHomeAsUpEnabled(true);
+                    mDrawerToggle.syncState();
+                } else {
+                    searchView.post(new Runnable() {
+                        @Override
+                        public void run() {
+                            searchView.setQuery("", true);
+                        }
+                    });
+                }
+                return true;
+            }
+        });
+
+        ViewTreeObserver vto = mSearchEditFrame.getViewTreeObserver();
+        vto.addOnGlobalLayoutListener(new ViewTreeObserver.OnGlobalLayoutListener() {
+            int oldVisibility = -1;
+
+            @Override
+            public void onGlobalLayout() {
+
+                int currentVisibility = mSearchEditFrame.getVisibility();
+
+                if (currentVisibility != oldVisibility) {
+                    if (currentVisibility == View.VISIBLE) {
+                        setDrawerIndicatorEnabled(false);
+                    }
+
+                    oldVisibility = currentVisibility;
+                }
+
+            }
+        });
+
         return true;
     }
 
@@ -615,7 +688,7 @@ public class FileDisplayActivity extends HookActivity
                 if (isDrawerOpen()) {
                     closeDrawer();
                 } else if ((currentDir != null && currentDir.getParentId() != 0) ||
-                        (second != null && second.getFile() != null)) {
+                        (second != null && second.getFile() != null) || isSearchOpen()) {
                     onBackPressed();
 
                 } else {
@@ -859,18 +932,30 @@ public class FileDisplayActivity extends HookActivity
         getFileOperationsHelper().copyFiles(files, folderToMoveAt);
     }
 
+    private boolean isSearchOpen() {
+        final View mSearchEditFrame = searchView.findViewById(android.support.v7.appcompat.R.id.search_edit_frame);
+        return (mSearchEditFrame != null && mSearchEditFrame.getVisibility() == View.VISIBLE);
+    }
+
+
     @Override
     public void onBackPressed() {
         boolean isFabOpen = isFabOpen();
         boolean isDrawerOpen = isDrawerOpen();
+        boolean isSearchOpen = isSearchOpen();
 
         /*
          * BackPressed priority/hierarchy:
-         *    1. close drawer if opened
-         *    2. close FAB if open (only if drawer isn't open)
-         *    3. navigate up (only if drawer and FAB aren't open)
+         *    1. close search view if opened
+         *    2. close drawer if opened
+         *    3. close FAB if open (only if drawer isn't open)
+         *    4. navigate up (only if drawer and FAB aren't open)
          */
-        if(isDrawerOpen && isFabOpen) {
+        if (isSearchOpen && searchView != null) {
+            searchView.setQuery("", true);
+            searchView.onActionViewCollapsed();
+            setDrawerIndicatorEnabled(isDrawerIndicatorAvailable());
+        } else if(isDrawerOpen && isFabOpen) {
             // close drawer first
             super.onBackPressed();
         } else if(isDrawerOpen && !isFabOpen) {
@@ -910,7 +995,9 @@ public class FileDisplayActivity extends HookActivity
         //outState.putBoolean(FileDisplayActivity.KEY_REFRESH_SHARES_IN_PROGRESS,
         // mRefreshSharesInProgress);
         outState.putParcelable(FileDisplayActivity.KEY_WAITING_TO_SEND, mWaitingToSend);
-
+        if (searchView != null) {
+            outState.putString(KEY_SEARCH_QUERY, searchView.getQuery().toString());
+        }
         Log_OC.v(TAG, "onSaveInstanceState() end");
     }
 
@@ -920,7 +1007,12 @@ public class FileDisplayActivity extends HookActivity
         super.onResume();
 
         // refresh list of files
-        refreshListOfFilesFragment();
+
+        if (searchView != null && !TextUtils.isEmpty(searchQuery)) {
+            searchView.setQuery(searchQuery, true);
+        } else {
+            refreshListOfFilesFragment(false);
+        }
 
         // Listen for sync messages
         IntentFilter syncIntentFilter = new IntentFilter(FileSyncAdapter.EVENT_FULL_SYNC_START);
@@ -1038,7 +1130,7 @@ public class FileDisplayActivity extends HookActivity
                                 OCFileListFragment fileListFragment = getListOfFilesFragment();
                                 if (fileListFragment != null) {
                                     fileListFragment.listDirectory(currentDir,
-                                    MainApp.isOnlyOnDevice());
+                                    MainApp.isOnlyOnDevice(), false);
                                 }
                             }
                             setFile(currentFile);
@@ -1100,7 +1192,7 @@ public class FileDisplayActivity extends HookActivity
         OCFileListFragment ocFileListFragment = getListOfFilesFragment();
         if (ocFileListFragment != null) {
             if (!mSyncInProgress) {
-                ocFileListFragment.setEmptyListMessage();
+                    ocFileListFragment.setEmptyListMessage(false);
             } else {
                 ocFileListFragment.setEmptyListLoadingMessage();
             }
@@ -1132,7 +1224,7 @@ public class FileDisplayActivity extends HookActivity
                     String linkedToRemotePath =
                             intent.getStringExtra(FileUploader.EXTRA_LINKED_TO_PATH);
                     if (linkedToRemotePath == null || isAscendant(linkedToRemotePath)) {
-                        refreshListOfFilesFragment();
+                        refreshListOfFilesFragment(false);
                     }
                 }
 
@@ -1225,7 +1317,7 @@ public class FileDisplayActivity extends HookActivity
                     String linkedToRemotePath =
                             intent.getStringExtra(FileDownloader.EXTRA_LINKED_TO_PATH);
                     if (linkedToRemotePath == null || isAscendant(linkedToRemotePath)) {
-                        refreshListOfFilesFragment();
+                        refreshListOfFilesFragment(false);
                     }
                     refreshSecondFragment(
                             intent.getAction(),
@@ -1278,7 +1370,7 @@ public class FileDisplayActivity extends HookActivity
         OCFileListFragment listOfFiles = getListOfFilesFragment();
         if (listOfFiles != null) {  // should never be null, indeed
             OCFile root = getStorageManager().getFileByPath(OCFile.ROOT_PATH);
-            listOfFiles.listDirectory(root, MainApp.isOnlyOnDevice());
+            listOfFiles.listDirectory(root, MainApp.isOnlyOnDevice(), false);
             setFile(listOfFiles.getCurrentFile());
             startSyncFolderOperation(root, false);
         }
@@ -1369,7 +1461,7 @@ public class FileDisplayActivity extends HookActivity
             // getFileDownloadBinder() - THIS IS A MESS
             OCFileListFragment listOfFiles = getListOfFilesFragment();
             if (listOfFiles != null) {
-                listOfFiles.listDirectory(MainApp.isOnlyOnDevice());
+                listOfFiles.listDirectory(MainApp.isOnlyOnDevice(), false);
             }
             FileFragment secondFragment = getSecondFragment();
             if (secondFragment instanceof FileDetailFragment) {
@@ -1470,7 +1562,7 @@ public class FileDisplayActivity extends HookActivity
                 cleanSecondFragment();
             }
             if (getStorageManager().getFileById(removedFile.getParentId()).equals(getCurrentDir())) {
-                refreshListOfFilesFragment();
+                refreshListOfFilesFragment(false);
             }
             invalidateOptionsMenu();
         } else {
@@ -1492,7 +1584,7 @@ public class FileDisplayActivity extends HookActivity
     private void onMoveFileOperationFinish(MoveFileOperation operation,
                                            RemoteOperationResult result) {
         if (result.isSuccess()) {
-            refreshListOfFilesFragment();
+            refreshListOfFilesFragment(false);
         } else {
             try {
                 Toast msg = Toast.makeText(FileDisplayActivity.this,
@@ -1515,7 +1607,7 @@ public class FileDisplayActivity extends HookActivity
      */
     private void onCopyFileOperationFinish(CopyFileOperation operation, RemoteOperationResult result) {
         if (result.isSuccess()) {
-            refreshListOfFilesFragment();
+            refreshListOfFilesFragment(false);
         } else {
             try {
                 Toast msg = Toast.makeText(FileDisplayActivity.this,
@@ -1568,7 +1660,7 @@ public class FileDisplayActivity extends HookActivity
             }
 
             if (getStorageManager().getFileById(renamedFile.getParentId()).equals(getCurrentDir())) {
-                refreshListOfFilesFragment();
+                refreshListOfFilesFragment(false);
             }
 
         } else {
@@ -1605,7 +1697,7 @@ public class FileDisplayActivity extends HookActivity
     private void onCreateFolderOperationFinish(CreateFolderOperation operation,
                                                RemoteOperationResult result) {
         if (result.isSuccess()) {
-            refreshListOfFilesFragment();
+            refreshListOfFilesFragment(false);
         } else {
             try {
                 Toast msg = Toast.makeText(FileDisplayActivity.this,
@@ -1625,7 +1717,7 @@ public class FileDisplayActivity extends HookActivity
      */
     @Override
     public void onTransferStateChanged(OCFile file, boolean downloading, boolean uploading) {
-        refreshListOfFilesFragment();
+        refreshListOfFilesFragment(false);
         FileFragment details = getSecondFragment();
         if (details instanceof FileDetailFragment &&
                 file.equals(details.getFile())) {
@@ -1676,43 +1768,44 @@ public class FileDisplayActivity extends HookActivity
 
         // the execution is slightly delayed to allow the activity get the window focus if it's being started
         // or if the method is called from a dialog that is being dismissed
-        getHandler().postDelayed(
-                new Runnable() {
-                    @Override
-                    public void run() {
-                        if (hasWindowFocus()) {
-                            long currentSyncTime = System.currentTimeMillis();
-                            mSyncInProgress = true;
-
-                            // perform folder synchronization
-                            RemoteOperation synchFolderOp = new RefreshFolderOperation(folder,
-                                    currentSyncTime,
-                                    false,
-                                    getFileOperationsHelper().isSharedSupported(),
-                                    ignoreETag,
-                                    getStorageManager(),
-                                    getAccount(),
-                                    getApplicationContext()
-                            );
-                            synchFolderOp.execute(
-                                    getAccount(),
-                                    MainApp.getAppContext(),
-                                    FileDisplayActivity.this,
-                                    null,
-                                    null
-                            );
-
-                            setIndeterminate(true);
-
-                            setBackgroundText();
-
-                        }   // else: NOTHING ; lets' not refresh when the user rotates the device but there is
-                        // another window floating over
-                    }
-                },
-                DELAY_TO_REQUEST_REFRESH_OPERATION_LATER
-        );
-
+        if (TextUtils.isEmpty(searchQuery)) {
+            getHandler().postDelayed(
+                    new Runnable() {
+                        @Override
+                        public void run() {
+                            if (hasWindowFocus()) {
+                                long currentSyncTime = System.currentTimeMillis();
+                                mSyncInProgress = true;
+
+                                // perform folder synchronization
+                                RemoteOperation synchFolderOp = new RefreshFolderOperation(folder,
+                                        currentSyncTime,
+                                        false,
+                                        getFileOperationsHelper().isSharedSupported(),
+                                        ignoreETag,
+                                        getStorageManager(),
+                                        getAccount(),
+                                        getApplicationContext()
+                                );
+                                synchFolderOp.execute(
+                                        getAccount(),
+                                        MainApp.getAppContext(),
+                                        FileDisplayActivity.this,
+                                        null,
+                                        null
+                                );
+
+                                setIndeterminate(true);
+
+                                setBackgroundText();
+
+                            }   // else: NOTHING ; lets' not refresh when the user rotates the device but there is
+                            // another window floating over
+                        }
+                    },
+                    DELAY_TO_REQUEST_REFRESH_OPERATION_LATER
+            );
+        }
     }
 
     private void requestForDownload(OCFile file) {

+ 4 - 4
src/com/owncloud/android/ui/activity/FolderPickerActivity.java

@@ -136,7 +136,7 @@ public class FolderPickerActivity extends FileActivity implements FileFragment.C
             
             if (!stateWasRecovered) {
                 OCFileListFragment listOfFolders = getListOfFilesFragment(); 
-                listOfFolders.listDirectory(folder, false);
+                listOfFolders.listDirectory(folder, false, false);
                 
                 startSyncFolderOperation(folder, false);
             }
@@ -311,7 +311,7 @@ public class FolderPickerActivity extends FileActivity implements FileFragment.C
     protected void refreshListOfFilesFragment() {
         OCFileListFragment fileListFragment = getListOfFilesFragment();
         if (fileListFragment != null) {
-            fileListFragment.listDirectory(false);
+            fileListFragment.listDirectory(false, false);
         }
     }
 
@@ -319,7 +319,7 @@ public class FolderPickerActivity extends FileActivity implements FileFragment.C
         OCFileListFragment listOfFiles = getListOfFilesFragment(); 
         if (listOfFiles != null) {  // should never be null, indeed
             OCFile root = getStorageManager().getFileByPath(OCFile.ROOT_PATH);
-            listOfFiles.listDirectory(root, false);
+            listOfFiles.listDirectory(root, false, false);
             setFile(listOfFiles.getCurrentFile());
             updateNavigationElementsInActionBar();
             startSyncFolderOperation(root, false);
@@ -467,7 +467,7 @@ public class FolderPickerActivity extends FileActivity implements FileFragment.C
                             if (currentDir.getRemotePath().equals(synchFolderRemotePath)) {
                                 OCFileListFragment fileListFragment = getListOfFilesFragment();
                                 if (fileListFragment != null) {
-                                    fileListFragment.listDirectory(currentDir, false);
+                                    fileListFragment.listDirectory(currentDir, false, false);
                                 }
                             }
                             setFile(currentFile);

+ 1 - 1
src/com/owncloud/android/ui/activity/UploadPathActivity.java

@@ -67,7 +67,7 @@ public class UploadPathActivity extends FolderPickerActivity implements FileFrag
 
             if (!stateWasRecovered) {
                 OCFileListFragment listOfFolders = getListOfFilesFragment();
-                listOfFolders.listDirectory(folder, false);
+                listOfFolders.listDirectory(folder, false, false);
 
                 startSyncFolderOperation(folder, false);
             }

+ 72 - 28
src/com/owncloud/android/ui/adapter/FileListListAdapter.java

@@ -27,12 +27,14 @@ import android.accounts.Account;
 import android.content.Context;
 import android.graphics.Bitmap;
 import android.graphics.Color;
+import android.text.TextUtils;
 import android.util.SparseBooleanArray;
 import android.view.LayoutInflater;
 import android.view.View;
 import android.view.ViewGroup;
 import android.widget.AbsListView;
 import android.widget.BaseAdapter;
+import android.widget.Filter;
 import android.widget.GridView;
 import android.widget.ImageView;
 import android.widget.LinearLayout;
@@ -48,6 +50,7 @@ import com.owncloud.android.files.services.FileDownloader.FileDownloaderBinder;
 import com.owncloud.android.files.services.FileUploader.FileUploaderBinder;
 import com.owncloud.android.services.OperationsService.OperationsServiceBinder;
 import com.owncloud.android.ui.activity.ComponentsGetter;
+import com.owncloud.android.ui.interfaces.ExtendedListFragmentInterface;
 import com.owncloud.android.utils.DisplayUtils;
 import com.owncloud.android.utils.FileStorageUtils;
 import com.owncloud.android.utils.MimeTypeUtil;
@@ -60,7 +63,7 @@ import java.util.Vector;
  * This Adapter populates a ListView with all files and folders in an ownCloud
  * instance.
  */
-public class FileListListAdapter extends BaseAdapter implements FilterableListAdapter {
+public class FileListListAdapter extends BaseAdapter {
 
     private Context mContext;
     private Vector<OCFile> mFilesAll = new Vector<OCFile>();
@@ -71,13 +74,19 @@ public class FileListListAdapter extends BaseAdapter implements FilterableListAd
     private FileDataStorageManager mStorageManager;
     private Account mAccount;
     private ComponentsGetter mTransferServiceGetter;
+    private ExtendedListFragmentInterface extendedListFragmentInterface;
+
+    private FilesFilter mFilesFilter;
+    private OCFile currentDirectory;
 
     public FileListListAdapter(
             boolean justFolders,
             Context context,
-            ComponentsGetter transferServiceGetter
+            ComponentsGetter transferServiceGetter,
+            ExtendedListFragmentInterface extendedListFragmentInterface
     ) {
 
+        this.extendedListFragmentInterface = extendedListFragmentInterface;
         mJustFolders = justFolders;
         mContext = context;
         mAccount = AccountUtils.getCurrentOwnCloudAccount(mContext);
@@ -274,7 +283,7 @@ public class FileListListAdapter extends BaseAdapter implements FilterableListAd
             AbsListView parentList = (AbsListView) parent;
             if (parentList.getChoiceMode() != AbsListView.CHOICE_MODE_NONE &&
                     parentList.getCheckedItemCount() > 0
-                ) {
+                    ) {
                 if (parentList.isItemChecked(position)) {
                     view.setBackgroundColor(mContext.getResources().getColor(
                             R.color.selected_item_background));
@@ -325,9 +334,9 @@ public class FileListListAdapter extends BaseAdapter implements FilterableListAd
                             }
                             final ThumbnailsCacheManager.AsyncThumbnailDrawable asyncDrawable =
                                     new ThumbnailsCacheManager.AsyncThumbnailDrawable(
-                                    mContext.getResources(), 
-                                    thumbnail, 
-                                    task
+                                            mContext.getResources(),
+                                            thumbnail,
+                                            task
                                     );
                             fileIcon.setImageDrawable(asyncDrawable);
                             task.execute(file);
@@ -377,7 +386,7 @@ public class FileListListAdapter extends BaseAdapter implements FilterableListAd
     /**
      * Change the adapted directory for a new one
      *
-     * @param directory                New folder to adapt. Can be NULL, meaning
+     * @param directory             New folder to adapt. Can be NULL, meaning
      *                              "no content to adapt".
      * @param updatedStorageManager Optional updated storage manager; used to replace
      *                              mStorageManager if is different (and not NULL)
@@ -398,7 +407,10 @@ public class FileListListAdapter extends BaseAdapter implements FilterableListAd
                 mFiles = filterHiddenFiles(mFiles);
             }
             mFiles = FileStorageUtils.sortOcFolder(mFiles);
+            mFilesAll.clear();
             mFilesAll.addAll(mFiles);
+
+            currentDirectory = directory;
         } else {
             mFiles = null;
             mFilesAll.clear();
@@ -410,8 +422,8 @@ public class FileListListAdapter extends BaseAdapter implements FilterableListAd
     /**
      * Filter for getting only the folders
      *
-     * @param files             Collection of files to filter
-     * @return                  Folders in the input
+     * @param files Collection of files to filter
+     * @return Folders in the input
      */
     public Vector<OCFile> getFolders(Vector<OCFile> files) {
         Vector<OCFile> ret = new Vector<>();
@@ -430,7 +442,7 @@ public class FileListListAdapter extends BaseAdapter implements FilterableListAd
 
         PreferenceManager.setSortOrder(mContext, order);
         PreferenceManager.setSortAscending(mContext, ascending);
-        
+
         FileStorageUtils.mSortOrder = order;
         FileStorageUtils.mSortAscending = ascending;
 
@@ -443,47 +455,79 @@ public class FileListListAdapter extends BaseAdapter implements FilterableListAd
         SparseBooleanArray checkedPositions = parentList.getCheckedItemPositions();
         ArrayList<OCFile> files = new ArrayList<>();
         Object item;
-        for (int i=0; i < checkedPositions.size(); i++) {
+        for (int i = 0; i < checkedPositions.size(); i++) {
             if (checkedPositions.valueAt(i)) {
                 item = getItem(checkedPositions.keyAt(i));
                 if (item != null) {
-                    files.add((OCFile)item);
+                    files.add((OCFile) item);
                 }
             }
         }
         return files;
     }
 
-    public void filter(String text){
-        if(text.isEmpty()){
-            mFiles.clear();
-            mFiles.addAll(mFilesAll);
-        } else {
-            ArrayList<OCFile> result = new ArrayList<>();
-            text = text.toLowerCase();
-            for(OCFile file: mFilesAll){
-                if(file.getFileName().toLowerCase().contains(text)){
-                    result.add(file);
+    public Filter getFilter() {
+        if (mFilesFilter == null) {
+            mFilesFilter = new FilesFilter();
+        }
+        return mFilesFilter;
+    }
+
+    private class FilesFilter extends Filter {
+
+        @Override
+        protected FilterResults performFiltering(CharSequence constraint) {
+            FilterResults results = new FilterResults();
+            Vector<OCFile> filteredFiles = new Vector<>();
+
+            if (!TextUtils.isEmpty(constraint)) {
+                for (int i = 0; i < mFilesAll.size(); i++) {
+                    OCFile currentFile = mFilesAll.get(i);
+                    if (currentFile.getParentRemotePath().equals(currentDirectory.getRemotePath()) &&
+                            currentFile.getFileName().toLowerCase().contains(constraint.toString().toLowerCase()) &&
+                            !filteredFiles.contains(currentFile)) {
+                        filteredFiles.add(currentFile);
+                    }
                 }
             }
-            mFiles.clear();
-            mFiles.addAll(result);
+
+            results.values = filteredFiles;
+            results.count = filteredFiles.size();
+
+            return results;
+        }
+
+        @Override
+        protected void publishResults(CharSequence constraint, Filter.FilterResults results) {
+            Vector<OCFile> ocFiles = (Vector<OCFile>) results.values;
+            mFiles = new Vector<>();
+            if (ocFiles != null && ocFiles.size() > 0) {
+                mFiles.addAll(ocFiles);
+                if (!mShowHiddenFiles) {
+                    mFiles = filterHiddenFiles(mFiles);
+                }
+                mFiles = FileStorageUtils.sortOcFolder(mFiles);
+            }
+
+            notifyDataSetChanged();
+            extendedListFragmentInterface.finishedFiltering();
+
         }
-        notifyDataSetChanged();
     }
 
+
     /**
      * Filter for hidden files
      *
-     * @param files             Collection of files to filter
-     * @return                  Non-hidden files
+     * @param files Collection of files to filter
+     * @return Non-hidden files
      */
     public Vector<OCFile> filterHiddenFiles(Vector<OCFile> files) {
         Vector<OCFile> ret = new Vector<>();
         OCFile current;
         for (int i = 0; i < files.size(); i++) {
             current = files.get(i);
-            if (!current.isHidden()) {
+            if (!current.isHidden() && !ret.contains(current)) {
                 ret.add(current);
             }
         }

+ 144 - 18
src/com/owncloud/android/ui/fragment/ExtendedListFragment.java

@@ -20,22 +20,28 @@
 
 package com.owncloud.android.ui.fragment;
 
+import android.animation.LayoutTransition;
 import android.os.Bundle;
+import android.os.Handler;
 import android.support.annotation.DrawableRes;
 import android.support.annotation.StringRes;
 import android.support.v4.app.Fragment;
 import android.support.v4.view.MenuItemCompat;
 import android.support.v4.widget.SwipeRefreshLayout;
 import android.support.v7.widget.SearchView;
+import android.text.TextUtils;
+import android.util.DisplayMetrics;
 import android.view.LayoutInflater;
 import android.view.Menu;
 import android.view.MenuInflater;
 import android.view.MenuItem;
 import android.view.View;
 import android.view.ViewGroup;
+import android.view.ViewTreeObserver;
 import android.widget.AbsListView;
 import android.widget.AdapterView;
 import android.widget.AdapterView.OnItemClickListener;
+import android.widget.BaseAdapter;
 import android.widget.GridView;
 import android.widget.ImageView;
 import android.widget.LinearLayout;
@@ -47,13 +53,17 @@ import com.getbase.floatingactionbutton.FloatingActionsMenu;
 import com.owncloud.android.R;
 import com.owncloud.android.lib.common.utils.Log_OC;
 import com.owncloud.android.ui.ExtendedListView;
+import com.owncloud.android.ui.activity.FileDisplayActivity;
 import com.owncloud.android.ui.activity.OnEnforceableRefreshListener;
-import com.owncloud.android.ui.adapter.FilterableListAdapter;
+import com.owncloud.android.ui.adapter.FileListListAdapter;
+import com.owncloud.android.ui.adapter.LocalFileListAdapter;
 
 import java.util.ArrayList;
 
 import third_parties.in.srain.cube.GridViewWithHeaderAndFooter;
 
+import static android.content.res.Configuration.ORIENTATION_LANDSCAPE;
+
 public class ExtendedListFragment extends Fragment
         implements OnItemClickListener, OnEnforceableRefreshListener, SearchView.OnQueryTextListener {
 
@@ -96,9 +106,12 @@ public class ExtendedListFragment extends Fragment
     private GridViewWithHeaderAndFooter mGridView;
     private View mGridFooterView;
 
-    private FilterableListAdapter mAdapter;
+    private BaseAdapter mAdapter;
+
+    protected SearchView searchView;
+    private Handler handler = new Handler();
 
-    protected void setListAdapter(FilterableListAdapter listAdapter) {
+    protected void setListAdapter(BaseAdapter listAdapter) {
         mAdapter = listAdapter;
         mCurrentListView.setAdapter(listAdapter);
         mCurrentListView.invalidateViews();
@@ -151,21 +164,119 @@ public class ExtendedListFragment extends Fragment
     @Override
     public void onCreateOptionsMenu(Menu menu, MenuInflater inflater) {
         final MenuItem item = menu.findItem(R.id.action_search);
-        final SearchView searchView = (SearchView) MenuItemCompat.getActionView(item);
+        searchView = (SearchView) MenuItemCompat.getActionView(item);
         searchView.setOnQueryTextListener(this);
+
+        final Handler handler = new Handler();
+
+        DisplayMetrics displaymetrics = new DisplayMetrics();
+        getActivity().getWindowManager().getDefaultDisplay().getMetrics(displaymetrics);
+        int width = displaymetrics.widthPixels;
+        if (getResources().getConfiguration().orientation == ORIENTATION_LANDSCAPE) {
+            searchView.setMaxWidth((int)(width * 0.4));
+        } else {
+            searchView.setMaxWidth((int)(width * 0.7));
+        }
+
+        searchView.setOnQueryTextFocusChangeListener(new View.OnFocusChangeListener() {
+            @Override
+            public void onFocusChange(View v, final boolean hasFocus) {
+                if (hasFocus) {
+                    mFabMain.collapse();
+                }
+
+                handler.postDelayed(new Runnable() {
+                    @Override
+                    public void run() {
+                        setFabEnabled(!hasFocus);
+                    }
+                }, 100);
+            }
+        });
+
+        final View mSearchEditFrame = searchView
+                .findViewById(android.support.v7.appcompat.R.id.search_edit_frame);
+
+        ViewTreeObserver vto = mSearchEditFrame.getViewTreeObserver();
+        vto.addOnGlobalLayoutListener(new ViewTreeObserver.OnGlobalLayoutListener() {
+            int oldVisibility = -1;
+
+            @Override
+            public void onGlobalLayout() {
+
+                int currentVisibility = mSearchEditFrame.getVisibility();
+
+                if (currentVisibility != oldVisibility) {
+                    if (currentVisibility == View.VISIBLE) {
+                        setEmptyListMessage(true);
+                    } else {
+                        setEmptyListMessage(false);
+                    }
+
+                    oldVisibility = currentVisibility;
+                }
+
+            }
+        });
+
+
+        LinearLayout searchBar = (LinearLayout) searchView.findViewById(R.id.search_bar);
+        searchBar.setLayoutTransition(new LayoutTransition());
     }
 
-    public boolean onQueryTextChange(String query) {
-        mAdapter.filter(query);
+    public boolean onQueryTextChange(final String query) {
+        performSearch(query, false);
         return true;
     }
 
     @Override
     public boolean onQueryTextSubmit(String query) {
-        mAdapter.filter(query);
+        performSearch(query, true);
         return true;
     }
 
+    private void performSearch(final String query, boolean isSubmit) {
+        handler.removeCallbacksAndMessages(null);
+
+        if (!TextUtils.isEmpty(query)) {
+
+            int delay = 500;
+
+            if (isSubmit) {
+                delay = 0;
+            }
+
+            if (mAdapter != null && mAdapter instanceof FileListListAdapter) {
+                handler.postDelayed(new Runnable() {
+                    @Override
+                    public void run() {
+                        FileListListAdapter fileListListAdapter = (FileListListAdapter) mAdapter;
+                        fileListListAdapter.getFilter().filter(query);
+                    }
+                }, delay);
+            } else if (mAdapter != null && mAdapter instanceof LocalFileListAdapter) {
+                handler.postDelayed(new Runnable() {
+                    @Override
+                    public void run() {
+                        LocalFileListAdapter localFileListAdapter = (LocalFileListAdapter) mAdapter;
+                        localFileListAdapter.filter(query);
+                    }
+                }, delay);
+            }
+
+            if (searchView != null && delay == 0) {
+                searchView.clearFocus();
+            }
+        } else {
+            if (getActivity() != null) {
+                ((FileDisplayActivity) getActivity()).refreshListOfFilesFragment(true);
+
+            }
+        }
+
+    }
+
+
     @Override
     public View onCreateView(LayoutInflater inflater, ViewGroup container,
                              Bundle savedInstanceState) {
@@ -188,7 +299,7 @@ public class ExtendedListFragment extends Fragment
         mRefreshListLayout = (SwipeRefreshLayout) v.findViewById(R.id.swipe_containing_list);
         mRefreshGridLayout = (SwipeRefreshLayout) v.findViewById(R.id.swipe_containing_grid);
         mRefreshEmptyLayout = (SwipeRefreshLayout) v.findViewById(R.id.swipe_containing_empty);
-        
+
         onCreateSwipeToRefresh(mRefreshListLayout);
         onCreateSwipeToRefresh(mRefreshGridLayout);
         onCreateSwipeToRefresh(mRefreshEmptyLayout);
@@ -203,6 +314,8 @@ public class ExtendedListFragment extends Fragment
 
         mCurrentListView = mListView;   // list by default
         if (savedInstanceState != null) {
+
+
             if (savedInstanceState.getBoolean(KEY_IS_GRID_VISIBLE, false)) {
                 switchToGridView();
             }
@@ -345,6 +458,16 @@ public class ExtendedListFragment extends Fragment
 
     @Override
     public void onRefresh() {
+
+        if (searchView != null) {
+            searchView.onActionViewCollapsed();
+
+            if (getActivity() != null) {
+                FileDisplayActivity fileDisplayActivity = (FileDisplayActivity) getActivity();
+                fileDisplayActivity.setDrawerIndicatorEnabled(fileDisplayActivity.isDrawerIndicatorAvailable());
+            }
+        }
+
         mRefreshListLayout.setRefreshing(false);
         mRefreshGridLayout.setRefreshing(false);
         mRefreshEmptyLayout.setRefreshing(false);
@@ -353,6 +476,7 @@ public class ExtendedListFragment extends Fragment
             mOnRefreshListener.onRefresh();
         }
     }
+
     public void setOnRefreshListener(OnEnforceableRefreshListener listener) {
         mOnRefreshListener = listener;
     }
@@ -415,15 +539,18 @@ public class ExtendedListFragment extends Fragment
         }
     }
 
-    /**
-     * Set message for empty list view.
-     */
-    public void setEmptyListMessage() {
-        setMessageForEmptyList(
-                R.string.file_list_empty_headline,
-                R.string.file_list_empty,
-                R.drawable.ic_list_empty_folder
-        );
+    public void setEmptyListMessage(boolean isSearch) {
+        if (isSearch) {
+            setMessageForEmptyList(R.string.file_list_empty_headline_search,
+                    R.string.file_list_empty_search, R.drawable.ic_search_light_grey);
+
+        } else {
+            setMessageForEmptyList(
+                    R.string.file_list_empty_headline,
+                    R.string.file_list_empty,
+                    R.drawable.ic_list_empty_folder
+            );
+        }
     }
 
     /**
@@ -451,7 +578,6 @@ public class ExtendedListFragment extends Fragment
     protected void onCreateSwipeToRefresh(SwipeRefreshLayout refreshLayout) {
         // Colors in animations
         refreshLayout.setColorSchemeResources(R.color.color_accent, R.color.primary, R.color.primary_dark);
-
         refreshLayout.setOnRefreshListener(this);
     }
 

+ 42 - 11
src/com/owncloud/android/ui/fragment/OCFileListFragment.java

@@ -63,6 +63,7 @@ import com.owncloud.android.ui.dialog.CreateFolderDialogFragment;
 import com.owncloud.android.ui.dialog.RemoveFilesDialogFragment;
 import com.owncloud.android.ui.dialog.RenameFileDialogFragment;
 import com.owncloud.android.ui.helpers.SparseBooleanArrayParcelable;
+import com.owncloud.android.ui.interfaces.ExtendedListFragmentInterface;
 import com.owncloud.android.ui.preview.PreviewImageFragment;
 import com.owncloud.android.ui.preview.PreviewMediaFragment;
 import com.owncloud.android.ui.preview.PreviewTextFragment;
@@ -78,7 +79,7 @@ import java.util.List;
  *
  * TODO refactor to get rid of direct dependency on FileDisplayActivity
  */
-public class OCFileListFragment extends ExtendedListFragment {
+public class OCFileListFragment extends ExtendedListFragment implements ExtendedListFragmentInterface {
 
     private static final String TAG = OCFileListFragment.class.getSimpleName();
 
@@ -193,7 +194,8 @@ public class OCFileListFragment extends ExtendedListFragment {
         mAdapter = new FileListListAdapter(
                 mJustFolders,
                 getActivity(),
-                mContainerActivity
+                mContainerActivity,
+                this
         );
         setListAdapter(mAdapter);
 
@@ -351,6 +353,11 @@ public class OCFileListFragment extends ExtendedListFragment {
                 com.getbase.floatingactionbutton.R.id.fab_label)).setVisibility(View.GONE);
     }
 
+    @Override
+    public void finishedFiltering() {
+        updateFooter();
+    }
+
     /**
      * Handler for multiple selection mode.
      *
@@ -586,7 +593,7 @@ public class OCFileListFragment extends ExtendedListFragment {
             }   // exit is granted because storageManager.getFileByPath("/") never returns null
             mFile = parentDir;
 
-            listDirectory(mFile, MainApp.isOnlyOnDevice());
+            listDirectory(mFile, MainApp.isOnlyOnDevice(), false);
 
             onRefresh(false);
 
@@ -604,7 +611,7 @@ public class OCFileListFragment extends ExtendedListFragment {
         if (file != null) {
             if (file.isFolder()) {
                 // update state and view of this fragment
-                listDirectory(file, MainApp.isOnlyOnDevice());
+                listDirectory(file, MainApp.isOnlyOnDevice(), false);
                 // then, notify parent activity to let it update its state and view
                 mContainerActivity.onBrowsedDownTo(file);
                 // save index and top position
@@ -740,14 +747,14 @@ public class OCFileListFragment extends ExtendedListFragment {
     }
 
     /**
-     * Calls {@link OCFileListFragment#listDirectory(OCFile, boolean)} with a null parameter
+     * Calls {@link OCFileListFragment#listDirectory(OCFile, boolean, boolean)} with a null parameter
      */
-    public void listDirectory(boolean onlyOnDevice){
-        listDirectory(null, onlyOnDevice);
+    public void listDirectory(boolean onlyOnDevice, boolean fromSearch){
+        listDirectory(null, onlyOnDevice, fromSearch);
     }
 
     public void refreshDirectory(){
-        listDirectory(getCurrentFile(), MainApp.isOnlyOnDevice());
+        listDirectory(getCurrentFile(), MainApp.isOnlyOnDevice(), false);
     }
 
     /**
@@ -757,7 +764,7 @@ public class OCFileListFragment extends ExtendedListFragment {
      *
      * @param directory File to be listed
      */
-    public void listDirectory(OCFile directory, boolean onlyOnDevice) {
+    public void listDirectory(OCFile directory, boolean onlyOnDevice, boolean fromSearch) {
         FileDataStorageManager storageManager = mContainerActivity.getStorageManager();
         if (storageManager != null) {
 
@@ -780,6 +787,25 @@ public class OCFileListFragment extends ExtendedListFragment {
                 directory = storageManager.getFileById(directory.getParentId());
             }
 
+
+            if (searchView != null && !searchView.isIconified() && !fromSearch) {
+
+                searchView.post(new Runnable() {
+                    @Override
+                    public void run() {
+                        searchView.setQuery("", false);
+                        searchView.onActionViewCollapsed();
+                        if (getActivity() != null) {
+                            FileDisplayActivity fileDisplayActivity = (FileDisplayActivity) getActivity();
+                            if (getCurrentFile() != null) {
+                                fileDisplayActivity.setDrawerIndicatorEnabled(fileDisplayActivity.isRoot(getCurrentFile()));
+                            }
+                        }
+
+                    }
+                });
+            }
+
             mAdapter.swapDirectory(directory, storageManager, onlyOnDevice);
             if (mFile == null || !mFile.equals(directory)) {
                 mCurrentListView.setSelection(0);
@@ -791,12 +817,12 @@ public class OCFileListFragment extends ExtendedListFragment {
         }
     }
 
-    private void updateLayout() {
+    private void updateFooter() {
         if (!mJustFolders) {
             int filesCount = 0, foldersCount = 0;
             int count = mAdapter.getCount();
             OCFile file;
-            for (int i=0; i < count ; i++) {
+            for (int i = 0; i < count; i++) {
                 file = (OCFile) mAdapter.getItem(i);
                 if (file.isFolder()) {
                     foldersCount++;
@@ -808,7 +834,12 @@ public class OCFileListFragment extends ExtendedListFragment {
             }
             // set footer text
             setFooterText(generateFooterText(filesCount, foldersCount));
+        }
+    }
 
+    private void updateLayout() {
+        if (!mJustFolders) {
+            updateFooter();
             // decide grid vs list view
             OwnCloudVersion version = AccountUtils.getServerVersion(
                     ((FileActivity)mContainerActivity).getAccount());

+ 29 - 0
src/com/owncloud/android/ui/interfaces/ExtendedListFragmentInterface.java

@@ -0,0 +1,29 @@
+/**
+ * Nextcloud Android client application
+ *
+ * @author Mario Danic
+ * Copyright (C) 2017 Mario Danic
+ * Copyright (C) 2017 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 <http://www.gnu.org/licenses/>.
+ */
+package com.owncloud.android.ui.interfaces;
+
+/**
+ * Interface for signaling filter finish
+ */
+
+public interface ExtendedListFragmentInterface {
+    void finishedFiltering();
+}