Binding Dialogs

I wish I could see the light at the end of the tunnel
This commit is contained in:
Jays2Kings 2021-03-29 21:46:54 -04:00
parent 5845912aaf
commit aba58f70c4
6 changed files with 111 additions and 125 deletions

View File

@ -2,10 +2,10 @@ package eu.kanade.tachiyomi.ui.category
import android.app.Dialog
import android.os.Bundle
import android.view.View
import android.widget.CompoundButton
import com.afollestad.materialdialogs.MaterialDialog
import com.afollestad.materialdialogs.customview.customView
import com.afollestad.materialdialogs.customview.getCustomView
import com.tfcporciuncula.flow.Preference
import eu.kanade.tachiyomi.R
import eu.kanade.tachiyomi.data.database.DatabaseHelper
@ -36,22 +36,21 @@ class ManageCategoryDialog(bundle: Bundle? = null) :
private val preferences by injectLazy<PreferencesHelper>()
private val db by injectLazy<DatabaseHelper>()
var binding: MangaCategoryDialogBinding? = null
lateinit var binding: MangaCategoryDialogBinding
override fun onCreateDialog(savedViewState: Bundle?): Dialog {
binding = MangaCategoryDialogBinding.inflate(activity!!.layoutInflater)
val dialog = MaterialDialog(activity!!).apply {
title(R.string.manage_category)
customView(view = binding!!.root)
customView(viewRes = R.layout.manga_category_dialog)
negativeButton(android.R.string.cancel)
positiveButton(R.string.save) { onPositiveButtonClick() }
}
onViewCreated(dialog.view)
binding = MangaCategoryDialogBinding.bind(dialog.getCustomView())
onViewCreated()
return dialog
}
private fun onPositiveButtonClick() {
val binding = binding ?: return
val category = category ?: return
if (category.id ?: 0 <= 0) return
val text = binding.title.text.toString()
@ -85,8 +84,7 @@ class ManageCategoryDialog(bundle: Bundle? = null) :
}
}
fun onViewCreated(view: View) {
val binding = binding ?: return
fun onViewCreated() {
val category = category ?: return
if (category.id ?: 0 <= 0) {
binding.title.gone()
@ -133,11 +131,6 @@ class ManageCategoryDialog(bundle: Bundle? = null) :
return updateCategories.isNotEmpty()
}
override fun onDestroyView(view: View) {
super.onDestroyView(view)
binding = null
}
private fun setCheckbox(
box: CompoundButton,
categories: Preference<Set<String>>,

View File

@ -3,33 +3,33 @@ package eu.kanade.tachiyomi.ui.manga
import android.app.Dialog
import android.net.Uri
import android.os.Bundle
import android.view.View
import coil.api.loadAny
import coil.request.Parameters
import com.afollestad.materialdialogs.MaterialDialog
import com.afollestad.materialdialogs.customview.customView
import com.afollestad.materialdialogs.customview.getCustomView
import eu.kanade.tachiyomi.R
import eu.kanade.tachiyomi.data.database.DatabaseHelper
import eu.kanade.tachiyomi.data.database.models.Manga
import eu.kanade.tachiyomi.data.image.coil.MangaFetcher
import eu.kanade.tachiyomi.databinding.EditMangaDialogBinding
import eu.kanade.tachiyomi.source.LocalSource
import eu.kanade.tachiyomi.ui.base.controller.DialogController
import eu.kanade.tachiyomi.util.lang.chop
import eu.kanade.tachiyomi.util.view.visibleIf
import kotlinx.android.synthetic.main.edit_manga_dialog.view.*
import uy.kohesive.injekt.Injekt
import uy.kohesive.injekt.api.get
class EditMangaDialog : DialogController {
private var dialogView: View? = null
private val manga: Manga
private var customCoverUri: Uri? = null
private var willResetCover = false
lateinit var binding: EditMangaDialogBinding
private val infoController
get() = targetController as MangaDetailsController
@ -55,8 +55,8 @@ class EditMangaDialog : DialogController {
negativeButton(android.R.string.cancel)
positiveButton(R.string.save) { onPositiveButtonClick() }
}
dialogView = dialog.view
onViewCreated(dialog.view)
binding = EditMangaDialogBinding.bind(dialog.getCustomView())
onViewCreated()
dialog.setOnShowListener {
val dView = (it as? MaterialDialog)?.view
dView?.contentLayout?.scrollView?.scrollTo(0, 0)
@ -64,57 +64,57 @@ class EditMangaDialog : DialogController {
return dialog
}
fun onViewCreated(view: View) {
view.manga_cover.loadAny(manga)
fun onViewCreated() {
binding.mangaCover.loadAny(manga)
val isLocal = manga.source == LocalSource.ID
if (isLocal) {
if (manga.title != manga.url) {
view.title.append(manga.title)
binding.title.append(manga.title)
}
view.title.hint = "${resources?.getString(R.string.title)}: ${manga.url}"
view.manga_author.append(manga.author ?: "")
view.manga_artist.append(manga.artist ?: "")
view.manga_description.append(manga.description ?: "")
view.manga_genres_tags.setTags(manga.genre?.split(", ") ?: emptyList())
binding.title.hint = "${resources?.getString(R.string.title)}: ${manga.url}"
binding.mangaAuthor.append(manga.author ?: "")
binding.mangaArtist.append(manga.artist ?: "")
binding.mangaDescription.append(manga.description ?: "")
binding.mangaGenresTags.setTags(manga.genre?.split(", ") ?: emptyList())
} else {
if (manga.title != manga.originalTitle) {
view.title.append(manga.title)
binding.title.append(manga.title)
}
if (manga.author != manga.originalAuthor) {
view.manga_author.append(manga.author ?: "")
binding.mangaAuthor.append(manga.author ?: "")
}
if (manga.artist != manga.originalArtist) {
view.manga_artist.append(manga.artist ?: "")
binding.mangaArtist.append(manga.artist ?: "")
}
if (manga.description != manga.originalDescription) {
view.manga_description.append(manga.description ?: "")
binding.mangaDescription.append(manga.description ?: "")
}
view.manga_genres_tags.setTags(manga.genre?.split(", ") ?: emptyList())
binding.mangaGenresTags.setTags(manga.genre?.split(", ") ?: emptyList())
view.title.hint = "${resources?.getString(R.string.title)}: ${manga.originalTitle}"
binding.title.hint = "${resources?.getString(R.string.title)}: ${manga.originalTitle}"
if (manga.originalAuthor != null) {
view.manga_author.hint = "${resources?.getString(R.string.author)}: ${manga.originalAuthor}"
binding.mangaAuthor.hint = "${resources?.getString(R.string.author)}: ${manga.originalAuthor}"
}
if (manga.originalArtist != null) {
view.manga_artist.hint = "${resources?.getString(R.string.artist)}: ${manga.originalArtist}"
binding.mangaArtist.hint = "${resources?.getString(R.string.artist)}: ${manga.originalArtist}"
}
if (manga.originalDescription != null) {
view.manga_description.hint =
binding.mangaDescription.hint =
"${resources?.getString(R.string.description)}: ${manga.originalDescription?.replace(
"\n",
" "
)?.chop(20)}"
}
}
view.manga_genres_tags.clearFocus()
view.cover_layout.setOnClickListener {
binding.mangaGenresTags.clearFocus()
binding.coverLayout.setOnClickListener {
infoController.changeCover()
}
view.reset_tags.setOnClickListener { resetTags() }
view.reset_cover.visibleIf(!isLocal)
view.reset_cover.setOnClickListener {
view.manga_cover.loadAny(
binding.resetTags.setOnClickListener { resetTags() }
binding.resetCover.visibleIf(!isLocal)
binding.resetCover.setOnClickListener {
binding.mangaCover.loadAny(
manga,
builder = {
parameters(Parameters.Builder().set(MangaFetcher.realCover, true).build())
@ -125,31 +125,26 @@ class EditMangaDialog : DialogController {
}
private fun resetTags() {
if (manga.genre.isNullOrBlank() || manga.source == LocalSource.ID) dialogView?.manga_genres_tags?.setTags(
if (manga.genre.isNullOrBlank() || manga.source == LocalSource.ID) binding.mangaGenresTags.setTags(
emptyList()
)
else dialogView?.manga_genres_tags?.setTags(manga.originalGenre?.split(", "))
else binding.mangaGenresTags.setTags(manga.originalGenre?.split(", "))
}
fun updateCover(uri: Uri) {
willResetCover = false
dialogView!!.manga_cover.loadAny(uri)
binding.mangaCover.loadAny(uri)
customCoverUri = uri
}
override fun onDestroyView(view: View) {
super.onDestroyView(view)
dialogView = null
}
private fun onPositiveButtonClick() {
infoController.presenter.updateManga(
dialogView?.title?.text.toString(),
dialogView?.manga_author?.text.toString(),
dialogView?.manga_artist?.text.toString(),
binding.title.text.toString(),
binding.mangaAuthor.text.toString(),
binding.mangaArtist.text.toString(),
customCoverUri,
dialogView?.manga_description?.text.toString(),
dialogView?.manga_genres_tags?.tags,
binding.mangaDescription.text.toString(),
binding.mangaGenresTags.tags,
willResetCover
)
}

View File

@ -5,6 +5,7 @@ import android.os.Bundle
import android.view.View
import com.afollestad.materialdialogs.MaterialDialog
import com.afollestad.materialdialogs.customview.customView
import com.afollestad.materialdialogs.customview.getCustomView
import com.jakewharton.rxbinding.widget.itemClicks
import com.jakewharton.rxbinding.widget.textChanges
import eu.kanade.tachiyomi.R
@ -12,10 +13,10 @@ import eu.kanade.tachiyomi.data.database.models.Track
import eu.kanade.tachiyomi.data.track.TrackManager
import eu.kanade.tachiyomi.data.track.TrackService
import eu.kanade.tachiyomi.data.track.model.TrackSearch
import eu.kanade.tachiyomi.databinding.TrackSearchDialogBinding
import eu.kanade.tachiyomi.ui.base.controller.DialogController
import eu.kanade.tachiyomi.ui.manga.MangaDetailsPresenter
import eu.kanade.tachiyomi.util.lang.plusAssign
import kotlinx.android.synthetic.main.track_search_dialog.view.*
import rx.Subscription
import rx.android.schedulers.AndroidSchedulers
import rx.subscriptions.CompositeSubscription
@ -25,8 +26,6 @@ import java.util.concurrent.TimeUnit
class TrackSearchDialog : DialogController {
private var dialogView: View? = null
private var adapter: TrackSearchAdapter? = null
private var selectedItem: Track? = null
@ -42,6 +41,7 @@ class TrackSearchDialog : DialogController {
private var wasPreviouslyTracked: Boolean = false
private lateinit var presenter: MangaDetailsPresenter
lateinit var binding: TrackSearchDialogBinding
constructor(target: TrackingBottomSheet, service: TrackService, wasTracked: Boolean) : super(
Bundle()
@ -66,33 +66,32 @@ class TrackSearchDialog : DialogController {
negativeButton(android.R.string.cancel)
}
binding = TrackSearchDialogBinding.bind(dialog.getCustomView())
if (subscriptions.isUnsubscribed) {
subscriptions = CompositeSubscription()
}
dialogView = dialog.view
onViewCreated(dialog.view, savedViewState)
onViewCreated(savedViewState)
return dialog
}
fun onViewCreated(view: View, savedState: Bundle?) {
fun onViewCreated(savedState: Bundle?) {
// Create adapter
val adapter = TrackSearchAdapter(view.context)
val adapter = TrackSearchAdapter(binding.root.context)
this.adapter = adapter
view.track_search_list.adapter = adapter
binding.trackSearchList.adapter = adapter
// Set listeners
selectedItem = null
subscriptions += view.track_search_list.itemClicks().subscribe { position ->
subscriptions += binding.trackSearchList.itemClicks().subscribe { position ->
trackItem(position)
}
// Do an initial search based on the manga's title
if (savedState == null) {
val title = presenter.manga.title
view.track_search.append(title)
binding.trackSearch.append(title)
search(title)
}
}
@ -107,13 +106,12 @@ class TrackSearchDialog : DialogController {
override fun onDestroyView(view: View) {
super.onDestroyView(view)
subscriptions.unsubscribe()
dialogView = null
adapter = null
}
override fun onAttach(view: View) {
super.onAttach(view)
searchTextSubscription = dialogView!!.track_search.textChanges()
searchTextSubscription = binding.trackSearch.textChanges()
.skip(1)
.debounce(1, TimeUnit.SECONDS, AndroidSchedulers.mainThread())
.map { it.toString() }
@ -127,17 +125,15 @@ class TrackSearchDialog : DialogController {
}
private fun search(query: String) {
val view = dialogView ?: return
view.progress.visibility = View.VISIBLE
view.track_search_list.visibility = View.INVISIBLE
binding.progress.visibility = View.VISIBLE
binding.trackSearchList.visibility = View.INVISIBLE
presenter.trackSearch(query, service)
}
fun onSearchResults(results: List<TrackSearch>) {
selectedItem = null
val view = dialogView ?: return
view.progress.visibility = View.INVISIBLE
view.track_search_list.visibility = View.VISIBLE
binding.progress.visibility = View.INVISIBLE
binding.trackSearchList.visibility = View.VISIBLE
adapter?.setItems(results)
if (results.size == 1 && !wasPreviouslyTracked) {
trackItem(0)
@ -145,9 +141,8 @@ class TrackSearchDialog : DialogController {
}
fun onSearchResultsError() {
val view = dialogView ?: return
view.progress.visibility = View.VISIBLE
view.track_search_list.visibility = View.INVISIBLE
binding.progress.visibility = View.VISIBLE
binding.trackSearchList.visibility = View.INVISIBLE
adapter?.setItems(emptyList())
}

View File

@ -15,6 +15,7 @@ import com.google.android.material.bottomsheet.BottomSheetDialog
import eu.kanade.tachiyomi.R
import eu.kanade.tachiyomi.data.preference.PreferencesHelper
import eu.kanade.tachiyomi.data.preference.getOrDefault
import eu.kanade.tachiyomi.databinding.MigrationBottomSheetBinding
import eu.kanade.tachiyomi.ui.migration.MigrationFlags
import eu.kanade.tachiyomi.util.system.dpToPx
import eu.kanade.tachiyomi.util.system.toast
@ -22,7 +23,6 @@ import eu.kanade.tachiyomi.util.view.gone
import eu.kanade.tachiyomi.util.view.setBottomEdge
import eu.kanade.tachiyomi.util.view.setEdgeToEdge
import eu.kanade.tachiyomi.util.view.visible
import kotlinx.android.synthetic.main.migration_bottom_sheet.*
import uy.kohesive.injekt.injectLazy
class MigrationBottomSheetDialog(
@ -35,36 +35,36 @@ class MigrationBottomSheetDialog(
*/
private val preferences by injectLazy<PreferencesHelper>()
private val binding = MigrationBottomSheetBinding.inflate(activity.layoutInflater)
init {
val view = activity.layoutInflater.inflate(R.layout.migration_bottom_sheet, null)
setContentView(view)
// Use activity theme for this layout
setContentView(binding.root)
if (activity.resources.configuration?.orientation == Configuration.ORIENTATION_LANDSCAPE) {
sourceGroup.orientation = LinearLayout.HORIZONTAL
val params = skip_step.layoutParams as ConstraintLayout.LayoutParams
binding.sourceGroup.orientation = LinearLayout.HORIZONTAL
val params = binding.skipStep.layoutParams as ConstraintLayout.LayoutParams
params.apply {
topToBottom = -1
startToStart = -1
bottomToBottom = extra_search_param.id
startToEnd = extra_search_param.id
endToEnd = sourceGroup.id
topToTop = extra_search_param.id
bottomToBottom = binding.extraSearchParam.id
startToEnd = binding.extraSearchParam.id
endToEnd = binding.sourceGroup.id
topToTop = binding.extraSearchParam.id
marginStart = 16.dpToPx
}
skip_step.layoutParams = params
binding.skipStep.layoutParams = params
val params2 = extra_search_param_text.layoutParams as ConstraintLayout.LayoutParams
params2.bottomToBottom = options_layout.id
extra_search_param_text.layoutParams = params2
val params2 = binding.extraSearchParamText.layoutParams as ConstraintLayout.LayoutParams
params2.bottomToBottom = binding.optionsLayout.id
binding.extraSearchParamText.layoutParams = params2
val params3 = extra_search_param.layoutParams as ConstraintLayout.LayoutParams
val params3 = binding.extraSearchParam.layoutParams as ConstraintLayout.LayoutParams
params3.endToEnd = -1
extra_search_param.layoutParams = params3
binding.extraSearchParam.layoutParams = params3
}
setEdgeToEdge(activity, view)
setEdgeToEdge(activity, binding.root)
setBottomEdge(
if (activity.resources.configuration?.orientation == Configuration.ORIENTATION_LANDSCAPE) extra_search_param_text
else skip_step,
if (activity.resources.configuration?.orientation == Configuration.ORIENTATION_LANDSCAPE) binding.extraSearchParamText
else binding.skipStep,
activity
)
}
@ -79,10 +79,10 @@ class MigrationBottomSheetDialog(
// window?.addFlags(WindowManager.LayoutParams.FLAG_LAYOUT_NO_LIMITS)
fab.setOnClickListener {
preferences.skipPreMigration().set(skip_step.isChecked)
binding.fab.setOnClickListener {
preferences.skipPreMigration().set(binding.skipStep.isChecked)
listener.startMigration(
if (extra_search_param.isChecked && extra_search_param_text.text.isNotBlank()) extra_search_param_text.text.toString() else null
if (binding.extraSearchParam.isChecked && binding.extraSearchParamText.text.isNotBlank()) binding.extraSearchParamText.text.toString() else null
)
dismiss()
}
@ -94,26 +94,26 @@ class MigrationBottomSheetDialog(
private fun initPreferences() {
val flags = preferences.migrateFlags().getOrDefault()
mig_chapters.isChecked = MigrationFlags.hasChapters(flags)
mig_categories.isChecked = MigrationFlags.hasCategories(flags)
mig_tracking.isChecked = MigrationFlags.hasTracks(flags)
binding.migChapters.isChecked = MigrationFlags.hasChapters(flags)
binding.migCategories.isChecked = MigrationFlags.hasCategories(flags)
binding.migTracking.isChecked = MigrationFlags.hasTracks(flags)
mig_chapters.setOnCheckedChangeListener { _, _ -> setFlags() }
mig_categories.setOnCheckedChangeListener { _, _ -> setFlags() }
mig_tracking.setOnCheckedChangeListener { _, _ -> setFlags() }
binding.migChapters.setOnCheckedChangeListener { _, _ -> setFlags() }
binding.migCategories.setOnCheckedChangeListener { _, _ -> setFlags() }
binding.migTracking.setOnCheckedChangeListener { _, _ -> setFlags() }
extra_search_param_text.gone()
extra_search_param.setOnCheckedChangeListener { _, isChecked ->
binding.extraSearchParamText.gone()
binding.extraSearchParam.setOnCheckedChangeListener { _, isChecked ->
if (isChecked) {
extra_search_param_text.visible()
binding.extraSearchParamText.visible()
} else {
extra_search_param_text.gone()
binding.extraSearchParamText.gone()
}
}
sourceGroup.bindToPreference(preferences.useSourceWithMost())
binding.sourceGroup.bindToPreference(preferences.useSourceWithMost())
skip_step.isChecked = preferences.skipPreMigration().getOrDefault()
skip_step.setOnCheckedChangeListener { _, isChecked ->
binding.skipStep.isChecked = preferences.skipPreMigration().getOrDefault()
binding.skipStep.setOnCheckedChangeListener { _, isChecked ->
if (isChecked) (listener as? Controller)?.activity?.toast(
R.string.to_show_again_setting_sources,
Toast.LENGTH_LONG
@ -123,9 +123,9 @@ class MigrationBottomSheetDialog(
private fun setFlags() {
var flags = 0
if (mig_chapters.isChecked) flags = flags or MigrationFlags.CHAPTERS
if (mig_categories.isChecked) flags = flags or MigrationFlags.CATEGORIES
if (mig_tracking.isChecked) flags = flags or MigrationFlags.TRACK
if (binding.migChapters.isChecked) flags = flags or MigrationFlags.CHAPTERS
if (binding.migCategories.isChecked) flags = flags or MigrationFlags.CATEGORIES
if (binding.migTracking.isChecked) flags = flags or MigrationFlags.TRACK
preferences.migrateFlags().set(flags)
}

View File

@ -6,10 +6,12 @@ import android.view.View
import androidx.annotation.StringRes
import com.afollestad.materialdialogs.MaterialDialog
import com.afollestad.materialdialogs.customview.customView
import com.afollestad.materialdialogs.customview.getCustomView
import com.bluelinelabs.conductor.ControllerChangeHandler
import com.bluelinelabs.conductor.ControllerChangeType
import eu.kanade.tachiyomi.R
import eu.kanade.tachiyomi.data.preference.PreferencesHelper
import eu.kanade.tachiyomi.databinding.PrefAccountLoginBinding
import eu.kanade.tachiyomi.ui.base.controller.DialogController
import kotlinx.android.synthetic.main.pref_account_login.view.*
import kotlinx.coroutines.CoroutineScope
@ -28,6 +30,7 @@ abstract class LoginDialogPreference(
var v: View? = null
private set
protected lateinit var binding: PrefAccountLoginBinding
val preferences: PreferencesHelper by injectLazy()
val scope = CoroutineScope(Job() + Dispatchers.Main)
@ -40,6 +43,7 @@ abstract class LoginDialogPreference(
val dialog = MaterialDialog(activity!!).apply {
customView(R.layout.pref_account_login, scrollable = false)
}
binding = PrefAccountLoginBinding.bind(dialog.getCustomView())
onViewCreated(dialog.view)

View File

@ -8,7 +8,6 @@ import eu.kanade.tachiyomi.R
import eu.kanade.tachiyomi.data.track.TrackManager
import eu.kanade.tachiyomi.data.track.TrackService
import eu.kanade.tachiyomi.util.system.toast
import kotlinx.android.synthetic.main.pref_account_login.view.*
import kotlinx.coroutines.launch
import uy.kohesive.injekt.Injekt
import uy.kohesive.injekt.api.get
@ -25,18 +24,18 @@ class TrackLoginDialog(@StringRes usernameLabelRes: Int? = null, bundle: Bundle?
override fun setCredentialsOnView(view: View) = with(view) {
val serviceName = context.getString(service.nameRes())
dialog_title.text = context.getString(R.string.log_in_to_, serviceName)
username.setText(service.getUsername())
password.setText(service.getPassword())
binding.dialogTitle.text = context.getString(R.string.log_in_to_, serviceName)
binding.username.setText(service.getUsername())
binding.password.setText(service.getPassword())
}
override fun checkLogin() {
v?.apply {
login.apply {
binding.login.apply {
progressType = ProgressType.INDETERMINATE
startAnimation()
}
if (username.text.isNullOrBlank() || password.text.isNullOrBlank()) {
if (binding.username.text.isNullOrBlank() || binding.password.text.isNullOrBlank()) {
errorResult()
context.toast(R.string.username_must_not_be_blank)
return
@ -44,8 +43,8 @@ class TrackLoginDialog(@StringRes usernameLabelRes: Int? = null, bundle: Bundle?
dialog?.setCancelable(false)
dialog?.setCanceledOnTouchOutside(false)
val user = username.text.toString()
val pass = password.text.toString()
val user = binding.username.text.toString()
val pass = binding.password.text.toString()
scope.launch {
try {
val result = service.login(user, pass)
@ -67,8 +66,8 @@ class TrackLoginDialog(@StringRes usernameLabelRes: Int? = null, bundle: Bundle?
v?.apply {
dialog?.setCancelable(true)
dialog?.setCanceledOnTouchOutside(true)
login.revertAnimation {
login.text = activity!!.getText(R.string.unknown_error)
binding.login.revertAnimation {
binding.login.text = activity!!.getText(R.string.unknown_error)
}
}
}