diff --git a/app/src/main/java/com/emanuelef/remote_capture/adapters/AppsTogglesAdapter.java b/app/src/main/java/com/emanuelef/remote_capture/adapters/AppsTogglesAdapter.java index 278845b5..f88e1be5 100644 --- a/app/src/main/java/com/emanuelef/remote_capture/adapters/AppsTogglesAdapter.java +++ b/app/src/main/java/com/emanuelef/remote_capture/adapters/AppsTogglesAdapter.java @@ -47,7 +47,9 @@ public class AppsTogglesAdapter extends RecyclerView.Adapter mCheckedItems; private AppToggleListener mListener; + private String mFilter = ""; private List mApps = new ArrayList<>(); + private final List mFilteredApps = new ArrayList<>(); private @Nullable RecyclerView mRecyclerView; public AppsTogglesAdapter(Context context, Set checkedItems) { @@ -125,16 +127,23 @@ public class AppsTogglesAdapter extends RecyclerView.Adapter getApps() { + if(mFilter.isEmpty()) + return mApps; + else + return mFilteredApps; + } + @Override public int getItemCount() { - return mApps.size(); + return getApps().size(); } public AppDescriptor getItem(int pos) { - if((pos < 0) || (pos > mApps.size())) + if((pos < 0) || (pos > getItemCount())) return null; - return mApps.get(pos); + return getApps().get(pos); } private void handleToggle(int old_pos, boolean checked) { @@ -152,10 +161,12 @@ public class AppsTogglesAdapter extends RecyclerView.Adapter apps = getApps(); + // determine the new item position int new_pos = old_pos; - for(int i=0; i apps) { mApps = apps; - Collections.sort(mApps, this::compareCheckedFirst); + refreshedFiteredApps(); + } - notifyDataSetChanged(); + public void setFilter(String text) { + mFilter = text; + refreshedFiteredApps(); } public void setAppToggleListener(final AppToggleListener listener) { diff --git a/app/src/main/java/com/emanuelef/remote_capture/adapters/ConnectionsAdapter.java b/app/src/main/java/com/emanuelef/remote_capture/adapters/ConnectionsAdapter.java index 95085f13..940b3a94 100644 --- a/app/src/main/java/com/emanuelef/remote_capture/adapters/ConnectionsAdapter.java +++ b/app/src/main/java/com/emanuelef/remote_capture/adapters/ConnectionsAdapter.java @@ -19,6 +19,7 @@ package com.emanuelef.remote_capture.adapters; +import android.annotation.SuppressLint; import android.content.Context; import android.graphics.drawable.Drawable; import android.util.Log; @@ -370,6 +371,7 @@ public class ConnectionsAdapter extends RecyclerView.Adapter apps) { mAdapter.setApps(apps); + mEmptyText.setText(R.string.no_matches_found); } // Must be implemented in sub-classes diff --git a/app/src/main/java/com/emanuelef/remote_capture/fragments/ConnectionsFragment.java b/app/src/main/java/com/emanuelef/remote_capture/fragments/ConnectionsFragment.java index a7e63612..1d204b8c 100644 --- a/app/src/main/java/com/emanuelef/remote_capture/fragments/ConnectionsFragment.java +++ b/app/src/main/java/com/emanuelef/remote_capture/fragments/ConnectionsFragment.java @@ -107,10 +107,7 @@ public class ConnectionsFragment extends Fragment implements ConnectionsListener public void onResume() { super.onResume(); - if((CaptureService.getConnsRegister() != null) || CaptureService.isServiceActive()) - mEmptyText.setText(R.string.no_connections); - else - mEmptyText.setText(R.string.capture_not_running_status); + refreshEmptyText(); registerConnsListener(); mRecyclerView.setEmptyView(mEmptyText); // after registerConnsListener, when the adapter is populated @@ -146,6 +143,13 @@ public class ConnectionsFragment extends Fragment implements ConnectionsListener return inflater.inflate(R.layout.connections, container, false); } + private void refreshEmptyText() { + if((CaptureService.getConnsRegister() != null) || CaptureService.isServiceActive()) + mEmptyText.setText(mAdapter.hasFilter() ? R.string.no_matches_found : R.string.no_connections); + else + mEmptyText.setText(R.string.capture_not_running_status); + } + private void registerConnsListener() { if (!listenerSet) { ConnectionsRegister reg = CaptureService.getConnsRegister(); @@ -810,6 +814,7 @@ public class ConnectionsFragment extends Fragment implements ConnectionsListener public boolean onQueryTextChange(String newText) { mAdapter.setSearch(newText); recheckScroll(); + refreshEmptyText(); return true; } diff --git a/app/src/main/java/com/emanuelef/remote_capture/model/AppDescriptor.java b/app/src/main/java/com/emanuelef/remote_capture/model/AppDescriptor.java index 0ffba28d..3fe08dc6 100644 --- a/app/src/main/java/com/emanuelef/remote_capture/model/AppDescriptor.java +++ b/app/src/main/java/com/emanuelef/remote_capture/model/AppDescriptor.java @@ -131,4 +131,10 @@ public class AppDescriptor implements Comparable, Serializable { return rv; } + + public boolean matches(String filter, boolean exactPackage) { + return getName().toLowerCase().contains(filter) || + (exactPackage && getPackageName().equals(filter)) || + (!exactPackage && getPackageName().contains(filter)); + } } diff --git a/app/src/main/java/com/emanuelef/remote_capture/model/ConnectionDescriptor.java b/app/src/main/java/com/emanuelef/remote_capture/model/ConnectionDescriptor.java index d6c5eb8e..063e856d 100644 --- a/app/src/main/java/com/emanuelef/remote_capture/model/ConnectionDescriptor.java +++ b/app/src/main/java/com/emanuelef/remote_capture/model/ConnectionDescriptor.java @@ -235,8 +235,7 @@ public class ConnectionDescriptor { Integer.toString(uid).equals(filter) || Integer.toString(dst_port).contains(filter) || Integer.toString(src_port).equals(filter) || - ((app != null) && (app.getName().toLowerCase().contains(filter) || - app.getPackageName().equals(filter))) + ((app != null) && (app.matches(filter, true))) ); } diff --git a/app/src/main/res/menu/search_menu.xml b/app/src/main/res/menu/search_menu.xml new file mode 100644 index 00000000..dd5b4f47 --- /dev/null +++ b/app/src/main/res/menu/search_menu.xml @@ -0,0 +1,15 @@ + + + + + + \ No newline at end of file diff --git a/app/src/main/res/values/strings.xml b/app/src/main/res/values/strings.xml index 05d3faa8..644fefb9 100644 --- a/app/src/main/res/values/strings.xml +++ b/app/src/main/res/values/strings.xml @@ -374,4 +374,5 @@ The app uses notifications to send alerts in case of anomalous events. Grant it the permission to send notifications in the next screen VPN Exceptions Exclude some apps from the VPN connection. Their traffic will not be monitored + No matches