Przeglądaj źródła

Added handling empty and error states

Vadik Sirekanyan 7 lat temu
rodzic
commit
3e164eebdd

+ 38 - 30
app/src/main/java/me/vadik/knigopis/MainActivity.kt

@@ -18,6 +18,7 @@ import com.tbruyelle.rxpermissions2.RxPermissions
 import kotlinx.android.synthetic.main.about.view.*
 import kotlinx.android.synthetic.main.activity_main.*
 import kotlinx.android.synthetic.main.books_page.*
+import kotlinx.android.synthetic.main.notes_page.*
 import kotlinx.android.synthetic.main.users_page.*
 import me.vadik.knigopis.adapters.BooksAdapter
 import me.vadik.knigopis.adapters.notes.NotesAdapter
@@ -344,43 +345,43 @@ class MainActivity : AppCompatActivity(), Router {
 
     private fun isFirstOpenTab(tab: CurrentTab) =
         when (tab) {
-            HOME_TAB -> booksRecyclerView.adapter == null
-            USERS_TAB -> usersRecyclerView.adapter == null
-            NOTES_TAB -> notesRecyclerView.adapter == null
+            HOME_TAB -> booksRecyclerView.adapter == null || booksErrorPlaceholder.isVisible
+            USERS_TAB -> usersRecyclerView.adapter == null || usersErrorPlaceholder.isVisible
+            NOTES_TAB -> notesRecyclerView.adapter == null || notesErrorPlaceholder.isVisible
         }
 
     private fun togglePage(tab: CurrentTab) {
         booksPage.show(tab == HOME_TAB)
         usersPage.show(tab == USERS_TAB)
-        notesRecyclerView.show(tab == NOTES_TAB)
+        notesPage.show(tab == NOTES_TAB)
     }
 
     private fun refreshHomeTab() {
-        if (booksProgressBar.alpha > 0) {
-            return
-        }
         bookRepository.loadBooks()
             .io2main()
             .doOnSubscribe {
                 if (!swipeRefresh.isRefreshing) {
                     booksProgressBar.show()
                 }
-                booksPlaceholder.hide()
             }
             .doFinally {
                 booksProgressBar.hide()
                 swipeRefresh.isRefreshing = false
             }
             .subscribe({ books ->
-                if (books.isEmpty()) {
-                    booksPlaceholder.setText(R.string.error_no_books)
-                    booksPlaceholder.show()
-                }
+                booksPlaceholder.show(books.isEmpty())
+                booksErrorPlaceholder.hide()
                 allBooks.clear()
                 allBooks.addAll(books)
                 allBooksAdapter.notifyDataSetChanged()
             }, {
-                handleNetworkError("cannot load books", it)
+                logError("cannot load books", it)
+                if (booksPlaceholder.isVisible || allBooksAdapter.itemCount > 0) {
+                    toast(it.messageRes)
+                } else {
+                    booksErrorPlaceholder.setText(it.messageRes)
+                    booksErrorPlaceholder.show()
+                }
             })
     }
 
@@ -391,22 +392,25 @@ class MainActivity : AppCompatActivity(), Router {
                 if (!swipeRefresh.isRefreshing) {
                     booksProgressBar.show()
                 }
-                usersPlaceholder.hide()
             }
             .doFinally {
                 booksProgressBar.hide()
                 swipeRefresh.isRefreshing = false
             }
             .subscribe({ subscriptions ->
-                if (subscriptions.isEmpty()) {
-                    usersPlaceholder.setText(R.string.error_no_users)
-                    usersPlaceholder.show()
-                }
+                usersPlaceholder.show(subscriptions.isEmpty())
+                usersErrorPlaceholder.hide()
                 allUsers.clear()
                 allUsers.addAll(subscriptions)
                 usersAdapter.notifyDataSetChanged()
             }, {
-                handleNetworkError("cannot load users", it)
+                logError("cannot load users", it)
+                if (usersPlaceholder.isVisible || usersAdapter.itemCount > 0) {
+                    toast(it.messageRes)
+                } else {
+                    usersErrorPlaceholder.setText(it.messageRes)
+                    usersErrorPlaceholder.show()
+                }
             })
     }
 
@@ -423,23 +427,27 @@ class MainActivity : AppCompatActivity(), Router {
                 swipeRefresh.isRefreshing = false
             }
             .subscribe({ notes ->
+                notesPlaceholder.show(notes.isEmpty())
+                notesErrorPlaceholder.hide()
                 allNotes.clear()
                 allNotes.addAll(notes.values)
                 notesAdapter.notifyDataSetChanged()
             }, {
-                handleNetworkError("cannot load notes", it)
+                logError("cannot load notes", it)
+                if (notesPlaceholder.isVisible || notesAdapter.itemCount > 0) {
+                    toast(it.messageRes)
+                } else {
+                    notesErrorPlaceholder.setText(it.messageRes)
+                    notesErrorPlaceholder.show()
+                }
             })
     }
 
-    private fun handleNetworkError(message: String, throwable: Throwable) {
-        logError(message, throwable)
-        toast(
-            if (throwable is HttpException && throwable.code() == 401) {
-                R.string.error_unauthorized
-            } else {
-                R.string.error_loading_data
-            }
-        )
-    }
+    private val Throwable.messageRes
+        get() = if (this is HttpException && code() == 401) {
+            R.string.error_unauthorized
+        } else {
+            R.string.error_loading_data
+        }
 
 }

+ 2 - 0
app/src/main/java/me/vadik/knigopis/extensions.kt

@@ -111,6 +111,8 @@ fun View.hide() {
         .start()
 }
 
+val View.isVisible get() = visibility == View.VISIBLE
+
 fun ProgressBar.setProgressSmoothly(progress: Int) {
     ObjectAnimator.ofInt(this, "progress", progress).start()
 }

+ 10 - 11
app/src/main/res/layout/activity_main.xml

@@ -32,19 +32,18 @@
             android:layout_width="match_parent"
             android:layout_height="match_parent">
 
-            <include layout="@layout/books_page" />
+            <include
+                layout="@layout/books_page"
+                android:visibility="gone"
+                tools:visibility="visible" />
 
-            <include layout="@layout/users_page" />
+            <include
+                layout="@layout/users_page"
+                android:visibility="gone" />
 
-            <android.support.v7.widget.RecyclerView
-                android:id="@+id/notesRecyclerView"
-                android:layout_width="match_parent"
-                android:layout_height="match_parent"
-                android:clipToPadding="false"
-                android:paddingBottom="8dp"
-                android:paddingTop="8dp"
-                tools:listitem="@layout/note"
-                tools:visibility="gone" />
+            <include
+                layout="@layout/notes_page"
+                android:visibility="gone" />
 
             <ProgressBar
                 android:id="@+id/booksProgressBar"

+ 6 - 11
app/src/main/res/layout/books_page.xml

@@ -12,19 +12,14 @@
         android:layout_height="match_parent"
         tools:listitem="@layout/book" />
 
+    <TextView
+        android:id="@+id/booksErrorPlaceholder"
+        style="@style/PlaceholderStyle" />
+
     <TextView
         android:id="@+id/booksPlaceholder"
-        android:layout_width="wrap_content"
-        android:layout_height="wrap_content"
-        android:layout_gravity="center"
-        android:alpha="0"
-        android:gravity="center"
-        android:padding="16dp"
-        android:textSize="16sp"
-        android:visibility="gone"
-        tools:alpha="1"
-        tools:text="@string/error_loading_data"
-        tools:visibility="visible" />
+        style="@style/PlaceholderStyle"
+        android:text="@string/error_no_books" />
 
     <android.support.design.widget.FloatingActionButton
         android:id="@+id/addBookButton"

+ 26 - 0
app/src/main/res/layout/notes_page.xml

@@ -0,0 +1,26 @@
+<?xml version="1.0" encoding="utf-8"?>
+<FrameLayout xmlns:android="http://schemas.android.com/apk/res/android"
+    xmlns:tools="http://schemas.android.com/tools"
+    android:id="@+id/notesPage"
+    android:layout_width="match_parent"
+    android:layout_height="match_parent">
+
+    <android.support.v7.widget.RecyclerView
+        android:id="@+id/notesRecyclerView"
+        android:layout_width="match_parent"
+        android:layout_height="match_parent"
+        android:clipToPadding="false"
+        android:paddingBottom="8dp"
+        android:paddingTop="8dp"
+        tools:listitem="@layout/note" />
+
+    <TextView
+        android:id="@+id/notesErrorPlaceholder"
+        style="@style/PlaceholderStyle" />
+
+    <TextView
+        android:id="@+id/notesPlaceholder"
+        style="@style/PlaceholderStyle"
+        android:text="@string/error_no_notes" />
+
+</FrameLayout>

+ 7 - 13
app/src/main/res/layout/users_page.xml

@@ -12,21 +12,15 @@
         android:clipToPadding="false"
         android:paddingBottom="8dp"
         android:paddingTop="8dp"
-        tools:listitem="@layout/user"
-        tools:visibility="gone" />
+        tools:listitem="@layout/user" />
+
+    <TextView
+        android:id="@+id/usersErrorPlaceholder"
+        style="@style/PlaceholderStyle" />
 
     <TextView
         android:id="@+id/usersPlaceholder"
-        android:layout_width="wrap_content"
-        android:layout_height="wrap_content"
-        android:layout_gravity="center"
-        android:alpha="0"
-        android:gravity="center"
-        android:padding="16dp"
-        android:textSize="16sp"
-        android:visibility="gone"
-        tools:alpha="1"
-        tools:text="@string/error_loading_data"
-        tools:visibility="visible" />
+        style="@style/PlaceholderStyle"
+        android:text="@string/error_no_users" />
 
 </FrameLayout>

+ 2 - 1
app/src/main/res/values-ru/strings.xml

@@ -53,10 +53,11 @@
     <string name="about_designer">Дизайн:\nanna@sirekanyan.com</string>
 
     <!-- error -->
-    <string name="error_unauthorized">Это — Книгопись. Привет!</string>
+    <string name="error_unauthorized">Пожалуйста, авторизуйтесь.</string>
     <string name="error_loading_data">Проверьте подключение к сети.</string>
     <string name="error_no_books">У вас пока нет книг.</string>
     <string name="error_no_users">Вы ещё ни на кого не подписаны.</string>
+    <string name="error_no_notes">Нет новых комментариев.</string>
 
     <!-- permissions -->
     <string name="no_access">Нет доступа</string>

+ 2 - 1
app/src/main/res/values/strings.xml

@@ -59,10 +59,11 @@
     <string name="about_designer">Design:\nanna@sirekanyan.com</string>
 
     <!-- error -->
-    <string name="error_unauthorized">Welcome to Knigopis! Please log in.</string>
+    <string name="error_unauthorized">Please log in.</string>
     <string name="error_loading_data">Check your network connection.</string>
     <string name="error_no_books">You don\'t have any books.</string>
     <string name="error_no_users">You don\'t have any subscriptions yet.</string>
+    <string name="error_no_notes">No one is posted yet.</string>
 
     <!-- permissions -->
     <string name="no_access">Permission denied</string>

+ 11 - 0
app/src/main/res/values/styles.xml

@@ -37,6 +37,17 @@
         <item name="android:paddingEnd">-4dp</item>
     </style>
 
+    <style name="PlaceholderStyle">
+        <item name="android:layout_width">wrap_content</item>
+        <item name="android:layout_height">wrap_content</item>
+        <item name="android:layout_gravity">center</item>
+        <item name="android:alpha">0</item>
+        <item name="android:gravity">center</item>
+        <item name="android:padding">16dp</item>
+        <item name="android:textSize">16sp</item>
+        <item name="android:visibility">gone</item>
+    </style>
+
     <style name="WhiteAccent">
         <item name="colorAccent">@color/white</item>
     </style>