mirror of
https://codeberg.org/Freeyourgadget/Gadgetbridge
synced 2024-09-01 03:55:47 +02:00
Data Management: Add basic search to file manager
This commit is contained in:
parent
c9e4379346
commit
d033c5e33e
@ -17,10 +17,16 @@
|
|||||||
package nodomain.freeyourgadget.gadgetbridge.activities.files;
|
package nodomain.freeyourgadget.gadgetbridge.activities.files;
|
||||||
|
|
||||||
import android.os.Bundle;
|
import android.os.Bundle;
|
||||||
|
import android.view.Menu;
|
||||||
|
import android.view.MenuInflater;
|
||||||
import android.view.MenuItem;
|
import android.view.MenuItem;
|
||||||
|
import android.view.View;
|
||||||
import android.widget.Toast;
|
import android.widget.Toast;
|
||||||
|
|
||||||
|
import androidx.annotation.NonNull;
|
||||||
import androidx.appcompat.app.ActionBar;
|
import androidx.appcompat.app.ActionBar;
|
||||||
|
import androidx.appcompat.widget.SearchView;
|
||||||
|
import androidx.core.view.MenuProvider;
|
||||||
import androidx.recyclerview.widget.LinearLayoutManager;
|
import androidx.recyclerview.widget.LinearLayoutManager;
|
||||||
import androidx.recyclerview.widget.RecyclerView;
|
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.FileUtils;
|
||||||
import nodomain.freeyourgadget.gadgetbridge.util.GB;
|
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);
|
private static final Logger LOG = LoggerFactory.getLogger(FileManagerActivity.class);
|
||||||
|
|
||||||
public static final String EXTRA_PATH = "path";
|
public static final String EXTRA_PATH = "path";
|
||||||
|
|
||||||
|
private SearchView searchView;
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
protected void onCreate(final Bundle savedInstanceState) {
|
protected void onCreate(final Bundle savedInstanceState) {
|
||||||
super.onCreate(savedInstanceState);
|
super.onCreate(savedInstanceState);
|
||||||
setContentView(R.layout.activity_file_manager);
|
setContentView(R.layout.activity_file_manager);
|
||||||
|
addMenuProvider(this);
|
||||||
|
|
||||||
final RecyclerView fileListView = findViewById(R.id.fileListView);
|
final RecyclerView fileListView = findViewById(R.id.fileListView);
|
||||||
fileListView.setLayoutManager(new LinearLayoutManager(this));
|
fileListView.setLayoutManager(new LinearLayoutManager(this));
|
||||||
@ -76,6 +85,40 @@ public class FileManagerActivity extends AbstractGBActivity {
|
|||||||
final FileManagerAdapter appListAdapter = new FileManagerAdapter(this, directory);
|
final FileManagerAdapter appListAdapter = new FileManagerAdapter(this, directory);
|
||||||
|
|
||||||
fileListView.setAdapter(appListAdapter);
|
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
|
@Override
|
||||||
|
@ -21,6 +21,7 @@ import android.content.Intent;
|
|||||||
import android.view.LayoutInflater;
|
import android.view.LayoutInflater;
|
||||||
import android.view.View;
|
import android.view.View;
|
||||||
import android.view.ViewGroup;
|
import android.view.ViewGroup;
|
||||||
|
import android.widget.Filter;
|
||||||
import android.widget.ImageView;
|
import android.widget.ImageView;
|
||||||
import android.widget.PopupMenu;
|
import android.widget.PopupMenu;
|
||||||
import android.widget.TextView;
|
import android.widget.TextView;
|
||||||
@ -36,6 +37,7 @@ import org.slf4j.LoggerFactory;
|
|||||||
import java.io.File;
|
import java.io.File;
|
||||||
import java.io.IOException;
|
import java.io.IOException;
|
||||||
import java.text.DecimalFormat;
|
import java.text.DecimalFormat;
|
||||||
|
import java.util.ArrayList;
|
||||||
import java.util.Arrays;
|
import java.util.Arrays;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
|
|
||||||
@ -49,11 +51,13 @@ public class FileManagerAdapter extends RecyclerView.Adapter<FileManagerAdapter.
|
|||||||
private final List<File> fileList;
|
private final List<File> fileList;
|
||||||
private final Context mContext;
|
private final Context mContext;
|
||||||
|
|
||||||
|
private final FileFilter fileFilter;
|
||||||
|
|
||||||
public FileManagerAdapter(final Context context, final File directory) {
|
public FileManagerAdapter(final Context context, final File directory) {
|
||||||
mContext = context;
|
mContext = context;
|
||||||
|
|
||||||
// FIXME: This can be slow, make it async
|
// FIXME: This can be slow, make it async
|
||||||
fileList = Arrays.asList(directory.listFiles());
|
fileList = new ArrayList<>(Arrays.asList(directory.listFiles()));
|
||||||
fileList.sort((f1, f2) -> {
|
fileList.sort((f1, f2) -> {
|
||||||
if (f1.isDirectory() && f2.isFile())
|
if (f1.isDirectory() && f2.isFile())
|
||||||
return -1;
|
return -1;
|
||||||
@ -62,6 +66,8 @@ public class FileManagerAdapter extends RecyclerView.Adapter<FileManagerAdapter.
|
|||||||
|
|
||||||
return String.CASE_INSENSITIVE_ORDER.compare(f1.getName(), f2.getName());
|
return String.CASE_INSENSITIVE_ORDER.compare(f1.getName(), f2.getName());
|
||||||
});
|
});
|
||||||
|
|
||||||
|
fileFilter = new FileFilter(this, fileList);
|
||||||
}
|
}
|
||||||
|
|
||||||
@NonNull
|
@NonNull
|
||||||
@ -125,6 +131,10 @@ public class FileManagerAdapter extends RecyclerView.Adapter<FileManagerAdapter.
|
|||||||
return fileList.size();
|
return fileList.size();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public Filter getFilter() {
|
||||||
|
return fileFilter;
|
||||||
|
}
|
||||||
|
|
||||||
public static class FileManagerViewHolder extends RecyclerView.ViewHolder {
|
public static class FileManagerViewHolder extends RecyclerView.ViewHolder {
|
||||||
final ImageView icon;
|
final ImageView icon;
|
||||||
final TextView name;
|
final TextView name;
|
||||||
@ -149,4 +159,48 @@ public class FileManagerAdapter extends RecyclerView.Adapter<FileManagerAdapter.
|
|||||||
int digitGroups = (int) (Math.log10(size) / Math.log10(1024));
|
int digitGroups = (int) (Math.log10(size) / Math.log10(1024));
|
||||||
return SIZE_FORMAT.format(size / Math.pow(1024, digitGroups)) + " " + units[digitGroups];
|
return SIZE_FORMAT.format(size / Math.pow(1024, digitGroups)) + " " + units[digitGroups];
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private class FileFilter extends Filter {
|
||||||
|
private final FileManagerAdapter adapter;
|
||||||
|
private final List<File> originalList;
|
||||||
|
private final List<File> filteredList;
|
||||||
|
|
||||||
|
private FileFilter(final FileManagerAdapter adapter, final List<File> 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<File>) filterResults.values);
|
||||||
|
adapter.notifyDataSetChanged();
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
12
app/src/main/res/drawable/ic_search.xml
Normal file
12
app/src/main/res/drawable/ic_search.xml
Normal file
@ -0,0 +1,12 @@
|
|||||||
|
<vector xmlns:android="http://schemas.android.com/apk/res/android"
|
||||||
|
android:width="24dp"
|
||||||
|
android:height="24dp"
|
||||||
|
android:tint="#7E7E7E"
|
||||||
|
android:viewportWidth="24"
|
||||||
|
android:viewportHeight="24">
|
||||||
|
|
||||||
|
<path
|
||||||
|
android:fillColor="@android:color/white"
|
||||||
|
android:pathData="M15.5,14h-0.79l-0.28,-0.27C15.41,12.59 16,11.11 16,9.5 16,5.91 13.09,3 9.5,3S3,5.91 3,9.5 5.91,16 9.5,16c1.61,0 3.09,-0.59 4.23,-1.57l0.27,0.28v0.79l5,4.99L20.49,19l-4.99,-5zM9.5,14C7.01,14 5,11.99 5,9.5S7.01,5 9.5,5 14,7.01 14,9.5 11.99,14 9.5,14z" />
|
||||||
|
|
||||||
|
</vector>
|
@ -4,10 +4,19 @@
|
|||||||
android:layout_height="match_parent"
|
android:layout_height="match_parent"
|
||||||
tools:context=".activities.files.FileManagerActivity">
|
tools:context=".activities.files.FileManagerActivity">
|
||||||
|
|
||||||
|
<androidx.appcompat.widget.SearchView
|
||||||
|
android:id="@+id/fileListSearchView"
|
||||||
|
android:layout_width="match_parent"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:layout_alignParentTop="true"
|
||||||
|
android:paddingStart="8dp"
|
||||||
|
android:paddingEnd="8dp" />
|
||||||
|
|
||||||
<androidx.recyclerview.widget.RecyclerView
|
<androidx.recyclerview.widget.RecyclerView
|
||||||
android:id="@+id/fileListView"
|
android:id="@+id/fileListView"
|
||||||
android:layout_width="match_parent"
|
android:layout_width="match_parent"
|
||||||
android:layout_height="match_parent"
|
android:layout_height="match_parent"
|
||||||
|
android:layout_below="@id/fileListSearchView"
|
||||||
android:layout_centerHorizontal="true"
|
android:layout_centerHorizontal="true"
|
||||||
android:divider="@null"
|
android:divider="@null"
|
||||||
android:scrollbarSize="5dp"
|
android:scrollbarSize="5dp"
|
||||||
|
11
app/src/main/res/menu/menu_file_manager.xml
Normal file
11
app/src/main/res/menu/menu_file_manager.xml
Normal file
@ -0,0 +1,11 @@
|
|||||||
|
<menu xmlns:android="http://schemas.android.com/apk/res/android"
|
||||||
|
xmlns:app="http://schemas.android.com/apk/res-auto"
|
||||||
|
xmlns:tools="http://schemas.android.com/tools"
|
||||||
|
tools:context="nodomain.freeyourgadget.gadgetbridge.activities.files.FileManagerActivity">
|
||||||
|
<item
|
||||||
|
android:id="@+id/file_manager_search"
|
||||||
|
android:icon="@drawable/ic_search"
|
||||||
|
android:title="@string/search"
|
||||||
|
app:iconTint="?attr/actionmenu_icon_color"
|
||||||
|
app:showAsAction="always" />
|
||||||
|
</menu>
|
@ -37,6 +37,7 @@
|
|||||||
<string name="action_changelog">Changelog</string>
|
<string name="action_changelog">Changelog</string>
|
||||||
<string name="controlcenter_fetch_activity_data">Synchronize</string>
|
<string name="controlcenter_fetch_activity_data">Synchronize</string>
|
||||||
<string name="controlcenter_find_device">Find lost device</string>
|
<string name="controlcenter_find_device">Find lost device</string>
|
||||||
|
<string name="search">Search</string>
|
||||||
<string name="find_lost_device_message">Search for %1$s?</string>
|
<string name="find_lost_device_message">Search for %1$s?</string>
|
||||||
<string name="controlcenter_take_screenshot">Take Screenshot</string>
|
<string name="controlcenter_take_screenshot">Take Screenshot</string>
|
||||||
<string name="controlcenter_power_off">Power Off</string>
|
<string name="controlcenter_power_off">Power Off</string>
|
||||||
|
Loading…
Reference in New Issue
Block a user