diff --git a/app/src/main/java/com/aurora/store/ErrorType.java b/app/src/main/java/com/aurora/store/ErrorType.java index 134f5f11f..487320c22 100644 --- a/app/src/main/java/com/aurora/store/ErrorType.java +++ b/app/src/main/java/com/aurora/store/ErrorType.java @@ -25,6 +25,7 @@ public enum ErrorType { NO_APPS, NO_UPDATES, NO_SEARCH, + NO_SEARCH_RESULT, NO_DOWNLOADS, UNKNOWN, APP_NOT_FOUND, diff --git a/app/src/main/java/com/aurora/store/activity/AuroraActivity.java b/app/src/main/java/com/aurora/store/activity/AuroraActivity.java index bbdc159bf..3db8678ec 100644 --- a/app/src/main/java/com/aurora/store/activity/AuroraActivity.java +++ b/app/src/main/java/com/aurora/store/activity/AuroraActivity.java @@ -42,6 +42,7 @@ import com.aurora.store.R; import com.aurora.store.adapter.ViewPagerAdapter; import com.aurora.store.fragment.AppsFragment; import com.aurora.store.fragment.HomeFragment; +import com.aurora.store.fragment.SearchAppsFragment; import com.aurora.store.fragment.SearchFragment; import com.aurora.store.utility.Accountant; import com.aurora.store.utility.PrefUtil; @@ -198,7 +199,7 @@ public class AuroraActivity extends AppCompatActivity { pagerAdapter = new ViewPagerAdapter(getSupportFragmentManager()); pagerAdapter.addFragment(0, new HomeFragment()); pagerAdapter.addFragment(1, new AppsFragment()); - pagerAdapter.addFragment(2, new SearchFragment()); + pagerAdapter.addFragment(2, new SearchAppsFragment()); viewPager.setAdapter(pagerAdapter); viewPager.setScroll(false); viewPager.setOffscreenPageLimit(2); diff --git a/app/src/main/java/com/aurora/store/adapter/InstalledAppsAdapter.java b/app/src/main/java/com/aurora/store/adapter/InstalledAppsAdapter.java index b784163e8..f073c77b0 100644 --- a/app/src/main/java/com/aurora/store/adapter/InstalledAppsAdapter.java +++ b/app/src/main/java/com/aurora/store/adapter/InstalledAppsAdapter.java @@ -101,6 +101,11 @@ public class InstalledAppsAdapter extends RecyclerView.Adapter relatedTags = new ArrayList<>(); - private BottomNavigationView bottomNavigationView; private EndlessAppsAdapter endlessAppsAdapter; private SearchTask searchTask; @@ -94,7 +94,21 @@ public class SearchAppsFragment extends BaseFragment { } private void setQuery(String query) { - this.query = query; + if (looksLikeAPackageId(query)) { + context.startActivity(DetailsActivity.getDetailsIntent(getContext(), query)); + } else { + this.query = query; + fetchSearchAppsList(false); + } + } + + private boolean looksLikeAPackageId(String query) { + if (TextUtils.isEmpty(query)) { + return false; + } + String pattern = "([\\p{L}_$][\\p{L}\\p{N}_$]*\\.)+[\\p{L}_$][\\p{L}\\p{N}_$]*"; + Pattern r = Pattern.compile(pattern); + return r.matcher(query).matches(); } @Override @@ -108,67 +122,89 @@ public class SearchAppsFragment extends BaseFragment { public View onCreateView(@NonNull LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) { view = inflater.inflate(R.layout.fragment_search_applist, container, false); ButterKnife.bind(this, view); - Bundle arguments = getArguments(); - if (arguments != null) { - setQuery(arguments.getString("SearchQuery")); - searchQuery.setText(getQuery()); - } else - Log.e("No category id provided"); return view; } @Override public void onViewCreated(@NonNull View view, @Nullable Bundle savedInstanceState) { super.onViewCreated(view, savedInstanceState); - setupQueryEdit(); - setErrorView(ErrorType.UNKNOWN); + setErrorView(ErrorType.NO_SEARCH); + switchViews(true); + setupSearch(); setupRecycler(); - if (getActivity() instanceof AuroraActivity) { - bottomNavigationView = ((AuroraActivity) getActivity()).getBottomNavigation(); - setBaseBottomNavigationView(bottomNavigationView); - } - if (bottomNavigationView != null) - ViewUtil.hideBottomNav(bottomNavigationView, true); - filterFab.show(); filterFab.setOnClickListener(v -> getFilterDialog()); } @Override public void onResume() { super.onResume(); - if (endlessAppsAdapter == null || endlessAppsAdapter.isDataEmpty()) - fetchSearchAppsList(false); + } + + public void setUserVisibleHint(boolean isVisibleToUser) { + super.setUserVisibleHint(isVisibleToUser); + if (isVisibleToUser) { + if (searchView != null && Util.isIMEEnabled(context)) + searchView.requestFocus(); + } } @Override public void onDestroy() { Glide.with(this).pauseAllRequests(); disposable.dispose(); - if (bottomNavigationView != null) - ViewUtil.showBottomNav(bottomNavigationView, true); if (Util.filterSearchNonPersistent(context)) new Filter(context).resetFilterPreferences(); super.onDestroy(); } - private void setupQueryEdit() { - searchQuery.setOnFocusChangeListener((v, hasFocus) -> { - if (hasFocus) - searchQuery.setCompoundDrawablesWithIntrinsicBounds(0, 0, R.drawable.ic_search, 0); - else - searchQuery.setCompoundDrawablesWithIntrinsicBounds(0, 0, R.drawable.ic_edit, 0); - }); - searchQuery.setOnEditorActionListener((v, actionId, event) -> { - if (actionId == EditorInfo.IME_ACTION_SEARCH) { - query = searchQuery.getText().toString(); - fetchSearchAppsList(false); - searchQuery.setCompoundDrawablesWithIntrinsicBounds(0, 0, R.drawable.ic_edit, 0); - InputMethodManager imm = (InputMethodManager) v.getContext().getSystemService(Context.INPUT_METHOD_SERVICE); - imm.hideSoftInputFromWindow(v.getWindowToken(), 0); - searchQuery.clearFocus(); + private void setupSearch() { + SearchManager searchManager = (SearchManager) context.getSystemService(Context.SEARCH_SERVICE); + ComponentName componentName = getActivity().getComponentName(); + + if (null != searchManager && componentName != null) { + searchView.setSearchableInfo(searchManager.getSearchableInfo(componentName)); + } + + if (!StringUtils.isEmpty(AuroraActivity.externalQuery)) + setQuery(AuroraActivity.externalQuery); + + searchView.setOnQueryTextListener(new SearchView.OnQueryTextListener() { + @Override + public boolean onQueryTextChange(String query) { + if (StringUtils.isEmpty(query)) { + endlessAppsAdapter.clearData(); + switchViews(true); + filterFab.hide(); + } return true; - } else - return false; + } + + @Override + public boolean onQueryTextSubmit(String query) { + searchView.clearFocus(); + setQuery(query); + return true; + } + }); + + searchView.setOnSuggestionListener(new SearchView.OnSuggestionListener() { + @Override + public boolean onSuggestionSelect(int position) { + return true; + } + + @Override + public boolean onSuggestionClick(int position) { + Cursor cursor = searchView.getSuggestionsAdapter().getCursor(); + cursor.moveToPosition(position); + if (position == 0) { + searchView.setQuery(cursor.getString(2), true); + searchView.setQuery(cursor.getString(1), false); + } else + searchView.setQuery(cursor.getString(1), true); + setQuery(cursor.getString(0)); + return true; + } }); } @@ -201,17 +237,17 @@ public class SearchAppsFragment extends BaseFragment { disposable.add(Observable.fromCallable(() -> searchTask.getSearchResults(iterator)) .subscribeOn(Schedulers.io()) .observeOn(AndroidSchedulers.mainThread()) - .doOnSubscribe(d -> ViewUtil.showWithAnimation(layoutProgress)) - .doOnTerminate(() -> ViewUtil.hideWithAnimation(layoutProgress)) .subscribe(appList -> { if (view != null) { if (shouldIterate) { addApps(appList); } else if (appList.isEmpty() && endlessAppsAdapter.isDataEmpty()) { - setErrorView(ErrorType.NO_SEARCH); + filterFab.hide(true); + setErrorView(ErrorType.NO_SEARCH_RESULT); switchViews(true); } else { switchViews(false); + filterFab.show(true); if (endlessAppsAdapter != null) endlessAppsAdapter.addData(appList); if (!relatedTags.isEmpty()) @@ -246,18 +282,16 @@ public class SearchAppsFragment extends BaseFragment { } private void setupRecycler() { - LinearLayoutManager mLayoutManager = new LinearLayoutManager(getContext(), RecyclerView.VERTICAL, false); + LinearLayoutManager layoutManager = new LinearLayoutManager(getContext(), RecyclerView.VERTICAL, false); endlessAppsAdapter = new EndlessAppsAdapter(context); - recyclerView.setLayoutManager(mLayoutManager); - recyclerView.setLayoutAnimation(AnimationUtils.loadLayoutAnimation(this.getActivity(), R.anim.anim_falldown)); + recyclerView.setLayoutManager(layoutManager); recyclerView.setAdapter(endlessAppsAdapter); - EndlessScrollListener endlessScrollListener = new EndlessScrollListener(mLayoutManager) { + recyclerView.addOnScrollListener(new EndlessScrollListener(layoutManager) { @Override public void onLoadMore(int page, int totalItemsCount, RecyclerView view) { fetchSearchAppsList(true); } - }; - recyclerView.addOnScrollListener(endlessScrollListener); + }); recyclerView.setOnFlingListener(new RecyclerView.OnFlingListener() { @Override public boolean onFling(int velocityX, int velocityY) { @@ -265,8 +299,6 @@ public class SearchAppsFragment extends BaseFragment { filterFab.show(); } else if (velocityY > 0) { filterFab.hide(); - if (bottomNavigationView != null) - ViewUtil.hideBottomNav(bottomNavigationView, true); } return false; } @@ -289,11 +321,9 @@ public class SearchAppsFragment extends BaseFragment { if (chip.isChecked()) { query = query + " " + tag; fetchData(); - searchQuery.setText(query); } else { query = query.replace(tag, ""); fetchData(); - searchQuery.setText(query); } }); relatedChipGroup.addView(chip); diff --git a/app/src/main/java/com/aurora/store/task/UpdatableAppsTask.java b/app/src/main/java/com/aurora/store/task/UpdatableAppsTask.java index 7dc822988..79973e437 100644 --- a/app/src/main/java/com/aurora/store/task/UpdatableAppsTask.java +++ b/app/src/main/java/com/aurora/store/task/UpdatableAppsTask.java @@ -25,10 +25,12 @@ import android.content.pm.PackageInfo; import android.content.pm.PackageManager; import android.text.TextUtils; +import com.aurora.store.exception.MalformedRequestException; import com.aurora.store.manager.BlacklistManager; import com.aurora.store.model.App; import com.aurora.store.model.AppBuilder; import com.aurora.store.utility.Accountant; +import com.aurora.store.utility.Log; import com.aurora.store.utility.PackageUtil; import com.dragons.aurora.playstoreapiv2.BulkDetailsEntry; @@ -75,13 +77,21 @@ public class UpdatableAppsTask extends AllAppsTask { private List getRemoteAppList(List packageNames) throws IOException { final List appList = new ArrayList<>(); - final List bulkDetailsEntries = getApi().bulkDetails(packageNames).getEntryList(); - for (BulkDetailsEntry bulkDetailsEntry : bulkDetailsEntries) { - if (!bulkDetailsEntry.hasDoc()) { - continue; + try { + final List bulkDetailsEntries = getApi().bulkDetails(packageNames).getEntryList(); + for (BulkDetailsEntry bulkDetailsEntry : bulkDetailsEntries) { + if (!bulkDetailsEntry.hasDoc()) { + continue; + } + appList.add(AppBuilder.build(bulkDetailsEntry.getDoc())); } - appList.add(AppBuilder.build(bulkDetailsEntry.getDoc())); + } catch (Exception e) { + if (e instanceof MalformedRequestException) { + Log.e("Malformed Request : %s", e.getMessage()); + } else + throw e; } + return appList; } diff --git a/app/src/main/java/com/aurora/store/view/ErrorView.java b/app/src/main/java/com/aurora/store/view/ErrorView.java index bb8f741b2..b0eb67672 100644 --- a/app/src/main/java/com/aurora/store/view/ErrorView.java +++ b/app/src/main/java/com/aurora/store/view/ErrorView.java @@ -74,6 +74,11 @@ public class ErrorView extends RelativeLayout { txtError.setText(R.string.list_empty_updates); break; case NO_SEARCH: + imgError.setImageDrawable(context.getDrawable(R.drawable.ic_search_alt)); + txtError.setText(R.string.title_search); + btnError.setVisibility(GONE); + break; + case NO_SEARCH_RESULT: imgError.setImageDrawable(context.getDrawable(R.drawable.ic_search_alt)); txtError.setText(R.string.error_search_not_found); break; diff --git a/app/src/main/res/drawable/ic_filter.xml b/app/src/main/res/drawable/ic_filter.xml index ffa1f2336..cc6f7ec5f 100644 --- a/app/src/main/res/drawable/ic_filter.xml +++ b/app/src/main/res/drawable/ic_filter.xml @@ -24,6 +24,6 @@ android:viewportWidth="24.0" android:viewportHeight="24.0"> diff --git a/app/src/main/res/layout/fragment_search_applist.xml b/app/src/main/res/layout/fragment_search_applist.xml index c5578a833..d460e8ba2 100644 --- a/app/src/main/res/layout/fragment_search_applist.xml +++ b/app/src/main/res/layout/fragment_search_applist.xml @@ -23,30 +23,26 @@ xmlns:tools="http://schemas.android.com/tools" android:id="@+id/coordinator" android:layout_width="match_parent" - android:layout_height="match_parent" - android:background="?android:attr/colorBackground"> + android:layout_height="match_parent"> - + app:iconifiedByDefault="false" + app:queryBackground="@android:color/transparent" + app:queryHint="@string/title_search" + app:searchIcon="@drawable/ic_round_search" /> - - - - + - - - - + android:layout_gravity="center_horizontal|bottom" + android:layout_marginEnd="@dimen/margin_normal" + android:layout_marginBottom="@dimen/margin_bottom" + android:text="Filter" + android:textAppearance="@style/TextAppearance.Aurora.Button" + android:textColor="@color/colorWhite" + android:visibility="gone" + app:backgroundTint="@color/colorAccent" + app:icon="@drawable/ic_filter" + app:iconTint="@color/colorWhite" + app:layout_anchorGravity="top|end" /> \ No newline at end of file diff --git a/app/src/main/res/values/dimens.xml b/app/src/main/res/values/dimens.xml index b934326af..1450897aa 100755 --- a/app/src/main/res/values/dimens.xml +++ b/app/src/main/res/values/dimens.xml @@ -20,6 +20,7 @@ --> + 64dp 32dp 24dp 16dp