From ae97bb04458c6a754c6e0ca05a2a3b96ce16894f Mon Sep 17 00:00:00 2001 From: Ivan Iskandar <12537387+ivaniskandar@users.noreply.github.com> Date: Thu, 15 Jul 2021 05:04:03 +0700 Subject: [PATCH] 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 --- app/build.gradle.kts | 6 - .../data/track/anilist/AnilistApi.kt | 9 +- .../browse/extension/ExtensionTrustDialog.kt | 13 +- .../migration/search/SearchController.kt | 44 +++---- .../ui/browse/source/SourceController.kt | 13 +- .../source/browse/BrowseSourceController.kt | 11 +- .../ui/category/CategoryCreateDialog.kt | 20 ++- .../ui/category/CategoryRenameDialog.kt | 20 ++- .../ui/library/ChangeMangaCategoriesDialog.kt | 41 +++--- .../ui/library/ChangeMangaCoverDialog.kt | 13 +- .../ui/library/DeleteLibraryMangasDialog.kt | 27 ++-- .../ui/main/WhatsNewDialogController.kt | 11 +- .../tachiyomi/ui/manga/MangaController.kt | 2 +- .../ui/manga/chapter/DeleteChaptersDialog.kt | 11 +- .../chapter/DownloadCustomChaptersDialog.kt | 14 +- .../manga/chapter/SetChapterSettingsDialog.kt | 17 +-- .../ui/manga/track/SetTrackChaptersDialog.kt | 35 ++--- .../manga/track/SetTrackReadingDatesDialog.kt | 87 ------------- .../ui/manga/track/SetTrackScoreDialog.kt | 35 ++--- .../ui/manga/track/SetTrackStatusDialog.kt | 25 ++-- .../tachiyomi/ui/manga/track/TrackAdapter.kt | 10 +- .../tachiyomi/ui/manga/track/TrackHolder.kt | 44 ++++++- .../ui/manga/track/TrackSearchDialog.kt | 5 - .../tachiyomi/ui/manga/track/TrackSheet.kt | 91 ++++++++++--- .../tachiyomi/ui/more/AboutController.kt | 13 +- .../tachiyomi/ui/reader/ReaderPageSheet.kt | 11 +- .../ui/recent/history/HistoryController.kt | 11 +- .../ui/recent/history/RemoveHistoryDialog.kt | 14 +- .../updates/ConfirmDeleteChaptersDialog.kt | 11 +- .../ui/setting/SettingsAdvancedController.kt | 11 +- .../ui/setting/SettingsBackupController.kt | 59 +++++---- .../ui/setting/SettingsDownloadController.kt | 58 +++++---- .../ui/setting/SettingsLibraryController.kt | 67 +++++----- .../ui/setting/track/TrackLogoutDialog.kt | 11 +- .../tachiyomi/util/lang/DateExtensions.kt | 26 ++++ .../MaterialAlertDialogBuilderExtensions.kt | 54 ++++++++ .../MaterialDialogMultiChoiceExt.kt | 26 ---- .../materialdialogs/QuadStateCheckBox.kt | 34 ----- .../QuadStateMultiChoiceDialogAdapter.kt | 123 +++--------------- .../QuadStateMultiChoiceViewHolder.kt | 11 +- .../materialdialogs/QuadStateTextView.kt | 45 +++++++ .../preference/LoginDialogPreference.kt | 17 +-- app/src/main/res/drawable/ic_more_vert_24.xml | 10 ++ .../layout/common_dialog_with_checkbox.xml | 6 +- .../dialog_quadstatemultichoice_item.xml | 18 +++ .../dialog_stub_quadstatemultichoice.xml | 9 ++ .../main/res/layout/dialog_stub_textinput.xml | 20 +++ .../res/layout/download_custom_amount.xml | 3 +- .../md_listitem_quadstatemultichoice.xml | 15 --- app/src/main/res/layout/track_item.xml | 46 ++++--- app/src/main/res/menu/track_item.xml | 15 +++ app/src/main/res/menu/track_item_date.xml | 15 +++ app/src/main/res/menu/track_search.xml | 8 -- app/src/main/res/values/dimens.xml | 3 - app/src/main/res/values/styles.xml | 15 --- app/src/main/res/values/themes.xml | 8 -- 56 files changed, 701 insertions(+), 696 deletions(-) delete mode 100644 app/src/main/java/eu/kanade/tachiyomi/ui/manga/track/SetTrackReadingDatesDialog.kt create mode 100644 app/src/main/java/eu/kanade/tachiyomi/widget/materialdialogs/MaterialAlertDialogBuilderExtensions.kt delete mode 100644 app/src/main/java/eu/kanade/tachiyomi/widget/materialdialogs/MaterialDialogMultiChoiceExt.kt delete mode 100644 app/src/main/java/eu/kanade/tachiyomi/widget/materialdialogs/QuadStateCheckBox.kt create mode 100644 app/src/main/java/eu/kanade/tachiyomi/widget/materialdialogs/QuadStateTextView.kt create mode 100644 app/src/main/res/drawable/ic_more_vert_24.xml create mode 100644 app/src/main/res/layout/dialog_quadstatemultichoice_item.xml create mode 100644 app/src/main/res/layout/dialog_stub_quadstatemultichoice.xml create mode 100644 app/src/main/res/layout/dialog_stub_textinput.xml delete mode 100644 app/src/main/res/layout/md_listitem_quadstatemultichoice.xml create mode 100644 app/src/main/res/menu/track_item.xml create mode 100644 app/src/main/res/menu/track_item_date.xml diff --git a/app/build.gradle.kts b/app/build.gradle.kts index b88f8710c2..406c52182b 100644 --- a/app/build.gradle.kts +++ b/app/build.gradle.kts @@ -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") diff --git a/app/src/main/java/eu/kanade/tachiyomi/data/track/anilist/AnilistApi.kt b/app/src/main/java/eu/kanade/tachiyomi/data/track/anilist/AnilistApi.kt index fcc4cdc27b..758423b155 100644 --- a/app/src/main/java/eu/kanade/tachiyomi/data/track/anilist/AnilistApi.kt +++ b/app/src/main/java/eu/kanade/tachiyomi/data/track/anilist/AnilistApi.kt @@ -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)) } } diff --git a/app/src/main/java/eu/kanade/tachiyomi/ui/browse/extension/ExtensionTrustDialog.kt b/app/src/main/java/eu/kanade/tachiyomi/ui/browse/extension/ExtensionTrustDialog.kt index ef82c62111..644ec93812 100644 --- a/app/src/main/java/eu/kanade/tachiyomi/ui/browse/extension/ExtensionTrustDialog.kt +++ b/app/src/main/java/eu/kanade/tachiyomi/ui/browse/extension/ExtensionTrustDialog.kt @@ -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(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 { diff --git a/app/src/main/java/eu/kanade/tachiyomi/ui/browse/migration/search/SearchController.kt b/app/src/main/java/eu/kanade/tachiyomi/ui/browse/migration/search/SearchController.kt index cd8912f8ea..079dc2808a 100644 --- a/app/src/main/java/eu/kanade/tachiyomi/ui/browse/migration/search/SearchController.kt +++ b/app/src/main/java/eu/kanade/tachiyomi/ui/browse/migration/search/SearchController.kt @@ -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() + 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() } } diff --git a/app/src/main/java/eu/kanade/tachiyomi/ui/browse/source/SourceController.kt b/app/src/main/java/eu/kanade/tachiyomi/ui/browse/source/SourceController.kt index d9c3aad7af..02383e9fd8 100644 --- a/app/src/main/java/eu/kanade/tachiyomi/ui/browse/source/SourceController.kt +++ b/app/src/main/java/eu/kanade/tachiyomi/ui/browse/source/SourceController.kt @@ -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() } } diff --git a/app/src/main/java/eu/kanade/tachiyomi/ui/browse/source/browse/BrowseSourceController.kt b/app/src/main/java/eu/kanade/tachiyomi/ui/browse/source/browse/BrowseSourceController.kt index 29d70ba10f..d1809901b9 100644 --- a/app/src/main/java/eu/kanade/tachiyomi/ui/browse/source/browse/BrowseSourceController.kt +++ b/app/src/main/java/eu/kanade/tachiyomi/ui/browse/source/browse/BrowseSourceController.kt @@ -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) diff --git a/app/src/main/java/eu/kanade/tachiyomi/ui/category/CategoryCreateDialog.kt b/app/src/main/java/eu/kanade/tachiyomi/ui/category/CategoryCreateDialog.kt index bdaa51ad14..8134ee5017 100644 --- a/app/src/main/java/eu/kanade/tachiyomi/ui/category/CategoryCreateDialog.kt +++ b/app/src/main/java/eu/kanade/tachiyomi/ui/category/CategoryCreateDialog.kt @@ -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(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 { diff --git a/app/src/main/java/eu/kanade/tachiyomi/ui/category/CategoryRenameDialog.kt b/app/src/main/java/eu/kanade/tachiyomi/ui/category/CategoryRenameDialog.kt index ac1073b654..2910eb1e1d 100644 --- a/app/src/main/java/eu/kanade/tachiyomi/ui/category/CategoryRenameDialog.kt +++ b/app/src/main/java/eu/kanade/tachiyomi/ui/category/CategoryRenameDialog.kt @@ -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(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() } /** diff --git a/app/src/main/java/eu/kanade/tachiyomi/ui/library/ChangeMangaCategoriesDialog.kt b/app/src/main/java/eu/kanade/tachiyomi/ui/library/ChangeMangaCategoriesDialog.kt index f0dad157be..a443b8b2e9 100644 --- a/app/src/main/java/eu/kanade/tachiyomi/ui/library/ChangeMangaCategoriesDialog.kt +++ b/app/src/main/java/eu/kanade/tachiyomi/ui/library/ChangeMangaCategoriesDialog.kt @@ -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(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 { diff --git a/app/src/main/java/eu/kanade/tachiyomi/ui/library/ChangeMangaCoverDialog.kt b/app/src/main/java/eu/kanade/tachiyomi/ui/library/ChangeMangaCoverDialog.kt index 68485a4da8..d3bfb3603a 100644 --- a/app/src/main/java/eu/kanade/tachiyomi/ui/library/ChangeMangaCoverDialog.kt +++ b/app/src/main/java/eu/kanade/tachiyomi/ui/library/ChangeMangaCoverDialog.kt @@ -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(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 { diff --git a/app/src/main/java/eu/kanade/tachiyomi/ui/library/DeleteLibraryMangasDialog.kt b/app/src/main/java/eu/kanade/tachiyomi/ui/library/DeleteLibraryMangasDialog.kt index 4cd2f2bede..aa0d437703 100644 --- a/app/src/main/java/eu/kanade/tachiyomi/ui/library/DeleteLibraryMangasDialog.kt +++ b/app/src/main/java/eu/kanade/tachiyomi/ui/library/DeleteLibraryMangasDialog.kt @@ -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(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 { diff --git a/app/src/main/java/eu/kanade/tachiyomi/ui/main/WhatsNewDialogController.kt b/app/src/main/java/eu/kanade/tachiyomi/ui/main/WhatsNewDialogController.kt index 23e56b89b8..9cedc6c2cf 100644 --- a/app/src/main/java/eu/kanade/tachiyomi/ui/main/WhatsNewDialogController.kt +++ b/app/src/main/java/eu/kanade/tachiyomi/ui/main/WhatsNewDialogController.kt @@ -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() } } diff --git a/app/src/main/java/eu/kanade/tachiyomi/ui/manga/MangaController.kt b/app/src/main/java/eu/kanade/tachiyomi/ui/manga/MangaController.kt index d068cbd03e..e0a61591ab 100644 --- a/app/src/main/java/eu/kanade/tachiyomi/ui/manga/MangaController.kt +++ b/app/src/main/java/eu/kanade/tachiyomi/ui/manga/MangaController.kt @@ -289,7 +289,7 @@ class MangaController : } } - trackSheet = TrackSheet(this, manga!!) + trackSheet = TrackSheet(this, manga!!, (activity as MainActivity).supportFragmentManager) updateFilterIconState() } diff --git a/app/src/main/java/eu/kanade/tachiyomi/ui/manga/chapter/DeleteChaptersDialog.kt b/app/src/main/java/eu/kanade/tachiyomi/ui/manga/chapter/DeleteChaptersDialog.kt index 5c0f95271f..81177d46a1 100644 --- a/app/src/main/java/eu/kanade/tachiyomi/ui/manga/chapter/DeleteChaptersDialog.kt +++ b/app/src/main/java/eu/kanade/tachiyomi/ui/manga/chapter/DeleteChaptersDialog.kt @@ -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(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 { diff --git a/app/src/main/java/eu/kanade/tachiyomi/ui/manga/chapter/DownloadCustomChaptersDialog.kt b/app/src/main/java/eu/kanade/tachiyomi/ui/manga/chapter/DownloadCustomChaptersDialog.kt index ffec86ec7b..903c1f85a1 100644 --- a/app/src/main/java/eu/kanade/tachiyomi/ui/manga/chapter/DownloadCustomChaptersDialog.kt +++ b/app/src/main/java/eu/kanade/tachiyomi/ui/manga/chapter/DownloadCustomChaptersDialog.kt @@ -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 : 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 { diff --git a/app/src/main/java/eu/kanade/tachiyomi/ui/manga/chapter/SetChapterSettingsDialog.kt b/app/src/main/java/eu/kanade/tachiyomi/ui/manga/chapter/SetChapterSettingsDialog.kt index 40c1bd3bec..b867726397 100644 --- a/app/src/main/java/eu/kanade/tachiyomi/ui/manga/chapter/SetChapterSettingsDialog.kt +++ b/app/src/main/java/eu/kanade/tachiyomi/ui/manga/chapter/SetChapterSettingsDialog.kt @@ -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 { diff --git a/app/src/main/java/eu/kanade/tachiyomi/ui/manga/track/SetTrackChaptersDialog.kt b/app/src/main/java/eu/kanade/tachiyomi/ui/manga/track/SetTrackChaptersDialog.kt index f12e6d6ddf..e5c25db2ba 100644 --- a/app/src/main/java/eu/kanade/tachiyomi/ui/manga/track/SetTrackChaptersDialog.kt +++ b/app/src/main/java/eu/kanade/tachiyomi/ui/manga/track/SetTrackChaptersDialog.kt @@ -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 : 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 : 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 { diff --git a/app/src/main/java/eu/kanade/tachiyomi/ui/manga/track/SetTrackReadingDatesDialog.kt b/app/src/main/java/eu/kanade/tachiyomi/ui/manga/track/SetTrackReadingDatesDialog.kt deleted file mode 100644 index 34e1cfeba1..0000000000 --- a/app/src/main/java/eu/kanade/tachiyomi/ui/manga/track/SetTrackReadingDatesDialog.kt +++ /dev/null @@ -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 : 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().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" - } -} diff --git a/app/src/main/java/eu/kanade/tachiyomi/ui/manga/track/SetTrackScoreDialog.kt b/app/src/main/java/eu/kanade/tachiyomi/ui/manga/track/SetTrackScoreDialog.kt index 8277a58657..b70f1eb67c 100644 --- a/app/src/main/java/eu/kanade/tachiyomi/ui/manga/track/SetTrackScoreDialog.kt +++ b/app/src/main/java/eu/kanade/tachiyomi/ui/manga/track/SetTrackScoreDialog.kt @@ -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 : 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 : 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 { diff --git a/app/src/main/java/eu/kanade/tachiyomi/ui/manga/track/SetTrackStatusDialog.kt b/app/src/main/java/eu/kanade/tachiyomi/ui/manga/track/SetTrackStatusDialog.kt index 4753a41729..13aa209cee 100644 --- a/app/src/main/java/eu/kanade/tachiyomi/ui/manga/track/SetTrackStatusDialog.kt +++ b/app/src/main/java/eu/kanade/tachiyomi/ui/manga/track/SetTrackStatusDialog.kt @@ -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 : 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 { diff --git a/app/src/main/java/eu/kanade/tachiyomi/ui/manga/track/TrackAdapter.kt b/app/src/main/java/eu/kanade/tachiyomi/ui/manga/track/TrackAdapter.kt index 49d49240ab..05eca06989 100644 --- a/app/src/main/java/eu/kanade/tachiyomi/ui/manga/track/TrackAdapter.kt +++ b/app/src/main/java/eu/kanade/tachiyomi/ui/manga/track/TrackAdapter.kt @@ -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() { @@ -40,13 +39,16 @@ class TrackAdapter(listener: OnClickListener) : RecyclerView.Adapter 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) + } + } + } + } } } diff --git a/app/src/main/java/eu/kanade/tachiyomi/ui/manga/track/TrackSearchDialog.kt b/app/src/main/java/eu/kanade/tachiyomi/ui/manga/track/TrackSearchDialog.kt index a770e02d12..441c3943d5 100644 --- a/app/src/main/java/eu/kanade/tachiyomi/ui/manga/track/TrackSearchDialog.kt +++ b/app/src/main/java/eu/kanade/tachiyomi/ui/manga/track/TrackSearchDialog.kt @@ -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 -> diff --git a/app/src/main/java/eu/kanade/tachiyomi/ui/manga/track/TrackSheet.kt b/app/src/main/java/eu/kanade/tachiyomi/ui/manga/track/TrackSheet.kt index bccca0c6aa..33506fb91c 100644 --- a/app/src/main/java/eu/kanade/tachiyomi/ui/manga/track/TrackSheet.kt +++ b/app/src/main/java/eu/kanade/tachiyomi/ui/manga/track/TrackSheet.kt @@ -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 } diff --git a/app/src/main/java/eu/kanade/tachiyomi/ui/more/AboutController.kt b/app/src/main/java/eu/kanade/tachiyomi/ui/more/AboutController.kt index 0f880a541a..a1fe18be5c 100644 --- a/app/src/main/java/eu/kanade/tachiyomi/ui/more/AboutController.kt +++ b/app/src/main/java/eu/kanade/tachiyomi/ui/more/AboutController.kt @@ -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 { diff --git a/app/src/main/java/eu/kanade/tachiyomi/ui/reader/ReaderPageSheet.kt b/app/src/main/java/eu/kanade/tachiyomi/ui/reader/ReaderPageSheet.kt index 21ce88725a..e47ac8a9f7 100644 --- a/app/src/main/java/eu/kanade/tachiyomi/ui/reader/ReaderPageSheet.kt +++ b/app/src/main/java/eu/kanade/tachiyomi/ui/reader/ReaderPageSheet.kt @@ -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() } diff --git a/app/src/main/java/eu/kanade/tachiyomi/ui/recent/history/HistoryController.kt b/app/src/main/java/eu/kanade/tachiyomi/ui/recent/history/HistoryController.kt index 511acf043b..a4dcd26e56 100644 --- a/app/src/main/java/eu/kanade/tachiyomi/ui/recent/history/HistoryController.kt +++ b/app/src/main/java/eu/kanade/tachiyomi/ui/recent/history/HistoryController.kt @@ -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() } } diff --git a/app/src/main/java/eu/kanade/tachiyomi/ui/recent/history/RemoveHistoryDialog.kt b/app/src/main/java/eu/kanade/tachiyomi/ui/recent/history/RemoveHistoryDialog.kt index faeb1373ce..6243ed1d82 100644 --- a/app/src/main/java/eu/kanade/tachiyomi/ui/recent/history/RemoveHistoryDialog.kt +++ b/app/src/main/java/eu/kanade/tachiyomi/ui/recent/history/RemoveHistoryDialog.kt @@ -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(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) { diff --git a/app/src/main/java/eu/kanade/tachiyomi/ui/recent/updates/ConfirmDeleteChaptersDialog.kt b/app/src/main/java/eu/kanade/tachiyomi/ui/recent/updates/ConfirmDeleteChaptersDialog.kt index 4d4c048069..221037e450 100644 --- a/app/src/main/java/eu/kanade/tachiyomi/ui/recent/updates/ConfirmDeleteChaptersDialog.kt +++ b/app/src/main/java/eu/kanade/tachiyomi/ui/recent/updates/ConfirmDeleteChaptersDialog.kt @@ -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(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 { diff --git a/app/src/main/java/eu/kanade/tachiyomi/ui/setting/SettingsAdvancedController.kt b/app/src/main/java/eu/kanade/tachiyomi/ui/setting/SettingsAdvancedController.kt index 3b11796002..0b0d8c9cac 100644 --- a/app/src/main/java/eu/kanade/tachiyomi/ui/setting/SettingsAdvancedController.kt +++ b/app/src/main/java/eu/kanade/tachiyomi/ui/setting/SettingsAdvancedController.kt @@ -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() } } diff --git a/app/src/main/java/eu/kanade/tachiyomi/ui/setting/SettingsBackupController.kt b/app/src/main/java/eu/kanade/tachiyomi/ui/setting/SettingsBackupController.kt index f90538467d..94fe870c8c 100644 --- a/app/src/main/java/eu/kanade/tachiyomi/ui/setting/SettingsBackupController.kt +++ b/app/src/main/java/eu/kanade/tachiyomi/ui/setting/SettingsBackupController.kt @@ -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() } } diff --git a/app/src/main/java/eu/kanade/tachiyomi/ui/setting/SettingsDownloadController.kt b/app/src/main/java/eu/kanade/tachiyomi/ui/setting/SettingsDownloadController.kt index 48b0eee937..18e5a1e717 100644 --- a/app/src/main/java/eu/kanade/tachiyomi/ui/setting/SettingsDownloadController.kt +++ b/app/src/main/java/eu/kanade/tachiyomi/ui/setting/SettingsDownloadController.kt @@ -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 { @@ -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() } } diff --git a/app/src/main/java/eu/kanade/tachiyomi/ui/setting/SettingsLibraryController.kt b/app/src/main/java/eu/kanade/tachiyomi/ui/setting/SettingsLibraryController.kt index 7f3f358471..892e440bee 100644 --- a/app/src/main/java/eu/kanade/tachiyomi/ui/setting/SettingsLibraryController.kt +++ b/app/src/main/java/eu/kanade/tachiyomi/ui/setting/SettingsLibraryController.kt @@ -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() } } } diff --git a/app/src/main/java/eu/kanade/tachiyomi/ui/setting/track/TrackLogoutDialog.kt b/app/src/main/java/eu/kanade/tachiyomi/ui/setting/track/TrackLogoutDialog.kt index 308dbd08d3..0f89efdb59 100644 --- a/app/src/main/java/eu/kanade/tachiyomi/ui/setting/track/TrackLogoutDialog.kt +++ b/app/src/main/java/eu/kanade/tachiyomi/ui/setting/track/TrackLogoutDialog.kt @@ -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 { diff --git a/app/src/main/java/eu/kanade/tachiyomi/util/lang/DateExtensions.kt b/app/src/main/java/eu/kanade/tachiyomi/util/lang/DateExtensions.kt index 2b4f4d8af4..310b698d04 100644 --- a/app/src/main/java/eu/kanade/tachiyomi/util/lang/DateExtensions.kt +++ b/app/src/main/java/eu/kanade/tachiyomi/util/lang/DateExtensions.kt @@ -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) + ) + } +} diff --git a/app/src/main/java/eu/kanade/tachiyomi/widget/materialdialogs/MaterialAlertDialogBuilderExtensions.kt b/app/src/main/java/eu/kanade/tachiyomi/widget/materialdialogs/MaterialAlertDialogBuilderExtensions.kt new file mode 100644 index 0000000000..ea2f66c7f0 --- /dev/null +++ b/app/src/main/java/eu/kanade/tachiyomi/widget/materialdialogs/MaterialAlertDialogBuilderExtensions.kt @@ -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()?.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, + 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 +} diff --git a/app/src/main/java/eu/kanade/tachiyomi/widget/materialdialogs/MaterialDialogMultiChoiceExt.kt b/app/src/main/java/eu/kanade/tachiyomi/widget/materialdialogs/MaterialDialogMultiChoiceExt.kt deleted file mode 100644 index b44abf88f3..0000000000 --- a/app/src/main/java/eu/kanade/tachiyomi/widget/materialdialogs/MaterialDialogMultiChoiceExt.kt +++ /dev/null @@ -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, - disabledIndices: IntArray? = null, - initialSelected: IntArray = IntArray(items.size), - selection: QuadStateMultiChoiceListener -): MaterialDialog { - return customListAdapter( - QuadStateMultiChoiceDialogAdapter( - dialog = this, - items = items, - disabledItems = disabledIndices, - initialSelected = initialSelected, - selection = selection - ) - ) -} diff --git a/app/src/main/java/eu/kanade/tachiyomi/widget/materialdialogs/QuadStateCheckBox.kt b/app/src/main/java/eu/kanade/tachiyomi/widget/materialdialogs/QuadStateCheckBox.kt deleted file mode 100644 index b01d224374..0000000000 --- a/app/src/main/java/eu/kanade/tachiyomi/widget/materialdialogs/QuadStateCheckBox.kt +++ /dev/null @@ -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, - ; - } -} diff --git a/app/src/main/java/eu/kanade/tachiyomi/widget/materialdialogs/QuadStateMultiChoiceDialogAdapter.kt b/app/src/main/java/eu/kanade/tachiyomi/widget/materialdialogs/QuadStateMultiChoiceDialogAdapter.kt index 5d40486672..9fcf299337 100644 --- a/app/src/main/java/eu/kanade/tachiyomi/widget/materialdialogs/QuadStateMultiChoiceDialogAdapter.kt +++ b/app/src/main/java/eu/kanade/tachiyomi/widget/materialdialogs/QuadStateMultiChoiceDialogAdapter.kt @@ -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, disabledItems: IntArray?, initialSelected: IntArray, - internal var selection: QuadStateMultiChoiceListener -) : RecyclerView.Adapter(), - DialogAdapter { + internal var listener: QuadStateMultiChoiceListener +) : RecyclerView.Adapter() { - 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, - 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 } diff --git a/app/src/main/java/eu/kanade/tachiyomi/widget/materialdialogs/QuadStateMultiChoiceViewHolder.kt b/app/src/main/java/eu/kanade/tachiyomi/widget/materialdialogs/QuadStateMultiChoiceViewHolder.kt index d0cb30e7bd..fbdaee7707 100644 --- a/app/src/main/java/eu/kanade/tachiyomi/widget/materialdialogs/QuadStateMultiChoiceViewHolder.kt +++ b/app/src/main/java/eu/kanade/tachiyomi/widget/materialdialogs/QuadStateMultiChoiceViewHolder.kt @@ -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) diff --git a/app/src/main/java/eu/kanade/tachiyomi/widget/materialdialogs/QuadStateTextView.kt b/app/src/main/java/eu/kanade/tachiyomi/widget/materialdialogs/QuadStateTextView.kt new file mode 100644 index 0000000000..cb52fa17d3 --- /dev/null +++ b/app/src/main/java/eu/kanade/tachiyomi/widget/materialdialogs/QuadStateTextView.kt @@ -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, + ; + } +} diff --git a/app/src/main/java/eu/kanade/tachiyomi/widget/preference/LoginDialogPreference.kt b/app/src/main/java/eu/kanade/tachiyomi/widget/preference/LoginDialogPreference.kt index 68b223de85..f14ec107f4 100644 --- a/app/src/main/java/eu/kanade/tachiyomi/widget/preference/LoginDialogPreference.kt +++ b/app/src/main/java/eu/kanade/tachiyomi/widget/preference/LoginDialogPreference.kt @@ -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) { diff --git a/app/src/main/res/drawable/ic_more_vert_24.xml b/app/src/main/res/drawable/ic_more_vert_24.xml new file mode 100644 index 0000000000..34b93ecdf2 --- /dev/null +++ b/app/src/main/res/drawable/ic_more_vert_24.xml @@ -0,0 +1,10 @@ + + + diff --git a/app/src/main/res/layout/common_dialog_with_checkbox.xml b/app/src/main/res/layout/common_dialog_with_checkbox.xml index 91f03a4c04..412fe85624 100644 --- a/app/src/main/res/layout/common_dialog_with_checkbox.xml +++ b/app/src/main/res/layout/common_dialog_with_checkbox.xml @@ -2,7 +2,9 @@ + android:orientation="vertical" + android:paddingHorizontal="24dp" + android:paddingTop="16dp"> diff --git a/app/src/main/res/layout/dialog_quadstatemultichoice_item.xml b/app/src/main/res/layout/dialog_quadstatemultichoice_item.xml new file mode 100644 index 0000000000..0c7edc0798 --- /dev/null +++ b/app/src/main/res/layout/dialog_quadstatemultichoice_item.xml @@ -0,0 +1,18 @@ + + diff --git a/app/src/main/res/layout/dialog_stub_quadstatemultichoice.xml b/app/src/main/res/layout/dialog_stub_quadstatemultichoice.xml new file mode 100644 index 0000000000..a79a4ac8ed --- /dev/null +++ b/app/src/main/res/layout/dialog_stub_quadstatemultichoice.xml @@ -0,0 +1,9 @@ + + diff --git a/app/src/main/res/layout/dialog_stub_textinput.xml b/app/src/main/res/layout/dialog_stub_textinput.xml new file mode 100644 index 0000000000..1a4b99e619 --- /dev/null +++ b/app/src/main/res/layout/dialog_stub_textinput.xml @@ -0,0 +1,20 @@ + + + + + + + + + + diff --git a/app/src/main/res/layout/download_custom_amount.xml b/app/src/main/res/layout/download_custom_amount.xml index 4d19941e80..384052130a 100644 --- a/app/src/main/res/layout/download_custom_amount.xml +++ b/app/src/main/res/layout/download_custom_amount.xml @@ -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"> - - - - - - - diff --git a/app/src/main/res/layout/track_item.xml b/app/src/main/res/layout/track_item.xml index d37f78e121..6e362086ba 100644 --- a/app/src/main/res/layout/track_item.xml +++ b/app/src/main/res/layout/track_item.xml @@ -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 @@ + + @@ -100,11 +108,11 @@ android:textAppearance="?attr/textAppearanceBody2" tools:text="Reading" /> - + - + - + + + + + + + + diff --git a/app/src/main/res/menu/track_item_date.xml b/app/src/main/res/menu/track_item_date.xml new file mode 100644 index 0000000000..088ee7870a --- /dev/null +++ b/app/src/main/res/menu/track_item_date.xml @@ -0,0 +1,15 @@ + + + + + + + + diff --git a/app/src/main/res/menu/track_search.xml b/app/src/main/res/menu/track_search.xml index 58c62dface..154d900835 100644 --- a/app/src/main/res/menu/track_search.xml +++ b/app/src/main/res/menu/track_search.xml @@ -2,14 +2,6 @@ - - 16dp 128dp - - - 4dp diff --git a/app/src/main/res/values/styles.xml b/app/src/main/res/values/styles.xml index cb736b1781..10ca284dbd 100644 --- a/app/src/main/res/values/styles.xml +++ b/app/src/main/res/values/styles.xml @@ -300,21 +300,6 @@ 15sp - - - - - - - diff --git a/app/src/main/res/values/themes.xml b/app/src/main/res/values/themes.xml index dcbf8d8b0d..b84a4773df 100644 --- a/app/src/main/res/values/themes.xml +++ b/app/src/main/res/values/themes.xml @@ -67,14 +67,6 @@ false false - - ?attr/colorSurface - ?attr/colorOnSurface - ?attr/colorOnSurface - ?attr/colorPrimary - literal - @dimen/dialog_radius - @color/filter_light