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:
		
							parent
							
								
									510ec5f7c7
								
							
						
					
					
						commit
						ab5ea39f7c
					
				| @ -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 | ||||
|  | ||||
| @ -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 | ||||
|  | ||||
| @ -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" | ||||
|  | ||||
| @ -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" | ||||
|  | ||||
| @ -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> | ||||
| 
 | ||||
|  | ||||
| @ -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> | ||||
|  | ||||
		Loading…
	
	
			
			x
			
			
		
	
		Reference in New Issue
	
	Block a user
	 Peter Serwylo
						Peter Serwylo