From d033c5e33e587b602fa6f7ca7a453da02f4f1300 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jos=C3=A9=20Rebelo?= Date: Thu, 29 Aug 2024 22:00:18 +0100 Subject: [PATCH] Data Management: Add basic search to file manager --- .../activities/files/FileManagerActivity.java | 45 ++++++++++++++- .../activities/files/FileManagerAdapter.java | 56 ++++++++++++++++++- app/src/main/res/drawable/ic_search.xml | 12 ++++ .../main/res/layout/activity_file_manager.xml | 9 +++ app/src/main/res/menu/menu_file_manager.xml | 11 ++++ app/src/main/res/values/strings.xml | 1 + 6 files changed, 132 insertions(+), 2 deletions(-) create mode 100644 app/src/main/res/drawable/ic_search.xml create mode 100644 app/src/main/res/menu/menu_file_manager.xml diff --git a/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/activities/files/FileManagerActivity.java b/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/activities/files/FileManagerActivity.java index 6e5412d4f..77357191a 100644 --- a/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/activities/files/FileManagerActivity.java +++ b/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/activities/files/FileManagerActivity.java @@ -17,10 +17,16 @@ package nodomain.freeyourgadget.gadgetbridge.activities.files; import android.os.Bundle; +import android.view.Menu; +import android.view.MenuInflater; import android.view.MenuItem; +import android.view.View; import android.widget.Toast; +import androidx.annotation.NonNull; import androidx.appcompat.app.ActionBar; +import androidx.appcompat.widget.SearchView; +import androidx.core.view.MenuProvider; import androidx.recyclerview.widget.LinearLayoutManager; import androidx.recyclerview.widget.RecyclerView; @@ -35,15 +41,18 @@ import nodomain.freeyourgadget.gadgetbridge.activities.AbstractGBActivity; import nodomain.freeyourgadget.gadgetbridge.util.FileUtils; import nodomain.freeyourgadget.gadgetbridge.util.GB; -public class FileManagerActivity extends AbstractGBActivity { +public class FileManagerActivity extends AbstractGBActivity implements MenuProvider { private static final Logger LOG = LoggerFactory.getLogger(FileManagerActivity.class); public static final String EXTRA_PATH = "path"; + private SearchView searchView; + @Override protected void onCreate(final Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_file_manager); + addMenuProvider(this); final RecyclerView fileListView = findViewById(R.id.fileListView); fileListView.setLayoutManager(new LinearLayoutManager(this)); @@ -76,6 +85,40 @@ public class FileManagerActivity extends AbstractGBActivity { final FileManagerAdapter appListAdapter = new FileManagerAdapter(this, directory); fileListView.setAdapter(appListAdapter); + + searchView = findViewById(R.id.fileListSearchView); + searchView.setIconifiedByDefault(false); + searchView.setVisibility(View.GONE); + searchView.setIconified(false); + searchView.setQuery("", false); + searchView.clearFocus(); + searchView.setOnQueryTextListener(new SearchView.OnQueryTextListener() { + @Override + public boolean onQueryTextSubmit(final String query) { + return false; + } + + @Override + public boolean onQueryTextChange(final String newText) { + appListAdapter.getFilter().filter(newText); + return true; + } + }); + } + + @Override + public void onCreateMenu(@NonNull final Menu menu, @NonNull final MenuInflater menuInflater) { + menuInflater.inflate(R.menu.menu_file_manager, menu); + } + + @Override + public boolean onMenuItemSelected(@NonNull final MenuItem menuItem) { + final int itemId = menuItem.getItemId(); + if (itemId == R.id.file_manager_search) { + searchView.setVisibility(View.VISIBLE); + searchView.requestFocus(); + } + return false; } @Override diff --git a/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/activities/files/FileManagerAdapter.java b/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/activities/files/FileManagerAdapter.java index e64d0245b..1f78997f2 100644 --- a/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/activities/files/FileManagerAdapter.java +++ b/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/activities/files/FileManagerAdapter.java @@ -21,6 +21,7 @@ import android.content.Intent; import android.view.LayoutInflater; import android.view.View; import android.view.ViewGroup; +import android.widget.Filter; import android.widget.ImageView; import android.widget.PopupMenu; import android.widget.TextView; @@ -36,6 +37,7 @@ import org.slf4j.LoggerFactory; import java.io.File; import java.io.IOException; import java.text.DecimalFormat; +import java.util.ArrayList; import java.util.Arrays; import java.util.List; @@ -49,11 +51,13 @@ public class FileManagerAdapter extends RecyclerView.Adapter fileList; private final Context mContext; + private final FileFilter fileFilter; + public FileManagerAdapter(final Context context, final File directory) { mContext = context; // FIXME: This can be slow, make it async - fileList = Arrays.asList(directory.listFiles()); + fileList = new ArrayList<>(Arrays.asList(directory.listFiles())); fileList.sort((f1, f2) -> { if (f1.isDirectory() && f2.isFile()) return -1; @@ -62,6 +66,8 @@ public class FileManagerAdapter extends RecyclerView.Adapter originalList; + private final List filteredList; + + private FileFilter(final FileManagerAdapter adapter, final List originalList) { + super(); + this.originalList = new ArrayList<>(originalList); + this.filteredList = new ArrayList<>(); + this.adapter = adapter; + } + + + @Override + protected FilterResults performFiltering(final CharSequence filter) { + filteredList.clear(); + final Filter.FilterResults results = new Filter.FilterResults(); + + if (filter == null || filter.length() == 0) + filteredList.addAll(originalList); + else { + final String filterPattern = filter.toString().toLowerCase().trim(); + + for (File f : originalList) { + final CharSequence name = f.getName(); + if (name.toString().toLowerCase().contains(filterPattern)) { + filteredList.add(f); + } + } + } + + results.values = filteredList; + results.count = filteredList.size(); + return results; + } + + @Override + protected void publishResults(final CharSequence constraint, final FilterResults filterResults) { + adapter.fileList.clear(); + adapter.fileList.addAll((List) filterResults.values); + adapter.notifyDataSetChanged(); + } + } } diff --git a/app/src/main/res/drawable/ic_search.xml b/app/src/main/res/drawable/ic_search.xml new file mode 100644 index 000000000..0aedebe3d --- /dev/null +++ b/app/src/main/res/drawable/ic_search.xml @@ -0,0 +1,12 @@ + + + + + diff --git a/app/src/main/res/layout/activity_file_manager.xml b/app/src/main/res/layout/activity_file_manager.xml index bdd6d30ec..c40ba3e2e 100644 --- a/app/src/main/res/layout/activity_file_manager.xml +++ b/app/src/main/res/layout/activity_file_manager.xml @@ -4,10 +4,19 @@ android:layout_height="match_parent" tools:context=".activities.files.FileManagerActivity"> + + + + diff --git a/app/src/main/res/values/strings.xml b/app/src/main/res/values/strings.xml index 567e00859..4d8784765 100644 --- a/app/src/main/res/values/strings.xml +++ b/app/src/main/res/values/strings.xml @@ -37,6 +37,7 @@ Changelog Synchronize Find lost device + Search Search for %1$s? Take Screenshot Power Off