Replace material-dialogs usage with Material Components' (#5423)
* Use Material Components' dialogs For all dialogs that has direct replacement. * Convert text input dialogs * Convert quad-state multi choices dialogs * Convert date picker dialogs This also changes the flow to remove selected start/finish tracking date and the track item itself * Remove material-dialogs dependencies
This commit is contained in:
parent
117fd4bd0f
commit
ae97bb0445
@ -245,12 +245,6 @@ dependencies {
|
||||
implementation("com.github.tachiyomiorg:DirectionalViewPager:1.0.0")
|
||||
implementation("dev.chrisbanes.insetter:insetter:0.6.0")
|
||||
|
||||
// 3.2.0+ introduces weird UI blinking or cut off issues on some devices
|
||||
val materialDialogsVersion = "3.1.1"
|
||||
implementation("com.afollestad.material-dialogs:core:$materialDialogsVersion")
|
||||
implementation("com.afollestad.material-dialogs:input:$materialDialogsVersion")
|
||||
implementation("com.afollestad.material-dialogs:datetime:$materialDialogsVersion")
|
||||
|
||||
// Conductor
|
||||
val conductorVersion = "3.0.0"
|
||||
implementation("com.bluelinelabs:conductor:$conductorVersion")
|
||||
|
@ -2,9 +2,6 @@ package eu.kanade.tachiyomi.data.track.anilist
|
||||
|
||||
import android.net.Uri
|
||||
import androidx.core.net.toUri
|
||||
import com.afollestad.date.dayOfMonth
|
||||
import com.afollestad.date.month
|
||||
import com.afollestad.date.year
|
||||
import eu.kanade.tachiyomi.data.database.models.Track
|
||||
import eu.kanade.tachiyomi.data.track.model.TrackSearch
|
||||
import eu.kanade.tachiyomi.network.POST
|
||||
@ -315,9 +312,9 @@ class AnilistApi(val client: OkHttpClient, interceptor: AnilistInterceptor) {
|
||||
val calendar = Calendar.getInstance()
|
||||
calendar.timeInMillis = dateValue
|
||||
return buildJsonObject {
|
||||
put("year", calendar.year)
|
||||
put("month", calendar.month + 1)
|
||||
put("day", calendar.dayOfMonth)
|
||||
put("year", calendar.get(Calendar.YEAR))
|
||||
put("month", calendar.get(Calendar.MONTH) + 1)
|
||||
put("day", calendar.get(Calendar.DAY_OF_MONTH))
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -3,8 +3,8 @@ package eu.kanade.tachiyomi.ui.browse.extension
|
||||
import android.app.Dialog
|
||||
import android.os.Bundle
|
||||
import androidx.core.os.bundleOf
|
||||
import com.afollestad.materialdialogs.MaterialDialog
|
||||
import com.bluelinelabs.conductor.Controller
|
||||
import com.google.android.material.dialog.MaterialAlertDialogBuilder
|
||||
import eu.kanade.tachiyomi.R
|
||||
import eu.kanade.tachiyomi.ui.base.controller.DialogController
|
||||
|
||||
@ -21,15 +21,16 @@ class ExtensionTrustDialog<T>(bundle: Bundle? = null) : DialogController(bundle)
|
||||
}
|
||||
|
||||
override fun onCreateDialog(savedViewState: Bundle?): Dialog {
|
||||
return MaterialDialog(activity!!)
|
||||
.title(R.string.untrusted_extension)
|
||||
.message(R.string.untrusted_extension_message)
|
||||
.positiveButton(R.string.ext_trust) {
|
||||
return MaterialAlertDialogBuilder(activity!!)
|
||||
.setTitle(R.string.untrusted_extension)
|
||||
.setMessage(R.string.untrusted_extension_message)
|
||||
.setPositiveButton(R.string.ext_trust) { _, _ ->
|
||||
(targetController as? Listener)?.trustSignature(args.getString(SIGNATURE_KEY)!!)
|
||||
}
|
||||
.negativeButton(R.string.ext_uninstall) {
|
||||
.setNegativeButton(R.string.ext_uninstall) { _, _ ->
|
||||
(targetController as? Listener)?.uninstallExtension(args.getString(PKGNAME_KEY)!!)
|
||||
}
|
||||
.create()
|
||||
}
|
||||
|
||||
private companion object {
|
||||
|
@ -3,10 +3,9 @@ package eu.kanade.tachiyomi.ui.browse.migration.search
|
||||
import android.app.Dialog
|
||||
import android.os.Bundle
|
||||
import androidx.core.view.isVisible
|
||||
import com.afollestad.materialdialogs.MaterialDialog
|
||||
import com.afollestad.materialdialogs.list.listItemsMultiChoice
|
||||
import com.bluelinelabs.conductor.Controller
|
||||
import com.bluelinelabs.conductor.RouterTransaction
|
||||
import com.google.android.material.dialog.MaterialAlertDialogBuilder
|
||||
import eu.kanade.tachiyomi.R
|
||||
import eu.kanade.tachiyomi.data.database.models.Manga
|
||||
import eu.kanade.tachiyomi.data.preference.PreferencesHelper
|
||||
@ -89,26 +88,26 @@ class SearchController(
|
||||
@Suppress("DEPRECATION")
|
||||
override fun onCreateDialog(savedViewState: Bundle?): Dialog {
|
||||
val prefValue = preferences.migrateFlags().get()
|
||||
val enabledFlagsPositions = MigrationFlags.getEnabledFlagsPositions(prefValue)
|
||||
val items = MigrationFlags.titles
|
||||
.map { resources?.getString(it) }
|
||||
.toTypedArray()
|
||||
val selected = items
|
||||
.mapIndexed { i, _ -> enabledFlagsPositions.contains(i) }
|
||||
.toBooleanArray()
|
||||
|
||||
val preselected =
|
||||
MigrationFlags.getEnabledFlagsPositions(
|
||||
prefValue
|
||||
)
|
||||
|
||||
return MaterialDialog(activity!!)
|
||||
.title(R.string.migration_dialog_what_to_include)
|
||||
.listItemsMultiChoice(
|
||||
items = MigrationFlags.titles.map { resources?.getString(it) as CharSequence },
|
||||
initialSelection = preselected.toIntArray()
|
||||
) { _, positions, _ ->
|
||||
// Save current settings for the next time
|
||||
val newValue =
|
||||
MigrationFlags.getFlagsFromPositions(
|
||||
positions.toTypedArray()
|
||||
)
|
||||
preferences.migrateFlags().set(newValue)
|
||||
return MaterialAlertDialogBuilder(activity!!)
|
||||
.setTitle(R.string.migration_dialog_what_to_include)
|
||||
.setMultiChoiceItems(items, selected) { _, which, checked ->
|
||||
selected[which] = checked
|
||||
}
|
||||
.positiveButton(R.string.migrate) {
|
||||
.setPositiveButton(R.string.migrate) { _, _ ->
|
||||
// Save current settings for the next time
|
||||
val selectedIndices = mutableListOf<Int>()
|
||||
selected.forEachIndexed { i, b -> if (b) selectedIndices.add(i) }
|
||||
val newValue = MigrationFlags.getFlagsFromPositions(selectedIndices.toTypedArray())
|
||||
preferences.migrateFlags().set(newValue)
|
||||
|
||||
if (callingController != null) {
|
||||
if (callingController.javaClass == SourceSearchController::class.java) {
|
||||
router.popController(callingController)
|
||||
@ -116,7 +115,7 @@ class SearchController(
|
||||
}
|
||||
(targetController as? SearchController)?.migrateManga(manga, newManga)
|
||||
}
|
||||
.negativeButton(R.string.copy) {
|
||||
.setNegativeButton(R.string.copy) { _, _, ->
|
||||
if (callingController != null) {
|
||||
if (callingController.javaClass == SourceSearchController::class.java) {
|
||||
router.popController(callingController)
|
||||
@ -124,7 +123,8 @@ class SearchController(
|
||||
}
|
||||
(targetController as? SearchController)?.copyManga(manga, newManga)
|
||||
}
|
||||
.neutralButton(android.R.string.cancel)
|
||||
.setNeutralButton(android.R.string.cancel, null)
|
||||
.create()
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -9,10 +9,9 @@ import android.view.MenuInflater
|
||||
import android.view.MenuItem
|
||||
import android.view.View
|
||||
import androidx.recyclerview.widget.LinearLayoutManager
|
||||
import com.afollestad.materialdialogs.MaterialDialog
|
||||
import com.afollestad.materialdialogs.list.listItems
|
||||
import com.bluelinelabs.conductor.ControllerChangeHandler
|
||||
import com.bluelinelabs.conductor.ControllerChangeType
|
||||
import com.google.android.material.dialog.MaterialAlertDialogBuilder
|
||||
import dev.chrisbanes.insetter.applyInsetter
|
||||
import eu.davidea.flexibleadapter.FlexibleAdapter
|
||||
import eu.davidea.flexibleadapter.items.IFlexible
|
||||
@ -238,15 +237,13 @@ class SourceController :
|
||||
}
|
||||
|
||||
override fun onCreateDialog(savedViewState: Bundle?): Dialog {
|
||||
return MaterialDialog(activity!!)
|
||||
.title(text = source)
|
||||
.listItems(
|
||||
items = items.map { it.first },
|
||||
waitForPositiveButton = false
|
||||
) { dialog, which, _ ->
|
||||
return MaterialAlertDialogBuilder(activity!!)
|
||||
.setTitle(source)
|
||||
.setItems(items.map { it.first }.toTypedArray()) { dialog, which ->
|
||||
items[which].second()
|
||||
dialog.dismiss()
|
||||
}
|
||||
.create()
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -13,8 +13,7 @@ import androidx.core.view.updatePadding
|
||||
import androidx.recyclerview.widget.GridLayoutManager
|
||||
import androidx.recyclerview.widget.LinearLayoutManager
|
||||
import androidx.recyclerview.widget.RecyclerView
|
||||
import com.afollestad.materialdialogs.MaterialDialog
|
||||
import com.afollestad.materialdialogs.list.listItems
|
||||
import com.google.android.material.dialog.MaterialAlertDialogBuilder
|
||||
import com.google.android.material.floatingactionbutton.ExtendedFloatingActionButton
|
||||
import com.google.android.material.snackbar.Snackbar
|
||||
import com.tfcporciuncula.flow.Preference
|
||||
@ -589,11 +588,9 @@ open class BrowseSourceController(bundle: Bundle) :
|
||||
val manga = (adapter?.getItem(position) as? SourceItem?)?.manga ?: return
|
||||
|
||||
if (manga.favorite) {
|
||||
MaterialDialog(activity)
|
||||
.listItems(
|
||||
items = listOf(activity.getString(R.string.remove_from_library)),
|
||||
waitForPositiveButton = false
|
||||
) { _, which, _ ->
|
||||
MaterialAlertDialogBuilder(activity)
|
||||
.setTitle(manga.title)
|
||||
.setItems(arrayOf(activity.getString(R.string.remove_from_library))) { _, which ->
|
||||
when (which) {
|
||||
0 -> {
|
||||
presenter.changeMangaFavorite(manga)
|
||||
|
@ -2,11 +2,11 @@ package eu.kanade.tachiyomi.ui.category
|
||||
|
||||
import android.app.Dialog
|
||||
import android.os.Bundle
|
||||
import com.afollestad.materialdialogs.MaterialDialog
|
||||
import com.afollestad.materialdialogs.input.input
|
||||
import com.bluelinelabs.conductor.Controller
|
||||
import com.google.android.material.dialog.MaterialAlertDialogBuilder
|
||||
import eu.kanade.tachiyomi.R
|
||||
import eu.kanade.tachiyomi.ui.base.controller.DialogController
|
||||
import eu.kanade.tachiyomi.widget.materialdialogs.setTextInput
|
||||
|
||||
/**
|
||||
* Dialog to create a new category for the library.
|
||||
@ -30,18 +30,16 @@ class CategoryCreateDialog<T>(bundle: Bundle? = null) : DialogController(bundle)
|
||||
* @return a new dialog instance.
|
||||
*/
|
||||
override fun onCreateDialog(savedViewState: Bundle?): Dialog {
|
||||
return MaterialDialog(activity!!)
|
||||
.title(R.string.action_add_category)
|
||||
.negativeButton(android.R.string.cancel)
|
||||
.input(
|
||||
hint = resources?.getString(R.string.name),
|
||||
prefill = currentName
|
||||
) { _, input ->
|
||||
currentName = input.toString()
|
||||
return MaterialAlertDialogBuilder(activity!!)
|
||||
.setTitle(R.string.action_add_category)
|
||||
.setTextInput(prefill = currentName) {
|
||||
currentName = it
|
||||
}
|
||||
.positiveButton(android.R.string.ok) {
|
||||
.setPositiveButton(android.R.string.ok) { _, _ ->
|
||||
(targetController as? Listener)?.createCategory(currentName)
|
||||
}
|
||||
.setNegativeButton(android.R.string.cancel, null)
|
||||
.create()
|
||||
}
|
||||
|
||||
interface Listener {
|
||||
|
@ -2,12 +2,12 @@ package eu.kanade.tachiyomi.ui.category
|
||||
|
||||
import android.app.Dialog
|
||||
import android.os.Bundle
|
||||
import com.afollestad.materialdialogs.MaterialDialog
|
||||
import com.afollestad.materialdialogs.input.input
|
||||
import com.bluelinelabs.conductor.Controller
|
||||
import com.google.android.material.dialog.MaterialAlertDialogBuilder
|
||||
import eu.kanade.tachiyomi.R
|
||||
import eu.kanade.tachiyomi.data.database.models.Category
|
||||
import eu.kanade.tachiyomi.ui.base.controller.DialogController
|
||||
import eu.kanade.tachiyomi.widget.materialdialogs.setTextInput
|
||||
|
||||
/**
|
||||
* Dialog to rename an existing category of the library.
|
||||
@ -35,16 +35,14 @@ class CategoryRenameDialog<T>(bundle: Bundle? = null) : DialogController(bundle)
|
||||
* @return a new dialog instance.
|
||||
*/
|
||||
override fun onCreateDialog(savedViewState: Bundle?): Dialog {
|
||||
return MaterialDialog(activity!!)
|
||||
.title(R.string.action_rename_category)
|
||||
.negativeButton(android.R.string.cancel)
|
||||
.input(
|
||||
hint = resources?.getString(R.string.name),
|
||||
prefill = currentName
|
||||
) { _, input ->
|
||||
currentName = input.toString()
|
||||
return MaterialAlertDialogBuilder(activity!!)
|
||||
.setTitle(R.string.action_rename_category)
|
||||
.setTextInput(prefill = currentName) {
|
||||
currentName = it
|
||||
}
|
||||
.positiveButton(android.R.string.ok) { onPositive() }
|
||||
.setPositiveButton(android.R.string.ok) { _, _ -> onPositive() }
|
||||
.setNegativeButton(android.R.string.cancel, null)
|
||||
.create()
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -2,9 +2,8 @@ package eu.kanade.tachiyomi.ui.library
|
||||
|
||||
import android.app.Dialog
|
||||
import android.os.Bundle
|
||||
import com.afollestad.materialdialogs.MaterialDialog
|
||||
import com.afollestad.materialdialogs.list.listItemsMultiChoice
|
||||
import com.bluelinelabs.conductor.Controller
|
||||
import com.google.android.material.dialog.MaterialAlertDialogBuilder
|
||||
import eu.kanade.tachiyomi.R
|
||||
import eu.kanade.tachiyomi.data.database.models.Category
|
||||
import eu.kanade.tachiyomi.data.database.models.Manga
|
||||
@ -32,32 +31,34 @@ class ChangeMangaCategoriesDialog<T>(bundle: Bundle? = null) :
|
||||
}
|
||||
|
||||
override fun onCreateDialog(savedViewState: Bundle?): Dialog {
|
||||
return MaterialDialog(activity!!)
|
||||
.title(R.string.action_move_category)
|
||||
.negativeButton(android.R.string.cancel)
|
||||
return MaterialAlertDialogBuilder(activity!!)
|
||||
.setTitle(R.string.action_move_category)
|
||||
.setNegativeButton(android.R.string.cancel, null)
|
||||
.apply {
|
||||
if (categories.isNotEmpty()) {
|
||||
listItemsMultiChoice(
|
||||
items = categories.map { it.name },
|
||||
initialSelection = preselected.toIntArray(),
|
||||
allowEmptySelection = true
|
||||
) { _, selections, _ ->
|
||||
val newCategories = selections.map { categories[it] }
|
||||
val selected = categories
|
||||
.mapIndexed { i, _ -> preselected.contains(i) }
|
||||
.toBooleanArray()
|
||||
setMultiChoiceItems(categories.map { it.name }.toTypedArray(), selected) { _, which, checked ->
|
||||
selected[which] = checked
|
||||
}
|
||||
setPositiveButton(android.R.string.ok) { _, _ ->
|
||||
val newCategories = categories.filterIndexed { i, _ -> selected[i] }
|
||||
(targetController as? Listener)?.updateCategoriesForMangas(mangas, newCategories)
|
||||
}
|
||||
.positiveButton(android.R.string.ok)
|
||||
} else {
|
||||
message(R.string.information_empty_category_dialog)
|
||||
.positiveButton(R.string.action_edit_categories) {
|
||||
if (targetController is LibraryController) {
|
||||
val libController = targetController as LibraryController
|
||||
libController.clearSelection()
|
||||
}
|
||||
router.popCurrentController()
|
||||
router.pushController(CategoryController().withFadeTransaction())
|
||||
setMessage(R.string.information_empty_category_dialog)
|
||||
setPositiveButton(R.string.action_edit_categories) { _, _ ->
|
||||
if (targetController is LibraryController) {
|
||||
val libController = targetController as LibraryController
|
||||
libController.clearSelection()
|
||||
}
|
||||
router.popCurrentController()
|
||||
router.pushController(CategoryController().withFadeTransaction())
|
||||
}
|
||||
}
|
||||
}
|
||||
.create()
|
||||
}
|
||||
|
||||
interface Listener {
|
||||
|
@ -2,8 +2,8 @@ package eu.kanade.tachiyomi.ui.library
|
||||
|
||||
import android.app.Dialog
|
||||
import android.os.Bundle
|
||||
import com.afollestad.materialdialogs.MaterialDialog
|
||||
import com.bluelinelabs.conductor.Controller
|
||||
import com.google.android.material.dialog.MaterialAlertDialogBuilder
|
||||
import eu.kanade.tachiyomi.R
|
||||
import eu.kanade.tachiyomi.data.database.models.Manga
|
||||
import eu.kanade.tachiyomi.ui.base.controller.DialogController
|
||||
@ -20,15 +20,16 @@ class ChangeMangaCoverDialog<T>(bundle: Bundle? = null) :
|
||||
|
||||
@Suppress("DEPRECATION")
|
||||
override fun onCreateDialog(savedViewState: Bundle?): Dialog {
|
||||
return MaterialDialog(activity!!)
|
||||
.title(R.string.action_edit_cover)
|
||||
.positiveButton(R.string.action_edit) {
|
||||
return MaterialAlertDialogBuilder(activity!!)
|
||||
.setTitle(R.string.action_edit_cover)
|
||||
.setPositiveButton(R.string.action_edit) { _, _ ->
|
||||
(targetController as? Listener)?.openMangaCoverPicker(manga)
|
||||
}
|
||||
.negativeButton(android.R.string.cancel)
|
||||
.neutralButton(R.string.action_delete) {
|
||||
.setNegativeButton(android.R.string.cancel, null)
|
||||
.setNeutralButton(R.string.action_delete) { _, _ ->
|
||||
(targetController as? Listener)?.deleteMangaCover(manga)
|
||||
}
|
||||
.create()
|
||||
}
|
||||
|
||||
interface Listener {
|
||||
|
@ -2,9 +2,8 @@ package eu.kanade.tachiyomi.ui.library
|
||||
|
||||
import android.app.Dialog
|
||||
import android.os.Bundle
|
||||
import com.afollestad.materialdialogs.MaterialDialog
|
||||
import com.afollestad.materialdialogs.list.listItemsMultiChoice
|
||||
import com.bluelinelabs.conductor.Controller
|
||||
import com.google.android.material.dialog.MaterialAlertDialogBuilder
|
||||
import eu.kanade.tachiyomi.R
|
||||
import eu.kanade.tachiyomi.data.database.models.Manga
|
||||
import eu.kanade.tachiyomi.ui.base.controller.DialogController
|
||||
@ -20,18 +19,22 @@ class DeleteLibraryMangasDialog<T>(bundle: Bundle? = null) :
|
||||
}
|
||||
|
||||
override fun onCreateDialog(savedViewState: Bundle?): Dialog {
|
||||
return MaterialDialog(activity!!)
|
||||
.title(R.string.action_remove)
|
||||
.listItemsMultiChoice(
|
||||
R.array.delete_selected_mangas,
|
||||
initialSelection = intArrayOf(0)
|
||||
) { _, selections, _ ->
|
||||
val deleteFromLibrary = 0 in selections
|
||||
val deleteChapters = 1 in selections
|
||||
val items = resources!!.getStringArray(R.array.delete_selected_mangas)
|
||||
val selected = items
|
||||
.mapIndexed { i, _ -> i == 0 }
|
||||
.toBooleanArray()
|
||||
return MaterialAlertDialogBuilder(activity!!)
|
||||
.setTitle(R.string.action_remove)
|
||||
.setMultiChoiceItems(items, selected) { _, which, checked ->
|
||||
selected[which] = checked
|
||||
}
|
||||
.setPositiveButton(android.R.string.ok) { _, _ ->
|
||||
val deleteFromLibrary = selected[0]
|
||||
val deleteChapters = selected[1]
|
||||
(targetController as? Listener)?.deleteMangas(mangas, deleteFromLibrary, deleteChapters)
|
||||
}
|
||||
.positiveButton(android.R.string.ok)
|
||||
.negativeButton(android.R.string.cancel)
|
||||
.setNegativeButton(android.R.string.cancel, null)
|
||||
.create()
|
||||
}
|
||||
|
||||
interface Listener {
|
||||
|
@ -2,7 +2,7 @@ package eu.kanade.tachiyomi.ui.main
|
||||
|
||||
import android.app.Dialog
|
||||
import android.os.Bundle
|
||||
import com.afollestad.materialdialogs.MaterialDialog
|
||||
import com.google.android.material.dialog.MaterialAlertDialogBuilder
|
||||
import eu.kanade.tachiyomi.BuildConfig
|
||||
import eu.kanade.tachiyomi.R
|
||||
import eu.kanade.tachiyomi.ui.base.controller.DialogController
|
||||
@ -12,11 +12,12 @@ class WhatsNewDialogController(bundle: Bundle? = null) : DialogController(bundle
|
||||
|
||||
@Suppress("DEPRECATION")
|
||||
override fun onCreateDialog(savedViewState: Bundle?): Dialog {
|
||||
return MaterialDialog(activity!!)
|
||||
.title(text = activity!!.getString(R.string.updated_version, BuildConfig.VERSION_NAME))
|
||||
.positiveButton(android.R.string.ok)
|
||||
.neutralButton(R.string.whats_new) {
|
||||
return MaterialAlertDialogBuilder(activity!!)
|
||||
.setTitle(activity!!.getString(R.string.updated_version, BuildConfig.VERSION_NAME))
|
||||
.setPositiveButton(android.R.string.ok, null)
|
||||
.setNeutralButton(R.string.whats_new) { _, _ ->
|
||||
openInBrowser("https://github.com/tachiyomiorg/tachiyomi/releases/tag/v${BuildConfig.VERSION_NAME}")
|
||||
}
|
||||
.create()
|
||||
}
|
||||
}
|
||||
|
@ -289,7 +289,7 @@ class MangaController :
|
||||
}
|
||||
}
|
||||
|
||||
trackSheet = TrackSheet(this, manga!!)
|
||||
trackSheet = TrackSheet(this, manga!!, (activity as MainActivity).supportFragmentManager)
|
||||
|
||||
updateFilterIconState()
|
||||
}
|
||||
|
@ -2,8 +2,8 @@ package eu.kanade.tachiyomi.ui.manga.chapter
|
||||
|
||||
import android.app.Dialog
|
||||
import android.os.Bundle
|
||||
import com.afollestad.materialdialogs.MaterialDialog
|
||||
import com.bluelinelabs.conductor.Controller
|
||||
import com.google.android.material.dialog.MaterialAlertDialogBuilder
|
||||
import eu.kanade.tachiyomi.R
|
||||
import eu.kanade.tachiyomi.ui.base.controller.DialogController
|
||||
|
||||
@ -15,12 +15,13 @@ class DeleteChaptersDialog<T>(bundle: Bundle? = null) : DialogController(bundle)
|
||||
}
|
||||
|
||||
override fun onCreateDialog(savedViewState: Bundle?): Dialog {
|
||||
return MaterialDialog(activity!!)
|
||||
.message(R.string.confirm_delete_chapters)
|
||||
.positiveButton(android.R.string.ok) {
|
||||
return MaterialAlertDialogBuilder(activity!!)
|
||||
.setMessage(R.string.confirm_delete_chapters)
|
||||
.setPositiveButton(android.R.string.ok) { _, _ ->
|
||||
(targetController as? Listener)?.deleteChapters()
|
||||
}
|
||||
.negativeButton(android.R.string.cancel)
|
||||
.setNegativeButton(android.R.string.cancel, null)
|
||||
.create()
|
||||
}
|
||||
|
||||
interface Listener {
|
||||
|
@ -3,9 +3,8 @@ package eu.kanade.tachiyomi.ui.manga.chapter
|
||||
import android.app.Dialog
|
||||
import android.os.Bundle
|
||||
import androidx.core.os.bundleOf
|
||||
import com.afollestad.materialdialogs.MaterialDialog
|
||||
import com.afollestad.materialdialogs.customview.customView
|
||||
import com.bluelinelabs.conductor.Controller
|
||||
import com.google.android.material.dialog.MaterialAlertDialogBuilder
|
||||
import eu.kanade.tachiyomi.R
|
||||
import eu.kanade.tachiyomi.ui.base.controller.DialogController
|
||||
import eu.kanade.tachiyomi.widget.DialogCustomDownloadView
|
||||
@ -57,13 +56,14 @@ class DownloadCustomChaptersDialog<T> : DialogController
|
||||
|
||||
// Build dialog.
|
||||
// when positive dialog is pressed call custom listener.
|
||||
return MaterialDialog(activity)
|
||||
.title(R.string.custom_download)
|
||||
.customView(view = view, scrollable = true)
|
||||
.positiveButton(android.R.string.ok) {
|
||||
return MaterialAlertDialogBuilder(activity)
|
||||
.setTitle(R.string.custom_download)
|
||||
.setView(view)
|
||||
.setPositiveButton(android.R.string.ok) { _, _ ->
|
||||
(targetController as? Listener)?.downloadCustomChapters(view.amount)
|
||||
}
|
||||
.negativeButton(android.R.string.cancel)
|
||||
.setNegativeButton(android.R.string.cancel, null)
|
||||
.create()
|
||||
}
|
||||
|
||||
interface Listener {
|
||||
|
@ -3,8 +3,7 @@ package eu.kanade.tachiyomi.ui.manga.chapter
|
||||
import android.app.Dialog
|
||||
import android.os.Bundle
|
||||
import androidx.core.os.bundleOf
|
||||
import com.afollestad.materialdialogs.MaterialDialog
|
||||
import com.afollestad.materialdialogs.customview.customView
|
||||
import com.google.android.material.dialog.MaterialAlertDialogBuilder
|
||||
import eu.kanade.tachiyomi.R
|
||||
import eu.kanade.tachiyomi.data.database.models.Manga
|
||||
import eu.kanade.tachiyomi.ui.base.controller.DialogController
|
||||
@ -24,13 +23,10 @@ class SetChapterSettingsDialog(bundle: Bundle? = null) : DialogController(bundle
|
||||
setOptionDescription(R.string.also_set_chapter_settings_for_library)
|
||||
}
|
||||
|
||||
return MaterialDialog(activity!!)
|
||||
.title(R.string.chapter_settings)
|
||||
.customView(
|
||||
view = view,
|
||||
horizontalPadding = true
|
||||
)
|
||||
.positiveButton(android.R.string.ok) {
|
||||
return MaterialAlertDialogBuilder(activity!!)
|
||||
.setTitle(R.string.chapter_settings)
|
||||
.setView(view)
|
||||
.setPositiveButton(android.R.string.ok) { _, _ ->
|
||||
ChapterSettingsHelper.setGlobalSettings(args.getSerializable(MANGA_KEY)!! as Manga)
|
||||
if (view.isChecked()) {
|
||||
ChapterSettingsHelper.updateAllMangasWithGlobalDefaults()
|
||||
@ -38,7 +34,8 @@ class SetChapterSettingsDialog(bundle: Bundle? = null) : DialogController(bundle
|
||||
|
||||
activity?.toast(activity!!.getString(R.string.chapter_settings_updated))
|
||||
}
|
||||
.negativeButton(android.R.string.cancel)
|
||||
.setNegativeButton(android.R.string.cancel, null)
|
||||
.create()
|
||||
}
|
||||
|
||||
private companion object {
|
||||
|
@ -2,15 +2,14 @@ package eu.kanade.tachiyomi.ui.manga.track
|
||||
|
||||
import android.app.Dialog
|
||||
import android.os.Bundle
|
||||
import android.widget.NumberPicker
|
||||
import android.view.LayoutInflater
|
||||
import androidx.core.os.bundleOf
|
||||
import com.afollestad.materialdialogs.MaterialDialog
|
||||
import com.afollestad.materialdialogs.customview.customView
|
||||
import com.afollestad.materialdialogs.customview.getCustomView
|
||||
import com.bluelinelabs.conductor.Controller
|
||||
import com.google.android.material.dialog.MaterialAlertDialogBuilder
|
||||
import eu.kanade.tachiyomi.R
|
||||
import eu.kanade.tachiyomi.data.database.models.Track
|
||||
import eu.kanade.tachiyomi.data.track.TrackManager
|
||||
import eu.kanade.tachiyomi.databinding.TrackChaptersDialogBinding
|
||||
import eu.kanade.tachiyomi.ui.base.controller.DialogController
|
||||
import uy.kohesive.injekt.Injekt
|
||||
import uy.kohesive.injekt.api.get
|
||||
@ -38,23 +37,9 @@ class SetTrackChaptersDialog<T> : DialogController
|
||||
}
|
||||
|
||||
override fun onCreateDialog(savedViewState: Bundle?): Dialog {
|
||||
val item = item
|
||||
val pickerView = TrackChaptersDialogBinding.inflate(LayoutInflater.from(activity!!))
|
||||
val np = pickerView.chaptersPicker
|
||||
|
||||
val dialog = MaterialDialog(activity!!)
|
||||
.title(R.string.chapters)
|
||||
.customView(R.layout.track_chapters_dialog, dialogWrapContent = false)
|
||||
.positiveButton(android.R.string.ok) { dialog ->
|
||||
val view = dialog.getCustomView()
|
||||
// Remove focus to update selected number
|
||||
val np: NumberPicker = view.findViewById(R.id.chapters_picker)
|
||||
np.clearFocus()
|
||||
|
||||
listener.setChaptersRead(item, np.value)
|
||||
}
|
||||
.negativeButton(android.R.string.cancel)
|
||||
|
||||
val view = dialog.getCustomView()
|
||||
val np: NumberPicker = view.findViewById(R.id.chapters_picker)
|
||||
// Set initial value
|
||||
np.value = item.track?.last_chapter_read ?: 0
|
||||
|
||||
@ -66,7 +51,15 @@ class SetTrackChaptersDialog<T> : DialogController
|
||||
// Don't allow to go from 0 to 9999
|
||||
np.wrapSelectorWheel = false
|
||||
|
||||
return dialog
|
||||
return MaterialAlertDialogBuilder(activity!!)
|
||||
.setTitle(R.string.chapters)
|
||||
.setView(pickerView.root)
|
||||
.setPositiveButton(android.R.string.ok) { _, _ ->
|
||||
np.clearFocus()
|
||||
listener.setChaptersRead(item, np.value)
|
||||
}
|
||||
.setNegativeButton(android.R.string.cancel, null)
|
||||
.create()
|
||||
}
|
||||
|
||||
interface Listener {
|
||||
|
@ -1,87 +0,0 @@
|
||||
package eu.kanade.tachiyomi.ui.manga.track
|
||||
|
||||
import android.app.Dialog
|
||||
import android.os.Bundle
|
||||
import androidx.core.os.bundleOf
|
||||
import com.afollestad.materialdialogs.MaterialDialog
|
||||
import com.afollestad.materialdialogs.datetime.datePicker
|
||||
import com.bluelinelabs.conductor.Controller
|
||||
import eu.kanade.tachiyomi.R
|
||||
import eu.kanade.tachiyomi.data.database.models.Track
|
||||
import eu.kanade.tachiyomi.data.track.TrackManager
|
||||
import eu.kanade.tachiyomi.ui.base.controller.DialogController
|
||||
import uy.kohesive.injekt.Injekt
|
||||
import uy.kohesive.injekt.api.get
|
||||
import java.util.Calendar
|
||||
|
||||
class SetTrackReadingDatesDialog<T> : DialogController
|
||||
where T : Controller {
|
||||
|
||||
private val item: TrackItem
|
||||
|
||||
private val dateToUpdate: ReadingDate
|
||||
|
||||
private lateinit var listener: Listener
|
||||
|
||||
constructor(target: T, listener: Listener, dateToUpdate: ReadingDate, item: TrackItem) : super(
|
||||
bundleOf(KEY_ITEM_TRACK to item.track)
|
||||
) {
|
||||
targetController = target
|
||||
this.listener = listener
|
||||
this.item = item
|
||||
this.dateToUpdate = dateToUpdate
|
||||
}
|
||||
|
||||
@Suppress("unused")
|
||||
constructor(bundle: Bundle) : super(bundle) {
|
||||
val track = bundle.getSerializable(KEY_ITEM_TRACK) as Track
|
||||
val service = Injekt.get<TrackManager>().getService(track.sync_id)!!
|
||||
item = TrackItem(track, service)
|
||||
dateToUpdate = ReadingDate.Start
|
||||
}
|
||||
|
||||
@Suppress("DEPRECATION")
|
||||
override fun onCreateDialog(savedViewState: Bundle?): Dialog {
|
||||
return MaterialDialog(activity!!)
|
||||
.title(
|
||||
when (dateToUpdate) {
|
||||
ReadingDate.Start -> R.string.track_started_reading_date
|
||||
ReadingDate.Finish -> R.string.track_finished_reading_date
|
||||
}
|
||||
)
|
||||
.datePicker(currentDate = getCurrentDate()) { _, date ->
|
||||
listener.setReadingDate(item, dateToUpdate, date.timeInMillis)
|
||||
}
|
||||
.neutralButton(R.string.action_remove) {
|
||||
listener.setReadingDate(item, dateToUpdate, 0L)
|
||||
}
|
||||
}
|
||||
|
||||
private fun getCurrentDate(): Calendar {
|
||||
// Today if no date is set, otherwise the already set date
|
||||
return Calendar.getInstance().apply {
|
||||
item.track?.let {
|
||||
val date = when (dateToUpdate) {
|
||||
ReadingDate.Start -> it.started_reading_date
|
||||
ReadingDate.Finish -> it.finished_reading_date
|
||||
}
|
||||
if (date != 0L) {
|
||||
timeInMillis = date
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
interface Listener {
|
||||
fun setReadingDate(item: TrackItem, type: ReadingDate, date: Long)
|
||||
}
|
||||
|
||||
enum class ReadingDate {
|
||||
Start,
|
||||
Finish
|
||||
}
|
||||
|
||||
companion object {
|
||||
private const val KEY_ITEM_TRACK = "SetTrackReadingDatesDialog.item.track"
|
||||
}
|
||||
}
|
@ -2,15 +2,14 @@ package eu.kanade.tachiyomi.ui.manga.track
|
||||
|
||||
import android.app.Dialog
|
||||
import android.os.Bundle
|
||||
import android.widget.NumberPicker
|
||||
import android.view.LayoutInflater
|
||||
import androidx.core.os.bundleOf
|
||||
import com.afollestad.materialdialogs.MaterialDialog
|
||||
import com.afollestad.materialdialogs.customview.customView
|
||||
import com.afollestad.materialdialogs.customview.getCustomView
|
||||
import com.bluelinelabs.conductor.Controller
|
||||
import com.google.android.material.dialog.MaterialAlertDialogBuilder
|
||||
import eu.kanade.tachiyomi.R
|
||||
import eu.kanade.tachiyomi.data.database.models.Track
|
||||
import eu.kanade.tachiyomi.data.track.TrackManager
|
||||
import eu.kanade.tachiyomi.databinding.TrackScoreDialogBinding
|
||||
import eu.kanade.tachiyomi.ui.base.controller.DialogController
|
||||
import uy.kohesive.injekt.Injekt
|
||||
import uy.kohesive.injekt.api.get
|
||||
@ -38,23 +37,9 @@ class SetTrackScoreDialog<T> : DialogController
|
||||
}
|
||||
|
||||
override fun onCreateDialog(savedViewState: Bundle?): Dialog {
|
||||
val item = item
|
||||
val pickerView = TrackScoreDialogBinding.inflate(LayoutInflater.from(activity!!))
|
||||
val np = pickerView.scorePicker
|
||||
|
||||
val dialog = MaterialDialog(activity!!)
|
||||
.title(R.string.score)
|
||||
.customView(R.layout.track_score_dialog, dialogWrapContent = false)
|
||||
.positiveButton(android.R.string.ok) { dialog ->
|
||||
val view = dialog.getCustomView()
|
||||
// Remove focus to update selected number
|
||||
val np: NumberPicker = view.findViewById(R.id.score_picker)
|
||||
np.clearFocus()
|
||||
|
||||
listener.setScore(item, np.value)
|
||||
}
|
||||
.negativeButton(android.R.string.cancel)
|
||||
|
||||
val view = dialog.getCustomView()
|
||||
val np: NumberPicker = view.findViewById(R.id.score_picker)
|
||||
val scores = item.service.getScoreList().toTypedArray()
|
||||
np.maxValue = scores.size - 1
|
||||
np.displayedValues = scores
|
||||
@ -66,7 +51,15 @@ class SetTrackScoreDialog<T> : DialogController
|
||||
np.value = if (index != -1) index else 0
|
||||
}
|
||||
|
||||
return dialog
|
||||
return MaterialAlertDialogBuilder(activity!!)
|
||||
.setTitle(R.string.score)
|
||||
.setView(pickerView.root)
|
||||
.setPositiveButton(android.R.string.ok) { _, _ ->
|
||||
np.clearFocus()
|
||||
listener.setScore(item, np.value)
|
||||
}
|
||||
.setNegativeButton(android.R.string.cancel, null)
|
||||
.create()
|
||||
}
|
||||
|
||||
interface Listener {
|
||||
|
@ -3,9 +3,8 @@ package eu.kanade.tachiyomi.ui.manga.track
|
||||
import android.app.Dialog
|
||||
import android.os.Bundle
|
||||
import androidx.core.os.bundleOf
|
||||
import com.afollestad.materialdialogs.MaterialDialog
|
||||
import com.afollestad.materialdialogs.list.listItemsSingleChoice
|
||||
import com.bluelinelabs.conductor.Controller
|
||||
import com.google.android.material.dialog.MaterialAlertDialogBuilder
|
||||
import eu.kanade.tachiyomi.R
|
||||
import eu.kanade.tachiyomi.data.database.models.Track
|
||||
import eu.kanade.tachiyomi.data.track.TrackManager
|
||||
@ -36,22 +35,20 @@ class SetTrackStatusDialog<T> : DialogController
|
||||
}
|
||||
|
||||
override fun onCreateDialog(savedViewState: Bundle?): Dialog {
|
||||
val item = item
|
||||
val statusList = item.service.getStatusList()
|
||||
val statusString = statusList.map { item.service.getStatus(it) }
|
||||
val selectedIndex = statusList.indexOf(item.track?.status)
|
||||
var selectedIndex = statusList.indexOf(item.track?.status)
|
||||
|
||||
return MaterialDialog(activity!!)
|
||||
.title(R.string.status)
|
||||
.negativeButton(android.R.string.cancel)
|
||||
.listItemsSingleChoice(
|
||||
items = statusString,
|
||||
initialSelection = selectedIndex,
|
||||
waitForPositiveButton = false
|
||||
) { dialog, position, _ ->
|
||||
listener.setStatus(item, position)
|
||||
dialog.dismiss()
|
||||
return MaterialAlertDialogBuilder(activity!!)
|
||||
.setTitle(R.string.status)
|
||||
.setSingleChoiceItems(statusString.toTypedArray(), selectedIndex) { _, which ->
|
||||
selectedIndex = which
|
||||
}
|
||||
.setPositiveButton(android.R.string.ok) { _, _ ->
|
||||
listener.setStatus(item, selectedIndex)
|
||||
}
|
||||
.setNegativeButton(android.R.string.cancel, null)
|
||||
.create()
|
||||
}
|
||||
|
||||
interface Listener {
|
||||
|
@ -5,7 +5,6 @@ import android.view.ViewGroup
|
||||
import androidx.recyclerview.widget.RecyclerView
|
||||
import eu.kanade.tachiyomi.databinding.TrackItemBinding
|
||||
import eu.kanade.tachiyomi.util.view.applyElevationOverlay
|
||||
import uy.kohesive.injekt.api.get
|
||||
|
||||
class TrackAdapter(listener: OnClickListener) : RecyclerView.Adapter<TrackHolder>() {
|
||||
|
||||
@ -40,13 +39,16 @@ class TrackAdapter(listener: OnClickListener) : RecyclerView.Adapter<TrackHolder
|
||||
}
|
||||
|
||||
interface OnClickListener {
|
||||
fun onLogoClick(position: Int)
|
||||
fun onOpenInBrowserClick(position: Int)
|
||||
fun onSetClick(position: Int)
|
||||
fun onTitleLongClick(position: Int)
|
||||
fun onStatusClick(position: Int)
|
||||
fun onChaptersClick(position: Int)
|
||||
fun onScoreClick(position: Int)
|
||||
fun onStartDateClick(position: Int)
|
||||
fun onFinishDateClick(position: Int)
|
||||
fun onStartDateEditClick(position: Int)
|
||||
fun onStartDateRemoveClick(position: Int)
|
||||
fun onFinishDateEditClick(position: Int)
|
||||
fun onFinishDateRemoveClick(position: Int)
|
||||
fun onRemoveItemClick(position: Int)
|
||||
}
|
||||
}
|
||||
|
@ -6,6 +6,7 @@ import androidx.recyclerview.widget.RecyclerView
|
||||
import eu.kanade.tachiyomi.R
|
||||
import eu.kanade.tachiyomi.data.preference.PreferencesHelper
|
||||
import eu.kanade.tachiyomi.databinding.TrackItemBinding
|
||||
import eu.kanade.tachiyomi.util.view.popupMenu
|
||||
import uy.kohesive.injekt.injectLazy
|
||||
import java.text.DateFormat
|
||||
|
||||
@ -17,10 +18,9 @@ class TrackHolder(private val binding: TrackItemBinding, adapter: TrackAdapter)
|
||||
preferences.dateFormat()
|
||||
}
|
||||
|
||||
init {
|
||||
val listener = adapter.rowClickListener
|
||||
private val listener = adapter.rowClickListener
|
||||
|
||||
binding.logoContainer.setOnClickListener { listener.onLogoClick(bindingAdapterPosition) }
|
||||
init {
|
||||
binding.trackSet.setOnClickListener { listener.onSetClick(bindingAdapterPosition) }
|
||||
binding.trackTitle.setOnClickListener { listener.onSetClick(bindingAdapterPosition) }
|
||||
binding.trackTitle.setOnLongClickListener {
|
||||
@ -30,8 +30,6 @@ class TrackHolder(private val binding: TrackItemBinding, adapter: TrackAdapter)
|
||||
binding.trackStatus.setOnClickListener { listener.onStatusClick(bindingAdapterPosition) }
|
||||
binding.trackChapters.setOnClickListener { listener.onChaptersClick(bindingAdapterPosition) }
|
||||
binding.trackScore.setOnClickListener { listener.onScoreClick(bindingAdapterPosition) }
|
||||
binding.trackStartDate.setOnClickListener { listener.onStartDateClick(bindingAdapterPosition) }
|
||||
binding.trackFinishDate.setOnClickListener { listener.onFinishDateClick(bindingAdapterPosition) }
|
||||
}
|
||||
|
||||
@SuppressLint("SetTextI18n")
|
||||
@ -42,6 +40,7 @@ class TrackHolder(private val binding: TrackItemBinding, adapter: TrackAdapter)
|
||||
|
||||
binding.trackSet.isVisible = track == null
|
||||
binding.trackTitle.isVisible = track != null
|
||||
binding.more.isVisible = track != null
|
||||
|
||||
binding.middleRow.isVisible = track != null
|
||||
binding.bottomDivider.isVisible = track != null
|
||||
@ -77,20 +76,55 @@ class TrackHolder(private val binding: TrackItemBinding, adapter: TrackAdapter)
|
||||
if (track.started_reading_date != 0L) {
|
||||
binding.trackStartDate.text = dateFormat.format(track.started_reading_date)
|
||||
binding.trackStartDate.alpha = SET_STATUS_TEXT_ALPHA
|
||||
binding.trackStartDate.setOnClickListener {
|
||||
it.popupMenu(R.menu.track_item_date) {
|
||||
when (itemId) {
|
||||
R.id.action_edit -> listener.onStartDateEditClick(bindingAdapterPosition)
|
||||
R.id.action_remove -> listener.onStartDateRemoveClick(bindingAdapterPosition)
|
||||
}
|
||||
}
|
||||
}
|
||||
} else {
|
||||
binding.trackStartDate.text = ctx.getString(R.string.track_started_reading_date)
|
||||
binding.trackStartDate.alpha = UNSET_STATUS_TEXT_ALPHA
|
||||
binding.trackStartDate.setOnClickListener {
|
||||
listener.onStartDateEditClick(bindingAdapterPosition)
|
||||
}
|
||||
}
|
||||
if (track.finished_reading_date != 0L) {
|
||||
binding.trackFinishDate.text = dateFormat.format(track.finished_reading_date)
|
||||
binding.trackFinishDate.alpha = SET_STATUS_TEXT_ALPHA
|
||||
binding.trackFinishDate.setOnClickListener {
|
||||
it.popupMenu(R.menu.track_item_date) {
|
||||
when (itemId) {
|
||||
R.id.action_edit -> listener.onFinishDateEditClick(bindingAdapterPosition)
|
||||
R.id.action_remove -> listener.onFinishDateRemoveClick(bindingAdapterPosition)
|
||||
}
|
||||
}
|
||||
}
|
||||
} else {
|
||||
binding.trackFinishDate.text = ctx.getString(R.string.track_finished_reading_date)
|
||||
binding.trackFinishDate.alpha = UNSET_STATUS_TEXT_ALPHA
|
||||
binding.trackFinishDate.setOnClickListener {
|
||||
listener.onFinishDateEditClick(bindingAdapterPosition)
|
||||
}
|
||||
}
|
||||
}
|
||||
binding.bottomDivider.isVisible = supportsReadingDates
|
||||
binding.bottomRow.isVisible = supportsReadingDates
|
||||
|
||||
binding.more.setOnClickListener {
|
||||
it.popupMenu(R.menu.track_item) {
|
||||
when (itemId) {
|
||||
R.id.action_open_in_browser -> {
|
||||
listener.onOpenInBrowserClick(bindingAdapterPosition)
|
||||
}
|
||||
R.id.action_remove -> {
|
||||
listener.onRemoveItemClick(bindingAdapterPosition)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -74,14 +74,9 @@ class TrackSearchDialog : DialogController {
|
||||
dialog?.dismiss()
|
||||
}
|
||||
}
|
||||
R.id.remove -> {
|
||||
trackController.presenter.unregisterTracking(service)
|
||||
dialog?.dismiss()
|
||||
}
|
||||
}
|
||||
true
|
||||
}
|
||||
binding!!.toolbar.menu.findItem(R.id.remove).isVisible = currentTrackUrl != null
|
||||
|
||||
// Create adapter
|
||||
adapter = TrackSearchAdapter(currentTrackUrl) { which ->
|
||||
|
@ -3,9 +3,14 @@ package eu.kanade.tachiyomi.ui.manga.track
|
||||
import android.os.Bundle
|
||||
import android.view.LayoutInflater
|
||||
import android.view.View
|
||||
import androidx.fragment.app.FragmentManager
|
||||
import androidx.recyclerview.widget.LinearLayoutManager
|
||||
import com.google.android.material.bottomsheet.BottomSheetBehavior
|
||||
import eu.kanade.tachiyomi.R.string
|
||||
import com.google.android.material.datepicker.CalendarConstraints
|
||||
import com.google.android.material.datepicker.DateValidatorPointBackward
|
||||
import com.google.android.material.datepicker.DateValidatorPointForward
|
||||
import com.google.android.material.datepicker.MaterialDatePicker
|
||||
import eu.kanade.tachiyomi.R
|
||||
import eu.kanade.tachiyomi.data.database.models.Manga
|
||||
import eu.kanade.tachiyomi.data.track.UnattendedTrackService
|
||||
import eu.kanade.tachiyomi.databinding.TrackControllerBinding
|
||||
@ -13,6 +18,7 @@ import eu.kanade.tachiyomi.source.SourceManager
|
||||
import eu.kanade.tachiyomi.ui.base.controller.openInBrowser
|
||||
import eu.kanade.tachiyomi.ui.manga.MangaController
|
||||
import eu.kanade.tachiyomi.util.lang.launchIO
|
||||
import eu.kanade.tachiyomi.util.lang.toUtcCalendar
|
||||
import eu.kanade.tachiyomi.util.lang.withUIContext
|
||||
import eu.kanade.tachiyomi.util.system.copyToClipboard
|
||||
import eu.kanade.tachiyomi.util.system.toast
|
||||
@ -23,13 +29,13 @@ import uy.kohesive.injekt.api.get
|
||||
class TrackSheet(
|
||||
val controller: MangaController,
|
||||
val manga: Manga,
|
||||
val fragmentManager: FragmentManager,
|
||||
private val sourceManager: SourceManager = Injekt.get()
|
||||
) : BaseBottomSheetDialog(controller.activity!!),
|
||||
TrackAdapter.OnClickListener,
|
||||
SetTrackStatusDialog.Listener,
|
||||
SetTrackChaptersDialog.Listener,
|
||||
SetTrackScoreDialog.Listener,
|
||||
SetTrackReadingDatesDialog.Listener {
|
||||
SetTrackScoreDialog.Listener {
|
||||
|
||||
private lateinit var binding: TrackControllerBinding
|
||||
|
||||
@ -63,7 +69,7 @@ class TrackSheet(
|
||||
}
|
||||
}
|
||||
|
||||
override fun onLogoClick(position: Int) {
|
||||
override fun onOpenInBrowserClick(position: Int) {
|
||||
val track = adapter.getItem(position)?.track ?: return
|
||||
|
||||
if (track.tracking_url.isNotBlank()) {
|
||||
@ -81,7 +87,7 @@ class TrackSheet(
|
||||
}
|
||||
|
||||
if (!item.service.accept(sourceManager.getOrStub(manga.source))) {
|
||||
controller.presenter.view?.applicationContext?.toast(string.source_unsupported)
|
||||
controller.presenter.view?.applicationContext?.toast(R.string.source_unsupported)
|
||||
return
|
||||
}
|
||||
|
||||
@ -90,9 +96,9 @@ class TrackSheet(
|
||||
item.service.match(manga)?.let { track ->
|
||||
controller.presenter.registerTracking(track, item.service)
|
||||
}
|
||||
?: withUIContext { controller.presenter.view?.applicationContext?.toast(string.error_no_match) }
|
||||
?: withUIContext { controller.presenter.view?.applicationContext?.toast(R.string.error_no_match) }
|
||||
} catch (e: Exception) {
|
||||
withUIContext { controller.presenter.view?.applicationContext?.toast(string.error_no_match) }
|
||||
withUIContext { controller.presenter.view?.applicationContext?.toast(R.string.error_no_match) }
|
||||
}
|
||||
}
|
||||
} else {
|
||||
@ -128,18 +134,74 @@ class TrackSheet(
|
||||
SetTrackScoreDialog(controller, this, item).showDialog(controller.router)
|
||||
}
|
||||
|
||||
override fun onStartDateClick(position: Int) {
|
||||
override fun onStartDateEditClick(position: Int) {
|
||||
val item = adapter.getItem(position) ?: return
|
||||
if (item.track == null) return
|
||||
|
||||
SetTrackReadingDatesDialog(controller, this, SetTrackReadingDatesDialog.ReadingDate.Start, item).showDialog(controller.router)
|
||||
val selection = item.track.started_reading_date.toUtcCalendar()?.timeInMillis
|
||||
?: MaterialDatePicker.todayInUtcMilliseconds()
|
||||
|
||||
// No time travellers allowed
|
||||
val constraints = CalendarConstraints.Builder().apply {
|
||||
val finishedMillis = item.track.finished_reading_date.toUtcCalendar()?.timeInMillis
|
||||
if (finishedMillis != null) {
|
||||
setValidator(DateValidatorPointBackward.before(finishedMillis))
|
||||
}
|
||||
}.build()
|
||||
|
||||
val picker = MaterialDatePicker.Builder.datePicker()
|
||||
.setTitleText(R.string.track_started_reading_date)
|
||||
.setSelection(selection)
|
||||
.setCalendarConstraints(constraints)
|
||||
.build()
|
||||
picker.addOnPositiveButtonClickListener {
|
||||
controller.presenter.setTrackerStartDate(item, it)
|
||||
}
|
||||
picker.show(fragmentManager, null)
|
||||
}
|
||||
|
||||
override fun onFinishDateClick(position: Int) {
|
||||
override fun onFinishDateEditClick(position: Int) {
|
||||
val item = adapter.getItem(position) ?: return
|
||||
if (item.track == null) return
|
||||
|
||||
SetTrackReadingDatesDialog(controller, this, SetTrackReadingDatesDialog.ReadingDate.Finish, item).showDialog(controller.router)
|
||||
val selection = item.track.finished_reading_date.toUtcCalendar()?.timeInMillis
|
||||
?: MaterialDatePicker.todayInUtcMilliseconds()
|
||||
|
||||
// No time travellers allowed
|
||||
val constraints = CalendarConstraints.Builder().apply {
|
||||
val startMillis = item.track.started_reading_date.toUtcCalendar()?.timeInMillis
|
||||
if (startMillis != null) {
|
||||
setValidator(DateValidatorPointForward.from(item.track.started_reading_date))
|
||||
}
|
||||
}.build()
|
||||
|
||||
val picker = MaterialDatePicker.Builder.datePicker()
|
||||
.setTitleText(R.string.track_finished_reading_date)
|
||||
.setSelection(selection)
|
||||
.setCalendarConstraints(constraints)
|
||||
.build()
|
||||
picker.addOnPositiveButtonClickListener {
|
||||
controller.presenter.setTrackerFinishDate(item, it)
|
||||
}
|
||||
picker.show(fragmentManager, null)
|
||||
}
|
||||
|
||||
override fun onStartDateRemoveClick(position: Int) {
|
||||
val item = adapter.getItem(position) ?: return
|
||||
if (item.track == null) return
|
||||
controller.presenter.setTrackerStartDate(item, 0)
|
||||
}
|
||||
|
||||
override fun onFinishDateRemoveClick(position: Int) {
|
||||
val item = adapter.getItem(position) ?: return
|
||||
if (item.track == null) return
|
||||
controller.presenter.setTrackerFinishDate(item, 0)
|
||||
}
|
||||
|
||||
override fun onRemoveItemClick(position: Int) {
|
||||
val item = adapter.getItem(position) ?: return
|
||||
if (item.track == null) return
|
||||
controller.presenter.unregisterTracking(item.service)
|
||||
}
|
||||
|
||||
override fun setStatus(item: TrackItem, selection: Int) {
|
||||
@ -154,13 +216,6 @@ class TrackSheet(
|
||||
controller.presenter.setTrackerScore(item, score)
|
||||
}
|
||||
|
||||
override fun setReadingDate(item: TrackItem, type: SetTrackReadingDatesDialog.ReadingDate, date: Long) {
|
||||
when (type) {
|
||||
SetTrackReadingDatesDialog.ReadingDate.Start -> controller.presenter.setTrackerStartDate(item, date)
|
||||
SetTrackReadingDatesDialog.ReadingDate.Finish -> controller.presenter.setTrackerFinishDate(item, date)
|
||||
}
|
||||
}
|
||||
|
||||
fun getSearchDialog(): TrackSearchDialog? {
|
||||
return controller.router.getControllerWithTag(TAG_SEARCH_CONTROLLER) as? TrackSearchDialog
|
||||
}
|
||||
|
@ -4,7 +4,7 @@ import android.app.Dialog
|
||||
import android.os.Bundle
|
||||
import androidx.core.os.bundleOf
|
||||
import androidx.preference.PreferenceScreen
|
||||
import com.afollestad.materialdialogs.MaterialDialog
|
||||
import com.google.android.material.dialog.MaterialAlertDialogBuilder
|
||||
import com.mikepenz.aboutlibraries.LibsBuilder
|
||||
import eu.kanade.tachiyomi.BuildConfig
|
||||
import eu.kanade.tachiyomi.R
|
||||
@ -133,10 +133,10 @@ class AboutController : SettingsController(), NoToolbarElevationController {
|
||||
)
|
||||
|
||||
override fun onCreateDialog(savedViewState: Bundle?): Dialog {
|
||||
return MaterialDialog(activity!!)
|
||||
.title(res = R.string.update_check_notification_update_available)
|
||||
.message(text = args.getString(BODY_KEY) ?: "")
|
||||
.positiveButton(R.string.update_check_confirm) {
|
||||
return MaterialAlertDialogBuilder(activity!!)
|
||||
.setTitle(R.string.update_check_notification_update_available)
|
||||
.setMessage(args.getString(BODY_KEY) ?: "")
|
||||
.setPositiveButton(R.string.update_check_confirm) { _, _ ->
|
||||
val appContext = applicationContext
|
||||
if (appContext != null) {
|
||||
// Start download
|
||||
@ -144,7 +144,8 @@ class AboutController : SettingsController(), NoToolbarElevationController {
|
||||
UpdaterService.start(appContext, url)
|
||||
}
|
||||
}
|
||||
.negativeButton(R.string.update_check_ignore)
|
||||
.setNegativeButton(R.string.update_check_ignore, null)
|
||||
.create()
|
||||
}
|
||||
|
||||
private companion object {
|
||||
|
@ -2,7 +2,7 @@ package eu.kanade.tachiyomi.ui.reader
|
||||
|
||||
import android.view.LayoutInflater
|
||||
import android.view.View
|
||||
import com.afollestad.materialdialogs.MaterialDialog
|
||||
import com.google.android.material.dialog.MaterialAlertDialogBuilder
|
||||
import eu.kanade.tachiyomi.R
|
||||
import eu.kanade.tachiyomi.databinding.ReaderPageSheetBinding
|
||||
import eu.kanade.tachiyomi.source.model.Page
|
||||
@ -35,13 +35,12 @@ class ReaderPageSheet(
|
||||
private fun setAsCover() {
|
||||
if (page.status != Page.READY) return
|
||||
|
||||
MaterialDialog(activity)
|
||||
.message(R.string.confirm_set_image_as_cover)
|
||||
.positiveButton(android.R.string.ok) {
|
||||
MaterialAlertDialogBuilder(activity)
|
||||
.setMessage(R.string.confirm_set_image_as_cover)
|
||||
.setPositiveButton(android.R.string.ok) { _, _ ->
|
||||
activity.setAsCover(page)
|
||||
dismiss()
|
||||
}
|
||||
.negativeButton(android.R.string.cancel)
|
||||
.setNegativeButton(android.R.string.cancel, null)
|
||||
.show()
|
||||
}
|
||||
|
||||
|
@ -9,7 +9,7 @@ import android.view.MenuItem
|
||||
import android.view.View
|
||||
import androidx.appcompat.widget.SearchView
|
||||
import androidx.recyclerview.widget.LinearLayoutManager
|
||||
import com.afollestad.materialdialogs.MaterialDialog
|
||||
import com.google.android.material.dialog.MaterialAlertDialogBuilder
|
||||
import dev.chrisbanes.insetter.applyInsetter
|
||||
import eu.davidea.flexibleadapter.FlexibleAdapter
|
||||
import eu.kanade.tachiyomi.R
|
||||
@ -221,12 +221,13 @@ class HistoryController :
|
||||
|
||||
class ClearHistoryDialogController : DialogController() {
|
||||
override fun onCreateDialog(savedViewState: Bundle?): Dialog {
|
||||
return MaterialDialog(activity!!)
|
||||
.message(R.string.clear_history_confirmation)
|
||||
.positiveButton(android.R.string.ok) {
|
||||
return MaterialAlertDialogBuilder(activity!!)
|
||||
.setMessage(R.string.clear_history_confirmation)
|
||||
.setPositiveButton(android.R.string.ok) { _, _ ->
|
||||
(targetController as? HistoryController)?.clearHistory()
|
||||
}
|
||||
.negativeButton(android.R.string.cancel)
|
||||
.setNegativeButton(android.R.string.cancel, null)
|
||||
.create()
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -2,9 +2,8 @@ package eu.kanade.tachiyomi.ui.recent.history
|
||||
|
||||
import android.app.Dialog
|
||||
import android.os.Bundle
|
||||
import com.afollestad.materialdialogs.MaterialDialog
|
||||
import com.afollestad.materialdialogs.customview.customView
|
||||
import com.bluelinelabs.conductor.Controller
|
||||
import com.google.android.material.dialog.MaterialAlertDialogBuilder
|
||||
import eu.kanade.tachiyomi.R
|
||||
import eu.kanade.tachiyomi.data.database.models.History
|
||||
import eu.kanade.tachiyomi.data.database.models.Manga
|
||||
@ -33,11 +32,12 @@ class RemoveHistoryDialog<T>(bundle: Bundle? = null) : DialogController(bundle)
|
||||
setOptionDescription(R.string.dialog_with_checkbox_reset)
|
||||
}
|
||||
|
||||
return MaterialDialog(activity)
|
||||
.title(R.string.action_remove)
|
||||
.customView(view = dialogCheckboxView, horizontalPadding = true)
|
||||
.positiveButton(R.string.action_remove) { onPositive(dialogCheckboxView.isChecked()) }
|
||||
.negativeButton(android.R.string.cancel)
|
||||
return MaterialAlertDialogBuilder(activity)
|
||||
.setTitle(R.string.action_remove)
|
||||
.setView(dialogCheckboxView)
|
||||
.setPositiveButton(R.string.action_remove) { _, _ -> onPositive(dialogCheckboxView.isChecked()) }
|
||||
.setNegativeButton(android.R.string.cancel, null)
|
||||
.create()
|
||||
}
|
||||
|
||||
private fun onPositive(checked: Boolean) {
|
||||
|
@ -2,8 +2,8 @@ package eu.kanade.tachiyomi.ui.recent.updates
|
||||
|
||||
import android.app.Dialog
|
||||
import android.os.Bundle
|
||||
import com.afollestad.materialdialogs.MaterialDialog
|
||||
import com.bluelinelabs.conductor.Controller
|
||||
import com.google.android.material.dialog.MaterialAlertDialogBuilder
|
||||
import eu.kanade.tachiyomi.R
|
||||
import eu.kanade.tachiyomi.ui.base.controller.DialogController
|
||||
|
||||
@ -18,12 +18,13 @@ class ConfirmDeleteChaptersDialog<T>(bundle: Bundle? = null) : DialogController(
|
||||
}
|
||||
|
||||
override fun onCreateDialog(savedViewState: Bundle?): Dialog {
|
||||
return MaterialDialog(activity!!)
|
||||
.message(R.string.confirm_delete_chapters)
|
||||
.positiveButton(android.R.string.ok) {
|
||||
return MaterialAlertDialogBuilder(activity!!)
|
||||
.setMessage(R.string.confirm_delete_chapters)
|
||||
.setPositiveButton(android.R.string.ok) { _, _ ->
|
||||
(targetController as? Listener)?.deleteChapters(chaptersToDelete)
|
||||
}
|
||||
.negativeButton(android.R.string.cancel)
|
||||
.setNegativeButton(android.R.string.cancel, null)
|
||||
.create()
|
||||
}
|
||||
|
||||
interface Listener {
|
||||
|
@ -8,7 +8,7 @@ import android.os.Bundle
|
||||
import android.provider.Settings
|
||||
import androidx.core.net.toUri
|
||||
import androidx.preference.PreferenceScreen
|
||||
import com.afollestad.materialdialogs.MaterialDialog
|
||||
import com.google.android.material.dialog.MaterialAlertDialogBuilder
|
||||
import eu.kanade.tachiyomi.BuildConfig
|
||||
import eu.kanade.tachiyomi.R
|
||||
import eu.kanade.tachiyomi.data.cache.ChapterCache
|
||||
@ -184,12 +184,13 @@ class SettingsAdvancedController : SettingsController() {
|
||||
|
||||
class ClearDatabaseDialogController : DialogController() {
|
||||
override fun onCreateDialog(savedViewState: Bundle?): Dialog {
|
||||
return MaterialDialog(activity!!)
|
||||
.message(R.string.clear_database_confirmation)
|
||||
.positiveButton(android.R.string.ok) {
|
||||
return MaterialAlertDialogBuilder(activity!!)
|
||||
.setMessage(R.string.clear_database_confirmation)
|
||||
.setPositiveButton(android.R.string.ok) { _, _ ->
|
||||
(targetController as? SettingsAdvancedController)?.clearDatabase()
|
||||
}
|
||||
.negativeButton(android.R.string.cancel)
|
||||
.setNegativeButton(android.R.string.cancel, null)
|
||||
.create()
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -9,12 +9,12 @@ import android.net.Uri
|
||||
import android.os.Bundle
|
||||
import android.view.View
|
||||
import android.widget.Toast
|
||||
import androidx.appcompat.app.AlertDialog
|
||||
import androidx.core.net.toUri
|
||||
import androidx.core.os.bundleOf
|
||||
import androidx.documentfile.provider.DocumentFile
|
||||
import androidx.preference.PreferenceScreen
|
||||
import com.afollestad.materialdialogs.MaterialDialog
|
||||
import com.afollestad.materialdialogs.list.listItemsMultiChoice
|
||||
import com.google.android.material.dialog.MaterialAlertDialogBuilder
|
||||
import com.hippo.unifile.UniFile
|
||||
import eu.kanade.tachiyomi.R
|
||||
import eu.kanade.tachiyomi.data.backup.BackupConst
|
||||
@ -246,29 +246,34 @@ class SettingsBackupController : SettingsController() {
|
||||
R.string.history
|
||||
)
|
||||
.map { activity.getString(it) }
|
||||
val selected = options.map { true }.toBooleanArray()
|
||||
|
||||
return MaterialDialog(activity)
|
||||
.title(R.string.pref_create_backup)
|
||||
.message(R.string.backup_choice)
|
||||
.listItemsMultiChoice(
|
||||
items = options,
|
||||
disabledIndices = intArrayOf(0),
|
||||
initialSelection = intArrayOf(0, 1, 2, 3, 4)
|
||||
) { _, positions, _ ->
|
||||
return MaterialAlertDialogBuilder(activity)
|
||||
.setTitle(R.string.backup_choice)
|
||||
.setMultiChoiceItems(options.toTypedArray(), selected) { dialog, which, checked ->
|
||||
if (which == 0) {
|
||||
(dialog as AlertDialog).listView.setItemChecked(which, true)
|
||||
} else {
|
||||
selected[which] = checked
|
||||
}
|
||||
}
|
||||
.setPositiveButton(R.string.action_create) { _, _ ->
|
||||
var flags = 0
|
||||
for (i in 1 until positions.size) {
|
||||
when (positions[i]) {
|
||||
1 -> flags = flags or BackupCreateService.BACKUP_CATEGORY
|
||||
2 -> flags = flags or BackupCreateService.BACKUP_CHAPTER
|
||||
3 -> flags = flags or BackupCreateService.BACKUP_TRACK
|
||||
4 -> flags = flags or BackupCreateService.BACKUP_HISTORY
|
||||
selected.forEachIndexed { i, checked ->
|
||||
if (checked) {
|
||||
when (i) {
|
||||
1 -> flags = flags or BackupCreateService.BACKUP_CATEGORY
|
||||
2 -> flags = flags or BackupCreateService.BACKUP_CHAPTER
|
||||
3 -> flags = flags or BackupCreateService.BACKUP_TRACK
|
||||
4 -> flags = flags or BackupCreateService.BACKUP_HISTORY
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
(targetController as? SettingsBackupController)?.createBackup(flags)
|
||||
}
|
||||
.positiveButton(R.string.action_create)
|
||||
.negativeButton(android.R.string.cancel)
|
||||
.setNegativeButton(android.R.string.cancel, null)
|
||||
.create()
|
||||
}
|
||||
}
|
||||
|
||||
@ -306,17 +311,19 @@ class SettingsBackupController : SettingsController() {
|
||||
message += "\n\n${activity.getString(R.string.backup_restore_missing_trackers)}\n${results.missingTrackers.joinToString("\n") { "- $it" }}"
|
||||
}
|
||||
|
||||
MaterialDialog(activity)
|
||||
.title(R.string.pref_restore_backup)
|
||||
.message(text = message)
|
||||
.positiveButton(R.string.action_restore) {
|
||||
MaterialAlertDialogBuilder(activity)
|
||||
.setTitle(R.string.pref_restore_backup)
|
||||
.setMessage(message)
|
||||
.setPositiveButton(R.string.action_restore) { _, _ ->
|
||||
BackupRestoreService.start(activity, uri, type)
|
||||
}
|
||||
.create()
|
||||
} catch (e: Exception) {
|
||||
MaterialDialog(activity)
|
||||
.title(R.string.invalid_backup_file)
|
||||
.message(text = e.message)
|
||||
.positiveButton(android.R.string.cancel)
|
||||
MaterialAlertDialogBuilder(activity)
|
||||
.setTitle(R.string.invalid_backup_file)
|
||||
.setMessage(e.message)
|
||||
.setPositiveButton(android.R.string.cancel, null)
|
||||
.create()
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -10,8 +10,7 @@ import androidx.core.content.ContextCompat
|
||||
import androidx.core.net.toUri
|
||||
import androidx.core.text.buildSpannedString
|
||||
import androidx.preference.PreferenceScreen
|
||||
import com.afollestad.materialdialogs.MaterialDialog
|
||||
import com.afollestad.materialdialogs.list.listItemsSingleChoice
|
||||
import com.google.android.material.dialog.MaterialAlertDialogBuilder
|
||||
import com.hippo.unifile.UniFile
|
||||
import eu.kanade.tachiyomi.R
|
||||
import eu.kanade.tachiyomi.data.database.DatabaseHelper
|
||||
@ -28,8 +27,8 @@ import eu.kanade.tachiyomi.util.preference.preferenceCategory
|
||||
import eu.kanade.tachiyomi.util.preference.switchPreference
|
||||
import eu.kanade.tachiyomi.util.preference.titleRes
|
||||
import eu.kanade.tachiyomi.util.system.toast
|
||||
import eu.kanade.tachiyomi.widget.materialdialogs.QuadStateCheckBox
|
||||
import eu.kanade.tachiyomi.widget.materialdialogs.listItemsQuadStateMultiChoice
|
||||
import eu.kanade.tachiyomi.widget.materialdialogs.QuadStateTextView
|
||||
import eu.kanade.tachiyomi.widget.materialdialogs.setQuadStateMultiChoiceItems
|
||||
import kotlinx.coroutines.flow.launchIn
|
||||
import kotlinx.coroutines.flow.onEach
|
||||
import uy.kohesive.injekt.Injekt
|
||||
@ -194,20 +193,22 @@ class SettingsDownloadController : SettingsController() {
|
||||
val activity = activity!!
|
||||
val currentDir = preferences.downloadsDirectory().get()
|
||||
val externalDirs = (getExternalDirs() + File(activity.getString(R.string.custom_dir))).map(File::toString)
|
||||
val selectedIndex = externalDirs.indexOfFirst { it in currentDir }
|
||||
var selectedIndex = externalDirs.indexOfFirst { it in currentDir }
|
||||
|
||||
return MaterialDialog(activity)
|
||||
.listItemsSingleChoice(
|
||||
items = externalDirs,
|
||||
initialSelection = selectedIndex
|
||||
) { _, position, text ->
|
||||
return MaterialAlertDialogBuilder(activity)
|
||||
.setTitle(R.string.pref_download_directory)
|
||||
.setSingleChoiceItems(externalDirs.toTypedArray(), selectedIndex) { _, which ->
|
||||
selectedIndex = which
|
||||
}
|
||||
.setPositiveButton(android.R.string.ok) { _, _ ->
|
||||
val target = targetController as? SettingsDownloadController
|
||||
if (position == externalDirs.lastIndex) {
|
||||
if (selectedIndex == externalDirs.lastIndex) {
|
||||
target?.customDirectorySelected()
|
||||
} else {
|
||||
target?.predefinedDirectorySelected(text.toString())
|
||||
target?.predefinedDirectorySelected(externalDirs[selectedIndex])
|
||||
}
|
||||
}
|
||||
.create()
|
||||
}
|
||||
|
||||
private fun getExternalDirs(): List<File> {
|
||||
@ -230,30 +231,33 @@ class SettingsDownloadController : SettingsController() {
|
||||
val categories = listOf(Category.createDefault()) + dbCategories
|
||||
|
||||
val items = categories.map { it.name }
|
||||
val preselected = categories
|
||||
var selected = categories
|
||||
.map {
|
||||
when (it.id.toString()) {
|
||||
in preferences.downloadNewCategories().get() -> QuadStateCheckBox.State.CHECKED.ordinal
|
||||
in preferences.downloadNewCategoriesExclude().get() -> QuadStateCheckBox.State.INVERSED.ordinal
|
||||
else -> QuadStateCheckBox.State.UNCHECKED.ordinal
|
||||
in preferences.downloadNewCategories().get() -> QuadStateTextView.State.CHECKED.ordinal
|
||||
in preferences.downloadNewCategoriesExclude().get() -> QuadStateTextView.State.INVERSED.ordinal
|
||||
else -> QuadStateTextView.State.UNCHECKED.ordinal
|
||||
}
|
||||
}
|
||||
.toIntArray()
|
||||
|
||||
return MaterialDialog(activity!!)
|
||||
.title(R.string.categories)
|
||||
.message(R.string.pref_download_new_categories_details)
|
||||
.listItemsQuadStateMultiChoice(
|
||||
return MaterialAlertDialogBuilder(activity!!)
|
||||
.setTitle(R.string.categories)
|
||||
.setMessage(R.string.pref_download_new_categories_details)
|
||||
.setQuadStateMultiChoiceItems(
|
||||
items = items,
|
||||
initialSelected = preselected
|
||||
initialSelected = selected
|
||||
) { selections ->
|
||||
val included = selections
|
||||
.mapIndexed { index, value -> if (value == QuadStateCheckBox.State.CHECKED.ordinal) index else null }
|
||||
selected = selections
|
||||
}
|
||||
.setPositiveButton(android.R.string.ok) { _, _ ->
|
||||
val included = selected
|
||||
.mapIndexed { index, value -> if (value == QuadStateTextView.State.CHECKED.ordinal) index else null }
|
||||
.filterNotNull()
|
||||
.map { categories[it].id.toString() }
|
||||
.toSet()
|
||||
val excluded = selections
|
||||
.mapIndexed { index, value -> if (value == QuadStateCheckBox.State.INVERSED.ordinal) index else null }
|
||||
val excluded = selected
|
||||
.mapIndexed { index, value -> if (value == QuadStateTextView.State.INVERSED.ordinal) index else null }
|
||||
.filterNotNull()
|
||||
.map { categories[it].id.toString() }
|
||||
.toSet()
|
||||
@ -261,8 +265,8 @@ class SettingsDownloadController : SettingsController() {
|
||||
preferences.downloadNewCategories().set(included)
|
||||
preferences.downloadNewCategoriesExclude().set(excluded)
|
||||
}
|
||||
.positiveButton(android.R.string.ok)
|
||||
.negativeButton(android.R.string.cancel)
|
||||
.setNegativeButton(android.R.string.cancel, null)
|
||||
.create()
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -2,12 +2,11 @@ package eu.kanade.tachiyomi.ui.setting
|
||||
|
||||
import android.app.Dialog
|
||||
import android.os.Bundle
|
||||
import android.view.View
|
||||
import android.view.LayoutInflater
|
||||
import androidx.core.content.ContextCompat
|
||||
import androidx.core.text.buildSpannedString
|
||||
import androidx.preference.PreferenceScreen
|
||||
import com.afollestad.materialdialogs.MaterialDialog
|
||||
import com.afollestad.materialdialogs.customview.customView
|
||||
import com.google.android.material.dialog.MaterialAlertDialogBuilder
|
||||
import eu.kanade.tachiyomi.R
|
||||
import eu.kanade.tachiyomi.data.database.DatabaseHelper
|
||||
import eu.kanade.tachiyomi.data.database.models.Category
|
||||
@ -17,6 +16,7 @@ import eu.kanade.tachiyomi.data.preference.PreferencesHelper
|
||||
import eu.kanade.tachiyomi.data.preference.UNMETERED_NETWORK
|
||||
import eu.kanade.tachiyomi.data.preference.asImmediateFlow
|
||||
import eu.kanade.tachiyomi.data.track.TrackManager
|
||||
import eu.kanade.tachiyomi.databinding.PrefLibraryColumnsBinding
|
||||
import eu.kanade.tachiyomi.ui.base.controller.DialogController
|
||||
import eu.kanade.tachiyomi.ui.base.controller.withFadeTransaction
|
||||
import eu.kanade.tachiyomi.ui.category.CategoryController
|
||||
@ -32,9 +32,8 @@ import eu.kanade.tachiyomi.util.preference.summaryRes
|
||||
import eu.kanade.tachiyomi.util.preference.switchPreference
|
||||
import eu.kanade.tachiyomi.util.preference.titleRes
|
||||
import eu.kanade.tachiyomi.util.system.isTablet
|
||||
import eu.kanade.tachiyomi.widget.MinMaxNumberPicker
|
||||
import eu.kanade.tachiyomi.widget.materialdialogs.QuadStateCheckBox
|
||||
import eu.kanade.tachiyomi.widget.materialdialogs.listItemsQuadStateMultiChoice
|
||||
import eu.kanade.tachiyomi.widget.materialdialogs.QuadStateTextView
|
||||
import eu.kanade.tachiyomi.widget.materialdialogs.setQuadStateMultiChoiceItems
|
||||
import kotlinx.coroutines.flow.combine
|
||||
import kotlinx.coroutines.flow.launchIn
|
||||
import kotlinx.coroutines.flow.onEach
|
||||
@ -299,21 +298,21 @@ class SettingsLibraryController : SettingsController() {
|
||||
private var landscape = preferences.landscapeColumns().get()
|
||||
|
||||
override fun onCreateDialog(savedViewState: Bundle?): Dialog {
|
||||
val dialog = MaterialDialog(activity!!)
|
||||
.title(R.string.pref_library_columns)
|
||||
.customView(R.layout.pref_library_columns, horizontalPadding = true)
|
||||
.positiveButton(android.R.string.ok) {
|
||||
val binding = PrefLibraryColumnsBinding.inflate(LayoutInflater.from(activity!!))
|
||||
onViewCreated(binding)
|
||||
return MaterialAlertDialogBuilder(activity!!)
|
||||
.setTitle(R.string.pref_library_columns)
|
||||
.setView(binding.root)
|
||||
.setPositiveButton(android.R.string.ok) { _, _ ->
|
||||
preferences.portraitColumns().set(portrait)
|
||||
preferences.landscapeColumns().set(landscape)
|
||||
}
|
||||
.negativeButton(android.R.string.cancel)
|
||||
|
||||
onViewCreated(dialog.view)
|
||||
return dialog
|
||||
.setNegativeButton(android.R.string.cancel, null)
|
||||
.create()
|
||||
}
|
||||
|
||||
fun onViewCreated(view: View) {
|
||||
with(view.findViewById(R.id.portrait_columns) as MinMaxNumberPicker) {
|
||||
fun onViewCreated(binding: PrefLibraryColumnsBinding) {
|
||||
with(binding.portraitColumns) {
|
||||
displayedValues = arrayOf(context.getString(R.string.default_columns)) +
|
||||
IntRange(1, 10).map(Int::toString)
|
||||
value = portrait
|
||||
@ -322,7 +321,7 @@ class SettingsLibraryController : SettingsController() {
|
||||
portrait = newValue
|
||||
}
|
||||
}
|
||||
with(view.findViewById(R.id.landscape_columns) as MinMaxNumberPicker) {
|
||||
with(binding.landscapeColumns) {
|
||||
displayedValues = arrayOf(context.getString(R.string.default_columns)) +
|
||||
IntRange(1, 10).map(Int::toString)
|
||||
value = landscape
|
||||
@ -344,30 +343,30 @@ class SettingsLibraryController : SettingsController() {
|
||||
val categories = listOf(Category.createDefault()) + dbCategories
|
||||
|
||||
val items = categories.map { it.name }
|
||||
val preselected = categories
|
||||
var selected = categories
|
||||
.map {
|
||||
when (it.id.toString()) {
|
||||
in preferences.libraryUpdateCategories().get() -> QuadStateCheckBox.State.CHECKED.ordinal
|
||||
in preferences.libraryUpdateCategoriesExclude().get() -> QuadStateCheckBox.State.INVERSED.ordinal
|
||||
else -> QuadStateCheckBox.State.UNCHECKED.ordinal
|
||||
in preferences.libraryUpdateCategories().get() -> QuadStateTextView.State.CHECKED.ordinal
|
||||
in preferences.libraryUpdateCategoriesExclude().get() -> QuadStateTextView.State.INVERSED.ordinal
|
||||
else -> QuadStateTextView.State.UNCHECKED.ordinal
|
||||
}
|
||||
}
|
||||
.toIntArray()
|
||||
|
||||
return MaterialDialog(activity!!)
|
||||
.title(R.string.categories)
|
||||
.message(R.string.pref_library_update_categories_details)
|
||||
.listItemsQuadStateMultiChoice(
|
||||
items = items,
|
||||
initialSelected = preselected
|
||||
) { selections ->
|
||||
val included = selections
|
||||
.mapIndexed { index, value -> if (value == QuadStateCheckBox.State.CHECKED.ordinal) index else null }
|
||||
return MaterialAlertDialogBuilder(activity!!)
|
||||
.setTitle(R.string.categories)
|
||||
.setMessage(R.string.pref_library_update_categories_details)
|
||||
.setQuadStateMultiChoiceItems(items = items, initialSelected = selected) { selections ->
|
||||
selected = selections
|
||||
}
|
||||
.setPositiveButton(android.R.string.ok) { _, _ ->
|
||||
val included = selected
|
||||
.mapIndexed { index, value -> if (value == QuadStateTextView.State.CHECKED.ordinal) index else null }
|
||||
.filterNotNull()
|
||||
.map { categories[it].id.toString() }
|
||||
.toSet()
|
||||
val excluded = selections
|
||||
.mapIndexed { index, value -> if (value == QuadStateCheckBox.State.INVERSED.ordinal) index else null }
|
||||
val excluded = selected
|
||||
.mapIndexed { index, value -> if (value == QuadStateTextView.State.INVERSED.ordinal) index else null }
|
||||
.filterNotNull()
|
||||
.map { categories[it].id.toString() }
|
||||
.toSet()
|
||||
@ -375,8 +374,8 @@ class SettingsLibraryController : SettingsController() {
|
||||
preferences.libraryUpdateCategories().set(included)
|
||||
preferences.libraryUpdateCategoriesExclude().set(excluded)
|
||||
}
|
||||
.positiveButton(android.R.string.ok)
|
||||
.negativeButton(android.R.string.cancel)
|
||||
.setNegativeButton(android.R.string.cancel, null)
|
||||
.create()
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -3,7 +3,7 @@ package eu.kanade.tachiyomi.ui.setting.track
|
||||
import android.app.Dialog
|
||||
import android.os.Bundle
|
||||
import androidx.core.os.bundleOf
|
||||
import com.afollestad.materialdialogs.MaterialDialog
|
||||
import com.google.android.material.dialog.MaterialAlertDialogBuilder
|
||||
import eu.kanade.tachiyomi.R
|
||||
import eu.kanade.tachiyomi.data.track.TrackManager
|
||||
import eu.kanade.tachiyomi.data.track.TrackService
|
||||
@ -20,14 +20,15 @@ class TrackLogoutDialog(bundle: Bundle? = null) : DialogController(bundle) {
|
||||
|
||||
override fun onCreateDialog(savedViewState: Bundle?): Dialog {
|
||||
val serviceName = activity!!.getString(service.nameRes())
|
||||
return MaterialDialog(activity!!)
|
||||
.title(text = activity!!.getString(R.string.logout_title, serviceName))
|
||||
.positiveButton(R.string.logout) {
|
||||
return MaterialAlertDialogBuilder(activity!!)
|
||||
.setTitle(activity!!.getString(R.string.logout_title, serviceName))
|
||||
.setPositiveButton(R.string.logout) { _, _ ->
|
||||
service.logout()
|
||||
(targetController as? Listener)?.trackLogoutDialogClosed(service)
|
||||
activity?.toast(R.string.logout_success)
|
||||
}
|
||||
.negativeButton(android.R.string.cancel)
|
||||
.setNegativeButton(android.R.string.cancel, null)
|
||||
.create()
|
||||
}
|
||||
|
||||
interface Listener {
|
||||
|
@ -3,6 +3,7 @@ package eu.kanade.tachiyomi.util.lang
|
||||
import java.text.DateFormat
|
||||
import java.util.Calendar
|
||||
import java.util.Date
|
||||
import java.util.TimeZone
|
||||
|
||||
fun Date.toDateTimestampString(dateFormatter: DateFormat): String {
|
||||
val date = dateFormatter.format(this)
|
||||
@ -43,3 +44,28 @@ fun Long.toCalendar(): Calendar? {
|
||||
cal.timeInMillis = this
|
||||
return cal
|
||||
}
|
||||
|
||||
/**
|
||||
* Convert epoch long to Calendar instance in UTC
|
||||
*
|
||||
* @return UTC Calendar instance at supplied epoch time. Null if epoch was 0.
|
||||
*/
|
||||
fun Long.toUtcCalendar(): Calendar? {
|
||||
if (this == 0L) {
|
||||
return null
|
||||
}
|
||||
val rawCalendar = Calendar.getInstance().apply {
|
||||
timeInMillis = this@toUtcCalendar
|
||||
}
|
||||
return Calendar.getInstance(TimeZone.getTimeZone("UTC")).apply {
|
||||
clear()
|
||||
set(
|
||||
rawCalendar.get(Calendar.YEAR),
|
||||
rawCalendar.get(Calendar.MONTH),
|
||||
rawCalendar.get(Calendar.DAY_OF_MONTH),
|
||||
rawCalendar.get(Calendar.HOUR_OF_DAY),
|
||||
rawCalendar.get(Calendar.MINUTE),
|
||||
rawCalendar.get(Calendar.SECOND)
|
||||
)
|
||||
}
|
||||
}
|
||||
|
@ -0,0 +1,54 @@
|
||||
package eu.kanade.tachiyomi.widget.materialdialogs
|
||||
|
||||
import android.view.LayoutInflater
|
||||
import android.view.inputmethod.InputMethodManager
|
||||
import android.widget.TextView
|
||||
import androidx.core.content.getSystemService
|
||||
import androidx.core.widget.doAfterTextChanged
|
||||
import androidx.recyclerview.widget.LinearLayoutManager
|
||||
import com.google.android.material.dialog.MaterialAlertDialogBuilder
|
||||
import eu.kanade.tachiyomi.databinding.DialogStubQuadstatemultichoiceBinding
|
||||
import eu.kanade.tachiyomi.databinding.DialogStubTextinputBinding
|
||||
|
||||
fun MaterialAlertDialogBuilder.setTextInput(
|
||||
hint: String? = null,
|
||||
prefill: String? = null,
|
||||
onTextChanged: (String) -> Unit
|
||||
): MaterialAlertDialogBuilder {
|
||||
val binding = DialogStubTextinputBinding.inflate(LayoutInflater.from(context))
|
||||
binding.textField.hint = hint
|
||||
binding.textField.editText?.apply {
|
||||
setText(prefill, TextView.BufferType.EDITABLE)
|
||||
doAfterTextChanged {
|
||||
onTextChanged(it?.toString() ?: "")
|
||||
}
|
||||
post {
|
||||
requestFocusFromTouch()
|
||||
context.getSystemService<InputMethodManager>()?.showSoftInput(this, 0)
|
||||
}
|
||||
}
|
||||
return setView(binding.root)
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets a list of items with checkboxes that supports 4 states.
|
||||
*
|
||||
* @see eu.kanade.tachiyomi.widget.materialdialogs.QuadStateTextView
|
||||
*/
|
||||
fun MaterialAlertDialogBuilder.setQuadStateMultiChoiceItems(
|
||||
items: List<CharSequence>,
|
||||
initialSelected: IntArray,
|
||||
disabledIndices: IntArray? = null,
|
||||
selection: QuadStateMultiChoiceListener
|
||||
): MaterialAlertDialogBuilder {
|
||||
val binding = DialogStubQuadstatemultichoiceBinding.inflate(LayoutInflater.from(context))
|
||||
binding.list.layoutManager = LinearLayoutManager(context)
|
||||
binding.list.adapter = QuadStateMultiChoiceDialogAdapter(
|
||||
items = items,
|
||||
disabledItems = disabledIndices,
|
||||
initialSelected = initialSelected,
|
||||
listener = selection
|
||||
)
|
||||
setView(binding.root)
|
||||
return this
|
||||
}
|
@ -1,26 +0,0 @@
|
||||
package eu.kanade.tachiyomi.widget.materialdialogs
|
||||
|
||||
import androidx.annotation.CheckResult
|
||||
import com.afollestad.materialdialogs.MaterialDialog
|
||||
import com.afollestad.materialdialogs.list.customListAdapter
|
||||
|
||||
/**
|
||||
* A variant of listItemsMultiChoice that allows for checkboxes that supports 4 states instead.
|
||||
*/
|
||||
@CheckResult
|
||||
fun MaterialDialog.listItemsQuadStateMultiChoice(
|
||||
items: List<CharSequence>,
|
||||
disabledIndices: IntArray? = null,
|
||||
initialSelected: IntArray = IntArray(items.size),
|
||||
selection: QuadStateMultiChoiceListener
|
||||
): MaterialDialog {
|
||||
return customListAdapter(
|
||||
QuadStateMultiChoiceDialogAdapter(
|
||||
dialog = this,
|
||||
items = items,
|
||||
disabledItems = disabledIndices,
|
||||
initialSelected = initialSelected,
|
||||
selection = selection
|
||||
)
|
||||
)
|
||||
}
|
@ -1,34 +0,0 @@
|
||||
package eu.kanade.tachiyomi.widget.materialdialogs
|
||||
|
||||
import android.content.Context
|
||||
import android.util.AttributeSet
|
||||
import androidx.appcompat.widget.AppCompatImageView
|
||||
import eu.kanade.tachiyomi.R
|
||||
import eu.kanade.tachiyomi.util.view.setVectorCompat
|
||||
|
||||
class QuadStateCheckBox @JvmOverloads constructor(context: Context, attrs: AttributeSet? = null) :
|
||||
AppCompatImageView(context, attrs) {
|
||||
|
||||
var state: State = State.UNCHECKED
|
||||
set(value) {
|
||||
field = value
|
||||
updateDrawable()
|
||||
}
|
||||
|
||||
private fun updateDrawable() {
|
||||
when (state) {
|
||||
State.UNCHECKED -> setVectorCompat(R.drawable.ic_check_box_outline_blank_24dp, R.attr.colorControlNormal)
|
||||
State.INDETERMINATE -> setVectorCompat(R.drawable.ic_indeterminate_check_box_24dp, R.attr.colorAccent)
|
||||
State.CHECKED -> setVectorCompat(R.drawable.ic_check_box_24dp, R.attr.colorAccent)
|
||||
State.INVERSED -> setVectorCompat(R.drawable.ic_check_box_x_24dp, R.attr.colorAccent)
|
||||
}
|
||||
}
|
||||
|
||||
enum class State {
|
||||
UNCHECKED,
|
||||
INDETERMINATE,
|
||||
CHECKED,
|
||||
INVERSED,
|
||||
;
|
||||
}
|
||||
}
|
@ -1,14 +1,9 @@
|
||||
package eu.kanade.tachiyomi.widget.materialdialogs
|
||||
|
||||
import android.view.View
|
||||
import android.view.LayoutInflater
|
||||
import android.view.ViewGroup
|
||||
import androidx.recyclerview.widget.RecyclerView
|
||||
import com.afollestad.materialdialogs.MaterialDialog
|
||||
import com.afollestad.materialdialogs.internal.list.DialogAdapter
|
||||
import com.afollestad.materialdialogs.list.getItemSelector
|
||||
import com.afollestad.materialdialogs.utils.MDUtil.inflate
|
||||
import com.afollestad.materialdialogs.utils.MDUtil.maybeSetTextColor
|
||||
import eu.kanade.tachiyomi.R
|
||||
import eu.kanade.tachiyomi.databinding.DialogQuadstatemultichoiceItemBinding
|
||||
|
||||
private object CheckPayload
|
||||
private object InverseCheckPayload
|
||||
@ -17,15 +12,13 @@ private object UncheckPayload
|
||||
typealias QuadStateMultiChoiceListener = (indices: IntArray) -> Unit
|
||||
|
||||
internal class QuadStateMultiChoiceDialogAdapter(
|
||||
private var dialog: MaterialDialog,
|
||||
internal var items: List<CharSequence>,
|
||||
disabledItems: IntArray?,
|
||||
initialSelected: IntArray,
|
||||
internal var selection: QuadStateMultiChoiceListener
|
||||
) : RecyclerView.Adapter<QuadStateMultiChoiceViewHolder>(),
|
||||
DialogAdapter<CharSequence, QuadStateMultiChoiceListener> {
|
||||
internal var listener: QuadStateMultiChoiceListener
|
||||
) : RecyclerView.Adapter<QuadStateMultiChoiceViewHolder>() {
|
||||
|
||||
private val states = QuadStateCheckBox.State.values()
|
||||
private val states = QuadStateTextView.State.values()
|
||||
|
||||
private var currentSelection: IntArray = initialSelected
|
||||
set(value) {
|
||||
@ -34,15 +27,15 @@ internal class QuadStateMultiChoiceDialogAdapter(
|
||||
previousSelection.forEachIndexed { index, previous ->
|
||||
val current = value[index]
|
||||
when {
|
||||
current == QuadStateCheckBox.State.CHECKED.ordinal && previous != QuadStateCheckBox.State.CHECKED.ordinal -> {
|
||||
current == QuadStateTextView.State.CHECKED.ordinal && previous != QuadStateTextView.State.CHECKED.ordinal -> {
|
||||
// This value was selected
|
||||
notifyItemChanged(index, CheckPayload)
|
||||
}
|
||||
current == QuadStateCheckBox.State.INVERSED.ordinal && previous != QuadStateCheckBox.State.INVERSED.ordinal -> {
|
||||
current == QuadStateTextView.State.INVERSED.ordinal && previous != QuadStateTextView.State.INVERSED.ordinal -> {
|
||||
// This value was inverse selected
|
||||
notifyItemChanged(index, InverseCheckPayload)
|
||||
}
|
||||
current == QuadStateCheckBox.State.UNCHECKED.ordinal && previous != QuadStateCheckBox.State.UNCHECKED.ordinal -> {
|
||||
current == QuadStateTextView.State.UNCHECKED.ordinal && previous != QuadStateTextView.State.UNCHECKED.ordinal -> {
|
||||
// This value was unselected
|
||||
notifyItemChanged(index, UncheckPayload)
|
||||
}
|
||||
@ -54,26 +47,24 @@ internal class QuadStateMultiChoiceDialogAdapter(
|
||||
internal fun itemClicked(index: Int) {
|
||||
val newSelection = this.currentSelection.toMutableList()
|
||||
newSelection[index] = when (currentSelection[index]) {
|
||||
QuadStateCheckBox.State.CHECKED.ordinal -> QuadStateCheckBox.State.INVERSED.ordinal
|
||||
QuadStateCheckBox.State.INVERSED.ordinal -> QuadStateCheckBox.State.UNCHECKED.ordinal
|
||||
QuadStateTextView.State.CHECKED.ordinal -> QuadStateTextView.State.INVERSED.ordinal
|
||||
QuadStateTextView.State.INVERSED.ordinal -> QuadStateTextView.State.UNCHECKED.ordinal
|
||||
// INDETERMINATE or UNCHECKED
|
||||
else -> QuadStateCheckBox.State.CHECKED.ordinal
|
||||
else -> QuadStateTextView.State.CHECKED.ordinal
|
||||
}
|
||||
this.currentSelection = newSelection.toIntArray()
|
||||
listener(currentSelection)
|
||||
}
|
||||
|
||||
override fun onCreateViewHolder(
|
||||
parent: ViewGroup,
|
||||
viewType: Int
|
||||
): QuadStateMultiChoiceViewHolder {
|
||||
val listItemView: View = parent.inflate(dialog.windowContext, R.layout.md_listitem_quadstatemultichoice)
|
||||
val viewHolder = QuadStateMultiChoiceViewHolder(
|
||||
itemView = listItemView,
|
||||
return QuadStateMultiChoiceViewHolder(
|
||||
itemBinding = DialogQuadstatemultichoiceItemBinding
|
||||
.inflate(LayoutInflater.from(parent.context), parent, false),
|
||||
adapter = this
|
||||
)
|
||||
viewHolder.titleView.maybeSetTextColor(dialog.windowContext, R.attr.md_color_content)
|
||||
|
||||
return viewHolder
|
||||
}
|
||||
|
||||
override fun getItemCount() = items.size
|
||||
@ -83,14 +74,8 @@ internal class QuadStateMultiChoiceDialogAdapter(
|
||||
position: Int
|
||||
) {
|
||||
holder.isEnabled = !disabledIndices.contains(position)
|
||||
|
||||
holder.controlView.state = states[currentSelection[position]]
|
||||
holder.titleView.text = items[position]
|
||||
holder.itemView.background = dialog.getItemSelector()
|
||||
|
||||
if (dialog.bodyFont != null) {
|
||||
holder.titleView.typeface = dialog.bodyFont
|
||||
}
|
||||
holder.controlView.text = items[position]
|
||||
}
|
||||
|
||||
override fun onBindViewHolder(
|
||||
@ -100,88 +85,18 @@ internal class QuadStateMultiChoiceDialogAdapter(
|
||||
) {
|
||||
when (payloads.firstOrNull()) {
|
||||
CheckPayload -> {
|
||||
holder.controlView.state = QuadStateCheckBox.State.CHECKED
|
||||
holder.controlView.state = QuadStateTextView.State.CHECKED
|
||||
return
|
||||
}
|
||||
InverseCheckPayload -> {
|
||||
holder.controlView.state = QuadStateCheckBox.State.INVERSED
|
||||
holder.controlView.state = QuadStateTextView.State.INVERSED
|
||||
return
|
||||
}
|
||||
UncheckPayload -> {
|
||||
holder.controlView.state = QuadStateCheckBox.State.UNCHECKED
|
||||
holder.controlView.state = QuadStateTextView.State.UNCHECKED
|
||||
return
|
||||
}
|
||||
}
|
||||
super.onBindViewHolder(holder, position, payloads)
|
||||
}
|
||||
|
||||
override fun positiveButtonClicked() {
|
||||
selection.invoke(currentSelection)
|
||||
}
|
||||
|
||||
override fun replaceItems(
|
||||
items: List<CharSequence>,
|
||||
listener: QuadStateMultiChoiceListener?
|
||||
) {
|
||||
this.items = items
|
||||
if (listener != null) {
|
||||
this.selection = listener
|
||||
}
|
||||
this.notifyDataSetChanged()
|
||||
}
|
||||
|
||||
override fun disableItems(indices: IntArray) {
|
||||
this.disabledIndices = indices
|
||||
notifyDataSetChanged()
|
||||
}
|
||||
|
||||
override fun checkItems(indices: IntArray) {
|
||||
val newSelection = this.currentSelection.toMutableList()
|
||||
for (index in indices) {
|
||||
newSelection[index] = QuadStateCheckBox.State.CHECKED.ordinal
|
||||
}
|
||||
this.currentSelection = newSelection.toIntArray()
|
||||
}
|
||||
|
||||
override fun uncheckItems(indices: IntArray) {
|
||||
val newSelection = this.currentSelection.toMutableList()
|
||||
for (index in indices) {
|
||||
newSelection[index] = QuadStateCheckBox.State.UNCHECKED.ordinal
|
||||
}
|
||||
this.currentSelection = newSelection.toIntArray()
|
||||
}
|
||||
|
||||
override fun toggleItems(indices: IntArray) {
|
||||
val newSelection = this.currentSelection.toMutableList()
|
||||
for (index in indices) {
|
||||
if (this.disabledIndices.contains(index)) {
|
||||
continue
|
||||
}
|
||||
|
||||
if (this.currentSelection[index] != QuadStateCheckBox.State.CHECKED.ordinal) {
|
||||
newSelection[index] = QuadStateCheckBox.State.CHECKED.ordinal
|
||||
} else {
|
||||
newSelection[index] = QuadStateCheckBox.State.UNCHECKED.ordinal
|
||||
}
|
||||
}
|
||||
this.currentSelection = newSelection.toIntArray()
|
||||
}
|
||||
|
||||
override fun checkAllItems() {
|
||||
this.currentSelection = IntArray(itemCount) { QuadStateCheckBox.State.CHECKED.ordinal }
|
||||
}
|
||||
|
||||
override fun uncheckAllItems() {
|
||||
this.currentSelection = IntArray(itemCount) { QuadStateCheckBox.State.UNCHECKED.ordinal }
|
||||
}
|
||||
|
||||
override fun toggleAllChecked() {
|
||||
if (this.currentSelection.any { it != QuadStateCheckBox.State.CHECKED.ordinal }) {
|
||||
checkAllItems()
|
||||
} else {
|
||||
uncheckAllItems()
|
||||
}
|
||||
}
|
||||
|
||||
override fun isItemChecked(index: Int) = this.currentSelection[index] == QuadStateCheckBox.State.CHECKED.ordinal
|
||||
}
|
||||
|
@ -1,27 +1,24 @@
|
||||
package eu.kanade.tachiyomi.widget.materialdialogs
|
||||
|
||||
import android.view.View
|
||||
import android.widget.TextView
|
||||
import androidx.recyclerview.widget.RecyclerView
|
||||
import eu.kanade.tachiyomi.R
|
||||
import eu.kanade.tachiyomi.databinding.DialogQuadstatemultichoiceItemBinding
|
||||
|
||||
internal class QuadStateMultiChoiceViewHolder(
|
||||
itemView: View,
|
||||
itemBinding: DialogQuadstatemultichoiceItemBinding,
|
||||
private val adapter: QuadStateMultiChoiceDialogAdapter
|
||||
) : RecyclerView.ViewHolder(itemView), View.OnClickListener {
|
||||
) : RecyclerView.ViewHolder(itemBinding.root), View.OnClickListener {
|
||||
init {
|
||||
itemView.setOnClickListener(this)
|
||||
}
|
||||
|
||||
val controlView: QuadStateCheckBox = itemView.findViewById(R.id.md_quad_state_control)
|
||||
val titleView: TextView = itemView.findViewById(R.id.md_quad_state_title)
|
||||
val controlView = itemBinding.quadStateControl
|
||||
|
||||
var isEnabled: Boolean
|
||||
get() = itemView.isEnabled
|
||||
set(value) {
|
||||
itemView.isEnabled = value
|
||||
controlView.isEnabled = value
|
||||
titleView.isEnabled = value
|
||||
}
|
||||
|
||||
override fun onClick(view: View) = adapter.itemClicked(bindingAdapterPosition)
|
||||
|
@ -0,0 +1,45 @@
|
||||
package eu.kanade.tachiyomi.widget.materialdialogs
|
||||
|
||||
import android.content.Context
|
||||
import android.content.res.ColorStateList
|
||||
import android.util.AttributeSet
|
||||
import androidx.appcompat.widget.AppCompatTextView
|
||||
import com.mikepenz.aboutlibraries.util.getThemeColor
|
||||
import eu.kanade.tachiyomi.R
|
||||
|
||||
class QuadStateTextView @JvmOverloads constructor(context: Context, attrs: AttributeSet? = null) :
|
||||
AppCompatTextView(context, attrs) {
|
||||
|
||||
var state: State = State.UNCHECKED
|
||||
set(value) {
|
||||
field = value
|
||||
updateDrawable()
|
||||
}
|
||||
|
||||
private fun updateDrawable() {
|
||||
val drawableStartId = when (state) {
|
||||
State.UNCHECKED -> R.drawable.ic_check_box_outline_blank_24dp
|
||||
State.INDETERMINATE -> R.drawable.ic_indeterminate_check_box_24dp
|
||||
State.CHECKED -> R.drawable.ic_check_box_24dp
|
||||
State.INVERSED -> R.drawable.ic_check_box_x_24dp
|
||||
}
|
||||
setCompoundDrawablesRelativeWithIntrinsicBounds(drawableStartId, 0, 0, 0)
|
||||
|
||||
val tint = if (state == State.UNCHECKED) {
|
||||
context.getThemeColor(R.attr.colorControlNormal)
|
||||
} else {
|
||||
context.getThemeColor(R.attr.colorAccent)
|
||||
}
|
||||
if (tint != 0) {
|
||||
compoundDrawableTintList = ColorStateList.valueOf(tint)
|
||||
}
|
||||
}
|
||||
|
||||
enum class State {
|
||||
UNCHECKED,
|
||||
INDETERMINATE,
|
||||
CHECKED,
|
||||
INVERSED,
|
||||
;
|
||||
}
|
||||
}
|
@ -5,11 +5,10 @@ import android.os.Bundle
|
||||
import android.view.LayoutInflater
|
||||
import android.view.View
|
||||
import androidx.annotation.StringRes
|
||||
import com.afollestad.materialdialogs.MaterialDialog
|
||||
import com.afollestad.materialdialogs.customview.customView
|
||||
import com.bluelinelabs.conductor.ControllerChangeHandler
|
||||
import com.bluelinelabs.conductor.ControllerChangeType
|
||||
import com.dd.processbutton.iml.ActionProcessButton
|
||||
import com.google.android.material.dialog.MaterialAlertDialogBuilder
|
||||
import eu.kanade.tachiyomi.R
|
||||
import eu.kanade.tachiyomi.data.preference.PreferencesHelper
|
||||
import eu.kanade.tachiyomi.databinding.PrefAccountLoginBinding
|
||||
@ -28,15 +27,13 @@ abstract class LoginDialogPreference(
|
||||
|
||||
override fun onCreateDialog(savedViewState: Bundle?): Dialog {
|
||||
binding = PrefAccountLoginBinding.inflate(LayoutInflater.from(activity!!))
|
||||
onViewCreated(binding!!.root)
|
||||
val titleName = activity!!.getString(getTitleName())
|
||||
val dialog = MaterialDialog(activity!!)
|
||||
.title(text = activity!!.getString(R.string.login_title, titleName))
|
||||
.customView(view = binding!!.root)
|
||||
.negativeButton(android.R.string.cancel)
|
||||
|
||||
onViewCreated(dialog.view)
|
||||
|
||||
return dialog
|
||||
return MaterialAlertDialogBuilder(activity!!)
|
||||
.setTitle(activity!!.getString(R.string.login_title, titleName))
|
||||
.setView(binding!!.root)
|
||||
.setNegativeButton(android.R.string.cancel, null)
|
||||
.create()
|
||||
}
|
||||
|
||||
fun onViewCreated(view: View) {
|
||||
|
10
app/src/main/res/drawable/ic_more_vert_24.xml
Normal file
10
app/src/main/res/drawable/ic_more_vert_24.xml
Normal file
@ -0,0 +1,10 @@
|
||||
<vector xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
android:width="24dp"
|
||||
android:height="24dp"
|
||||
android:viewportWidth="24"
|
||||
android:viewportHeight="24"
|
||||
android:tint="?attr/colorControlNormal">
|
||||
<path
|
||||
android:fillColor="@android:color/white"
|
||||
android:pathData="M12,8c1.1,0 2,-0.9 2,-2s-0.9,-2 -2,-2 -2,0.9 -2,2 0.9,2 2,2zM12,10c-1.1,0 -2,0.9 -2,2s0.9,2 2,2 2,-0.9 2,-2 -0.9,-2 -2,-2zM12,16c-1.1,0 -2,0.9 -2,2s0.9,2 2,2 2,-0.9 2,-2 -0.9,-2 -2,-2z"/>
|
||||
</vector>
|
@ -2,7 +2,9 @@
|
||||
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:orientation="vertical">
|
||||
android:orientation="vertical"
|
||||
android:paddingHorizontal="24dp"
|
||||
android:paddingTop="16dp">
|
||||
|
||||
<TextView
|
||||
android:id="@+id/description"
|
||||
@ -15,7 +17,7 @@
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_marginStart="-5dp"
|
||||
android:layout_marginTop="24dp"
|
||||
android:layout_marginTop="16dp"
|
||||
android:layout_marginEnd="0dp" />
|
||||
|
||||
</LinearLayout>
|
||||
|
18
app/src/main/res/layout/dialog_quadstatemultichoice_item.xml
Normal file
18
app/src/main/res/layout/dialog_quadstatemultichoice_item.xml
Normal file
@ -0,0 +1,18 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<eu.kanade.tachiyomi.widget.materialdialogs.QuadStateTextView xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
xmlns:tools="http://schemas.android.com/tools"
|
||||
xmlns:app="http://schemas.android.com/apk/res-auto"
|
||||
style="?attr/materialAlertDialogBodyTextStyle"
|
||||
android:id="@+id/quad_state_control"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:background="?attr/selectableItemBackground"
|
||||
android:minHeight="?attr/listPreferredItemHeightSmall"
|
||||
android:gravity="start|center_vertical"
|
||||
android:textAlignment="viewStart"
|
||||
android:paddingStart="@dimen/abc_select_dialog_padding_start_material"
|
||||
android:paddingEnd="?attr/dialogPreferredPadding"
|
||||
android:drawablePadding="20dp"
|
||||
android:ellipsize="marquee"
|
||||
app:drawableStartCompat="@drawable/ic_check_box_outline_blank_24dp"
|
||||
tools:text="Quad-state item" />
|
@ -0,0 +1,9 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<androidx.recyclerview.widget.RecyclerView xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
xmlns:tools="http://schemas.android.com/tools"
|
||||
android:id="@+id/list"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:paddingTop="8dp"
|
||||
android:scrollIndicators="none"
|
||||
tools:listitem="@layout/dialog_quadstatemultichoice_item" />
|
20
app/src/main/res/layout/dialog_stub_textinput.xml
Normal file
20
app/src/main/res/layout/dialog_stub_textinput.xml
Normal file
@ -0,0 +1,20 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<FrameLayout xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="match_parent"
|
||||
android:paddingHorizontal="24dp"
|
||||
android:paddingVertical="16dp">
|
||||
|
||||
<com.google.android.material.textfield.TextInputLayout
|
||||
style="@style/Widget.MaterialComponents.TextInputLayout.OutlinedBox"
|
||||
android:id="@+id/text_field"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content">
|
||||
|
||||
<com.google.android.material.textfield.TextInputEditText
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content" />
|
||||
|
||||
</com.google.android.material.textfield.TextInputLayout>
|
||||
|
||||
</FrameLayout>
|
@ -4,7 +4,8 @@
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:gravity="center"
|
||||
android:orientation="horizontal">
|
||||
android:orientation="horizontal"
|
||||
android:paddingVertical="8dp">
|
||||
|
||||
<androidx.appcompat.widget.AppCompatImageButton
|
||||
android:id="@+id/btn_decrease_10"
|
||||
|
@ -1,15 +0,0 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
xmlns:tools="http://schemas.android.com/tools"
|
||||
style="@style/MD_ListItem.Choice">
|
||||
|
||||
<eu.kanade.tachiyomi.widget.materialdialogs.QuadStateCheckBox
|
||||
android:id="@+id/md_quad_state_control"
|
||||
style="@style/MD_ListItem_Control" />
|
||||
|
||||
<com.afollestad.materialdialogs.internal.rtl.RtlTextView
|
||||
android:id="@+id/md_quad_state_title"
|
||||
style="@style/MD_ListItemText.Choice"
|
||||
tools:text="Item" />
|
||||
|
||||
</LinearLayout>
|
@ -20,9 +20,6 @@
|
||||
android:id="@+id/logo_container"
|
||||
android:layout_width="48dp"
|
||||
android:layout_height="48dp"
|
||||
android:clickable="true"
|
||||
android:focusable="true"
|
||||
android:foreground="?attr/selectableItemBackground"
|
||||
app:cardBackgroundColor="#2E51A2"
|
||||
app:cardElevation="0dp"
|
||||
app:shapeAppearanceOverlay="@style/ShapeAppearanceOverlay.MaterialCardView.Tracker">
|
||||
@ -54,8 +51,9 @@
|
||||
|
||||
<TextView
|
||||
android:id="@+id/track_title"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_width="0dp"
|
||||
android:layout_height="48dp"
|
||||
android:layout_weight="1"
|
||||
android:ellipsize="end"
|
||||
android:foreground="?attr/selectableItemBackgroundBorderless"
|
||||
android:gravity="center_vertical"
|
||||
@ -64,6 +62,16 @@
|
||||
android:textAppearance="?attr/textAppearanceSubtitle1"
|
||||
tools:text="Title" />
|
||||
|
||||
<ImageButton
|
||||
android:id="@+id/more"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_gravity="center_vertical"
|
||||
android:background="?selectableItemBackgroundBorderless"
|
||||
android:contentDescription="@string/label_more"
|
||||
android:padding="8dp"
|
||||
android:src="@drawable/ic_more_vert_24" />
|
||||
|
||||
</LinearLayout>
|
||||
|
||||
</LinearLayout>
|
||||
@ -100,11 +108,11 @@
|
||||
android:textAppearance="?attr/textAppearanceBody2"
|
||||
tools:text="Reading" />
|
||||
|
||||
<View
|
||||
android:id="@+id/vert_divider_1"
|
||||
android:layout_width="1dp"
|
||||
android:layout_height="match_parent"
|
||||
android:background="?android:divider" />
|
||||
<View
|
||||
android:id="@+id/vert_divider_1"
|
||||
android:layout_width="1dp"
|
||||
android:layout_height="match_parent"
|
||||
android:background="?android:divider" />
|
||||
|
||||
<TextView
|
||||
android:id="@+id/track_chapters"
|
||||
@ -119,11 +127,11 @@
|
||||
android:textAppearance="?attr/textAppearanceBody2"
|
||||
tools:text="12/24" />
|
||||
|
||||
<View
|
||||
android:id="@+id/vert_divider_2"
|
||||
android:layout_width="1dp"
|
||||
android:layout_height="match_parent"
|
||||
android:background="?android:divider"/>
|
||||
<View
|
||||
android:id="@+id/vert_divider_2"
|
||||
android:layout_width="1dp"
|
||||
android:layout_height="match_parent"
|
||||
android:background="?android:divider" />
|
||||
|
||||
<TextView
|
||||
android:id="@+id/track_score"
|
||||
@ -165,11 +173,11 @@
|
||||
android:textAppearance="?attr/textAppearanceBody2"
|
||||
tools:text="4/16/2020" />
|
||||
|
||||
<View
|
||||
android:id="@+id/vert_divider_3"
|
||||
android:layout_width="1dp"
|
||||
android:layout_height="match_parent"
|
||||
android:background="?android:divider" />
|
||||
<View
|
||||
android:id="@+id/vert_divider_3"
|
||||
android:layout_width="1dp"
|
||||
android:layout_height="match_parent"
|
||||
android:background="?android:divider" />
|
||||
|
||||
<TextView
|
||||
android:id="@+id/track_finish_date"
|
||||
|
15
app/src/main/res/menu/track_item.xml
Normal file
15
app/src/main/res/menu/track_item.xml
Normal file
@ -0,0 +1,15 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<menu xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
xmlns:app="http://schemas.android.com/apk/res-auto">
|
||||
|
||||
<item
|
||||
android:id="@+id/action_open_in_browser"
|
||||
android:title="@string/action_open_in_browser"
|
||||
app:showAsAction="never" />
|
||||
|
||||
<item
|
||||
android:id="@+id/action_remove"
|
||||
android:title="@string/action_remove"
|
||||
app:showAsAction="never" />
|
||||
|
||||
</menu>
|
15
app/src/main/res/menu/track_item_date.xml
Normal file
15
app/src/main/res/menu/track_item_date.xml
Normal file
@ -0,0 +1,15 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<menu xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
xmlns:app="http://schemas.android.com/apk/res-auto">
|
||||
|
||||
<item
|
||||
android:id="@+id/action_edit"
|
||||
android:title="@string/action_edit"
|
||||
app:showAsAction="never" />
|
||||
|
||||
<item
|
||||
android:id="@+id/action_remove"
|
||||
android:title="@string/action_remove"
|
||||
app:showAsAction="never" />
|
||||
|
||||
</menu>
|
@ -2,14 +2,6 @@
|
||||
<menu xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
xmlns:app="http://schemas.android.com/apk/res-auto">
|
||||
|
||||
<item
|
||||
android:id="@+id/remove"
|
||||
android:icon="@drawable/ic_delete_24dp"
|
||||
android:title="@string/action_remove"
|
||||
android:visible="false"
|
||||
app:iconTint="?attr/colorOnToolbar"
|
||||
app:showAsAction="ifRoom" />
|
||||
|
||||
<item
|
||||
android:id="@+id/done"
|
||||
android:enabled="false"
|
||||
|
@ -17,7 +17,4 @@
|
||||
<dimen name="screen_edge_margin">16dp</dimen>
|
||||
|
||||
<dimen name="tablet_horizontal_cover_margin">128dp</dimen>
|
||||
|
||||
<!-- material-dialogs button radius -->
|
||||
<dimen name="md_action_button_corner_radius">4dp</dimen>
|
||||
</resources>
|
||||
|
@ -300,21 +300,6 @@
|
||||
<item name="android:textSize">15sp</item>
|
||||
</style>
|
||||
|
||||
<!--================================-->
|
||||
<!--material-dialogs style overrides-->
|
||||
<!--================================-->
|
||||
<style name="MD_Light" parent="ThemeOverlay.MaterialComponents.Dialog.Alert">
|
||||
<item name="md_divider_color">@color/md_divider_light_theme</item>
|
||||
<item name="md_item_selector">@drawable/md_item_selector</item>
|
||||
<item name="md_button_selector">@drawable/md_btn_selector</item>
|
||||
</style>
|
||||
|
||||
<style name="MD_Dark" parent="ThemeOverlay.MaterialComponents.Dialog.Alert">
|
||||
<item name="md_divider_color">@color/md_divider_dark_theme</item>
|
||||
<item name="md_item_selector">@drawable/md_item_selector_dark</item>
|
||||
<item name="md_button_selector">@drawable/md_btn_selector_dark</item>
|
||||
</style>
|
||||
|
||||
<!--================-->
|
||||
<!--Shape Appearance-->
|
||||
<!--================-->
|
||||
|
@ -67,14 +67,6 @@
|
||||
<item name="elevationOverlayEnabled">false</item>
|
||||
<item name="lightSystemBarsOnPrimary">false</item>
|
||||
|
||||
<!-- Material Dialogs -->
|
||||
<item name="md_background_color">?attr/colorSurface</item>
|
||||
<item name="md_color_title">?attr/colorOnSurface</item>
|
||||
<item name="md_color_content">?attr/colorOnSurface</item>
|
||||
<item name="md_color_button_text">?attr/colorPrimary</item>
|
||||
<item name="md_button_casing">literal</item>
|
||||
<item name="md_corner_radius">@dimen/dialog_radius</item>
|
||||
|
||||
<!-- Custom Attributes-->
|
||||
<item name="colorFilterActive">@color/filter_light</item>
|
||||
</style>
|
||||
|
Loading…
Reference in New Issue
Block a user