Bladeren bron

Added sorting options on following page

Vadik Sirekanyan 5 jaren geleden
bovenliggende
commit
2f4f55bd68

+ 2 - 2
app/src/main/java/com/sirekanyan/knigopis/common/android/menu/OptionItems.kt

@@ -3,5 +3,5 @@ package com.sirekanyan.knigopis.common.android.menu
 inline fun <reified T> optionIds(): List<Int> where T : Enum<T>, T : OptionItem =
     enumValues<T>().map(OptionItem::id)
 
-inline fun <reified T> findOption(id: Int): T? where T : Enum<T>, T : OptionItem =
-    enumValues<T>().find { it.id == id }
+inline fun <reified T> getOption(id: Int): T where T : Enum<T>, T : OptionItem =
+    enumValues<T>().find { it.id == id } ?: enumValues<T>().first()

+ 7 - 5
app/src/main/java/com/sirekanyan/knigopis/dependency/app.kt

@@ -38,13 +38,15 @@ fun App.provideAuthRepository(): AuthRepository =
     AuthRepositoryImpl(endpoint, tokenStorage)
 
 fun App.provideBookRepository(): BookRepository {
-    val planned = PlannedBookOrganizerImpl(resourceProvider, config)
-    val finished = FinishedBookOrganizerImpl(resourceProvider, config)
-    return BookRepositoryImpl(endpoint, cache, planned, finished, networkChecker)
+    val plannedOrganizer = PlannedBookOrganizerImpl(resourceProvider, config)
+    val finishedOrganizer = FinishedBookOrganizerImpl(resourceProvider, config)
+    return BookRepositoryImpl(endpoint, cache, plannedOrganizer, finishedOrganizer, networkChecker)
 }
 
-fun App.provideUserRepository(): UserRepository =
-    UserRepositoryImpl(endpoint, cache, networkChecker)
+fun App.provideUserRepository(): UserRepository {
+    val organizer = UserOrganizer(config)
+    return UserRepositoryImpl(endpoint, cache, organizer, networkChecker)
+}
 
 fun App.provideNoteRepository(): NoteRepository =
     NoteRepositoryImpl(endpoint, cache, networkChecker)

+ 11 - 7
app/src/main/java/com/sirekanyan/knigopis/feature/MainPresenter.kt

@@ -5,12 +5,8 @@ import com.sirekanyan.knigopis.common.Presenter
 import com.sirekanyan.knigopis.common.functions.logError
 import com.sirekanyan.knigopis.feature.users.MainPresenterState
 import com.sirekanyan.knigopis.model.CurrentTab
-import com.sirekanyan.knigopis.model.CurrentTab.BOOKS_TAB
-import com.sirekanyan.knigopis.model.CurrentTab.NOTES_TAB
-import com.sirekanyan.knigopis.repository.AuthRepository
-import com.sirekanyan.knigopis.repository.BookSorting
-import com.sirekanyan.knigopis.repository.Configuration
-import com.sirekanyan.knigopis.repository.Theme
+import com.sirekanyan.knigopis.model.CurrentTab.*
+import com.sirekanyan.knigopis.repository.*
 import org.acra.ACRA
 
 interface MainPresenter : Presenter {
@@ -48,7 +44,8 @@ class MainPresenterImpl(
         get() = currentTab?.let { MainPresenterState(it) }
 
     override fun init(tab: CurrentTab?) {
-        view.setSortOptionChecked(config.bookSorting)
+        view.setOptionChecked(config.bookSorting)
+        view.setOptionChecked(config.userSorting)
         view.setThemeOptionChecked(Theme.getCurrent())
         view.setCrashReportOptionChecked(config.crashReportEnabled)
         val defaultTab = if (auth.isAuthorized()) BOOKS_TAB else NOTES_TAB
@@ -125,6 +122,13 @@ class MainPresenterImpl(
         }
     }
 
+    override fun onUserSortOptionClicked(sorting: UserSorting) {
+        if (currentTab == USERS_TAB) {
+            config.userSorting = sorting
+            refresh(isForce = true)
+        }
+    }
+
     override fun onLoginOptionClicked() {
         router.openLoginScreen()
     }

+ 17 - 6
app/src/main/java/com/sirekanyan/knigopis/feature/MainView.kt

@@ -6,7 +6,9 @@ import android.view.View
 import androidx.appcompat.app.AlertDialog
 import com.sirekanyan.knigopis.BuildConfig
 import com.sirekanyan.knigopis.R
+import com.sirekanyan.knigopis.common.android.menu.OptionItem
 import com.sirekanyan.knigopis.common.android.menu.addAll
+import com.sirekanyan.knigopis.common.android.menu.getOption
 import com.sirekanyan.knigopis.common.android.menu.optionIds
 import com.sirekanyan.knigopis.common.android.toast.CommonView
 import com.sirekanyan.knigopis.common.extensions.context
@@ -17,6 +19,7 @@ import com.sirekanyan.knigopis.model.CurrentTab
 import com.sirekanyan.knigopis.model.CurrentTab.*
 import com.sirekanyan.knigopis.repository.BookSorting
 import com.sirekanyan.knigopis.repository.Theme
+import com.sirekanyan.knigopis.repository.UserSorting
 import com.sirekanyan.knigopis.repository.cache.COMMON_PREFS_NAME
 import kotlinx.android.extensions.LayoutContainer
 import kotlinx.android.synthetic.main.about.view.*
@@ -36,7 +39,7 @@ interface MainView : CommonView {
     fun setNavigation(itemId: Int)
     fun showLoginOption(isVisible: Boolean)
     fun showProfileOption(isVisible: Boolean)
-    fun setSortOptionChecked(sorting: BookSorting)
+    fun setOptionChecked(item: OptionItem)
     fun setThemeOptionChecked(theme: Theme)
     fun setCrashReportOptionChecked(isChecked: Boolean)
 
@@ -46,6 +49,7 @@ interface MainView : CommonView {
         fun onProfileOptionClicked()
         fun onAboutOptionClicked()
         fun onSortOptionClicked(sorting: BookSorting)
+        fun onUserSortOptionClicked(sorting: UserSorting)
         fun onThemeOptionClicked(theme: Theme)
         fun onCrashReportOptionClicked(isChecked: Boolean)
     }
@@ -63,9 +67,10 @@ class MainViewImpl(
     init {
         toolbar.inflateMenu(R.menu.options)
         toolbar.menu.findItem(R.id.option_sort_books).addAll(BookSorting.values())
+        toolbar.menu.findItem(R.id.option_sort_users).addAll(UserSorting.values())
         val themeOptions = Theme.values().map(Theme::id)
         toolbar.setOnMenuItemClickListener { item ->
-            when (item.itemId) {
+            when (val itemId = item.itemId) {
                 R.id.option_login -> {
                     callbacks.onLoginOptionClicked()
                     true
@@ -80,12 +85,17 @@ class MainViewImpl(
                 }
                 in optionIds<BookSorting>() -> {
                     item.isChecked = true
-                    callbacks.onSortOptionClicked(BookSorting.getById(item.itemId))
+                    callbacks.onSortOptionClicked(getOption(itemId))
+                    true
+                }
+                in optionIds<UserSorting>() -> {
+                    item.isChecked = true
+                    callbacks.onUserSortOptionClicked(getOption(itemId))
                     true
                 }
                 in themeOptions -> {
                     item.isChecked = true
-                    callbacks.onThemeOptionClicked(Theme.getById(item.itemId))
+                    callbacks.onThemeOptionClicked(Theme.getById(itemId))
                     true
                 }
                 R.id.option_crash_report -> {
@@ -132,6 +142,7 @@ class MainViewImpl(
         usersPage.show(tab == USERS_TAB)
         notesPage.show(tab == NOTES_TAB)
         toolbar.menu.findItem(R.id.option_sort_books).isVisible = tab == BOOKS_TAB
+        toolbar.menu.findItem(R.id.option_sort_users).isVisible = tab == USERS_TAB
     }
 
     override fun showNavigation(isVisible: Boolean) {
@@ -159,8 +170,8 @@ class MainViewImpl(
         profileOption.isVisible = isVisible
     }
 
-    override fun setSortOptionChecked(sorting: BookSorting) {
-        toolbar.menu.findItem(sorting.id).isChecked = true
+    override fun setOptionChecked(item: OptionItem) {
+        toolbar.menu.findItem(item.id).isChecked = true
     }
 
     override fun setThemeOptionChecked(theme: Theme) {

+ 2 - 0
app/src/main/java/com/sirekanyan/knigopis/repository/Configuration.kt

@@ -10,6 +10,7 @@ private const val PREFS_NAME = "config"
 interface Configuration {
     var theme: Theme
     var bookSorting: BookSorting
+    var userSorting: UserSorting
     var crashReportEnabled: Boolean
 }
 
@@ -17,5 +18,6 @@ class ConfigurationImpl(context: Application) : Configuration {
     internal val prefs = context.getSharedPreferences(PREFS_NAME, MODE_PRIVATE)
     override var theme by enumPreference(Theme.DEFAULT)
     override var bookSorting by enumPreference(BookSorting.DEFAULT)
+    override var userSorting by enumPreference(UserSorting.DEFAULT)
     override var crashReportEnabled by booleanPreference()
 }

+ 32 - 0
app/src/main/java/com/sirekanyan/knigopis/repository/UserOrganizer.kt

@@ -0,0 +1,32 @@
+package com.sirekanyan.knigopis.repository
+
+import com.sirekanyan.knigopis.model.UserModel
+import com.sirekanyan.knigopis.model.dto.Subscription
+import com.sirekanyan.knigopis.model.toUserModel
+import com.sirekanyan.knigopis.repository.UserSorting.*
+
+class UserOrganizer(private val config: Configuration) {
+
+    fun organize(subscriptions: List<Subscription>): List<UserModel> =
+        sort(subscriptions.map(Subscription::toUserModel))
+
+
+    private fun sort(users: List<UserModel>): List<UserModel> =
+        when (config.userSorting) {
+            DEFAULT -> users
+            BY_NAME -> users.sortedBy(UserModel::name)
+            BY_COUNT -> {
+                users.sortedWith(
+                    compareByDescending(UserModel::booksCount)
+                        .thenByDescending(UserModel::newBooksCount)
+                )
+            }
+            BY_NEW_COUNT -> {
+                users.sortedWith(
+                    compareByDescending(UserModel::newBooksCount)
+                        .thenByDescending(UserModel::booksCount)
+                )
+            }
+        }
+
+}

+ 2 - 3
app/src/main/java/com/sirekanyan/knigopis/repository/UserRepository.kt

@@ -2,8 +2,6 @@ package com.sirekanyan.knigopis.repository
 
 import com.sirekanyan.knigopis.common.android.NetworkChecker
 import com.sirekanyan.knigopis.model.UserModel
-import com.sirekanyan.knigopis.model.dto.Subscription
-import com.sirekanyan.knigopis.model.toUserModel
 import com.sirekanyan.knigopis.repository.cache.CacheKey
 import com.sirekanyan.knigopis.repository.cache.CommonCache
 import com.sirekanyan.knigopis.repository.cache.genericType
@@ -21,6 +19,7 @@ interface UserRepository {
 class UserRepositoryImpl(
     private val api: Endpoint,
     private val cache: CommonCache,
+    private val organizer: UserOrganizer,
     networkChecker: NetworkChecker
 ) : CommonRepository<List<UserModel>>(networkChecker),
     UserRepository {
@@ -28,7 +27,7 @@ class UserRepositoryImpl(
     override fun observeUsers() = observe()
 
     override fun loadFromNetwork(): Single<List<UserModel>> =
-        api.getSubscriptions().map { it.map(Subscription::toUserModel) }
+        api.getSubscriptions().map(organizer::organize)
 
     override fun findCached(): Maybe<List<UserModel>> =
         cache.find(CacheKey.USERS, genericType<List<UserModel>>())

+ 18 - 0
app/src/main/java/com/sirekanyan/knigopis/repository/UserSorting.kt

@@ -0,0 +1,18 @@
+package com.sirekanyan.knigopis.repository
+
+import androidx.annotation.IdRes
+import androidx.annotation.StringRes
+import com.sirekanyan.knigopis.R
+import com.sirekanyan.knigopis.common.android.menu.OptionItem
+
+enum class UserSorting(
+    @IdRes override val id: Int,
+    @StringRes override val title: Int
+) : OptionItem {
+
+    DEFAULT(R.id.option_sort_users_by_time, R.string.main_option_sort_users_by_time),
+    BY_NAME(R.id.option_sort_users_by_name, R.string.main_option_sort_users_by_name),
+    BY_COUNT(R.id.option_sort_users_by_count, R.string.main_option_sort_users_by_count),
+    BY_NEW_COUNT(R.id.option_sort_users_by_new_count, R.string.main_option_sort_users_by_new_count);
+
+}

+ 15 - 1
app/src/main/res/menu/options.xml

@@ -18,7 +18,21 @@
 
     <item
         android:id="@+id/option_sort_books"
-        android:title="@string/main_option_sort">
+        android:title="@string/main_option_sort"
+        android:visible="false"
+        tools:title="Sort (books)"
+        tools:visible="true">
+        <menu>
+            <!-- dynamic content -->
+        </menu>
+    </item>
+
+    <item
+        android:id="@+id/option_sort_users"
+        android:title="@string/main_option_sort"
+        android:visible="false"
+        tools:title="Sort (users)"
+        tools:visible="true">
         <menu>
             <!-- dynamic content -->
         </menu>

+ 4 - 0
app/src/main/res/values-ru/strings.xml

@@ -27,6 +27,10 @@
     <string name="main_option_sort_by_time">По свежести</string>
     <string name="main_option_sort_by_title">По названию</string>
     <string name="main_option_sort_by_author">По автору</string>
+    <string name="main_option_sort_users_by_time">По активности</string>
+    <string name="main_option_sort_users_by_name">По имени</string>
+    <string name="main_option_sort_users_by_count">По числу книг</string>
+    <string name="main_option_sort_users_by_new_count">По числу новых книг</string>
     <string name="main_option_theme">Тема приложения</string>
     <string name="main_option_theme_light">Светлая</string>
     <string name="main_option_theme_dark">Тёмная</string>

+ 7 - 0
app/src/main/res/values/ids.xml

@@ -1,7 +1,14 @@
 <?xml version="1.0" encoding="utf-8"?>
 <resources>
+
     <item name="option_sort_by_time" type="id" />
     <item name="option_sort_by_progress" type="id" />
     <item name="option_sort_by_title" type="id" />
     <item name="option_sort_by_author" type="id" />
+
+    <item name="option_sort_users_by_time" type="id" />
+    <item name="option_sort_users_by_name" type="id" />
+    <item name="option_sort_users_by_count" type="id" />
+    <item name="option_sort_users_by_new_count" type="id" />
+
 </resources>

+ 4 - 0
app/src/main/res/values/strings.xml

@@ -26,6 +26,10 @@
     <string name="main_option_sort_by_time">By update time</string>
     <string name="main_option_sort_by_title">By title</string>
     <string name="main_option_sort_by_author">By author</string>
+    <string name="main_option_sort_users_by_time">By update time</string>
+    <string name="main_option_sort_users_by_name">By nickname</string>
+    <string name="main_option_sort_users_by_count">By books count</string>
+    <string name="main_option_sort_users_by_new_count">By new books count</string>
     <string name="main_option_theme">Theme</string>
     <string name="main_option_theme_light">Light</string>
     <string name="main_option_theme_dark">Dark</string>