Migrate to ViewBinding from Kotlin synthetics in controllers

This commit is contained in:
arkon 2020-04-08 23:06:28 -04:00
parent 89d45e7775
commit 627a720d4b
22 changed files with 273 additions and 301 deletions

View File

@ -57,6 +57,10 @@ android {
} }
} }
viewBinding {
enabled = true
}
buildTypes { buildTypes {
debug { debug {
versionNameSuffix "-${getCommitCount()}" versionNameSuffix "-${getCommitCount()}"

View File

@ -20,9 +20,6 @@ import uy.kohesive.injekt.injectLazy
*/ */
class DownloadProvider(private val context: Context) { class DownloadProvider(private val context: Context) {
/**
* Preferences helper.
*/
private val preferences: PreferencesHelper by injectLazy() private val preferences: PreferencesHelper by injectLazy()
/** /**

View File

@ -63,14 +63,8 @@ class DownloadService : Service() {
} }
} }
/**
* Download manager.
*/
private val downloadManager: DownloadManager by injectLazy() private val downloadManager: DownloadManager by injectLazy()
/**
* Preferences helper.
*/
private val preferences: PreferencesHelper by injectLazy() private val preferences: PreferencesHelper by injectLazy()
/** /**

View File

@ -9,8 +9,7 @@ abstract class BaseFlexibleViewHolder(
view: View, view: View,
adapter: FlexibleAdapter<*>, adapter: FlexibleAdapter<*>,
stickyHeader: Boolean = false stickyHeader: Boolean = false
) : ) : FlexibleViewHolder(view, adapter, stickyHeader), LayoutContainer {
FlexibleViewHolder(view, adapter, stickyHeader), LayoutContainer {
override val containerView: View? override val containerView: View?
get() = itemView get() = itemView

View File

@ -20,6 +20,7 @@ import eu.davidea.flexibleadapter.items.IFlexible
import eu.kanade.tachiyomi.R import eu.kanade.tachiyomi.R
import eu.kanade.tachiyomi.data.preference.PreferencesHelper import eu.kanade.tachiyomi.data.preference.PreferencesHelper
import eu.kanade.tachiyomi.data.preference.getOrDefault import eu.kanade.tachiyomi.data.preference.getOrDefault
import eu.kanade.tachiyomi.databinding.CatalogueMainControllerBinding
import eu.kanade.tachiyomi.source.CatalogueSource import eu.kanade.tachiyomi.source.CatalogueSource
import eu.kanade.tachiyomi.source.Source import eu.kanade.tachiyomi.source.Source
import eu.kanade.tachiyomi.ui.base.controller.NucleusController import eu.kanade.tachiyomi.ui.base.controller.NucleusController
@ -30,8 +31,6 @@ import eu.kanade.tachiyomi.ui.catalogue.browse.BrowseCatalogueController
import eu.kanade.tachiyomi.ui.catalogue.global_search.CatalogueSearchController import eu.kanade.tachiyomi.ui.catalogue.global_search.CatalogueSearchController
import eu.kanade.tachiyomi.ui.catalogue.latest.LatestUpdatesController import eu.kanade.tachiyomi.ui.catalogue.latest.LatestUpdatesController
import eu.kanade.tachiyomi.ui.setting.SettingsSourcesController import eu.kanade.tachiyomi.ui.setting.SettingsSourcesController
import kotlinx.android.synthetic.main.catalogue_main_controller.fast_scroller
import kotlinx.android.synthetic.main.catalogue_main_controller.recycler
import uy.kohesive.injekt.Injekt import uy.kohesive.injekt.Injekt
import uy.kohesive.injekt.api.get import uy.kohesive.injekt.api.get
@ -48,9 +47,6 @@ class CatalogueController : NucleusController<CataloguePresenter>(),
CatalogueAdapter.OnBrowseClickListener, CatalogueAdapter.OnBrowseClickListener,
CatalogueAdapter.OnLatestClickListener { CatalogueAdapter.OnLatestClickListener {
/**
* Application preferences.
*/
private val preferences: PreferencesHelper = Injekt.get() private val preferences: PreferencesHelper = Injekt.get()
/** /**
@ -58,9 +54,8 @@ class CatalogueController : NucleusController<CataloguePresenter>(),
*/ */
private var adapter: CatalogueAdapter? = null private var adapter: CatalogueAdapter? = null
/** private lateinit var binding: CatalogueMainControllerBinding
* Called when controller is initialized.
*/
init { init {
// Enable the option menu // Enable the option menu
setHasOptionsMenu(true) setHasOptionsMenu(true)
@ -92,7 +87,8 @@ class CatalogueController : NucleusController<CataloguePresenter>(),
* @return inflated view. * @return inflated view.
*/ */
override fun inflateView(inflater: LayoutInflater, container: ViewGroup): View { override fun inflateView(inflater: LayoutInflater, container: ViewGroup): View {
return inflater.inflate(R.layout.catalogue_main_controller, container, false) binding = CatalogueMainControllerBinding.inflate(inflater)
return binding.root
} }
/** /**
@ -106,10 +102,10 @@ class CatalogueController : NucleusController<CataloguePresenter>(),
adapter = CatalogueAdapter(this) adapter = CatalogueAdapter(this)
// Create recycler and set adapter. // Create recycler and set adapter.
recycler.layoutManager = LinearLayoutManager(view.context) binding.recycler.layoutManager = LinearLayoutManager(view.context)
recycler.adapter = adapter binding.recycler.adapter = adapter
recycler.addItemDecoration(SourceDividerItemDecoration(view.context)) binding.recycler.addItemDecoration(SourceDividerItemDecoration(view.context))
adapter?.fastScroller = fast_scroller adapter?.fastScroller = binding.fastScroller
requestPermissionsSafe(arrayOf(WRITE_EXTERNAL_STORAGE), 301) requestPermissionsSafe(arrayOf(WRITE_EXTERNAL_STORAGE), 301)
} }

View File

@ -25,6 +25,7 @@ import eu.kanade.tachiyomi.R
import eu.kanade.tachiyomi.data.database.models.Category import eu.kanade.tachiyomi.data.database.models.Category
import eu.kanade.tachiyomi.data.database.models.Manga import eu.kanade.tachiyomi.data.database.models.Manga
import eu.kanade.tachiyomi.data.preference.PreferencesHelper import eu.kanade.tachiyomi.data.preference.PreferencesHelper
import eu.kanade.tachiyomi.databinding.CatalogueControllerBinding
import eu.kanade.tachiyomi.source.CatalogueSource import eu.kanade.tachiyomi.source.CatalogueSource
import eu.kanade.tachiyomi.source.model.FilterList import eu.kanade.tachiyomi.source.model.FilterList
import eu.kanade.tachiyomi.source.online.HttpSource import eu.kanade.tachiyomi.source.online.HttpSource
@ -43,9 +44,6 @@ import eu.kanade.tachiyomi.util.view.visible
import eu.kanade.tachiyomi.widget.AutofitRecyclerView import eu.kanade.tachiyomi.widget.AutofitRecyclerView
import eu.kanade.tachiyomi.widget.EmptyView import eu.kanade.tachiyomi.widget.EmptyView
import java.util.concurrent.TimeUnit import java.util.concurrent.TimeUnit
import kotlinx.android.synthetic.main.catalogue_controller.catalogue_view
import kotlinx.android.synthetic.main.catalogue_controller.empty_view
import kotlinx.android.synthetic.main.catalogue_controller.progress
import kotlinx.android.synthetic.main.main_activity.drawer import kotlinx.android.synthetic.main.main_activity.drawer
import rx.Observable import rx.Observable
import rx.Subscription import rx.Subscription
@ -68,9 +66,6 @@ open class BrowseCatalogueController(bundle: Bundle) :
putLong(SOURCE_ID_KEY, source.id) putLong(SOURCE_ID_KEY, source.id)
}) })
/**
* Preferences helper.
*/
private val preferences: PreferencesHelper by injectLazy() private val preferences: PreferencesHelper by injectLazy()
/** /**
@ -108,6 +103,8 @@ open class BrowseCatalogueController(bundle: Bundle) :
*/ */
private var progressItem: ProgressItem? = null private var progressItem: ProgressItem? = null
private lateinit var binding: CatalogueControllerBinding
init { init {
setHasOptionsMenu(true) setHasOptionsMenu(true)
} }
@ -121,7 +118,8 @@ open class BrowseCatalogueController(bundle: Bundle) :
} }
override fun inflateView(inflater: LayoutInflater, container: ViewGroup): View { override fun inflateView(inflater: LayoutInflater, container: ViewGroup): View {
return inflater.inflate(R.layout.catalogue_controller, container, false) binding = CatalogueControllerBinding.inflate(inflater)
return binding.root
} }
override fun onViewCreated(view: View) { override fun onViewCreated(view: View) {
@ -133,7 +131,7 @@ open class BrowseCatalogueController(bundle: Bundle) :
navView?.setFilters(presenter.filterItems) navView?.setFilters(presenter.filterItems)
progress?.visible() binding.progress.visible()
} }
override fun onDestroyView(view: View) { override fun onDestroyView(view: View) {
@ -180,12 +178,12 @@ open class BrowseCatalogueController(bundle: Bundle) :
numColumnsSubscription?.unsubscribe() numColumnsSubscription?.unsubscribe()
var oldPosition = RecyclerView.NO_POSITION var oldPosition = RecyclerView.NO_POSITION
val oldRecycler = catalogue_view?.getChildAt(1) val oldRecycler = binding.catalogueView.getChildAt(1)
if (oldRecycler is RecyclerView) { if (oldRecycler is RecyclerView) {
oldPosition = (oldRecycler.layoutManager as LinearLayoutManager).findFirstVisibleItemPosition() oldPosition = (oldRecycler.layoutManager as LinearLayoutManager).findFirstVisibleItemPosition()
oldRecycler.adapter = null oldRecycler.adapter = null
catalogue_view?.removeView(oldRecycler) binding.catalogueView.removeView(oldRecycler)
} }
val recycler = if (presenter.isListMode) { val recycler = if (presenter.isListMode) {
@ -196,7 +194,7 @@ open class BrowseCatalogueController(bundle: Bundle) :
addItemDecoration(DividerItemDecoration(context, DividerItemDecoration.VERTICAL)) addItemDecoration(DividerItemDecoration(context, DividerItemDecoration.VERTICAL))
} }
} else { } else {
(catalogue_view.inflate(R.layout.catalogue_recycler_autofit) as AutofitRecyclerView).apply { (binding.catalogueView.inflate(R.layout.catalogue_recycler_autofit) as AutofitRecyclerView).apply {
numColumnsSubscription = getColumnsPreferenceForCurrentOrientation().asObservable() numColumnsSubscription = getColumnsPreferenceForCurrentOrientation().asObservable()
.doOnNext { spanCount = it } .doOnNext { spanCount = it }
.skip(1) .skip(1)
@ -216,7 +214,7 @@ open class BrowseCatalogueController(bundle: Bundle) :
recycler.setHasFixedSize(true) recycler.setHasFixedSize(true)
recycler.adapter = adapter recycler.adapter = adapter
catalogue_view.addView(recycler, 1) binding.catalogueView.addView(recycler, 1)
if (oldPosition != RecyclerView.NO_POSITION) { if (oldPosition != RecyclerView.NO_POSITION) {
recycler.layoutManager?.scrollToPosition(oldPosition) recycler.layoutManager?.scrollToPosition(oldPosition)
@ -353,45 +351,43 @@ open class BrowseCatalogueController(bundle: Bundle) :
snack?.dismiss() snack?.dismiss()
if (catalogue_view != null) { val message = getErrorMessage(error)
val message = getErrorMessage(error) val retryAction = View.OnClickListener {
val retryAction = View.OnClickListener {
// If not the first page, show bottom progress bar. // If not the first page, show bottom progress bar.
if (adapter.mainItemCount > 0 && progressItem != null) { if (adapter.mainItemCount > 0 && progressItem != null) {
adapter.addScrollableFooterWithDelay(progressItem!!, 0, true) adapter.addScrollableFooterWithDelay(progressItem!!, 0, true)
} else { } else {
showProgressBar() showProgressBar()
}
presenter.requestNext()
}
if (adapter.isEmpty) {
val actions = mutableListOf(EmptyView.Action(R.string.action_retry, retryAction))
if (presenter.source is HttpSource) {
val openInWebViewAction = View.OnClickListener {
openInWebView()
} }
presenter.requestNext() actions += EmptyView.Action(R.string.action_open_in_web_view, openInWebViewAction)
} }
if (adapter.isEmpty) { binding.emptyView.show(message, actions)
val actions = mutableListOf(EmptyView.Action(R.string.action_retry, retryAction)) } else {
if (presenter.source is HttpSource) { snack = binding.catalogueView.snack(message, Snackbar.LENGTH_INDEFINITE) {
val openInWebViewAction = View.OnClickListener { setAction(R.string.action_retry, retryAction)
openInWebView()
}
actions += EmptyView.Action(R.string.action_open_in_web_view, openInWebViewAction)
}
empty_view.show(message, actions)
} else {
snack = catalogue_view.snack(message, Snackbar.LENGTH_INDEFINITE) {
setAction(R.string.action_retry, retryAction)
}
} }
} }
} }
private fun getErrorMessage(error: Throwable): String { private fun getErrorMessage(error: Throwable): String {
if (error is NoResultsException) { if (error is NoResultsException) {
return catalogue_view.context.getString(R.string.no_results_found) return binding.catalogueView.context.getString(R.string.no_results_found)
} }
return when { return when {
error.message == null -> "" error.message == null -> ""
error.message!!.startsWith("HTTP error") -> "${error.message}: ${catalogue_view.context.getString(R.string.http_error_hint)}" error.message!!.startsWith("HTTP error") -> "${error.message}: ${binding.catalogueView.context.getString(R.string.http_error_hint)}"
else -> error.message!! else -> error.message!!
} }
} }
@ -484,7 +480,7 @@ open class BrowseCatalogueController(bundle: Bundle) :
* Shows the progress bar. * Shows the progress bar.
*/ */
private fun showProgressBar() { private fun showProgressBar() {
progress?.visible() binding.progress.visible()
snack?.dismiss() snack?.dismiss()
snack = null snack = null
} }
@ -493,8 +489,8 @@ open class BrowseCatalogueController(bundle: Bundle) :
* Hides active progress bars. * Hides active progress bars.
*/ */
private fun hideProgressBar() { private fun hideProgressBar() {
empty_view.hide() binding.emptyView.hide()
progress?.gone() binding.progress.gone()
} }
/** /**

View File

@ -12,11 +12,11 @@ import androidx.recyclerview.widget.LinearLayoutManager
import com.jakewharton.rxbinding.support.v7.widget.queryTextChangeEvents import com.jakewharton.rxbinding.support.v7.widget.queryTextChangeEvents
import eu.kanade.tachiyomi.R import eu.kanade.tachiyomi.R
import eu.kanade.tachiyomi.data.database.models.Manga import eu.kanade.tachiyomi.data.database.models.Manga
import eu.kanade.tachiyomi.databinding.CatalogueGlobalSearchControllerBinding
import eu.kanade.tachiyomi.source.CatalogueSource import eu.kanade.tachiyomi.source.CatalogueSource
import eu.kanade.tachiyomi.ui.base.controller.NucleusController import eu.kanade.tachiyomi.ui.base.controller.NucleusController
import eu.kanade.tachiyomi.ui.base.controller.withFadeTransaction import eu.kanade.tachiyomi.ui.base.controller.withFadeTransaction
import eu.kanade.tachiyomi.ui.manga.MangaController import eu.kanade.tachiyomi.ui.manga.MangaController
import kotlinx.android.synthetic.main.catalogue_global_search_controller.recycler
/** /**
* This controller shows and manages the different search result in global search. * This controller shows and manages the different search result in global search.
@ -34,6 +34,8 @@ open class CatalogueSearchController(
*/ */
protected var adapter: CatalogueSearchAdapter? = null protected var adapter: CatalogueSearchAdapter? = null
private lateinit var binding: CatalogueGlobalSearchControllerBinding
/** /**
* Called when controller is initialized. * Called when controller is initialized.
*/ */
@ -48,8 +50,9 @@ open class CatalogueSearchController(
* @param container containing parent views. * @param container containing parent views.
* @return inflated view * @return inflated view
*/ */
override fun inflateView(inflater: LayoutInflater, container: ViewGroup): android.view.View { override fun inflateView(inflater: LayoutInflater, container: ViewGroup): View {
return inflater.inflate(R.layout.catalogue_global_search_controller, container, false) binding = CatalogueGlobalSearchControllerBinding.inflate(inflater)
return binding.root
} }
/** /**
@ -136,8 +139,8 @@ open class CatalogueSearchController(
adapter = CatalogueSearchAdapter(this) adapter = CatalogueSearchAdapter(this)
// Create recycler and set adapter. // Create recycler and set adapter.
recycler.layoutManager = LinearLayoutManager(view.context) binding.recycler.layoutManager = LinearLayoutManager(view.context)
recycler.adapter = adapter binding.recycler.adapter = adapter
} }
override fun onDestroyView(view: View) { override fun onDestroyView(view: View) {

View File

@ -16,11 +16,9 @@ import eu.davidea.flexibleadapter.SelectableAdapter
import eu.davidea.flexibleadapter.helpers.UndoHelper import eu.davidea.flexibleadapter.helpers.UndoHelper
import eu.kanade.tachiyomi.R import eu.kanade.tachiyomi.R
import eu.kanade.tachiyomi.data.database.models.Category import eu.kanade.tachiyomi.data.database.models.Category
import eu.kanade.tachiyomi.databinding.CategoriesControllerBinding
import eu.kanade.tachiyomi.ui.base.controller.NucleusController import eu.kanade.tachiyomi.ui.base.controller.NucleusController
import eu.kanade.tachiyomi.util.system.toast import eu.kanade.tachiyomi.util.system.toast
import kotlinx.android.synthetic.main.categories_controller.empty_view
import kotlinx.android.synthetic.main.categories_controller.fab
import kotlinx.android.synthetic.main.categories_controller.recycler
/** /**
* Controller to manage the categories for the users' library. * Controller to manage the categories for the users' library.
@ -49,6 +47,8 @@ class CategoryController : NucleusController<CategoryPresenter>(),
*/ */
private var undoHelper: UndoHelper? = null private var undoHelper: UndoHelper? = null
private lateinit var binding: CategoriesControllerBinding
/** /**
* Creates the presenter for this controller. Not to be manually called. * Creates the presenter for this controller. Not to be manually called.
*/ */
@ -68,7 +68,8 @@ class CategoryController : NucleusController<CategoryPresenter>(),
* @param container The parent view for this one. * @param container The parent view for this one.
*/ */
override fun inflateView(inflater: LayoutInflater, container: ViewGroup): View { override fun inflateView(inflater: LayoutInflater, container: ViewGroup): View {
return inflater.inflate(R.layout.categories_controller, container, false) binding = CategoriesControllerBinding.inflate(inflater)
return binding.root
} }
/** /**
@ -80,13 +81,13 @@ class CategoryController : NucleusController<CategoryPresenter>(),
super.onViewCreated(view) super.onViewCreated(view)
adapter = CategoryAdapter(this@CategoryController) adapter = CategoryAdapter(this@CategoryController)
recycler.layoutManager = LinearLayoutManager(view.context) binding.recycler.layoutManager = LinearLayoutManager(view.context)
recycler.setHasFixedSize(true) binding.recycler.setHasFixedSize(true)
recycler.adapter = adapter binding.recycler.adapter = adapter
adapter?.isHandleDragEnabled = true adapter?.isHandleDragEnabled = true
adapter?.isPermanentDelete = false adapter?.isPermanentDelete = false
fab.clicks().subscribeUntilDestroy { binding.fab.clicks().subscribeUntilDestroy {
CategoryCreateDialog(this@CategoryController).showDialog(router, null) CategoryCreateDialog(this@CategoryController).showDialog(router, null)
} }
} }
@ -114,13 +115,13 @@ class CategoryController : NucleusController<CategoryPresenter>(),
actionMode?.finish() actionMode?.finish()
adapter?.updateDataSet(categories) adapter?.updateDataSet(categories)
if (categories.isNotEmpty()) { if (categories.isNotEmpty()) {
empty_view.hide() binding.emptyView.hide()
val selected = categories.filter { it.isSelected } val selected = categories.filter { it.isSelected }
if (selected.isNotEmpty()) { if (selected.isNotEmpty()) {
selected.forEach { onItemLongClick(categories.indexOf(it)) } selected.forEach { onItemLongClick(categories.indexOf(it)) }
} }
} else { } else {
empty_view.show(R.string.information_empty_category) binding.emptyView.show(R.string.information_empty_category)
} }
} }

View File

@ -10,12 +10,11 @@ import androidx.recyclerview.widget.LinearLayoutManager
import eu.kanade.tachiyomi.R import eu.kanade.tachiyomi.R
import eu.kanade.tachiyomi.data.download.DownloadService import eu.kanade.tachiyomi.data.download.DownloadService
import eu.kanade.tachiyomi.data.download.model.Download import eu.kanade.tachiyomi.data.download.model.Download
import eu.kanade.tachiyomi.databinding.DownloadControllerBinding
import eu.kanade.tachiyomi.source.model.Page import eu.kanade.tachiyomi.source.model.Page
import eu.kanade.tachiyomi.ui.base.controller.NucleusController import eu.kanade.tachiyomi.ui.base.controller.NucleusController
import java.util.HashMap import java.util.HashMap
import java.util.concurrent.TimeUnit import java.util.concurrent.TimeUnit
import kotlinx.android.synthetic.main.download_controller.empty_view
import kotlinx.android.synthetic.main.download_controller.recycler
import rx.Observable import rx.Observable
import rx.Subscription import rx.Subscription
import rx.android.schedulers.AndroidSchedulers import rx.android.schedulers.AndroidSchedulers
@ -42,12 +41,15 @@ class DownloadController : NucleusController<DownloadPresenter>(),
*/ */
private var isRunning: Boolean = false private var isRunning: Boolean = false
private lateinit var binding: DownloadControllerBinding
init { init {
setHasOptionsMenu(true) setHasOptionsMenu(true)
} }
override fun inflateView(inflater: LayoutInflater, container: ViewGroup): View { override fun inflateView(inflater: LayoutInflater, container: ViewGroup): View {
return inflater.inflate(R.layout.download_controller, container, false) binding = DownloadControllerBinding.inflate(inflater)
return binding.root
} }
override fun createPresenter(): DownloadPresenter { override fun createPresenter(): DownloadPresenter {
@ -66,12 +68,12 @@ class DownloadController : NucleusController<DownloadPresenter>(),
// Initialize adapter. // Initialize adapter.
adapter = DownloadAdapter(this@DownloadController) adapter = DownloadAdapter(this@DownloadController)
recycler.adapter = adapter binding.recycler.adapter = adapter
adapter?.isHandleDragEnabled = true adapter?.isHandleDragEnabled = true
// Set the layout manager for the recycler and fixed size. // Set the layout manager for the recycler and fixed size.
recycler.layoutManager = LinearLayoutManager(view.context) binding.recycler.layoutManager = LinearLayoutManager(view.context)
recycler.setHasFixedSize(true) binding.recycler.setHasFixedSize(true)
// Subscribe to changes // Subscribe to changes
DownloadService.runningRelay DownloadService.runningRelay
@ -242,7 +244,7 @@ class DownloadController : NucleusController<DownloadPresenter>(),
* @return the holder of the download or null if it's not bound. * @return the holder of the download or null if it's not bound.
*/ */
private fun getHolder(download: Download): DownloadHolder? { private fun getHolder(download: Download): DownloadHolder? {
return recycler?.findViewHolderForItemId(download.chapter.id!!) as? DownloadHolder return binding.recycler.findViewHolderForItemId(download.chapter.id!!) as? DownloadHolder
} }
/** /**
@ -250,9 +252,9 @@ class DownloadController : NucleusController<DownloadPresenter>(),
*/ */
private fun setInformationView() { private fun setInformationView() {
if (presenter.downloadQueue.isEmpty()) { if (presenter.downloadQueue.isEmpty()) {
empty_view?.show(R.string.information_no_downloads) binding.emptyView.show(R.string.information_no_downloads)
} else { } else {
empty_view?.hide() binding.emptyView.hide()
} }
} }

View File

@ -19,11 +19,11 @@ import eu.davidea.flexibleadapter.items.IFlexible
import eu.kanade.tachiyomi.R import eu.kanade.tachiyomi.R
import eu.kanade.tachiyomi.data.preference.PreferencesHelper import eu.kanade.tachiyomi.data.preference.PreferencesHelper
import eu.kanade.tachiyomi.data.preference.getOrDefault import eu.kanade.tachiyomi.data.preference.getOrDefault
import eu.kanade.tachiyomi.databinding.ExtensionControllerBinding
import eu.kanade.tachiyomi.extension.ExtensionUpdateJob import eu.kanade.tachiyomi.extension.ExtensionUpdateJob
import eu.kanade.tachiyomi.extension.model.Extension import eu.kanade.tachiyomi.extension.model.Extension
import eu.kanade.tachiyomi.ui.base.controller.NucleusController import eu.kanade.tachiyomi.ui.base.controller.NucleusController
import eu.kanade.tachiyomi.ui.base.controller.withFadeTransaction import eu.kanade.tachiyomi.ui.base.controller.withFadeTransaction
import kotlinx.android.synthetic.main.extension_controller.*
import uy.kohesive.injekt.Injekt import uy.kohesive.injekt.Injekt
import uy.kohesive.injekt.api.get import uy.kohesive.injekt.api.get
@ -47,6 +47,8 @@ open class ExtensionController : NucleusController<ExtensionPresenter>(),
private var query = "" private var query = ""
private lateinit var binding: ExtensionControllerBinding
init { init {
setHasOptionsMenu(true) setHasOptionsMenu(true)
} }
@ -60,24 +62,25 @@ open class ExtensionController : NucleusController<ExtensionPresenter>(),
} }
override fun inflateView(inflater: LayoutInflater, container: ViewGroup): View { override fun inflateView(inflater: LayoutInflater, container: ViewGroup): View {
return inflater.inflate(R.layout.extension_controller, container, false) binding = ExtensionControllerBinding.inflate(inflater)
return binding.root
} }
override fun onViewCreated(view: View) { override fun onViewCreated(view: View) {
super.onViewCreated(view) super.onViewCreated(view)
ext_swipe_refresh.isRefreshing = true binding.extSwipeRefresh.isRefreshing = true
ext_swipe_refresh.refreshes().subscribeUntilDestroy { binding.extSwipeRefresh.refreshes().subscribeUntilDestroy {
presenter.findAvailableExtensions() presenter.findAvailableExtensions()
} }
// Initialize adapter, scroll listener and recycler views // Initialize adapter, scroll listener and recycler views
adapter = ExtensionAdapter(this) adapter = ExtensionAdapter(this)
// Create recycler and set adapter. // Create recycler and set adapter.
ext_recycler.layoutManager = LinearLayoutManager(view.context) binding.extRecycler.layoutManager = LinearLayoutManager(view.context)
ext_recycler.adapter = adapter binding.extRecycler.adapter = adapter
ext_recycler.addItemDecoration(ExtensionDividerItemDecoration(view.context)) binding.extRecycler.addItemDecoration(ExtensionDividerItemDecoration(view.context))
adapter?.fastScroller = fast_scroller adapter?.fastScroller = binding.fastScroller
} }
override fun onDestroyView(view: View) { override fun onDestroyView(view: View) {
@ -184,7 +187,7 @@ open class ExtensionController : NucleusController<ExtensionPresenter>(),
} }
fun setExtensions(extensions: List<ExtensionItem>) { fun setExtensions(extensions: List<ExtensionItem>) {
ext_swipe_refresh?.isRefreshing = false binding.extSwipeRefresh.isRefreshing = false
this.extensions = extensions this.extensions = extensions
drawExtensions() drawExtensions()
} }

View File

@ -26,21 +26,13 @@ import com.jakewharton.rxbinding.view.clicks
import eu.kanade.tachiyomi.R import eu.kanade.tachiyomi.R
import eu.kanade.tachiyomi.data.preference.EmptyPreferenceDataStore import eu.kanade.tachiyomi.data.preference.EmptyPreferenceDataStore
import eu.kanade.tachiyomi.data.preference.SharedPreferencesDataStore import eu.kanade.tachiyomi.data.preference.SharedPreferencesDataStore
import eu.kanade.tachiyomi.databinding.ExtensionDetailControllerBinding
import eu.kanade.tachiyomi.source.ConfigurableSource import eu.kanade.tachiyomi.source.ConfigurableSource
import eu.kanade.tachiyomi.source.Source import eu.kanade.tachiyomi.source.Source
import eu.kanade.tachiyomi.ui.base.controller.NucleusController import eu.kanade.tachiyomi.ui.base.controller.NucleusController
import eu.kanade.tachiyomi.util.preference.preferenceCategory import eu.kanade.tachiyomi.util.preference.preferenceCategory
import eu.kanade.tachiyomi.util.system.LocaleHelper import eu.kanade.tachiyomi.util.system.LocaleHelper
import eu.kanade.tachiyomi.util.view.visible import eu.kanade.tachiyomi.util.view.visible
import kotlinx.android.synthetic.main.extension_detail_controller.extension_icon
import kotlinx.android.synthetic.main.extension_detail_controller.extension_lang
import kotlinx.android.synthetic.main.extension_detail_controller.extension_obsolete
import kotlinx.android.synthetic.main.extension_detail_controller.extension_pkg
import kotlinx.android.synthetic.main.extension_detail_controller.extension_prefs_empty_view
import kotlinx.android.synthetic.main.extension_detail_controller.extension_prefs_recycler
import kotlinx.android.synthetic.main.extension_detail_controller.extension_title
import kotlinx.android.synthetic.main.extension_detail_controller.extension_uninstall_button
import kotlinx.android.synthetic.main.extension_detail_controller.extension_version
@SuppressLint("RestrictedApi") @SuppressLint("RestrictedApi")
class ExtensionDetailsController(bundle: Bundle? = null) : class ExtensionDetailsController(bundle: Bundle? = null) :
@ -52,14 +44,16 @@ class ExtensionDetailsController(bundle: Bundle? = null) :
private var preferenceScreen: PreferenceScreen? = null private var preferenceScreen: PreferenceScreen? = null
private lateinit var binding: ExtensionDetailControllerBinding
constructor(pkgName: String) : this(Bundle().apply { constructor(pkgName: String) : this(Bundle().apply {
putString(PKGNAME_KEY, pkgName) putString(PKGNAME_KEY, pkgName)
}) })
override fun inflateView(inflater: LayoutInflater, container: ViewGroup): View { override fun inflateView(inflater: LayoutInflater, container: ViewGroup): View {
val themedInflater = inflater.cloneInContext(getPreferenceThemeContext()) val themedInflater = inflater.cloneInContext(getPreferenceThemeContext())
binding = ExtensionDetailControllerBinding.inflate(themedInflater)
return themedInflater.inflate(R.layout.extension_detail_controller, container, false) return binding.root
} }
override fun createPresenter(): ExtensionDetailsPresenter { override fun createPresenter(): ExtensionDetailsPresenter {
@ -77,17 +71,17 @@ class ExtensionDetailsController(bundle: Bundle? = null) :
val extension = presenter.extension ?: return val extension = presenter.extension ?: return
val context = view.context val context = view.context
extension_title.text = extension.name binding.extensionTitle.text = extension.name
extension_version.text = context.getString(R.string.ext_version_info, extension.versionName) binding.extensionVersion.text = context.getString(R.string.ext_version_info, extension.versionName)
extension_lang.text = context.getString(R.string.ext_language_info, LocaleHelper.getDisplayName(extension.lang, context)) binding.extensionLang.text = context.getString(R.string.ext_language_info, LocaleHelper.getDisplayName(extension.lang, context))
extension_pkg.text = extension.pkgName binding.extensionPkg.text = extension.pkgName
extension.getApplicationIcon(context)?.let { extension_icon.setImageDrawable(it) } extension.getApplicationIcon(context)?.let { binding.extensionIcon.setImageDrawable(it) }
extension_uninstall_button.clicks().subscribeUntilDestroy { binding.extensionUninstallButton.clicks().subscribeUntilDestroy {
presenter.uninstallExtension() presenter.uninstallExtension()
} }
if (extension.isObsolete) { if (extension.isObsolete) {
extension_obsolete.visible() binding.extensionObsolete.visible()
} }
val themedContext by lazy { getPreferenceThemeContext() } val themedContext by lazy { getPreferenceThemeContext() }
@ -107,12 +101,12 @@ class ExtensionDetailsController(bundle: Bundle? = null) :
manager.setPreferences(screen) manager.setPreferences(screen)
extension_prefs_recycler.layoutManager = LinearLayoutManager(context) binding.extensionPrefsRecycler.layoutManager = LinearLayoutManager(context)
extension_prefs_recycler.adapter = PreferenceGroupAdapter(screen) binding.extensionPrefsRecycler.adapter = PreferenceGroupAdapter(screen)
extension_prefs_recycler.addItemDecoration(DividerItemDecoration(context, VERTICAL)) binding.extensionPrefsRecycler.addItemDecoration(DividerItemDecoration(context, VERTICAL))
if (screen.preferenceCount == 0) { if (screen.preferenceCount == 0) {
extension_prefs_empty_view.show(R.string.ext_empty_preferences) binding.extensionPrefsEmptyView.show(R.string.ext_empty_preferences)
} }
} }

View File

@ -29,6 +29,7 @@ import eu.kanade.tachiyomi.data.database.models.Manga
import eu.kanade.tachiyomi.data.library.LibraryUpdateService import eu.kanade.tachiyomi.data.library.LibraryUpdateService
import eu.kanade.tachiyomi.data.preference.PreferencesHelper import eu.kanade.tachiyomi.data.preference.PreferencesHelper
import eu.kanade.tachiyomi.data.preference.getOrDefault import eu.kanade.tachiyomi.data.preference.getOrDefault
import eu.kanade.tachiyomi.databinding.LibraryControllerBinding
import eu.kanade.tachiyomi.ui.base.controller.NucleusController import eu.kanade.tachiyomi.ui.base.controller.NucleusController
import eu.kanade.tachiyomi.ui.base.controller.RootController import eu.kanade.tachiyomi.ui.base.controller.RootController
import eu.kanade.tachiyomi.ui.base.controller.TabbedController import eu.kanade.tachiyomi.ui.base.controller.TabbedController
@ -38,9 +39,6 @@ import eu.kanade.tachiyomi.ui.manga.MangaController
import eu.kanade.tachiyomi.util.system.getResourceColor import eu.kanade.tachiyomi.util.system.getResourceColor
import eu.kanade.tachiyomi.util.system.toast import eu.kanade.tachiyomi.util.system.toast
import java.io.IOException import java.io.IOException
import kotlinx.android.synthetic.main.library_controller.action_toolbar
import kotlinx.android.synthetic.main.library_controller.empty_view
import kotlinx.android.synthetic.main.library_controller.library_pager
import kotlinx.android.synthetic.main.main_activity.tabs import kotlinx.android.synthetic.main.main_activity.tabs
import rx.Subscription import rx.Subscription
import timber.log.Timber import timber.log.Timber
@ -127,6 +125,8 @@ class LibraryController(
private var searchViewSubscription: Subscription? = null private var searchViewSubscription: Subscription? = null
private lateinit var binding: LibraryControllerBinding
init { init {
setHasOptionsMenu(true) setHasOptionsMenu(true)
retainViewMode = RetainViewMode.RETAIN_DETACH retainViewMode = RetainViewMode.RETAIN_DETACH
@ -141,15 +141,16 @@ class LibraryController(
} }
override fun inflateView(inflater: LayoutInflater, container: ViewGroup): View { override fun inflateView(inflater: LayoutInflater, container: ViewGroup): View {
return inflater.inflate(R.layout.library_controller, container, false) binding = LibraryControllerBinding.inflate(inflater)
return binding.root
} }
override fun onViewCreated(view: View) { override fun onViewCreated(view: View) {
super.onViewCreated(view) super.onViewCreated(view)
adapter = LibraryAdapter(this) adapter = LibraryAdapter(this)
library_pager.adapter = adapter binding.libraryPager.adapter = adapter
library_pager.pageSelections().skip(1).subscribeUntilDestroy { binding.libraryPager.pageSelections().skip(1).subscribeUntilDestroy {
preferences.lastUsedCategory().set(it) preferences.lastUsedCategory().set(it)
activeCategory = it activeCategory = it
} }
@ -177,14 +178,14 @@ class LibraryController(
override fun onChangeStarted(handler: ControllerChangeHandler, type: ControllerChangeType) { override fun onChangeStarted(handler: ControllerChangeHandler, type: ControllerChangeType) {
super.onChangeStarted(handler, type) super.onChangeStarted(handler, type)
if (type.isEnter) { if (type.isEnter) {
activity?.tabs?.setupWithViewPager(library_pager) activity?.tabs?.setupWithViewPager(binding.libraryPager)
presenter.subscribeLibrary() presenter.subscribeLibrary()
} }
} }
override fun onDestroyView(view: View) { override fun onDestroyView(view: View) {
destroyActionModeIfNeeded() destroyActionModeIfNeeded()
action_toolbar.destroy() binding.actionToolbar.destroy()
adapter?.onDestroy() adapter?.onDestroy()
adapter = null adapter = null
settingsSheet = null settingsSheet = null
@ -224,14 +225,14 @@ class LibraryController(
// Show empty view if needed // Show empty view if needed
if (mangaMap.isNotEmpty()) { if (mangaMap.isNotEmpty()) {
empty_view.hide() binding.emptyView.hide()
} else { } else {
empty_view.show(R.string.information_empty_library) binding.emptyView.show(R.string.information_empty_library)
} }
// Get the current active category. // Get the current active category.
val activeCat = if (adapter.categories.isNotEmpty()) val activeCat = if (adapter.categories.isNotEmpty())
library_pager.currentItem binding.libraryPager.currentItem
else else
activeCategory activeCategory
@ -239,14 +240,14 @@ class LibraryController(
adapter.categories = categories adapter.categories = categories
// Restore active category. // Restore active category.
library_pager.setCurrentItem(activeCat, false) binding.libraryPager.setCurrentItem(activeCat, false)
tabsVisibilityRelay.call(categories.size > 1) tabsVisibilityRelay.call(categories.size > 1)
// Delay the scroll position to allow the view to be properly measured. // Delay the scroll position to allow the view to be properly measured.
view.post { view.post {
if (isAttached) { if (isAttached) {
activity?.tabs?.setScrollPosition(library_pager.currentItem, 0f, true) activity?.tabs?.setScrollPosition(binding.libraryPager.currentItem, 0f, true)
} }
} }
@ -291,11 +292,11 @@ class LibraryController(
private fun reattachAdapter() { private fun reattachAdapter() {
val adapter = adapter ?: return val adapter = adapter ?: return
val position = library_pager.currentItem val position = binding.libraryPager.currentItem
adapter.recycle = false adapter.recycle = false
library_pager.adapter = adapter binding.libraryPager.adapter = adapter
library_pager.currentItem = position binding.libraryPager.currentItem = position
adapter.recycle = true adapter.recycle = true
} }
@ -305,7 +306,7 @@ class LibraryController(
fun createActionModeIfNeeded() { fun createActionModeIfNeeded() {
if (actionMode == null) { if (actionMode == null) {
actionMode = (activity as AppCompatActivity).startSupportActionMode(this) actionMode = (activity as AppCompatActivity).startSupportActionMode(this)
action_toolbar.show( binding.actionToolbar.show(
actionMode!!, actionMode!!,
R.menu.library_selection R.menu.library_selection
) { onActionItemClicked(actionMode!!, it!!) } ) { onActionItemClicked(actionMode!!, it!!) }
@ -398,7 +399,7 @@ class LibraryController(
} else { } else {
mode.title = count.toString() mode.title = count.toString()
action_toolbar.findItem(R.id.action_edit_cover)?.isVisible = count == 1 binding.actionToolbar.findItem(R.id.action_edit_cover)?.isVisible = count == 1
} }
return false return false
} }
@ -419,7 +420,7 @@ class LibraryController(
} }
override fun onDestroyActionMode(mode: ActionMode?) { override fun onDestroyActionMode(mode: ActionMode?) {
action_toolbar.hide() binding.actionToolbar.hide()
// Clear all the manga selections and notify child views. // Clear all the manga selections and notify child views.
selectedMangas.clear() selectedMangas.clear()
selectionRelay.call(LibrarySelectionEvent.Cleared()) selectionRelay.call(LibrarySelectionEvent.Cleared())
@ -515,13 +516,13 @@ class LibraryController(
} }
private fun selectAllCategoryManga() { private fun selectAllCategoryManga() {
adapter?.categories?.getOrNull(library_pager.currentItem)?.id?.let { adapter?.categories?.getOrNull(binding.libraryPager.currentItem)?.id?.let {
selectAllRelay.call(it) selectAllRelay.call(it)
} }
} }
private fun selectInverseCategoryManga() { private fun selectInverseCategoryManga() {
adapter?.categories?.getOrNull(library_pager.currentItem)?.id?.let { adapter?.categories?.getOrNull(binding.libraryPager.currentItem)?.id?.let {
selectInverseRelay.call(it) selectInverseRelay.call(it)
} }
} }

View File

@ -18,6 +18,7 @@ import eu.kanade.tachiyomi.R
import eu.kanade.tachiyomi.data.database.DatabaseHelper import eu.kanade.tachiyomi.data.database.DatabaseHelper
import eu.kanade.tachiyomi.data.database.models.Manga import eu.kanade.tachiyomi.data.database.models.Manga
import eu.kanade.tachiyomi.data.track.TrackManager import eu.kanade.tachiyomi.data.track.TrackManager
import eu.kanade.tachiyomi.databinding.MangaControllerBinding
import eu.kanade.tachiyomi.source.Source import eu.kanade.tachiyomi.source.Source
import eu.kanade.tachiyomi.source.SourceManager import eu.kanade.tachiyomi.source.SourceManager
import eu.kanade.tachiyomi.ui.base.controller.RxController import eu.kanade.tachiyomi.ui.base.controller.RxController
@ -29,7 +30,6 @@ import eu.kanade.tachiyomi.ui.manga.track.TrackController
import eu.kanade.tachiyomi.util.system.toast import eu.kanade.tachiyomi.util.system.toast
import java.util.Date import java.util.Date
import kotlinx.android.synthetic.main.main_activity.tabs import kotlinx.android.synthetic.main.main_activity.tabs
import kotlinx.android.synthetic.main.manga_controller.manga_pager
import rx.Subscription import rx.Subscription
import uy.kohesive.injekt.Injekt import uy.kohesive.injekt.Injekt
import uy.kohesive.injekt.api.get import uy.kohesive.injekt.api.get
@ -68,6 +68,8 @@ class MangaController : RxController, TabbedController {
val mangaFavoriteRelay: PublishRelay<Boolean> = PublishRelay.create() val mangaFavoriteRelay: PublishRelay<Boolean> = PublishRelay.create()
private lateinit var binding: MangaControllerBinding
private val trackingIconRelay: BehaviorRelay<Boolean> = BehaviorRelay.create() private val trackingIconRelay: BehaviorRelay<Boolean> = BehaviorRelay.create()
private var trackingIconSubscription: Subscription? = null private var trackingIconSubscription: Subscription? = null
@ -77,7 +79,8 @@ class MangaController : RxController, TabbedController {
} }
override fun inflateView(inflater: LayoutInflater, container: ViewGroup): View { override fun inflateView(inflater: LayoutInflater, container: ViewGroup): View {
return inflater.inflate(R.layout.manga_controller, container, false) binding = MangaControllerBinding.inflate(inflater)
return binding.root
} }
override fun onViewCreated(view: View) { override fun onViewCreated(view: View) {
@ -88,11 +91,11 @@ class MangaController : RxController, TabbedController {
requestPermissionsSafe(arrayOf(WRITE_EXTERNAL_STORAGE), 301) requestPermissionsSafe(arrayOf(WRITE_EXTERNAL_STORAGE), 301)
adapter = MangaDetailAdapter() adapter = MangaDetailAdapter()
manga_pager.offscreenPageLimit = 3 binding.mangaPager.offscreenPageLimit = 3
manga_pager.adapter = adapter binding.mangaPager.adapter = adapter
if (!fromCatalogue) if (!fromCatalogue)
manga_pager.currentItem = CHAPTERS_CONTROLLER binding.mangaPager.currentItem = CHAPTERS_CONTROLLER
} }
override fun onDestroyView(view: View) { override fun onDestroyView(view: View) {
@ -103,7 +106,7 @@ class MangaController : RxController, TabbedController {
override fun onChangeStarted(handler: ControllerChangeHandler, type: ControllerChangeType) { override fun onChangeStarted(handler: ControllerChangeHandler, type: ControllerChangeType) {
super.onChangeStarted(handler, type) super.onChangeStarted(handler, type)
if (type.isEnter) { if (type.isEnter) {
activity?.tabs?.setupWithViewPager(manga_pager) activity?.tabs?.setupWithViewPager(binding.mangaPager)
trackingIconSubscription = trackingIconRelay.subscribe { setTrackingIconInternal(it) } trackingIconSubscription = trackingIconRelay.subscribe { setTrackingIconInternal(it) }
} }
} }

View File

@ -24,6 +24,7 @@ import eu.kanade.tachiyomi.R
import eu.kanade.tachiyomi.data.database.models.Chapter import eu.kanade.tachiyomi.data.database.models.Chapter
import eu.kanade.tachiyomi.data.database.models.Manga import eu.kanade.tachiyomi.data.database.models.Manga
import eu.kanade.tachiyomi.data.download.model.Download import eu.kanade.tachiyomi.data.download.model.Download
import eu.kanade.tachiyomi.databinding.ChaptersControllerBinding
import eu.kanade.tachiyomi.ui.base.controller.NucleusController import eu.kanade.tachiyomi.ui.base.controller.NucleusController
import eu.kanade.tachiyomi.ui.base.controller.popControllerWithTag import eu.kanade.tachiyomi.ui.base.controller.popControllerWithTag
import eu.kanade.tachiyomi.ui.manga.MangaController import eu.kanade.tachiyomi.ui.manga.MangaController
@ -32,12 +33,6 @@ import eu.kanade.tachiyomi.util.system.getResourceColor
import eu.kanade.tachiyomi.util.system.toast import eu.kanade.tachiyomi.util.system.toast
import eu.kanade.tachiyomi.util.view.getCoordinates import eu.kanade.tachiyomi.util.view.getCoordinates
import eu.kanade.tachiyomi.util.view.snack import eu.kanade.tachiyomi.util.view.snack
import kotlinx.android.synthetic.main.chapters_controller.action_toolbar
import kotlinx.android.synthetic.main.chapters_controller.fab
import kotlinx.android.synthetic.main.chapters_controller.fast_scroller
import kotlinx.android.synthetic.main.chapters_controller.recycler
import kotlinx.android.synthetic.main.chapters_controller.reveal_view
import kotlinx.android.synthetic.main.chapters_controller.swipe_refresh
import timber.log.Timber import timber.log.Timber
class ChaptersController : NucleusController<ChaptersPresenter>(), class ChaptersController : NucleusController<ChaptersPresenter>(),
@ -64,6 +59,8 @@ class ChaptersController : NucleusController<ChaptersPresenter>(),
private var lastClickPosition = -1 private var lastClickPosition = -1
private lateinit var binding: ChaptersControllerBinding
init { init {
setHasOptionsMenu(true) setHasOptionsMenu(true)
setOptionsMenuHidden(true) setOptionsMenuHidden(true)
@ -76,7 +73,8 @@ class ChaptersController : NucleusController<ChaptersPresenter>(),
} }
override fun inflateView(inflater: LayoutInflater, container: ViewGroup): View { override fun inflateView(inflater: LayoutInflater, container: ViewGroup): View {
return inflater.inflate(R.layout.chapters_controller, container, false) binding = ChaptersControllerBinding.inflate(inflater)
return binding.root
} }
override fun onViewCreated(view: View) { override fun onViewCreated(view: View) {
@ -85,15 +83,15 @@ class ChaptersController : NucleusController<ChaptersPresenter>(),
// Init RecyclerView and adapter // Init RecyclerView and adapter
adapter = ChaptersAdapter(this, view.context) adapter = ChaptersAdapter(this, view.context)
recycler.adapter = adapter binding.recycler.adapter = adapter
recycler.layoutManager = LinearLayoutManager(view.context) binding.recycler.layoutManager = LinearLayoutManager(view.context)
recycler.addItemDecoration(DividerItemDecoration(view.context, DividerItemDecoration.VERTICAL)) binding.recycler.addItemDecoration(DividerItemDecoration(view.context, DividerItemDecoration.VERTICAL))
recycler.setHasFixedSize(true) binding.recycler.setHasFixedSize(true)
adapter?.fastScroller = fast_scroller adapter?.fastScroller = binding.fastScroller
swipe_refresh.refreshes().subscribeUntilDestroy { fetchChaptersFromSource() } binding.swipeRefresh.refreshes().subscribeUntilDestroy { fetchChaptersFromSource() }
fab.clicks().subscribeUntilDestroy { binding.fab.clicks().subscribeUntilDestroy {
val item = presenter.getNextUnreadChapter() val item = presenter.getNextUnreadChapter()
if (item != null) { if (item != null) {
// Create animation listener // Create animation listener
@ -104,8 +102,8 @@ class ChaptersController : NucleusController<ChaptersPresenter>(),
} }
// Get coordinates and start animation // Get coordinates and start animation
val coordinates = fab.getCoordinates() val coordinates = binding.fab.getCoordinates()
if (!reveal_view.showRevealEffect(coordinates.x, coordinates.y, revealAnimationListener)) { if (!binding.revealView.showRevealEffect(coordinates.x, coordinates.y, revealAnimationListener)) {
openChapter(item.chapter) openChapter(item.chapter)
} }
} else { } else {
@ -116,7 +114,7 @@ class ChaptersController : NucleusController<ChaptersPresenter>(),
override fun onDestroyView(view: View) { override fun onDestroyView(view: View) {
destroyActionModeIfNeeded() destroyActionModeIfNeeded()
action_toolbar.destroy() binding.actionToolbar.destroy()
adapter = null adapter = null
super.onDestroyView(view) super.onDestroyView(view)
} }
@ -125,10 +123,10 @@ class ChaptersController : NucleusController<ChaptersPresenter>(),
if (view == null) return if (view == null) return
// Check if animation view is visible // Check if animation view is visible
if (reveal_view.visibility == View.VISIBLE) { if (binding.revealView.visibility == View.VISIBLE) {
// Show the unReveal effect // Show the unreveal effect
val coordinates = fab.getCoordinates() val coordinates = binding.fab.getCoordinates()
reveal_view.hideRevealEffect(coordinates.x, coordinates.y, 1920) binding.revealView.hideRevealEffect(coordinates.x, coordinates.y, 1920)
} }
super.onActivityResumed(activity) super.onActivityResumed(activity)
} }
@ -267,16 +265,16 @@ class ChaptersController : NucleusController<ChaptersPresenter>(),
} }
private fun fetchChaptersFromSource() { private fun fetchChaptersFromSource() {
swipe_refresh?.isRefreshing = true binding.swipeRefresh.isRefreshing = true
presenter.fetchChaptersFromSource() presenter.fetchChaptersFromSource()
} }
fun onFetchChaptersDone() { fun onFetchChaptersDone() {
swipe_refresh?.isRefreshing = false binding.swipeRefresh.isRefreshing = false
} }
fun onFetchChaptersError(error: Throwable) { fun onFetchChaptersError(error: Throwable) {
swipe_refresh?.isRefreshing = false binding.swipeRefresh.isRefreshing = false
activity?.toast(error.message) activity?.toast(error.message)
} }
@ -285,7 +283,7 @@ class ChaptersController : NucleusController<ChaptersPresenter>(),
} }
private fun getHolder(chapter: Chapter): ChapterHolder? { private fun getHolder(chapter: Chapter): ChapterHolder? {
return recycler?.findViewHolderForItemId(chapter.id!!) as? ChapterHolder return binding.recycler.findViewHolderForItemId(chapter.id!!) as? ChapterHolder
} }
fun openChapter(chapter: Chapter, hasAnimation: Boolean = false) { fun openChapter(chapter: Chapter, hasAnimation: Boolean = false) {
@ -357,7 +355,7 @@ class ChaptersController : NucleusController<ChaptersPresenter>(),
private fun createActionModeIfNeeded() { private fun createActionModeIfNeeded() {
if (actionMode == null) { if (actionMode == null) {
actionMode = (activity as? AppCompatActivity)?.startSupportActionMode(this) actionMode = (activity as? AppCompatActivity)?.startSupportActionMode(this)
action_toolbar.show( binding.actionToolbar.show(
actionMode!!, actionMode!!,
R.menu.chapter_selection R.menu.chapter_selection
) { onActionItemClicked(actionMode!!, it!!) } ) { onActionItemClicked(actionMode!!, it!!) }
@ -384,15 +382,15 @@ class ChaptersController : NucleusController<ChaptersPresenter>(),
mode.title = count.toString() mode.title = count.toString()
val chapters = getSelectedChapters() val chapters = getSelectedChapters()
action_toolbar.findItem(R.id.action_download)?.isVisible = chapters.any { !it.isDownloaded } binding.actionToolbar.findItem(R.id.action_download)?.isVisible = chapters.any { !it.isDownloaded }
action_toolbar.findItem(R.id.action_delete)?.isVisible = chapters.any { it.isDownloaded } binding.actionToolbar.findItem(R.id.action_delete)?.isVisible = chapters.any { it.isDownloaded }
action_toolbar.findItem(R.id.action_bookmark)?.isVisible = chapters.any { !it.chapter.bookmark } binding.actionToolbar.findItem(R.id.action_bookmark)?.isVisible = chapters.any { !it.chapter.bookmark }
action_toolbar.findItem(R.id.action_remove_bookmark)?.isVisible = chapters.all { it.chapter.bookmark } binding.actionToolbar.findItem(R.id.action_remove_bookmark)?.isVisible = chapters.all { it.chapter.bookmark }
action_toolbar.findItem(R.id.action_mark_as_read)?.isVisible = chapters.any { !it.chapter.read } binding.actionToolbar.findItem(R.id.action_mark_as_read)?.isVisible = chapters.any { !it.chapter.read }
action_toolbar.findItem(R.id.action_mark_as_unread)?.isVisible = chapters.all { it.chapter.read } binding.actionToolbar.findItem(R.id.action_mark_as_unread)?.isVisible = chapters.all { it.chapter.read }
// Hide FAB to avoid interfering with the bottom action toolbar // Hide FAB to avoid interfering with the bottom action toolbar
fab.hide() binding.fab.hide()
} }
return false return false
} }
@ -414,13 +412,13 @@ class ChaptersController : NucleusController<ChaptersPresenter>(),
} }
override fun onDestroyActionMode(mode: ActionMode) { override fun onDestroyActionMode(mode: ActionMode) {
action_toolbar.hide() binding.actionToolbar.hide()
adapter?.mode = SelectableAdapter.Mode.SINGLE adapter?.mode = SelectableAdapter.Mode.SINGLE
adapter?.clearSelection() adapter?.clearSelection()
selectedItems.clear() selectedItems.clear()
actionMode = null actionMode = null
fab.show() binding.fab.show()
} }
override fun onDetach(view: View) { override fun onDetach(view: View) {
@ -461,7 +459,7 @@ class ChaptersController : NucleusController<ChaptersPresenter>(),
val view = view val view = view
presenter.downloadChapters(chapters) presenter.downloadChapters(chapters)
if (view != null && !presenter.manga.favorite) { if (view != null && !presenter.manga.favorite) {
recycler?.snack(view.context.getString(R.string.snack_add_to_library), Snackbar.LENGTH_INDEFINITE) { binding.recycler.snack(view.context.getString(R.string.snack_add_to_library), Snackbar.LENGTH_INDEFINITE) {
setAction(R.string.action_add) { setAction(R.string.action_add) {
presenter.addToLibrary() presenter.addToLibrary()
} }

View File

@ -36,6 +36,7 @@ import eu.kanade.tachiyomi.data.glide.GlideApp
import eu.kanade.tachiyomi.data.notification.NotificationReceiver import eu.kanade.tachiyomi.data.notification.NotificationReceiver
import eu.kanade.tachiyomi.data.preference.PreferencesHelper import eu.kanade.tachiyomi.data.preference.PreferencesHelper
import eu.kanade.tachiyomi.data.preference.getOrDefault import eu.kanade.tachiyomi.data.preference.getOrDefault
import eu.kanade.tachiyomi.databinding.MangaInfoControllerBinding
import eu.kanade.tachiyomi.source.Source import eu.kanade.tachiyomi.source.Source
import eu.kanade.tachiyomi.source.SourceManager import eu.kanade.tachiyomi.source.SourceManager
import eu.kanade.tachiyomi.source.model.SManga import eu.kanade.tachiyomi.source.model.SManga
@ -57,20 +58,6 @@ import java.text.DateFormat
import java.text.DecimalFormat import java.text.DecimalFormat
import java.util.Date import java.util.Date
import jp.wasabeef.glide.transformations.CropSquareTransformation import jp.wasabeef.glide.transformations.CropSquareTransformation
import kotlinx.android.synthetic.main.manga_info_controller.backdrop
import kotlinx.android.synthetic.main.manga_info_controller.fab_favorite
import kotlinx.android.synthetic.main.manga_info_controller.manga_artist
import kotlinx.android.synthetic.main.manga_info_controller.manga_artist_label
import kotlinx.android.synthetic.main.manga_info_controller.manga_author
import kotlinx.android.synthetic.main.manga_info_controller.manga_chapters
import kotlinx.android.synthetic.main.manga_info_controller.manga_cover
import kotlinx.android.synthetic.main.manga_info_controller.manga_full_title
import kotlinx.android.synthetic.main.manga_info_controller.manga_genres_tags
import kotlinx.android.synthetic.main.manga_info_controller.manga_last_update
import kotlinx.android.synthetic.main.manga_info_controller.manga_source
import kotlinx.android.synthetic.main.manga_info_controller.manga_status
import kotlinx.android.synthetic.main.manga_info_controller.manga_summary
import kotlinx.android.synthetic.main.manga_info_controller.swipe_refresh
import uy.kohesive.injekt.Injekt import uy.kohesive.injekt.Injekt
import uy.kohesive.injekt.api.get import uy.kohesive.injekt.api.get
import uy.kohesive.injekt.injectLazy import uy.kohesive.injekt.injectLazy
@ -83,15 +70,14 @@ import uy.kohesive.injekt.injectLazy
class MangaInfoController : NucleusController<MangaInfoPresenter>(), class MangaInfoController : NucleusController<MangaInfoPresenter>(),
ChangeMangaCategoriesDialog.Listener { ChangeMangaCategoriesDialog.Listener {
/**
* Preferences helper.
*/
private val preferences: PreferencesHelper by injectLazy() private val preferences: PreferencesHelper by injectLazy()
private val dateFormat: DateFormat by lazy { private val dateFormat: DateFormat by lazy {
preferences.dateFormat().getOrDefault() preferences.dateFormat().getOrDefault()
} }
private lateinit var binding: MangaInfoControllerBinding
init { init {
setHasOptionsMenu(true) setHasOptionsMenu(true)
setOptionsMenuHidden(true) setOptionsMenuHidden(true)
@ -104,50 +90,51 @@ class MangaInfoController : NucleusController<MangaInfoPresenter>(),
} }
override fun inflateView(inflater: LayoutInflater, container: ViewGroup): View { override fun inflateView(inflater: LayoutInflater, container: ViewGroup): View {
return inflater.inflate(R.layout.manga_info_controller, container, false) binding = MangaInfoControllerBinding.inflate(inflater)
return binding.root
} }
override fun onViewCreated(view: View) { override fun onViewCreated(view: View) {
super.onViewCreated(view) super.onViewCreated(view)
// Set onclickListener to toggle favorite when FAB clicked. // Set onclickListener to toggle favorite when FAB clicked.
fab_favorite.clicks().subscribeUntilDestroy { onFabClick() } binding.fabFavorite.clicks().subscribeUntilDestroy { onFabClick() }
// Set onLongClickListener to manage categories when FAB is clicked. // Set onLongClickListener to manage categories when FAB is clicked.
fab_favorite.longClicks().subscribeUntilDestroy { onFabLongClick() } binding.fabFavorite.longClicks().subscribeUntilDestroy { onFabLongClick() }
// Set SwipeRefresh to refresh manga data. // Set SwipeRefresh to refresh manga data.
swipe_refresh.refreshes().subscribeUntilDestroy { fetchMangaFromSource() } binding.swipeRefresh.refreshes().subscribeUntilDestroy { fetchMangaFromSource() }
manga_full_title.longClicks().subscribeUntilDestroy { binding.mangaFullTitle.longClicks().subscribeUntilDestroy {
copyToClipboard(view.context.getString(R.string.title), manga_full_title.text.toString()) copyToClipboard(view.context.getString(R.string.title), binding.mangaFullTitle.text.toString())
} }
manga_full_title.clicks().subscribeUntilDestroy { binding.mangaFullTitle.clicks().subscribeUntilDestroy {
performGlobalSearch(manga_full_title.text.toString()) performGlobalSearch(binding.mangaFullTitle.text.toString())
} }
manga_artist.longClicks().subscribeUntilDestroy { binding.mangaArtist.longClicks().subscribeUntilDestroy {
copyToClipboard(manga_artist_label.text.toString(), manga_artist.text.toString()) copyToClipboard(binding.mangaArtistLabel.text.toString(), binding.mangaArtist.text.toString())
} }
manga_artist.clicks().subscribeUntilDestroy { binding.mangaArtist.clicks().subscribeUntilDestroy {
performGlobalSearch(manga_artist.text.toString()) performGlobalSearch(binding.mangaArtist.text.toString())
} }
manga_author.longClicks().subscribeUntilDestroy { binding.mangaAuthor.longClicks().subscribeUntilDestroy {
copyToClipboard(manga_author.text.toString(), manga_author.text.toString()) copyToClipboard(binding.mangaAuthor.text.toString(), binding.mangaAuthor.text.toString())
} }
manga_author.clicks().subscribeUntilDestroy { binding.mangaAuthor.clicks().subscribeUntilDestroy {
performGlobalSearch(manga_author.text.toString()) performGlobalSearch(binding.mangaAuthor.text.toString())
} }
manga_summary.longClicks().subscribeUntilDestroy { binding.mangaSummary.longClicks().subscribeUntilDestroy {
copyToClipboard(view.context.getString(R.string.description), manga_summary.text.toString()) copyToClipboard(view.context.getString(R.string.description), binding.mangaSummary.text.toString())
} }
manga_cover.longClicks().subscribeUntilDestroy { binding.mangaCover.longClicks().subscribeUntilDestroy {
copyToClipboard(view.context.getString(R.string.title), presenter.manga.title) copyToClipboard(view.context.getString(R.string.title), presenter.manga.title)
} }
} }
@ -197,21 +184,21 @@ class MangaInfoController : NucleusController<MangaInfoPresenter>(),
val view = view ?: return val view = view ?: return
// update full title TextView. // update full title TextView.
manga_full_title.text = if (manga.title.isBlank()) { binding.mangaFullTitle.text = if (manga.title.isBlank()) {
view.context.getString(R.string.unknown) view.context.getString(R.string.unknown)
} else { } else {
manga.title manga.title
} }
// Update artist TextView. // Update artist TextView.
manga_artist.text = if (manga.artist.isNullOrBlank()) { binding.mangaArtist.text = if (manga.artist.isNullOrBlank()) {
view.context.getString(R.string.unknown) view.context.getString(R.string.unknown)
} else { } else {
manga.artist manga.artist
} }
// Update author TextView. // Update author TextView.
manga_author.text = if (manga.author.isNullOrBlank()) { binding.mangaAuthor.text = if (manga.author.isNullOrBlank()) {
view.context.getString(R.string.unknown) view.context.getString(R.string.unknown)
} else { } else {
manga.author manga.author
@ -219,7 +206,7 @@ class MangaInfoController : NucleusController<MangaInfoPresenter>(),
// If manga source is known update source TextView. // If manga source is known update source TextView.
val mangaSource = source?.toString() val mangaSource = source?.toString()
with(manga_source) { with(binding.mangaSource) {
if (mangaSource != null) { if (mangaSource != null) {
text = mangaSource text = mangaSource
setOnClickListener { setOnClickListener {
@ -233,7 +220,7 @@ class MangaInfoController : NucleusController<MangaInfoPresenter>(),
// Update genres list // Update genres list
if (!manga.genre.isNullOrBlank()) { if (!manga.genre.isNullOrBlank()) {
manga_genres_tags.removeAllViews() binding.mangaGenresTags.removeAllViews()
manga.genre?.split(", ")?.forEach { genre -> manga.genre?.split(", ")?.forEach { genre ->
val chip = Chip(view.context).apply { val chip = Chip(view.context).apply {
@ -241,19 +228,19 @@ class MangaInfoController : NucleusController<MangaInfoPresenter>(),
setOnClickListener { performSearch(genre) } setOnClickListener { performSearch(genre) }
} }
manga_genres_tags.addView(chip) binding.mangaGenresTags.addView(chip)
} }
} }
// Update description TextView. // Update description TextView.
manga_summary.text = if (manga.description.isNullOrBlank()) { binding.mangaSummary.text = if (manga.description.isNullOrBlank()) {
view.context.getString(R.string.unknown) view.context.getString(R.string.unknown)
} else { } else {
manga.description manga.description
} }
// Update status TextView. // Update status TextView.
manga_status.setText(when (manga.status) { binding.mangaStatus.setText(when (manga.status) {
SManga.ONGOING -> R.string.ongoing SManga.ONGOING -> R.string.ongoing
SManga.COMPLETED -> R.string.completed SManga.COMPLETED -> R.string.completed
SManga.LICENSED -> R.string.licensed SManga.LICENSED -> R.string.licensed
@ -264,19 +251,19 @@ class MangaInfoController : NucleusController<MangaInfoPresenter>(),
setFavoriteDrawable(manga.favorite) setFavoriteDrawable(manga.favorite)
// Set cover if it wasn't already. // Set cover if it wasn't already.
if (manga_cover.drawable == null && !manga.thumbnail_url.isNullOrEmpty()) { if (binding.mangaCover.drawable == null && !manga.thumbnail_url.isNullOrEmpty()) {
GlideApp.with(view.context) GlideApp.with(view.context)
.load(manga) .load(manga)
.diskCacheStrategy(DiskCacheStrategy.RESOURCE) .diskCacheStrategy(DiskCacheStrategy.RESOURCE)
.centerCrop() .centerCrop()
.into(manga_cover) .into(binding.mangaCover)
if (backdrop != null) { if (binding.backdrop != null) {
GlideApp.with(view.context) GlideApp.with(view.context)
.load(manga) .load(manga)
.diskCacheStrategy(DiskCacheStrategy.RESOURCE) .diskCacheStrategy(DiskCacheStrategy.RESOURCE)
.centerCrop() .centerCrop()
.into(backdrop) .into(binding.backdrop!!)
} }
} }
} }
@ -288,17 +275,17 @@ class MangaInfoController : NucleusController<MangaInfoPresenter>(),
*/ */
fun setChapterCount(count: Float) { fun setChapterCount(count: Float) {
if (count > 0f) { if (count > 0f) {
manga_chapters?.text = DecimalFormat("#.#").format(count) binding.mangaChapters.text = DecimalFormat("#.#").format(count)
} else { } else {
manga_chapters?.text = resources?.getString(R.string.unknown) binding.mangaChapters.text = resources?.getString(R.string.unknown)
} }
} }
fun setLastUpdateDate(date: Date) { fun setLastUpdateDate(date: Date) {
if (date.time != 0L) { if (date.time != 0L) {
manga_last_update?.text = dateFormat.format(date) binding.mangaLastUpdate.text = dateFormat.format(date)
} else { } else {
manga_last_update?.text = resources?.getString(R.string.unknown) binding.mangaLastUpdate.text = resources?.getString(R.string.unknown)
} }
} }
@ -359,7 +346,7 @@ class MangaInfoController : NucleusController<MangaInfoPresenter>(),
private fun setFavoriteDrawable(isFavorite: Boolean) { private fun setFavoriteDrawable(isFavorite: Boolean) {
// Set the Favorite drawable to the correct one. // Set the Favorite drawable to the correct one.
// Border drawable if false, filled drawable if true. // Border drawable if false, filled drawable if true.
fab_favorite?.setImageResource(if (isFavorite) binding.fabFavorite.setImageResource(if (isFavorite)
R.drawable.ic_bookmark_24dp R.drawable.ic_bookmark_24dp
else else
R.drawable.ic_add_to_library_24dp) R.drawable.ic_add_to_library_24dp)
@ -395,7 +382,7 @@ class MangaInfoController : NucleusController<MangaInfoPresenter>(),
* @param value whether it should be refreshing or not. * @param value whether it should be refreshing or not.
*/ */
private fun setRefreshing(value: Boolean) { private fun setRefreshing(value: Boolean) {
swipe_refresh?.isRefreshing = value binding.swipeRefresh.isRefreshing = value
} }
private fun onFabClick() { private fun onFabClick() {

View File

@ -9,11 +9,10 @@ import androidx.recyclerview.widget.LinearLayoutManager
import com.jakewharton.rxbinding.support.v4.widget.refreshes import com.jakewharton.rxbinding.support.v4.widget.refreshes
import eu.kanade.tachiyomi.R import eu.kanade.tachiyomi.R
import eu.kanade.tachiyomi.data.track.model.TrackSearch import eu.kanade.tachiyomi.data.track.model.TrackSearch
import eu.kanade.tachiyomi.databinding.TrackControllerBinding
import eu.kanade.tachiyomi.ui.base.controller.NucleusController import eu.kanade.tachiyomi.ui.base.controller.NucleusController
import eu.kanade.tachiyomi.ui.manga.MangaController import eu.kanade.tachiyomi.ui.manga.MangaController
import eu.kanade.tachiyomi.util.system.toast import eu.kanade.tachiyomi.util.system.toast
import kotlinx.android.synthetic.main.track_controller.swipe_refresh
import kotlinx.android.synthetic.main.track_controller.track_recycler
import timber.log.Timber import timber.log.Timber
class TrackController : NucleusController<TrackPresenter>(), class TrackController : NucleusController<TrackPresenter>(),
@ -24,6 +23,8 @@ class TrackController : NucleusController<TrackPresenter>(),
private var adapter: TrackAdapter? = null private var adapter: TrackAdapter? = null
private lateinit var binding: TrackControllerBinding
init { init {
// There's no menu, but this avoids a bug when coming from the catalogue, where the menu // There's no menu, but this avoids a bug when coming from the catalogue, where the menu
// disappears if the searchview is expanded // disappears if the searchview is expanded
@ -35,19 +36,18 @@ class TrackController : NucleusController<TrackPresenter>(),
} }
override fun inflateView(inflater: LayoutInflater, container: ViewGroup): View { override fun inflateView(inflater: LayoutInflater, container: ViewGroup): View {
return inflater.inflate(R.layout.track_controller, container, false) binding = TrackControllerBinding.inflate(inflater)
return binding.root
} }
override fun onViewCreated(view: View) { override fun onViewCreated(view: View) {
super.onViewCreated(view) super.onViewCreated(view)
adapter = TrackAdapter(this) adapter = TrackAdapter(this)
with(view) { binding.trackRecycler.layoutManager = LinearLayoutManager(view.context)
track_recycler.layoutManager = LinearLayoutManager(context) binding.trackRecycler.adapter = adapter
track_recycler.adapter = adapter binding.swipeRefresh.isEnabled = false
swipe_refresh.isEnabled = false binding.swipeRefresh.refreshes().subscribeUntilDestroy { presenter.refresh() }
swipe_refresh.refreshes().subscribeUntilDestroy { presenter.refresh() }
}
} }
override fun onDestroyView(view: View) { override fun onDestroyView(view: View) {
@ -58,7 +58,7 @@ class TrackController : NucleusController<TrackPresenter>(),
fun onNextTrackings(trackings: List<TrackItem>) { fun onNextTrackings(trackings: List<TrackItem>) {
val atLeastOneLink = trackings.any { it.track != null } val atLeastOneLink = trackings.any { it.track != null }
adapter?.items = trackings adapter?.items = trackings
swipe_refresh?.isEnabled = atLeastOneLink binding.swipeRefresh.isEnabled = atLeastOneLink
(parentController as? MangaController)?.setTrackingIcon(atLeastOneLink) (parentController as? MangaController)?.setTrackingIcon(atLeastOneLink)
} }
@ -77,11 +77,11 @@ class TrackController : NucleusController<TrackPresenter>(),
} }
fun onRefreshDone() { fun onRefreshDone() {
swipe_refresh?.isRefreshing = false binding.swipeRefresh.isRefreshing = false
} }
fun onRefreshError(error: Throwable) { fun onRefreshError(error: Throwable) {
swipe_refresh?.isRefreshing = false binding.swipeRefresh.isRefreshing = false
activity?.toast(error.message) activity?.toast(error.message)
} }
@ -123,17 +123,17 @@ class TrackController : NucleusController<TrackPresenter>(),
override fun setStatus(item: TrackItem, selection: Int) { override fun setStatus(item: TrackItem, selection: Int) {
presenter.setStatus(item, selection) presenter.setStatus(item, selection)
swipe_refresh?.isRefreshing = true binding.swipeRefresh.isRefreshing = true
} }
override fun setScore(item: TrackItem, score: Int) { override fun setScore(item: TrackItem, score: Int) {
presenter.setScore(item, score) presenter.setScore(item, score)
swipe_refresh?.isRefreshing = true binding.swipeRefresh.isRefreshing = true
} }
override fun setChaptersRead(item: TrackItem, chaptersRead: Int) { override fun setChaptersRead(item: TrackItem, chaptersRead: Int) {
presenter.setLastChapterRead(item, chaptersRead) presenter.setLastChapterRead(item, chaptersRead)
swipe_refresh?.isRefreshing = true binding.swipeRefresh.isRefreshing = true
} }
private companion object { private companion object {

View File

@ -7,9 +7,9 @@ import androidx.recyclerview.widget.LinearLayoutManager
import eu.davidea.flexibleadapter.FlexibleAdapter import eu.davidea.flexibleadapter.FlexibleAdapter
import eu.davidea.flexibleadapter.items.IFlexible import eu.davidea.flexibleadapter.items.IFlexible
import eu.kanade.tachiyomi.R import eu.kanade.tachiyomi.R
import eu.kanade.tachiyomi.databinding.MigrationControllerBinding
import eu.kanade.tachiyomi.ui.base.controller.NucleusController import eu.kanade.tachiyomi.ui.base.controller.NucleusController
import eu.kanade.tachiyomi.ui.base.controller.withFadeTransaction import eu.kanade.tachiyomi.ui.base.controller.withFadeTransaction
import kotlinx.android.synthetic.main.migration_controller.migration_recycler
class MigrationController : NucleusController<MigrationPresenter>(), class MigrationController : NucleusController<MigrationPresenter>(),
FlexibleAdapter.OnItemClickListener, FlexibleAdapter.OnItemClickListener,
@ -23,20 +23,23 @@ class MigrationController : NucleusController<MigrationPresenter>(),
setTitle() setTitle()
} }
private lateinit var binding: MigrationControllerBinding
override fun createPresenter(): MigrationPresenter { override fun createPresenter(): MigrationPresenter {
return MigrationPresenter() return MigrationPresenter()
} }
override fun inflateView(inflater: LayoutInflater, container: ViewGroup): View { override fun inflateView(inflater: LayoutInflater, container: ViewGroup): View {
return inflater.inflate(R.layout.migration_controller, container, false) binding = MigrationControllerBinding.inflate(inflater)
return binding.root
} }
override fun onViewCreated(view: View) { override fun onViewCreated(view: View) {
super.onViewCreated(view) super.onViewCreated(view)
adapter = FlexibleAdapter(null, this) adapter = FlexibleAdapter(null, this)
migration_recycler.layoutManager = LinearLayoutManager(view.context) binding.migrationRecycler.layoutManager = LinearLayoutManager(view.context)
migration_recycler.adapter = adapter binding.migrationRecycler.adapter = adapter
} }
override fun onDestroyView(view: View) { override fun onDestroyView(view: View) {
@ -62,14 +65,14 @@ class MigrationController : NucleusController<MigrationPresenter>(),
title = resources?.getString(R.string.label_migration) title = resources?.getString(R.string.label_migration)
if (adapter !is SourceAdapter) { if (adapter !is SourceAdapter) {
adapter = SourceAdapter(this) adapter = SourceAdapter(this)
migration_recycler.adapter = adapter binding.migrationRecycler.adapter = adapter
} }
adapter?.updateDataSet(state.sourcesWithManga) adapter?.updateDataSet(state.sourcesWithManga)
} else { } else {
title = state.selectedSource.toString() title = state.selectedSource.toString()
if (adapter !is MangaAdapter) { if (adapter !is MangaAdapter) {
adapter = MangaAdapter(this) adapter = MangaAdapter(this)
migration_recycler.adapter = adapter binding.migrationRecycler.adapter = adapter
} }
adapter?.updateDataSet(state.mangaForSource) adapter?.updateDataSet(state.mangaForSource)
} }

View File

@ -84,9 +84,6 @@ import uy.kohesive.injekt.injectLazy
@RequiresPresenter(ReaderPresenter::class) @RequiresPresenter(ReaderPresenter::class)
class ReaderActivity : BaseRxActivity<ReaderPresenter>() { class ReaderActivity : BaseRxActivity<ReaderPresenter>() {
/**
* Preferences helper.
*/
private val preferences by injectLazy<PreferencesHelper>() private val preferences by injectLazy<PreferencesHelper>()
/** /**

View File

@ -38,9 +38,6 @@ import uy.kohesive.injekt.injectLazy
*/ */
class ReaderSettingsSheet(private val activity: ReaderActivity) : BottomSheetDialog(activity) { class ReaderSettingsSheet(private val activity: ReaderActivity) : BottomSheetDialog(activity) {
/**
* Preferences helper.
*/
private val preferences by injectLazy<PreferencesHelper>() private val preferences by injectLazy<PreferencesHelper>()
init { init {

View File

@ -8,6 +8,7 @@ import eu.davidea.flexibleadapter.FlexibleAdapter
import eu.kanade.tachiyomi.R import eu.kanade.tachiyomi.R
import eu.kanade.tachiyomi.data.database.models.History import eu.kanade.tachiyomi.data.database.models.History
import eu.kanade.tachiyomi.data.database.models.Manga import eu.kanade.tachiyomi.data.database.models.Manga
import eu.kanade.tachiyomi.databinding.HistoryControllerBinding
import eu.kanade.tachiyomi.ui.base.controller.NoToolbarElevationController import eu.kanade.tachiyomi.ui.base.controller.NoToolbarElevationController
import eu.kanade.tachiyomi.ui.base.controller.NucleusController import eu.kanade.tachiyomi.ui.base.controller.NucleusController
import eu.kanade.tachiyomi.ui.base.controller.RootController import eu.kanade.tachiyomi.ui.base.controller.RootController
@ -15,8 +16,6 @@ import eu.kanade.tachiyomi.ui.base.controller.withFadeTransaction
import eu.kanade.tachiyomi.ui.manga.MangaController import eu.kanade.tachiyomi.ui.manga.MangaController
import eu.kanade.tachiyomi.ui.reader.ReaderActivity import eu.kanade.tachiyomi.ui.reader.ReaderActivity
import eu.kanade.tachiyomi.util.system.toast import eu.kanade.tachiyomi.util.system.toast
import kotlinx.android.synthetic.main.history_controller.empty_view
import kotlinx.android.synthetic.main.history_controller.recycler
/** /**
* Fragment that shows recently read manga. * Fragment that shows recently read manga.
@ -38,6 +37,8 @@ class HistoryController : NucleusController<HistoryPresenter>(),
var adapter: HistoryAdapter? = null var adapter: HistoryAdapter? = null
private set private set
private lateinit var binding: HistoryControllerBinding
override fun getTitle(): String? { override fun getTitle(): String? {
return resources?.getString(R.string.label_recent_manga) return resources?.getString(R.string.label_recent_manga)
} }
@ -47,7 +48,8 @@ class HistoryController : NucleusController<HistoryPresenter>(),
} }
override fun inflateView(inflater: LayoutInflater, container: ViewGroup): View { override fun inflateView(inflater: LayoutInflater, container: ViewGroup): View {
return inflater.inflate(R.layout.history_controller, container, false) binding = HistoryControllerBinding.inflate(inflater)
return binding.root
} }
/** /**
@ -59,10 +61,10 @@ class HistoryController : NucleusController<HistoryPresenter>(),
super.onViewCreated(view) super.onViewCreated(view)
// Initialize adapter // Initialize adapter
recycler.layoutManager = LinearLayoutManager(view.context) binding.recycler.layoutManager = LinearLayoutManager(view.context)
adapter = HistoryAdapter(this@HistoryController) adapter = HistoryAdapter(this@HistoryController)
recycler.setHasFixedSize(true) binding.recycler.setHasFixedSize(true)
recycler.adapter = adapter binding.recycler.adapter = adapter
} }
override fun onDestroyView(view: View) { override fun onDestroyView(view: View) {
@ -81,9 +83,9 @@ class HistoryController : NucleusController<HistoryPresenter>(),
override fun onUpdateEmptyView(size: Int) { override fun onUpdateEmptyView(size: Int) {
if (size > 0) { if (size > 0) {
empty_view.hide() binding.emptyView.hide()
} else { } else {
empty_view.show(R.string.information_no_recent_manga) binding.emptyView.show(R.string.information_no_recent_manga)
} }
} }

View File

@ -19,6 +19,7 @@ import eu.kanade.tachiyomi.R
import eu.kanade.tachiyomi.data.download.model.Download import eu.kanade.tachiyomi.data.download.model.Download
import eu.kanade.tachiyomi.data.library.LibraryUpdateService import eu.kanade.tachiyomi.data.library.LibraryUpdateService
import eu.kanade.tachiyomi.data.notification.Notifications import eu.kanade.tachiyomi.data.notification.Notifications
import eu.kanade.tachiyomi.databinding.UpdatesControllerBinding
import eu.kanade.tachiyomi.ui.base.controller.NoToolbarElevationController import eu.kanade.tachiyomi.ui.base.controller.NoToolbarElevationController
import eu.kanade.tachiyomi.ui.base.controller.NucleusController import eu.kanade.tachiyomi.ui.base.controller.NucleusController
import eu.kanade.tachiyomi.ui.base.controller.RootController import eu.kanade.tachiyomi.ui.base.controller.RootController
@ -28,10 +29,6 @@ import eu.kanade.tachiyomi.ui.manga.MangaController
import eu.kanade.tachiyomi.ui.reader.ReaderActivity import eu.kanade.tachiyomi.ui.reader.ReaderActivity
import eu.kanade.tachiyomi.util.system.notificationManager import eu.kanade.tachiyomi.util.system.notificationManager
import eu.kanade.tachiyomi.util.system.toast import eu.kanade.tachiyomi.util.system.toast
import kotlinx.android.synthetic.main.updates_controller.action_toolbar
import kotlinx.android.synthetic.main.updates_controller.empty_view
import kotlinx.android.synthetic.main.updates_controller.recycler
import kotlinx.android.synthetic.main.updates_controller.swipe_refresh
import timber.log.Timber import timber.log.Timber
/** /**
@ -60,6 +57,8 @@ class UpdatesController : NucleusController<UpdatesPresenter>(),
var adapter: UpdatesAdapter? = null var adapter: UpdatesAdapter? = null
private set private set
private lateinit var binding: UpdatesControllerBinding
init { init {
setHasOptionsMenu(true) setHasOptionsMenu(true)
} }
@ -73,7 +72,8 @@ class UpdatesController : NucleusController<UpdatesPresenter>(),
} }
override fun inflateView(inflater: LayoutInflater, container: ViewGroup): View { override fun inflateView(inflater: LayoutInflater, container: ViewGroup): View {
return inflater.inflate(R.layout.updates_controller, container, false) binding = UpdatesControllerBinding.inflate(inflater)
return binding.root
} }
/** /**
@ -83,32 +83,33 @@ class UpdatesController : NucleusController<UpdatesPresenter>(),
override fun onViewCreated(view: View) { override fun onViewCreated(view: View) {
super.onViewCreated(view) super.onViewCreated(view)
view.context.notificationManager.cancel(Notifications.ID_NEW_CHAPTERS) view.context.notificationManager.cancel(Notifications.ID_NEW_CHAPTERS)
// Init RecyclerView and adapter // Init RecyclerView and adapter
val layoutManager = LinearLayoutManager(view.context) val layoutManager = LinearLayoutManager(view.context)
recycler.layoutManager = layoutManager binding.recycler.layoutManager = layoutManager
recycler.addItemDecoration(DividerItemDecoration(view.context, DividerItemDecoration.VERTICAL)) binding.recycler.addItemDecoration(DividerItemDecoration(view.context, DividerItemDecoration.VERTICAL))
recycler.setHasFixedSize(true) binding.recycler.setHasFixedSize(true)
adapter = UpdatesAdapter(this@UpdatesController) adapter = UpdatesAdapter(this@UpdatesController)
recycler.adapter = adapter binding.recycler.adapter = adapter
recycler.scrollStateChanges().subscribeUntilDestroy { binding.recycler.scrollStateChanges().subscribeUntilDestroy {
// Disable swipe refresh when view is not at the top // Disable swipe refresh when view is not at the top
val firstPos = layoutManager.findFirstCompletelyVisibleItemPosition() val firstPos = layoutManager.findFirstCompletelyVisibleItemPosition()
swipe_refresh.isEnabled = firstPos <= 0 binding.swipeRefresh.isEnabled = firstPos <= 0
} }
swipe_refresh.setDistanceToTriggerSync((2 * 64 * view.resources.displayMetrics.density).toInt()) binding.swipeRefresh.setDistanceToTriggerSync((2 * 64 * view.resources.displayMetrics.density).toInt())
swipe_refresh.refreshes().subscribeUntilDestroy { binding.swipeRefresh.refreshes().subscribeUntilDestroy {
updateLibrary() updateLibrary()
// It can be a very long operation, so we disable swipe refresh and show a toast. // It can be a very long operation, so we disable swipe refresh and show a toast.
swipe_refresh.isRefreshing = false binding.swipeRefresh.isRefreshing = false
} }
} }
override fun onDestroyView(view: View) { override fun onDestroyView(view: View) {
destroyActionModeIfNeeded() destroyActionModeIfNeeded()
action_toolbar.destroy() binding.actionToolbar.destroy()
adapter = null adapter = null
super.onDestroyView(view) super.onDestroyView(view)
} }
@ -167,7 +168,7 @@ class UpdatesController : NucleusController<UpdatesPresenter>(),
override fun onItemLongClick(position: Int) { override fun onItemLongClick(position: Int) {
if (actionMode == null) { if (actionMode == null) {
actionMode = (activity as AppCompatActivity).startSupportActionMode(this) actionMode = (activity as AppCompatActivity).startSupportActionMode(this)
action_toolbar.show( binding.actionToolbar.show(
actionMode!!, actionMode!!,
R.menu.updates_chapter_selection R.menu.updates_chapter_selection
) { onActionItemClicked(actionMode!!, it!!) } ) { onActionItemClicked(actionMode!!, it!!) }
@ -215,9 +216,9 @@ class UpdatesController : NucleusController<UpdatesPresenter>(),
override fun onUpdateEmptyView(size: Int) { override fun onUpdateEmptyView(size: Int) {
if (size > 0) { if (size > 0) {
empty_view?.hide() binding.emptyView.hide()
} else { } else {
empty_view?.show(R.string.information_no_recent) binding.emptyView.show(R.string.information_no_recent)
} }
} }
@ -234,7 +235,7 @@ class UpdatesController : NucleusController<UpdatesPresenter>(),
* @param download [Download] object containing download progress. * @param download [Download] object containing download progress.
*/ */
private fun getHolder(download: Download): UpdatesHolder? { private fun getHolder(download: Download): UpdatesHolder? {
return recycler?.findViewHolderForItemId(download.chapter.id!!) as? UpdatesHolder return binding.recycler.findViewHolderForItemId(download.chapter.id!!) as? UpdatesHolder
} }
/** /**
@ -321,10 +322,10 @@ class UpdatesController : NucleusController<UpdatesPresenter>(),
mode.title = count.toString() mode.title = count.toString()
val chapters = getSelectedChapters() val chapters = getSelectedChapters()
action_toolbar.findItem(R.id.action_download)?.isVisible = chapters.any { !it.isDownloaded } binding.actionToolbar.findItem(R.id.action_download)?.isVisible = chapters.any { !it.isDownloaded }
action_toolbar.findItem(R.id.action_delete)?.isVisible = chapters.any { it.isDownloaded } binding.actionToolbar.findItem(R.id.action_delete)?.isVisible = chapters.any { it.isDownloaded }
action_toolbar.findItem(R.id.action_mark_as_read)?.isVisible = chapters.any { !it.chapter.read } binding.actionToolbar.findItem(R.id.action_mark_as_read)?.isVisible = chapters.any { !it.chapter.read }
action_toolbar.findItem(R.id.action_mark_as_unread)?.isVisible = chapters.all { it.chapter.read } binding.actionToolbar.findItem(R.id.action_mark_as_unread)?.isVisible = chapters.all { it.chapter.read }
} }
return false return false
@ -354,7 +355,7 @@ class UpdatesController : NucleusController<UpdatesPresenter>(),
* @param mode the ActionMode object * @param mode the ActionMode object
*/ */
override fun onDestroyActionMode(mode: ActionMode?) { override fun onDestroyActionMode(mode: ActionMode?) {
action_toolbar.hide() binding.actionToolbar.hide()
adapter?.mode = SelectableAdapter.Mode.IDLE adapter?.mode = SelectableAdapter.Mode.IDLE
adapter?.clearSelection() adapter?.clearSelection()
actionMode = null actionMode = null

View File

@ -16,14 +16,8 @@ import uy.kohesive.injekt.injectLazy
@Suppress("DEPRECATION") @Suppress("DEPRECATION")
object LocaleHelper { object LocaleHelper {
/**
* Preferences helper.
*/
private val preferences: PreferencesHelper by injectLazy() private val preferences: PreferencesHelper by injectLazy()
/**
* The system's locale.
*/
private var systemLocale: Locale? = null private var systemLocale: Locale? = null
/** /**