Show empty state feedback for latest + categories

The text is more comprehensive on the main screen than on categories,
because this is the view that all users will see when they first open
F-Droid.

Fixes #879.
This commit is contained in:
Peter Serwylo 2017-04-05 12:05:29 +10:00
parent 510ec5f7c7
commit ab5ea39f7c
6 changed files with 89 additions and 2 deletions

View File

@ -12,6 +12,7 @@ import android.support.v7.widget.LinearLayoutManager;
import android.support.v7.widget.RecyclerView;
import android.view.View;
import android.widget.FrameLayout;
import android.widget.TextView;
import org.fdroid.fdroid.R;
import org.fdroid.fdroid.data.CategoryProvider;
@ -30,6 +31,8 @@ class CategoriesViewBinder implements LoaderManager.LoaderCallbacks<Cursor> {
private final CategoryAdapter categoryAdapter;
private final AppCompatActivity activity;
private final TextView emptyState;
private final RecyclerView categoriesList;
CategoriesViewBinder(final AppCompatActivity activity, FrameLayout parent) {
this.activity = activity;
@ -38,7 +41,9 @@ class CategoriesViewBinder implements LoaderManager.LoaderCallbacks<Cursor> {
categoryAdapter = new CategoryAdapter(activity, activity.getSupportLoaderManager());
RecyclerView categoriesList = (RecyclerView) categoriesView.findViewById(R.id.category_list);
emptyState = (TextView) categoriesView.findViewById(R.id.empty_state);
categoriesList = (RecyclerView) categoriesView.findViewById(R.id.category_list);
categoriesList.setHasFixedSize(true);
categoriesList.setLayoutManager(new LinearLayoutManager(activity));
categoriesList.setAdapter(categoryAdapter);
@ -77,6 +82,14 @@ class CategoriesViewBinder implements LoaderManager.LoaderCallbacks<Cursor> {
}
categoryAdapter.setCategoriesCursor(cursor);
if (categoryAdapter.getItemCount() == 0) {
emptyState.setVisibility(View.VISIBLE);
categoriesList.setVisibility(View.GONE);
} else {
emptyState.setVisibility(View.GONE);
categoriesList.setVisibility(View.VISIBLE);
}
}
@Override

View File

@ -13,14 +13,20 @@ import android.support.v7.widget.GridLayoutManager;
import android.support.v7.widget.RecyclerView;
import android.view.View;
import android.widget.FrameLayout;
import android.widget.TextView;
import org.fdroid.fdroid.R;
import org.fdroid.fdroid.UpdateService;
import org.fdroid.fdroid.data.AppProvider;
import org.fdroid.fdroid.data.RepoProvider;
import org.fdroid.fdroid.data.Schema;
import org.fdroid.fdroid.views.apps.AppListActivity;
import org.fdroid.fdroid.views.whatsnew.WhatsNewAdapter;
import java.util.Calendar;
import java.util.Date;
import java.util.concurrent.TimeUnit;
/**
* Loads a list of newly added or recently updated apps and displays them to the user.
*/
@ -30,6 +36,8 @@ class WhatsNewViewBinder implements LoaderManager.LoaderCallbacks<Cursor> {
private final WhatsNewAdapter whatsNewAdapter;
private final AppCompatActivity activity;
private final TextView emptyState;
private final RecyclerView appList;
WhatsNewViewBinder(final AppCompatActivity activity, FrameLayout parent) {
this.activity = activity;
@ -41,7 +49,9 @@ class WhatsNewViewBinder implements LoaderManager.LoaderCallbacks<Cursor> {
GridLayoutManager layoutManager = new GridLayoutManager(activity, 2);
layoutManager.setSpanSizeLookup(new WhatsNewAdapter.SpanSizeLookup());
RecyclerView appList = (RecyclerView) whatsNewView.findViewById(R.id.app_list);
emptyState = (TextView) whatsNewView.findViewById(R.id.empty_state);
appList = (RecyclerView) whatsNewView.findViewById(R.id.app_list);
appList.setHasFixedSize(true);
appList.setLayoutManager(layoutManager);
appList.setAdapter(whatsNewAdapter);
@ -89,6 +99,37 @@ class WhatsNewViewBinder implements LoaderManager.LoaderCallbacks<Cursor> {
}
whatsNewAdapter.setAppsCursor(cursor);
if (whatsNewAdapter.getItemCount() == 0) {
emptyState.setVisibility(View.VISIBLE);
appList.setVisibility(View.GONE);
explainEmptyStateToUser();
} else {
emptyState.setVisibility(View.GONE);
appList.setVisibility(View.VISIBLE);
}
}
private void explainEmptyStateToUser() {
StringBuilder emptyStateText = new StringBuilder();
emptyStateText.append(activity.getString(R.string.latest__empty_state__no_recent_apps));
emptyStateText.append("\n\n");
int repoCount = RepoProvider.Helper.countEnabledRepos(activity);
if (repoCount == 0) {
emptyStateText.append(activity.getString(R.string.latest__empty_state__no_enabled_repos));
} else {
Date lastUpdate = RepoProvider.Helper.lastUpdate(activity);
if (lastUpdate == null) {
emptyStateText.append(activity.getString(R.string.latest__empty_state__never_updated));
} else {
long msDiff = Calendar.getInstance().getTimeInMillis() - lastUpdate.getTime();
int daysDiff = (int) TimeUnit.MILLISECONDS.toDays(msDiff);
emptyStateText.append(activity.getResources().getQuantityString(R.plurals.details_last_update_days, daysDiff, daysDiff));
}
}
emptyState.setText(emptyStateText.toString());
}
@Override

View File

@ -16,6 +16,18 @@
app:layout_constraintEnd_toEndOf="parent"
tools:layout_editor_absoluteX="8dp" />
<TextView
android:id="@+id/empty_state"
android:layout_width="0dp"
android:layout_height="0dp"
style="@style/AppListEmptyText"
app:layout_constraintTop_toTopOf="parent"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintEnd_toEndOf="parent"
android:visibility="gone"
android:text="@string/categories__empty_state__no_categories" />
<android.support.v7.widget.RecyclerView
android:id="@+id/category_list"
android:layout_width="0dp"

View File

@ -21,6 +21,14 @@
android:layout_width="match_parent"
android:layout_height="wrap_content" />
<TextView
android:id="@+id/empty_state"
android:layout_width="match_parent"
android:layout_height="match_parent"
style="@style/AppListEmptyText"
android:visibility="gone"
tools:text="@string/latest__empty_state__no_recent_apps"/>
<android.support.v7.widget.RecyclerView
android:id="@+id/app_list"
android:layout_width="match_parent"

View File

@ -159,6 +159,12 @@
<string name="main_menu__categories">Categories</string>
<string name="main_menu__swap_nearby">Nearby</string>
<string name="latest__empty_state__no_recent_apps">No recent apps found</string>
<string name="latest__empty_state__never_updated">Once your list of apps has been updated, the latest apps should show here</string>
<string name="latest__empty_state__no_enabled_repos">Once you enable a repository and let it update, the latest apps should show here</string>
<string name="categories__empty_state__no_categories">No categories to display</string>
<string name="preference_category__my_apps">My Apps</string>
<string name="preference_manage_installed_apps">Manage Installed Apps</string>

View File

@ -93,6 +93,13 @@
</style>
<style name="BodyText" parent="BodyTextBase" />
<style name="AppListEmptyText">
<item name="android:id">@android:id/empty</item>
<item name="android:gravity">center</item>
<item name="android:padding">20dp</item>
<item name="android:textSize">20sp</item>
</style>
<style name="SwapTheme.Wizard" parent="Theme.AppCompat.Light.NoActionBar">
<item name="colorButtonNormal">@color/swap_bright_blue</item>
<item name="actionButtonStyle">@style/SwapTheme.Wizard.ActionButton</item>