From e5ce678960eb8649e5241ce0c118b3f9222f390f Mon Sep 17 00:00:00 2001 From: Seth Chhim Date: Mon, 27 Aug 2018 17:34:17 -0400 Subject: [PATCH] add browser option to show media as a list --- .../com/sethchhim/kuboo_client/Constants.kt | 1 + .../com/sethchhim/kuboo_client/Extensions.kt | 5 +- .../com/sethchhim/kuboo_client/Settings.kt | 1 + .../kuboo_client/data/model/Browser.kt | 1 + .../data/repository/BrowserRepository.kt | 6 +- .../kuboo_client/ui/main/MainActivity.kt | 2 + .../ui/main/MainActivityImpl0_View.kt | 43 ++++ .../ui/main/MainActivityImpl2_Selection.kt | 4 + .../ui/main/browser/BrowserBaseFragment.kt | 5 + .../BrowserBaseFragmentImpl1_Content.kt | 21 +- .../ui/main/browser/BrowserLatestFragment.kt | 13 +- .../ui/main/browser/BrowserRecentFragment.kt | 13 +- .../ui/main/browser/BrowserRemoteFragment.kt | 4 +- .../ui/main/browser/BrowserSearchFragment.kt | 12 +- .../ui/main/browser/BrowserSeriesFragment.kt | 11 +- .../browser/adapter/BrowserContentAdapter.kt | 185 ++++++++++++++---- .../custom/BrowserContentRecyclerView.kt | 15 +- .../main/browser/custom/BrowserContentType.kt | 2 +- .../kuboo_client/util/SharedPrefsHelper.kt | 8 + .../res/drawable/ic_view_list_white_24dp.xml | 5 + .../drawable/ic_view_module_white_24dp.xml | 5 + .../browser_item_content_media_force_list.xml | 80 ++++++++ app/src/main/res/menu/menu_main.xml | 5 + app/src/main/res/values/strings.xml | 4 +- 24 files changed, 383 insertions(+), 68 deletions(-) create mode 100644 app/src/main/res/drawable/ic_view_list_white_24dp.xml create mode 100644 app/src/main/res/drawable/ic_view_module_white_24dp.xml create mode 100644 app/src/main/res/layout/browser_item_content_media_force_list.xml diff --git a/app/src/main/java/com/sethchhim/kuboo_client/Constants.kt b/app/src/main/java/com/sethchhim/kuboo_client/Constants.kt index e6be064b..5ae408ab 100644 --- a/app/src/main/java/com/sethchhim/kuboo_client/Constants.kt +++ b/app/src/main/java/com/sethchhim/kuboo_client/Constants.kt @@ -24,6 +24,7 @@ object Constants { internal const val ARG_TRANSITION_URL = "ARG_TRANSITION_URL" internal const val KEY_APP_THEME = "KEY_APP_THEME" + internal const val KEY_BROWSER_MEDIA_FORCE_LIST = "KEY_BROWSER_MEDIA_FORCE_LIST" internal const val KEY_BROWSER_IMMERSIVE = "KEY_BROWSER_IMMERSIVE" internal const val KEY_DOWNLOAD_SAVE_PATH = "KEY_DOWNLOAD_SAVE_PATH" internal const val KEY_DOWNLOAD_TRACKING_INTERVAL = "KEY_DOWNLOAD_TRACKING_INTERVAL" diff --git a/app/src/main/java/com/sethchhim/kuboo_client/Extensions.kt b/app/src/main/java/com/sethchhim/kuboo_client/Extensions.kt index 39019b2f..e77de8d1 100644 --- a/app/src/main/java/com/sethchhim/kuboo_client/Extensions.kt +++ b/app/src/main/java/com/sethchhim/kuboo_client/Extensions.kt @@ -407,7 +407,10 @@ object Extensions { internal fun Book.getBrowserContentType() = when (isBrowserMediaType()) { - true -> BrowserContentType.MEDIA + true -> when (Settings.BROWSER_MEDIA_FORCE_LIST) { + true -> BrowserContentType.MEDIA_FORCE_LIST + false -> BrowserContentType.MEDIA + } false -> BrowserContentType.FOLDER } diff --git a/app/src/main/java/com/sethchhim/kuboo_client/Settings.kt b/app/src/main/java/com/sethchhim/kuboo_client/Settings.kt index e87c1204..48e06856 100644 --- a/app/src/main/java/com/sethchhim/kuboo_client/Settings.kt +++ b/app/src/main/java/com/sethchhim/kuboo_client/Settings.kt @@ -42,6 +42,7 @@ object Settings { var MARK_FINISHED = false var PREVIEW = true var REVERSE_LAYOUT = false + var BROWSER_MEDIA_FORCE_LIST = true const val SHARED_ELEMENT_TRANSITION_DURATION = 350L //Screen rotation delay before animation. const val RECYCLER_VIEW_DELAY = 600L diff --git a/app/src/main/java/com/sethchhim/kuboo_client/data/model/Browser.kt b/app/src/main/java/com/sethchhim/kuboo_client/data/model/Browser.kt index 4a41ea50..58eb841e 100644 --- a/app/src/main/java/com/sethchhim/kuboo_client/data/model/Browser.kt +++ b/app/src/main/java/com/sethchhim/kuboo_client/data/model/Browser.kt @@ -10,6 +10,7 @@ class Browser(var type: Int, var book: Book) : MultiItemEntity { companion object { const val FOLDER = 1 const val MEDIA = 2 + const val MEDIA_FORCE_LIST = 3 } override fun getItemType(): Int { diff --git a/app/src/main/java/com/sethchhim/kuboo_client/data/repository/BrowserRepository.kt b/app/src/main/java/com/sethchhim/kuboo_client/data/repository/BrowserRepository.kt index 5b5146a2..b13f2458 100644 --- a/app/src/main/java/com/sethchhim/kuboo_client/data/repository/BrowserRepository.kt +++ b/app/src/main/java/com/sethchhim/kuboo_client/data/repository/BrowserRepository.kt @@ -2,6 +2,7 @@ package com.sethchhim.kuboo_client.data.repository import android.os.Parcelable import com.sethchhim.kuboo_client.Extensions.isFileType +import com.sethchhim.kuboo_client.Settings import com.sethchhim.kuboo_client.data.model.Browser import com.sethchhim.kuboo_remote.model.Book import timber.log.Timber @@ -15,7 +16,10 @@ class BrowserRepository { contentList.clear() list.forEach { when (it.isFileType()) { - true -> contentList.add(Browser(Browser.MEDIA, it)) + true -> when (Settings.BROWSER_MEDIA_FORCE_LIST) { + true -> contentList.add(Browser(Browser.MEDIA_FORCE_LIST, it)) + false -> contentList.add(Browser(Browser.MEDIA, it)) + } false -> contentList.add(Browser(Browser.FOLDER, it)) } } diff --git a/app/src/main/java/com/sethchhim/kuboo_client/ui/main/MainActivity.kt b/app/src/main/java/com/sethchhim/kuboo_client/ui/main/MainActivity.kt index 7b9d052e..ce18b353 100644 --- a/app/src/main/java/com/sethchhim/kuboo_client/ui/main/MainActivity.kt +++ b/app/src/main/java/com/sethchhim/kuboo_client/ui/main/MainActivity.kt @@ -84,6 +84,7 @@ open class MainActivity : MainActivityImpl3_Service(), BottomNavigationView.OnNa override fun onCreateOptionsMenu(menu: Menu): Boolean { menuInflater.inflate(R.menu.menu_main, menu) + browserLayoutMenuItem = menu.findItem(R.id.main_action_browser_layout) downloadMenuItem = menu.findItem(R.id.main_action_download) httpsMenuItem = menu.findItem(R.id.main_action_https) markFinishedAddMenuItem = menu.findItem(R.id.main_action_mark_finished_add) @@ -189,6 +190,7 @@ open class MainActivity : MainActivityImpl3_Service(), BottomNavigationView.OnNa when (item.itemId) { R.id.main_overflow_about -> showActivityAbout() R.id.main_overflow_log -> showActivityLog() + R.id.main_action_browser_layout -> toggleBrowserLayout() R.id.main_action_https -> showDialogHttps() R.id.main_action_download -> startSelectionDownload() R.id.main_action_mark_finished_add -> startSelectionAddFinished() diff --git a/app/src/main/java/com/sethchhim/kuboo_client/ui/main/MainActivityImpl0_View.kt b/app/src/main/java/com/sethchhim/kuboo_client/ui/main/MainActivityImpl0_View.kt index f59ca0ff..9bbc4e59 100644 --- a/app/src/main/java/com/sethchhim/kuboo_client/ui/main/MainActivityImpl0_View.kt +++ b/app/src/main/java/com/sethchhim/kuboo_client/ui/main/MainActivityImpl0_View.kt @@ -4,6 +4,7 @@ import android.annotation.SuppressLint import android.content.Intent import android.support.design.widget.BottomNavigationView import android.support.v4.app.Fragment +import android.support.v4.content.ContextCompat import android.support.v7.widget.SearchView import android.support.v7.widget.Toolbar import android.view.MenuItem @@ -12,10 +13,12 @@ import android.widget.TextView import butterknife.BindView import com.sethchhim.kuboo_client.Extensions.show import com.sethchhim.kuboo_client.R +import com.sethchhim.kuboo_client.Settings import com.sethchhim.kuboo_client.ui.about.AboutActivity import com.sethchhim.kuboo_client.ui.base.BaseActivity import com.sethchhim.kuboo_client.ui.log.LogActivity import com.sethchhim.kuboo_client.ui.main.browser.* +import com.sethchhim.kuboo_client.ui.main.browser.custom.BrowserContentType import com.sethchhim.kuboo_client.ui.main.downloads.DownloadsFragment import com.sethchhim.kuboo_client.ui.main.home.HomeFragment import com.sethchhim.kuboo_client.ui.main.home.HomeFragmentImpl1_Content @@ -50,6 +53,7 @@ open class MainActivityImpl0_View : BaseActivity() { @BindView(R.id.main_layout_base_toolBar) lateinit var toolbar: Toolbar @BindView(R.id.main_layout_base_frameLayout) lateinit var frameLayout: FrameLayout + internal lateinit var browserLayoutMenuItem: MenuItem internal lateinit var downloadMenuItem: MenuItem internal lateinit var httpsMenuItem: MenuItem internal lateinit var markFinishedAddMenuItem: MenuItem @@ -76,12 +80,14 @@ open class MainActivityImpl0_View : BaseActivity() { } internal fun setStateDisconnected(response: Response?) { + hideMenuItemBrowserLayout() hideMenuItemSearch() hideMenuItemHttps() showFragmentFail(response) } internal fun setStateLoading() { + hideMenuItemBrowserLayout() hideMenuItemSearch() hideMenuItemHttps() showFragmentLoading() @@ -182,6 +188,10 @@ open class MainActivityImpl0_View : BaseActivity() { protected fun getSelectedBrowserTitle() = "${getString(R.string.main_selected)} (${viewModel.getSelectedListSize()})" + internal fun hideMenuItemBrowserLayout() { + if (::browserLayoutMenuItem.isInitialized && browserLayoutMenuItem.isVisible) browserLayoutMenuItem.isVisible = false + } + protected fun hideMenuItemHttps() { if (::httpsMenuItem.isInitialized && httpsMenuItem.isVisible) httpsMenuItem.isVisible = false } @@ -192,6 +202,10 @@ open class MainActivityImpl0_View : BaseActivity() { private fun showFragmentFail(response: Response?) = supportFragmentManager.show(FailFragment.newInstance(response), R.id.main_layout_base_frameLayout) + private fun showMenuItemBrowserLayout() { + if (::browserLayoutMenuItem.isInitialized && !browserLayoutMenuItem.isVisible) browserLayoutMenuItem.isVisible = true + } + private fun showMenuItemHttps() { if (::httpsMenuItem.isInitialized && !httpsMenuItem.isVisible) httpsMenuItem.isVisible = true } @@ -200,9 +214,38 @@ open class MainActivityImpl0_View : BaseActivity() { if (::searchMenuItem.isInitialized && !searchMenuItem.isVisible) searchMenuItem.isVisible = true } + internal fun toggleMenuItemBrowserLayout(browserContentType: BrowserContentType) { + if (::browserLayoutMenuItem.isInitialized) { + when (browserContentType) { + BrowserContentType.MEDIA -> { + browserLayoutMenuItem.icon = ContextCompat.getDrawable(this, R.drawable.ic_view_list_white_24dp) + showMenuItemBrowserLayout() + } + BrowserContentType.MEDIA_FORCE_LIST -> { + browserLayoutMenuItem.icon = ContextCompat.getDrawable(this, R.drawable.ic_view_module_white_24dp) + showMenuItemBrowserLayout() + } + else -> hideMenuItemBrowserLayout() + } + } + } + protected fun toggleMenuItemHttps() = when (viewModel.isConnectedEncrypted()) { true -> showMenuItemHttps() false -> hideMenuItemHttps() } + protected fun toggleBrowserLayout() { + Settings.BROWSER_MEDIA_FORCE_LIST = !Settings.BROWSER_MEDIA_FORCE_LIST + sharedPrefsHelper.saveBrowserMediaForceList() + (getCurrentFragment() as? BrowserBaseFragment)?.let { + it.contentRecyclerView.contentType = when (Settings.BROWSER_MEDIA_FORCE_LIST) { + true -> BrowserContentType.MEDIA_FORCE_LIST + false -> BrowserContentType.MEDIA + } + toggleMenuItemBrowserLayout(it.contentRecyclerView.contentType) + it.onSwipeRefresh() + } + } + } \ No newline at end of file diff --git a/app/src/main/java/com/sethchhim/kuboo_client/ui/main/MainActivityImpl2_Selection.kt b/app/src/main/java/com/sethchhim/kuboo_client/ui/main/MainActivityImpl2_Selection.kt index f87686ed..cc15f3c5 100644 --- a/app/src/main/java/com/sethchhim/kuboo_client/ui/main/MainActivityImpl2_Selection.kt +++ b/app/src/main/java/com/sethchhim/kuboo_client/ui/main/MainActivityImpl2_Selection.kt @@ -89,6 +89,8 @@ open class MainActivityImpl2_Selection : MainActivityImpl1_Content() { private fun resetAllColorState() = (getCurrentFragment() as? BrowserBaseFragment)?.contentAdapter?.resetAllColorState() + private fun getBrowserContentType() = (getCurrentFragment() as? BrowserBaseFragment)?.contentRecyclerView?.contentType + private fun setSelectionMenuStateSelected() { title = getSelectedBrowserTitle() downloadMenuItem.visible() @@ -96,6 +98,7 @@ open class MainActivityImpl2_Selection : MainActivityImpl1_Content() { markFinishedDeleteMenuItem.visible() markFinishedAddMenuItem.visible() + hideMenuItemBrowserLayout() hideMenuItemHttps() } @@ -106,6 +109,7 @@ open class MainActivityImpl2_Selection : MainActivityImpl1_Content() { markFinishedDeleteMenuItem.gone() markFinishedAddMenuItem.gone() + getBrowserContentType()?.let { toggleMenuItemBrowserLayout(it) } toggleMenuItemHttps() } diff --git a/app/src/main/java/com/sethchhim/kuboo_client/ui/main/browser/BrowserBaseFragment.kt b/app/src/main/java/com/sethchhim/kuboo_client/ui/main/browser/BrowserBaseFragment.kt index ed9f993a..62de8669 100644 --- a/app/src/main/java/com/sethchhim/kuboo_client/ui/main/browser/BrowserBaseFragment.kt +++ b/app/src/main/java/com/sethchhim/kuboo_client/ui/main/browser/BrowserBaseFragment.kt @@ -42,6 +42,11 @@ open class BrowserBaseFragment : BrowserBaseFragmentImpl1_Content() { isFirstInstance = false } + override fun onDestroy() { + super.onDestroy() + mainActivity.hideMenuItemBrowserLayout() + } + override fun onConfigurationChanged(newConfig: Configuration) { super.onConfigurationChanged(newConfig) setContentSpanCount(newConfig.orientation, contentRecyclerView.contentType) diff --git a/app/src/main/java/com/sethchhim/kuboo_client/ui/main/browser/BrowserBaseFragmentImpl1_Content.kt b/app/src/main/java/com/sethchhim/kuboo_client/ui/main/browser/BrowserBaseFragmentImpl1_Content.kt index 889f085d..c75b635b 100644 --- a/app/src/main/java/com/sethchhim/kuboo_client/ui/main/browser/BrowserBaseFragmentImpl1_Content.kt +++ b/app/src/main/java/com/sethchhim/kuboo_client/ui/main/browser/BrowserBaseFragmentImpl1_Content.kt @@ -10,6 +10,7 @@ import com.sethchhim.kuboo_client.Settings import com.sethchhim.kuboo_client.ui.main.browser.adapter.BrowserContentAdapter import com.sethchhim.kuboo_client.ui.main.browser.adapter.BrowserPathAdapter import com.sethchhim.kuboo_client.ui.main.browser.custom.BrowserContentType.MEDIA +import com.sethchhim.kuboo_client.ui.main.browser.custom.BrowserContentType.MEDIA_FORCE_LIST import com.sethchhim.kuboo_client.ui.main.browser.handler.PaginationHandler import com.sethchhim.kuboo_remote.model.Book import com.sethchhim.kuboo_remote.model.Pagination @@ -70,7 +71,10 @@ open class BrowserBaseFragmentImpl1_Content : BrowserBaseFragmentImpl0_View() { } setStateConnected() - setContentSpanCount(resources.configuration.orientation, book.getBrowserContentType()) + + val browserContentType = book.getBrowserContentType() + setContentSpanCount(resources.configuration.orientation, browserContentType) + mainActivity.toggleMenuItemBrowserLayout(browserContentType) populatePaginationLinks(book, newResult) contentAdapter.update(newResult) if (loadState) loadRecyclerViewState(book) @@ -106,8 +110,15 @@ open class BrowserBaseFragmentImpl1_Content : BrowserBaseFragmentImpl0_View() { private fun onPopulateMediaSuccess(book: Book?, result: List) { Timber.i("onPopulateMediaSuccess result: ${result.size}") setStateConnected() - setContentSpanCount(resources.configuration.orientation, MEDIA) - book?.let { populatePaginationLinks(it, result) } + setContentSpanCount(resources.configuration.orientation, when (Settings.BROWSER_MEDIA_FORCE_LIST) { + true -> MEDIA_FORCE_LIST + false -> MEDIA + }) + + book?.let { + populatePaginationLinks(it, result) + mainActivity.toggleMenuItemBrowserLayout(book.getBrowserContentType()) + } contentAdapter.update(result) } @@ -133,4 +144,8 @@ open class BrowserBaseFragmentImpl1_Content : BrowserBaseFragmentImpl0_View() { } } + open fun onSwipeRefresh() { + //override in children + } + } \ No newline at end of file diff --git a/app/src/main/java/com/sethchhim/kuboo_client/ui/main/browser/BrowserLatestFragment.kt b/app/src/main/java/com/sethchhim/kuboo_client/ui/main/browser/BrowserLatestFragment.kt index a4f28e0e..6860abc7 100644 --- a/app/src/main/java/com/sethchhim/kuboo_client/ui/main/browser/BrowserLatestFragment.kt +++ b/app/src/main/java/com/sethchhim/kuboo_client/ui/main/browser/BrowserLatestFragment.kt @@ -3,7 +3,9 @@ package com.sethchhim.kuboo_client.ui.main.browser import android.arch.lifecycle.Observer import android.os.Bundle import android.view.View +import com.sethchhim.kuboo_client.Constants.URL_PATH_LATEST import com.sethchhim.kuboo_client.Extensions.gone +import com.sethchhim.kuboo_remote.model.Book class BrowserLatestFragment : BrowserBaseFragment() { @@ -22,9 +24,14 @@ class BrowserLatestFragment : BrowserBaseFragment() { setStateLoading() resetRecyclerView() paginationHandler.reset() - viewModel.getLatestListFromServer().observe(this, Observer { handleMediaResult(null, it) }) + viewModel.getLatestListFromServer().observe(this, Observer { + val book = Book().apply { linkSubsection = URL_PATH_LATEST } + handleMediaResult(book, it) + }) } - private fun onSwipeRefresh() = populateLatest() - + override fun onSwipeRefresh() { + super.onSwipeRefresh() + populateLatest() + } } \ No newline at end of file diff --git a/app/src/main/java/com/sethchhim/kuboo_client/ui/main/browser/BrowserRecentFragment.kt b/app/src/main/java/com/sethchhim/kuboo_client/ui/main/browser/BrowserRecentFragment.kt index c32921b0..13d04d01 100644 --- a/app/src/main/java/com/sethchhim/kuboo_client/ui/main/browser/BrowserRecentFragment.kt +++ b/app/src/main/java/com/sethchhim/kuboo_client/ui/main/browser/BrowserRecentFragment.kt @@ -3,7 +3,9 @@ package com.sethchhim.kuboo_client.ui.main.browser import android.arch.lifecycle.Observer import android.os.Bundle import android.view.View +import com.sethchhim.kuboo_client.Constants import com.sethchhim.kuboo_client.Extensions.gone +import com.sethchhim.kuboo_remote.model.Book class BrowserRecentFragment : BrowserBaseFragment() { @@ -22,9 +24,14 @@ class BrowserRecentFragment : BrowserBaseFragment() { setStateLoading() resetRecyclerView() paginationHandler.reset() - viewModel.getRecentListFromDao().observe(this, Observer { handleMediaResult(null, it) }) + viewModel.getRecentListFromDao().observe(this, Observer { + val book = Book().apply { linkSubsection = Constants.URL_PATH_GRID_DIRECTORY } + handleMediaResult(book, it) + }) } - private fun onSwipeRefresh() = populateRecent() - + override fun onSwipeRefresh() { + super.onSwipeRefresh() + populateRecent() + } } \ No newline at end of file diff --git a/app/src/main/java/com/sethchhim/kuboo_client/ui/main/browser/BrowserRemoteFragment.kt b/app/src/main/java/com/sethchhim/kuboo_client/ui/main/browser/BrowserRemoteFragment.kt index 30c8fb48..f6cb3eed 100644 --- a/app/src/main/java/com/sethchhim/kuboo_client/ui/main/browser/BrowserRemoteFragment.kt +++ b/app/src/main/java/com/sethchhim/kuboo_client/ui/main/browser/BrowserRemoteFragment.kt @@ -52,7 +52,8 @@ class BrowserRemoteFragment : BrowserBaseFragment() { } } - private fun onSwipeRefresh() { + override fun onSwipeRefresh() { + super.onSwipeRefresh() val book = viewModel.getCurrentBook() when (book != null) { true -> { @@ -62,5 +63,4 @@ class BrowserRemoteFragment : BrowserBaseFragment() { false -> Timber.e("No licenseList available to populate swipe refresh!") } } - } \ No newline at end of file diff --git a/app/src/main/java/com/sethchhim/kuboo_client/ui/main/browser/BrowserSearchFragment.kt b/app/src/main/java/com/sethchhim/kuboo_client/ui/main/browser/BrowserSearchFragment.kt index d1a6226e..53d1386e 100644 --- a/app/src/main/java/com/sethchhim/kuboo_client/ui/main/browser/BrowserSearchFragment.kt +++ b/app/src/main/java/com/sethchhim/kuboo_client/ui/main/browser/BrowserSearchFragment.kt @@ -3,8 +3,10 @@ package com.sethchhim.kuboo_client.ui.main.browser import android.arch.lifecycle.Observer import android.os.Bundle import android.view.View +import com.sethchhim.kuboo_client.Constants import com.sethchhim.kuboo_client.Constants.ARG_SEARCH import com.sethchhim.kuboo_client.Extensions.gone +import com.sethchhim.kuboo_remote.model.Book class BrowserSearchFragment : BrowserBaseFragment() { @@ -24,13 +26,19 @@ class BrowserSearchFragment : BrowserBaseFragment() { populateSearch() } - private fun onSwipeRefresh() = populateSearch() + override fun onSwipeRefresh() { + super.onSwipeRefresh() + populateSearch() + } private fun populateSearch() { setStateLoading() resetRecyclerView() paginationHandler.reset() - viewModel.getListByQuery(stringQuery).observe(this, Observer { result -> handleMediaResult(null, result) }) + viewModel.getListByQuery(stringQuery).observe(this, Observer { result -> + val book = Book().apply { linkSubsection = "${Constants.URL_PATH_SEARCH}$stringQuery" } + handleMediaResult(book, result) + }) } companion object { diff --git a/app/src/main/java/com/sethchhim/kuboo_client/ui/main/browser/BrowserSeriesFragment.kt b/app/src/main/java/com/sethchhim/kuboo_client/ui/main/browser/BrowserSeriesFragment.kt index 33a2f3cd..3fb3bbef 100644 --- a/app/src/main/java/com/sethchhim/kuboo_client/ui/main/browser/BrowserSeriesFragment.kt +++ b/app/src/main/java/com/sethchhim/kuboo_client/ui/main/browser/BrowserSeriesFragment.kt @@ -23,15 +23,20 @@ class BrowserSeriesFragment : BrowserBaseFragment() { populateSeries() } - private fun onSwipeRefresh() = populateSeries() + override fun onSwipeRefresh() { + super.onSwipeRefresh() + populateSeries() + } private fun populateSeries() { setStateLoading() resetRecyclerView() paginationHandler.reset() val stringUrl = viewModel.getActiveServer() + seriesBook.linkXmlPath - val book = Book().apply { linkSubsection = seriesBook.linkXmlPath } - viewModel.getListByUrl(stringUrl).observe(this, Observer { result -> handleMediaResult(book, result) }) + viewModel.getListByUrl(stringUrl).observe(this, Observer { result -> + val book = Book().apply { linkSubsection = seriesBook.linkXmlPath } + handleMediaResult(book, result) + }) } companion object { diff --git a/app/src/main/java/com/sethchhim/kuboo_client/ui/main/browser/adapter/BrowserContentAdapter.kt b/app/src/main/java/com/sethchhim/kuboo_client/ui/main/browser/adapter/BrowserContentAdapter.kt index 0a178b7a..e9901807 100644 --- a/app/src/main/java/com/sethchhim/kuboo_client/ui/main/browser/adapter/BrowserContentAdapter.kt +++ b/app/src/main/java/com/sethchhim/kuboo_client/ui/main/browser/adapter/BrowserContentAdapter.kt @@ -2,6 +2,7 @@ package com.sethchhim.kuboo_client.ui.main.browser.adapter import android.arch.lifecycle.Observer import android.content.Context +import android.graphics.Color import android.graphics.drawable.Drawable import android.support.v7.widget.RecyclerView import android.view.View @@ -37,6 +38,9 @@ import com.sethchhim.kuboo_client.Settings import com.sethchhim.kuboo_client.data.ViewModel import com.sethchhim.kuboo_client.data.enum.Source import com.sethchhim.kuboo_client.data.model.Browser +import com.sethchhim.kuboo_client.data.model.Browser.Companion.FOLDER +import com.sethchhim.kuboo_client.data.model.Browser.Companion.MEDIA +import com.sethchhim.kuboo_client.data.model.Browser.Companion.MEDIA_FORCE_LIST import com.sethchhim.kuboo_client.data.model.ReadData import com.sethchhim.kuboo_client.ui.main.browser.BrowserBaseFragmentImpl1_Content import com.sethchhim.kuboo_client.ui.main.browser.custom.BrowserContentGridLayoutManager @@ -46,9 +50,12 @@ import com.sethchhim.kuboo_client.util.SystemUtil import com.sethchhim.kuboo_remote.model.Book import kotlinx.android.synthetic.main.browser_item_content_folder.view.* import kotlinx.android.synthetic.main.browser_item_content_media.view.* +import kotlinx.android.synthetic.main.browser_item_content_media_force_list.view.* import kotlinx.coroutines.experimental.android.UI import kotlinx.coroutines.experimental.delay import kotlinx.coroutines.experimental.launch +import org.jetbrains.anko.backgroundColor +import org.jetbrains.anko.backgroundResource import org.jetbrains.anko.collections.forEachWithIndex import org.jetbrains.anko.sdk25.coroutines.onClick import timber.log.Timber @@ -63,6 +70,7 @@ class BrowserContentAdapter(val browserFragment: BrowserBaseFragmentImpl1_Conten addItemType(Browser.FOLDER, R.layout.browser_item_content_folder) addItemType(Browser.MEDIA, R.layout.browser_item_content_media) + addItemType(Browser.MEDIA_FORCE_LIST, R.layout.browser_item_content_media_force_list) } @Inject lateinit var context: Context @@ -85,6 +93,7 @@ class BrowserContentAdapter(val browserFragment: BrowserBaseFragmentImpl1_Conten when (holder.itemViewType) { Browser.FOLDER -> FolderHandler().process(holder, item) Browser.MEDIA -> MediaHandler().process(holder, item) + Browser.MEDIA_FORCE_LIST -> MediaForceListHandler().process(holder, item) } } @@ -102,6 +111,12 @@ class BrowserContentAdapter(val browserFragment: BrowserBaseFragmentImpl1_Conten if (!holder.itemView.browser_item_content_folder_likeButton.isLiked) holder.itemView.browser_item_content_folder_likeButton.isLiked = false } Browser.MEDIA -> holder.itemView.browser_item_content_media_imageView.colorFilterNull() + Browser.MEDIA_FORCE_LIST -> { + Glide.with(browserFragment).clear(holder.itemView.browser_item_content_media_force_list_imageView3) + holder.itemView.browser_item_content_media_force_list_imageView1.visible() + holder.itemView.browser_item_content_media_force_list_imageView2.visible() + holder.itemView.browser_item_content_media_force_list_imageView3.invisible() + } } } @@ -136,9 +151,12 @@ class BrowserContentAdapter(val browserFragment: BrowserBaseFragmentImpl1_Conten private fun onItemSelectedMenuStateIsUnselected() { val book = viewModel.getBrowserContentItemAt(adapterPosition)?.book - when (book?.isFileType()) { - true -> startPreview(book) - false -> populateContent(book) + book?.let { + when (itemViewType) { + FOLDER -> populateContent(it) + MEDIA -> startPreview(it, itemView.browser_item_content_media_imageView) + MEDIA_FORCE_LIST -> startPreview(it, itemView.browser_item_content_media_force_list_imageView3) + } } } @@ -153,16 +171,18 @@ class BrowserContentAdapter(val browserFragment: BrowserBaseFragmentImpl1_Conten private fun onItemLongSelectedMenuStateIsUnselected() { val book = data[adapterPosition].book - if (book.isFileType()) { - browserFragment.mainActivity.enableSelectionMode(this, book) + book.let { + when (itemViewType) { + MEDIA -> browserFragment.mainActivity.enableSelectionMode(this, it) + MEDIA_FORCE_LIST -> browserFragment.mainActivity.enableSelectionMode(this, it) + } } } private fun onItemLongSelectedMenuStateIsSelected() = browserFragment.mainActivity.disableSelectionMode() - private fun startPreview(book: Book) { + private fun startPreview(book: Book, imageView: ImageView) { val previewUrl = book.getPreviewUrl(Settings.THUMBNAIL_SIZE_RECENT) - val imageView = itemView.browser_item_content_media_imageView imageView.transitionName = previewUrl mainActivity.startPreview(ReadData(book = book, sharedElement = imageView, source = Source.BROWSER)) } @@ -332,36 +352,9 @@ class BrowserContentAdapter(val browserFragment: BrowserBaseFragmentImpl1_Conten } override fun onResourceReady(resource: Drawable?, model: Any?, target: Target?, dataSource: DataSource?, isFirstResource: Boolean): Boolean { - setMediaColorState() + setMediaColorState(holder, book) return false } - - private fun setMediaColorState() { - //set color state locally - loadColorState(holder, book) - - //set color state remotely - launch(UI) { - //add delay to prevent remote request while fast scrolling - delay(Settings.RECYCLER_VIEW_DELAY) - try { - val firstVisible = layoutManager.findFirstVisibleItemPosition() - val lastVisible = layoutManager.findLastVisibleItemPosition() - val currentPosition = holder.adapterPosition - if (currentPosition in firstVisible..lastVisible) { - viewModel.getRemoteUserApi(book).observe(browserFragment, Observer { result -> - if (result != null) { - viewModel.updateBrowserItem(result) - loadColorState(holder, result) - } - }) - } - } catch (e: Exception) { - //views could be destroyed during delay, do nothing - } - } - - } }) } } @@ -386,6 +379,90 @@ class BrowserContentAdapter(val browserFragment: BrowserBaseFragmentImpl1_Conten } } + private inner class MediaForceListHandler { + internal fun process(holder: BrowserHolder, item: Browser) { + val itemView = holder.itemView + val book = item.book + + val isStateSelected = mainActivity.isMenuStateSelected() + if (isStateSelected) mainActivity.disableSelectionMode() + + itemView.browser_item_content_media_force_list_textView1.text = book.title + itemView.browser_item_content_media_force_list_textView2.text = when (book.isComic()) { + true -> { + when (book.totalPages > 1) { + true -> "${book.totalPages} ${context.getString(R.string.browser_pages)}" + false -> "${book.totalPages} ${context.getString(R.string.browser_page)}" + } + } + false -> context.getString(R.string.browser_media) + } + + //slight delay to prevent loading while fast scrolling + launch(UI) { + delay(Settings.RECYCLER_VIEW_DELAY) + try { + if (holder.bookId == book.id) { + itemView.browser_item_content_media_force_list_imageView3.loadFolderThumbnail(holder, book) + } + } catch (e: Exception) { + //views could be destroyed during delay, do nothing + } + } + } + + internal fun ImageView.loadFolderThumbnail(holder: BrowserHolder, book: Book) { + val requestOptions = RequestOptions() + .format(DecodeFormat.PREFER_RGB_565) + .diskCacheStrategy(DiskCacheStrategy.ALL) + + Glide.with(browserFragment) + .load(book.getPreviewUrl()) + .apply(requestOptions) + .listener(object : RequestListener { + override fun onLoadFailed(e: GlideException?, model: Any?, target: Target?, isFirstResource: Boolean): Boolean { + Timber.e("Thumbnail failed to load! ${book.server}${book.linkThumbnail}") + return false + } + + override fun onResourceReady(resource: Drawable?, model: Any?, target: com.bumptech.glide.request.target.Target?, dataSource: DataSource?, isFirstResource: Boolean): Boolean { + holder.itemView.browser_item_content_media_force_list_imageView1.invisible() + holder.itemView.browser_item_content_media_force_list_imageView2.invisible() + holder.itemView.browser_item_content_media_force_list_imageView3.fadeVisible() + setMediaColorState(holder, book) + return false + } + }) + .into(this) + } + } + + private fun setMediaColorState(holder: BrowserHolder, book: Book) { + //set color state locally + loadColorState(holder, book) + + //set color state remotely + launch(UI) { + //add delay to prevent remote request while fast scrolling + delay(Settings.RECYCLER_VIEW_DELAY) + try { + val firstVisible = layoutManager.findFirstVisibleItemPosition() + val lastVisible = layoutManager.findLastVisibleItemPosition() + val currentPosition = holder.adapterPosition + if (currentPosition in firstVisible..lastVisible) { + viewModel.getRemoteUserApi(book).observe(browserFragment, Observer { result -> + if (result != null) { + viewModel.updateBrowserItem(result) + loadColorState(holder, result) + } + }) + } + } catch (e: Exception) { + //views could be destroyed during delay, do nothing + } + } + } + internal fun update(result: List) { val diffUtilHelper = DiffUtilHelper(this) diffUtilHelper.liveData.observe(browserFragment, Observer { @@ -396,17 +473,34 @@ class BrowserContentAdapter(val browserFragment: BrowserBaseFragmentImpl1_Conten private fun onDiffUtilUpdateFinished(result: List) = viewModel.setBrowserContentList(result) - internal fun loadColorState(holder: BrowserHolder, book: Book) = holder.itemView.browser_item_content_media_imageView.apply { - when (viewModel.isSelected(book)) { - true -> colorFilterRed() - false -> - when (Settings.MARK_FINISHED) { - true -> when (book.isFinished && holder.bookId == book.id) { - true -> colorFilterGrey() + internal fun loadColorState(holder: BrowserHolder, book: Book) { + holder.itemView.browser_item_content_media_imageView?.apply { + when (viewModel.isSelected(book)) { + true -> colorFilterRed() + false -> + when (Settings.MARK_FINISHED) { + true -> when (book.isFinished && holder.bookId == book.id) { + true -> colorFilterGrey() + false -> colorFilterNull() + } false -> colorFilterNull() } + } + } + holder.itemView.browser_item_content_media_force_list_imageView3?.apply { + when (Settings.MARK_FINISHED) { + true -> when (book.isFinished && holder.bookId == book.id) { + true -> colorFilterGrey() false -> colorFilterNull() } + false -> colorFilterNull() + } + } + holder.itemView.browser_item_content_media_force_list_constraintLayout?.apply { + when (viewModel.isSelected(book)) { + true -> backgroundColor = Color.RED + false -> backgroundResource = 0 + } } } @@ -421,6 +515,13 @@ class BrowserContentAdapter(val browserFragment: BrowserBaseFragmentImpl1_Conten loadColorState(viewHolder, book) } } + if (viewHolder.itemViewType == Browser.MEDIA_FORCE_LIST) { + viewHolder.itemView.browser_item_content_media_force_list_imageView3?.let { + val data = (browserContentRecyclerView.adapter as BrowserContentAdapter).data + val book = data[viewHolder.adapterPosition].book + loadColorState(viewHolder, book) + } + } } } catch (e: Exception) { Timber.e("${e.message}") diff --git a/app/src/main/java/com/sethchhim/kuboo_client/ui/main/browser/custom/BrowserContentRecyclerView.kt b/app/src/main/java/com/sethchhim/kuboo_client/ui/main/browser/custom/BrowserContentRecyclerView.kt index fdddcf6c..df7fef4c 100644 --- a/app/src/main/java/com/sethchhim/kuboo_client/ui/main/browser/custom/BrowserContentRecyclerView.kt +++ b/app/src/main/java/com/sethchhim/kuboo_client/ui/main/browser/custom/BrowserContentRecyclerView.kt @@ -5,8 +5,7 @@ import android.support.v7.widget.LinearLayoutManager import android.support.v7.widget.RecyclerView import android.util.AttributeSet import com.sethchhim.kuboo_client.Settings -import com.sethchhim.kuboo_client.ui.main.browser.custom.BrowserContentType.FOLDER -import com.sethchhim.kuboo_client.ui.main.browser.custom.BrowserContentType.MEDIA +import com.sethchhim.kuboo_client.ui.main.browser.custom.BrowserContentType.* import jp.wasabeef.recyclerview.animators.SlideInUpAnimator class BrowserContentRecyclerView @JvmOverloads constructor(context: Context, attrs: AttributeSet? = null, defStyleAttr: Int = 0) : RecyclerView(context, attrs, defStyleAttr) { @@ -27,32 +26,36 @@ class BrowserContentRecyclerView @JvmOverloads constructor(context: Context, att internal fun setSpanCountPortrait(browserContentType: BrowserContentType) { when (browserContentType) { - MEDIA -> setSpanCount(3) FOLDER -> setSpanCount(1) + MEDIA_FORCE_LIST -> setSpanCount(1) + MEDIA -> setSpanCount(3) } this.contentType = browserContentType } internal fun setSpanCountLandscape(browserContentType: BrowserContentType) { when (browserContentType) { - MEDIA -> setSpanCount(5) FOLDER -> setSpanCount(2) + MEDIA_FORCE_LIST -> setSpanCount(2) + MEDIA -> setSpanCount(5) } this.contentType = browserContentType } internal fun setSpanCountPortraitHiDpi(browserContentType: BrowserContentType) { when (browserContentType) { + FOLDER -> setSpanCount(1) + MEDIA_FORCE_LIST -> setSpanCount(1) MEDIA -> setSpanCount(4) - FOLDER -> setSpanCount(2) } this.contentType = browserContentType } internal fun setSpanCountLandscapeHiDpi(browserContentType: BrowserContentType) { when (browserContentType) { + FOLDER -> setSpanCount(2) + MEDIA_FORCE_LIST -> setSpanCount(2) MEDIA -> setSpanCount(5) - FOLDER -> setSpanCount(3) } this.contentType = browserContentType } diff --git a/app/src/main/java/com/sethchhim/kuboo_client/ui/main/browser/custom/BrowserContentType.kt b/app/src/main/java/com/sethchhim/kuboo_client/ui/main/browser/custom/BrowserContentType.kt index 1a0a9e1f..245f1c21 100644 --- a/app/src/main/java/com/sethchhim/kuboo_client/ui/main/browser/custom/BrowserContentType.kt +++ b/app/src/main/java/com/sethchhim/kuboo_client/ui/main/browser/custom/BrowserContentType.kt @@ -1,5 +1,5 @@ package com.sethchhim.kuboo_client.ui.main.browser.custom enum class BrowserContentType { - MEDIA, FOLDER + FOLDER, MEDIA, MEDIA_FORCE_LIST } \ No newline at end of file diff --git a/app/src/main/java/com/sethchhim/kuboo_client/util/SharedPrefsHelper.kt b/app/src/main/java/com/sethchhim/kuboo_client/util/SharedPrefsHelper.kt index b45c5714..2235c252 100644 --- a/app/src/main/java/com/sethchhim/kuboo_client/util/SharedPrefsHelper.kt +++ b/app/src/main/java/com/sethchhim/kuboo_client/util/SharedPrefsHelper.kt @@ -6,6 +6,7 @@ import com.google.gson.Gson import com.google.gson.reflect.TypeToken import com.sethchhim.kuboo_client.Constants.KEY_APP_THEME import com.sethchhim.kuboo_client.Constants.KEY_BROWSER_IMMERSIVE +import com.sethchhim.kuboo_client.Constants.KEY_BROWSER_MEDIA_FORCE_LIST import com.sethchhim.kuboo_client.Constants.KEY_DOWNLOAD_SAVE_PATH import com.sethchhim.kuboo_client.Constants.KEY_DOWNLOAD_TRACKING_INTERVAL import com.sethchhim.kuboo_client.Constants.KEY_DOWNLOAD_TRACKING_LIMIT @@ -27,6 +28,7 @@ import com.sethchhim.kuboo_client.Constants.KEY_SCREEN_ORIENTATION import com.sethchhim.kuboo_client.Constants.KEY_VOLUME_PAGE_TURN import com.sethchhim.kuboo_client.Constants.KEY_WIFI_ONLY import com.sethchhim.kuboo_client.Settings.APP_THEME +import com.sethchhim.kuboo_client.Settings.BROWSER_MEDIA_FORCE_LIST import com.sethchhim.kuboo_client.Settings.DEFAULT_APP_THEME import com.sethchhim.kuboo_client.Settings.DEFAULT_DOWNLOAD_TRACKING_INTERVAL import com.sethchhim.kuboo_client.Settings.DEFAULT_DOWNLOAD_TRACKING_LIMIT @@ -69,6 +71,7 @@ class SharedPrefsHelper(val context: Context) { fun restoreSettings() { APP_THEME = sharedPreferences.getInt(KEY_APP_THEME, DEFAULT_APP_THEME) +// BROWSER_MEDIA_FORCE_LIST = sharedPreferences.getBoolean(KEY_BROWSER_MEDIA_FORCE_LIST, false) DOWNLOAD_TRACKING_LIMIT = sharedPreferences.getInt(KEY_DOWNLOAD_TRACKING_LIMIT, DEFAULT_DOWNLOAD_TRACKING_LIMIT) DOWNLOAD_TRACKING_INTERVAL = sharedPreferences.getInt(KEY_DOWNLOAD_TRACKING_INTERVAL, DEFAULT_DOWNLOAD_TRACKING_INTERVAL) DOWNLOAD_SAVE_PATH = sharedPreferences.getString(KEY_DOWNLOAD_SAVE_PATH, context.getExternalFilesDir(null).path) @@ -279,6 +282,11 @@ class SharedPrefsHelper(val context: Context) { sharedPreferences.edit().putBoolean(KEY_VOLUME_PAGE_TURN, VOLUME_PAGE_TURN).apply() } + fun saveBrowserMediaForceList() { + if (isDebugSharedPreferencesHelper) Timber.i("Saving BROWSER_MEDIA_FORCE_LIST: $BROWSER_MEDIA_FORCE_LIST") + sharedPreferences.edit().putBoolean(KEY_BROWSER_MEDIA_FORCE_LIST, BROWSER_MEDIA_FORCE_LIST).apply() + } + private fun Any.toJson() = Gson().toJson(this) } diff --git a/app/src/main/res/drawable/ic_view_list_white_24dp.xml b/app/src/main/res/drawable/ic_view_list_white_24dp.xml new file mode 100644 index 00000000..04570716 --- /dev/null +++ b/app/src/main/res/drawable/ic_view_list_white_24dp.xml @@ -0,0 +1,5 @@ + + + diff --git a/app/src/main/res/drawable/ic_view_module_white_24dp.xml b/app/src/main/res/drawable/ic_view_module_white_24dp.xml new file mode 100644 index 00000000..fc2b3a7e --- /dev/null +++ b/app/src/main/res/drawable/ic_view_module_white_24dp.xml @@ -0,0 +1,5 @@ + + + diff --git a/app/src/main/res/layout/browser_item_content_media_force_list.xml b/app/src/main/res/layout/browser_item_content_media_force_list.xml new file mode 100644 index 00000000..53fe2bdd --- /dev/null +++ b/app/src/main/res/layout/browser_item_content_media_force_list.xml @@ -0,0 +1,80 @@ + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/app/src/main/res/menu/menu_main.xml b/app/src/main/res/menu/menu_main.xml index d697e5e6..49e6bba4 100644 --- a/app/src/main/res/menu/menu_main.xml +++ b/app/src/main/res/menu/menu_main.xml @@ -30,6 +30,11 @@ app:actionViewClass="android.support.v7.widget.SearchView" app:showAsAction="always|collapseActionView"/> + + Folder Media NEXT + page + pages PREVIOUS Something went wrong! @@ -133,6 +135,7 @@ Latest Latest Added No Items Found! + Log MORE No server detected! Open Drawer @@ -248,5 +251,4 @@ Downloads Home Settings - Log