Refactor alert dialogs

This commit is contained in:
Koitharu
2024-08-31 09:44:42 +03:00
parent 0df67b86f8
commit 5ebbfd1c00
16 changed files with 194 additions and 298 deletions

View File

@@ -9,7 +9,6 @@ import androidx.activity.viewModels
import androidx.core.graphics.Insets import androidx.core.graphics.Insets
import androidx.core.view.updatePadding import androidx.core.view.updatePadding
import coil.ImageLoader import coil.ImageLoader
import com.google.android.material.dialog.MaterialAlertDialogBuilder
import dagger.hilt.android.AndroidEntryPoint import dagger.hilt.android.AndroidEntryPoint
import org.koitharu.kotatsu.R import org.koitharu.kotatsu.R
import org.koitharu.kotatsu.core.exceptions.resolve.SnackbarErrorObserver import org.koitharu.kotatsu.core.exceptions.resolve.SnackbarErrorObserver
@@ -18,8 +17,8 @@ import org.koitharu.kotatsu.core.model.parcelable.ParcelableManga
import org.koitharu.kotatsu.core.parser.MangaIntent import org.koitharu.kotatsu.core.parser.MangaIntent
import org.koitharu.kotatsu.core.ui.BaseActivity import org.koitharu.kotatsu.core.ui.BaseActivity
import org.koitharu.kotatsu.core.ui.BaseListAdapter import org.koitharu.kotatsu.core.ui.BaseListAdapter
import org.koitharu.kotatsu.core.ui.dialog.buildAlertDialog
import org.koitharu.kotatsu.core.ui.list.OnListItemClickListener import org.koitharu.kotatsu.core.ui.list.OnListItemClickListener
import org.koitharu.kotatsu.core.util.ext.DIALOG_THEME_CENTERED
import org.koitharu.kotatsu.core.util.ext.observe import org.koitharu.kotatsu.core.util.ext.observe
import org.koitharu.kotatsu.core.util.ext.observeEvent import org.koitharu.kotatsu.core.util.ext.observeEvent
import org.koitharu.kotatsu.databinding.ActivityAlternativesBinding import org.koitharu.kotatsu.databinding.ActivityAlternativesBinding
@@ -89,22 +88,23 @@ class AlternativesActivity : BaseActivity<ActivityAlternativesBinding>(),
} }
private fun confirmMigration(target: Manga) { private fun confirmMigration(target: Manga) {
MaterialAlertDialogBuilder(this, DIALOG_THEME_CENTERED) buildAlertDialog(this, isCentered = true) {
.setIcon(R.drawable.ic_replace) setIcon(R.drawable.ic_replace)
.setTitle(R.string.manga_migration) setTitle(R.string.manga_migration)
.setMessage( setMessage(
getString( getString(
R.string.migrate_confirmation, R.string.migrate_confirmation,
viewModel.manga.title, viewModel.manga.title,
viewModel.manga.source.getTitle(this), viewModel.manga.source.getTitle(context),
target.title, target.title,
target.source.getTitle(this), target.source.getTitle(context),
), ),
) )
.setNegativeButton(android.R.string.cancel, null) setNegativeButton(android.R.string.cancel, null)
.setPositiveButton(R.string.migrate) { _, _ -> setPositiveButton(R.string.migrate) { _, _ ->
viewModel.migrate(target) viewModel.migrate(target)
}.show() }
}.show()
} }
companion object { companion object {

View File

@@ -0,0 +1,67 @@
package org.koitharu.kotatsu.core.ui.dialog
import android.content.Context
import android.view.LayoutInflater
import android.widget.CompoundButton.OnCheckedChangeListener
import androidx.annotation.StringRes
import androidx.appcompat.app.AlertDialog
import androidx.core.view.updatePadding
import androidx.recyclerview.widget.LinearLayoutManager
import androidx.recyclerview.widget.RecyclerView
import com.google.android.material.dialog.MaterialAlertDialogBuilder
import com.hannesdorfmann.adapterdelegates4.AdapterDelegate
import com.hannesdorfmann.adapterdelegates4.AdapterDelegatesManager
import com.hannesdorfmann.adapterdelegates4.ListDelegationAdapter
import org.koitharu.kotatsu.R
import org.koitharu.kotatsu.databinding.DialogCheckboxBinding
import com.google.android.material.R as materialR
inline fun buildAlertDialog(
context: Context,
isCentered: Boolean = false,
block: MaterialAlertDialogBuilder.() -> Unit,
): AlertDialog = MaterialAlertDialogBuilder(
context,
if (isCentered) materialR.style.ThemeOverlay_Material3_MaterialAlertDialog_Centered else 0,
).apply(block).create()
fun <B : AlertDialog.Builder> B.setCheckbox(
@StringRes textResId: Int,
isChecked: Boolean,
onCheckedChangeListener: OnCheckedChangeListener
) = apply {
val binding = DialogCheckboxBinding.inflate(LayoutInflater.from(context))
binding.checkbox.setText(textResId)
binding.checkbox.isChecked = isChecked
binding.checkbox.setOnCheckedChangeListener(onCheckedChangeListener)
setView(binding.root)
}
fun <B : AlertDialog.Builder, T> B.setRecyclerViewList(
list: List<T>,
delegate: AdapterDelegate<List<T>>,
) = apply {
val delegatesManager = AdapterDelegatesManager<List<T>>()
delegatesManager.addDelegate(delegate)
setRecyclerViewList(ListDelegationAdapter(delegatesManager).also { it.items = list })
}
fun <B : AlertDialog.Builder, T> B.setRecyclerViewList(
list: List<T>,
vararg delegates: AdapterDelegate<List<T>>,
) = apply {
val delegatesManager = AdapterDelegatesManager<List<T>>()
delegates.forEach { delegatesManager.addDelegate(it) }
setRecyclerViewList(ListDelegationAdapter(delegatesManager).also { it.items = list })
}
fun <B : AlertDialog.Builder> B.setRecyclerViewList(adapter: RecyclerView.Adapter<*>) = apply {
val recyclerView = RecyclerView(context)
recyclerView.layoutManager = LinearLayoutManager(context)
recyclerView.updatePadding(
top = context.resources.getDimensionPixelOffset(R.dimen.list_spacing),
)
recyclerView.clipToPadding = false
recyclerView.adapter = adapter
setView(recyclerView)
}

View File

@@ -1,80 +0,0 @@
package org.koitharu.kotatsu.core.ui.dialog
import android.content.Context
import android.content.DialogInterface
import android.view.LayoutInflater
import androidx.annotation.DrawableRes
import androidx.annotation.StringRes
import androidx.appcompat.app.AlertDialog
import com.google.android.material.dialog.MaterialAlertDialogBuilder
import org.koitharu.kotatsu.databinding.DialogCheckboxBinding
class CheckBoxAlertDialog private constructor(private val delegate: AlertDialog) :
DialogInterface by delegate {
fun show() = delegate.show()
class Builder(context: Context) {
private val binding = DialogCheckboxBinding.inflate(LayoutInflater.from(context))
private val delegate = MaterialAlertDialogBuilder(context)
.setView(binding.root)
fun setTitle(@StringRes titleResId: Int): Builder {
delegate.setTitle(titleResId)
return this
}
fun setTitle(title: CharSequence): Builder {
delegate.setTitle(title)
return this
}
fun setMessage(@StringRes messageId: Int): Builder {
delegate.setMessage(messageId)
return this
}
fun setMessage(message: CharSequence): Builder {
delegate.setMessage(message)
return this
}
fun setCheckBoxText(@StringRes textId: Int): Builder {
binding.checkbox.setText(textId)
return this
}
fun setCheckBoxChecked(isChecked: Boolean): Builder {
binding.checkbox.isChecked = isChecked
return this
}
fun setIcon(@DrawableRes iconId: Int): Builder {
delegate.setIcon(iconId)
return this
}
fun setPositiveButton(
@StringRes textId: Int,
listener: (DialogInterface, Boolean) -> Unit
): Builder {
delegate.setPositiveButton(textId) { dialog, _ ->
listener(dialog, binding.checkbox.isChecked)
}
return this
}
fun setNegativeButton(
@StringRes textId: Int,
listener: DialogInterface.OnClickListener? = null
): Builder {
delegate.setNegativeButton(textId, listener)
return this
}
fun create() = CheckBoxAlertDialog(delegate.create())
}
}

View File

@@ -1,101 +0,0 @@
package org.koitharu.kotatsu.core.ui.dialog
import android.content.Context
import android.content.DialogInterface
import androidx.annotation.DrawableRes
import androidx.annotation.StringRes
import androidx.appcompat.app.AlertDialog
import androidx.core.view.updatePadding
import androidx.recyclerview.widget.LinearLayoutManager
import androidx.recyclerview.widget.RecyclerView
import com.google.android.material.dialog.MaterialAlertDialogBuilder
import com.hannesdorfmann.adapterdelegates4.AdapterDelegate
import com.hannesdorfmann.adapterdelegates4.AdapterDelegatesManager
import com.hannesdorfmann.adapterdelegates4.ListDelegationAdapter
import org.koitharu.kotatsu.R
class RecyclerViewAlertDialog private constructor(
private val delegate: AlertDialog
) : DialogInterface by delegate {
fun show() = delegate.show()
class Builder<T>(context: Context) {
private val recyclerView = RecyclerView(context)
private val delegatesManager = AdapterDelegatesManager<List<T>>()
private var items: List<T>? = null
private val delegate = MaterialAlertDialogBuilder(context)
.setView(recyclerView)
init {
recyclerView.layoutManager = LinearLayoutManager(context)
recyclerView.updatePadding(
top = context.resources.getDimensionPixelOffset(R.dimen.list_spacing),
)
recyclerView.clipToPadding = false
}
fun setTitle(@StringRes titleResId: Int): Builder<T> {
delegate.setTitle(titleResId)
return this
}
fun setTitle(title: CharSequence): Builder<T> {
delegate.setTitle(title)
return this
}
fun setIcon(@DrawableRes iconId: Int): Builder<T> {
delegate.setIcon(iconId)
return this
}
fun setPositiveButton(
@StringRes textId: Int,
listener: DialogInterface.OnClickListener,
): Builder<T> {
delegate.setPositiveButton(textId, listener)
return this
}
fun setNegativeButton(
@StringRes textId: Int,
listener: DialogInterface.OnClickListener? = null
): Builder<T> {
delegate.setNegativeButton(textId, listener)
return this
}
fun setNeutralButton(
@StringRes textId: Int,
listener: DialogInterface.OnClickListener,
): Builder<T> {
delegate.setNeutralButton(textId, listener)
return this
}
fun setCancelable(isCancelable: Boolean): Builder<T> {
delegate.setCancelable(isCancelable)
return this
}
fun addAdapterDelegate(subject: AdapterDelegate<List<T>>): Builder<T> {
delegatesManager.addDelegate(subject)
return this
}
fun setItems(list: List<T>): Builder<T> {
items = list
return this
}
fun create(): RecyclerViewAlertDialog {
recyclerView.adapter = ListDelegationAdapter(delegatesManager).also {
it.items = items
}
return RecyclerViewAlertDialog(delegate.create())
}
}
}

View File

@@ -0,0 +1,16 @@
package org.koitharu.kotatsu.core.ui.dialog
import android.widget.CompoundButton
import android.widget.CompoundButton.OnCheckedChangeListener
class RememberCheckListener(
initialValue: Boolean,
) : OnCheckedChangeListener {
var isChecked: Boolean = initialValue
private set
override fun onCheckedChanged(buttonView: CompoundButton?, isChecked: Boolean) {
this.isChecked = isChecked
}
}

View File

@@ -8,11 +8,9 @@ import androidx.annotation.AttrRes
import androidx.annotation.ColorInt import androidx.annotation.ColorInt
import androidx.annotation.FloatRange import androidx.annotation.FloatRange
import androidx.annotation.Px import androidx.annotation.Px
import androidx.annotation.StyleRes
import androidx.core.content.ContextCompat import androidx.core.content.ContextCompat
import androidx.core.content.res.use import androidx.core.content.res.use
import androidx.core.graphics.ColorUtils import androidx.core.graphics.ColorUtils
import com.google.android.material.R as materialR
fun Context.getThemeDrawable( fun Context.getThemeDrawable(
@AttrRes resId: Int, @AttrRes resId: Int,
@@ -77,7 +75,3 @@ fun TypedArray.getDrawableCompat(context: Context, index: Int): Drawable? {
val resId = getResourceId(index, 0) val resId = getResourceId(index, 0)
return if (resId != 0) ContextCompat.getDrawable(context, resId) else null return if (resId != 0) ContextCompat.getDrawable(context, resId) else null
} }
@get:StyleRes
val DIALOG_THEME_CENTERED: Int
inline get() = materialR.style.ThemeOverlay_Material3_MaterialAlertDialog_Centered

View File

@@ -4,7 +4,8 @@ import android.content.DialogInterface
import android.view.View import android.view.View
import org.koitharu.kotatsu.R import org.koitharu.kotatsu.R
import org.koitharu.kotatsu.core.model.ids import org.koitharu.kotatsu.core.model.ids
import org.koitharu.kotatsu.core.ui.dialog.RecyclerViewAlertDialog import org.koitharu.kotatsu.core.ui.dialog.buildAlertDialog
import org.koitharu.kotatsu.core.ui.dialog.setRecyclerViewList
import org.koitharu.kotatsu.core.ui.list.OnListItemClickListener import org.koitharu.kotatsu.core.ui.list.OnListItemClickListener
import org.koitharu.kotatsu.download.ui.dialog.DownloadOption import org.koitharu.kotatsu.download.ui.dialog.DownloadOption
import org.koitharu.kotatsu.download.ui.dialog.downloadOptionAD import org.koitharu.kotatsu.download.ui.dialog.downloadOptionAD
@@ -53,16 +54,14 @@ class DownloadDialogHelper(
callback.onItemClick(item, host) callback.onItemClick(item, host)
dialog?.dismiss() dialog?.dismiss()
} }
dialog = RecyclerViewAlertDialog.Builder<DownloadOption>(host.context) dialog = buildAlertDialog(host.context) {
.addAdapterDelegate(downloadOptionAD(listener)) setCancelable(true)
.setCancelable(true) setTitle(R.string.download)
.setTitle(R.string.download) setNegativeButton(android.R.string.cancel, null)
.setNegativeButton(android.R.string.cancel) setNeutralButton(R.string.settings) { _, _ ->
.setNeutralButton(R.string.settings) { _, _ ->
host.context.startActivity(SettingsActivity.newDownloadsSettingsIntent(host.context)) host.context.startActivity(SettingsActivity.newDownloadsSettingsIntent(host.context))
} }
.setItems(options) setRecyclerViewList(options, downloadOptionAD(listener))
.create() }.also { it.show() }
.also { it.show() }
} }
} }

View File

@@ -5,9 +5,8 @@ import android.view.Menu
import android.view.MenuInflater import android.view.MenuInflater
import android.view.MenuItem import android.view.MenuItem
import androidx.core.view.MenuProvider import androidx.core.view.MenuProvider
import com.google.android.material.dialog.MaterialAlertDialogBuilder
import org.koitharu.kotatsu.R import org.koitharu.kotatsu.R
import org.koitharu.kotatsu.core.util.ext.DIALOG_THEME_CENTERED import org.koitharu.kotatsu.core.ui.dialog.buildAlertDialog
import org.koitharu.kotatsu.settings.SettingsActivity import org.koitharu.kotatsu.settings.SettingsActivity
class DownloadsMenuProvider( class DownloadsMenuProvider(
@@ -42,24 +41,22 @@ class DownloadsMenuProvider(
} }
private fun confirmCancelAll() { private fun confirmCancelAll() {
MaterialAlertDialogBuilder(context, DIALOG_THEME_CENTERED) buildAlertDialog(context, isCentered = true) {
.setTitle(R.string.cancel_all) setTitle(R.string.cancel_all)
.setMessage(R.string.cancel_all_downloads_confirm) setMessage(R.string.cancel_all_downloads_confirm)
.setIcon(R.drawable.ic_cancel_multiple) setIcon(R.drawable.ic_cancel_multiple)
.setNegativeButton(android.R.string.cancel, null) setNegativeButton(android.R.string.cancel, null)
.setPositiveButton(R.string.confirm) { _, _ -> setPositiveButton(R.string.confirm) { _, _ -> viewModel.cancelAll() }
viewModel.cancelAll() }.show()
}.show()
} }
private fun confirmRemoveCompleted() { private fun confirmRemoveCompleted() {
MaterialAlertDialogBuilder(context, DIALOG_THEME_CENTERED) buildAlertDialog(context, isCentered = true) {
.setTitle(R.string.remove_completed) setTitle(R.string.remove_completed)
.setMessage(R.string.remove_completed_downloads_confirm) setMessage(R.string.remove_completed_downloads_confirm)
.setIcon(R.drawable.ic_clear_all) setIcon(R.drawable.ic_clear_all)
.setNegativeButton(android.R.string.cancel, null) setNegativeButton(android.R.string.cancel, null)
.setPositiveButton(R.string.clear) { _, _ -> setPositiveButton(R.string.clear) { _, _ -> viewModel.removeCompleted() }
viewModel.removeCompleted() }.show()
}.show()
} }
} }

View File

@@ -4,10 +4,9 @@ import android.view.Menu
import android.view.MenuItem import android.view.MenuItem
import androidx.appcompat.view.ActionMode import androidx.appcompat.view.ActionMode
import androidx.recyclerview.widget.RecyclerView import androidx.recyclerview.widget.RecyclerView
import com.google.android.material.dialog.MaterialAlertDialogBuilder
import org.koitharu.kotatsu.R import org.koitharu.kotatsu.R
import org.koitharu.kotatsu.core.ui.dialog.buildAlertDialog
import org.koitharu.kotatsu.core.ui.list.ListSelectionController import org.koitharu.kotatsu.core.ui.list.ListSelectionController
import org.koitharu.kotatsu.core.util.ext.DIALOG_THEME_CENTERED
class CategoriesSelectionCallback( class CategoriesSelectionCallback(
private val recyclerView: RecyclerView, private val recyclerView: RecyclerView,
@@ -74,15 +73,15 @@ class CategoriesSelectionCallback(
} }
private fun confirmDeleteCategories(ids: Set<Long>, mode: ActionMode) { private fun confirmDeleteCategories(ids: Set<Long>, mode: ActionMode) {
val context = recyclerView.context buildAlertDialog(recyclerView.context, isCentered = true) {
MaterialAlertDialogBuilder(context, DIALOG_THEME_CENTERED) setMessage(R.string.categories_delete_confirm)
.setMessage(R.string.categories_delete_confirm) setTitle(R.string.remove_category)
.setTitle(R.string.remove_category) setIcon(R.drawable.ic_delete)
.setIcon(R.drawable.ic_delete) setNegativeButton(android.R.string.cancel, null)
.setNegativeButton(android.R.string.cancel, null) setPositiveButton(R.string.remove) { _, _ ->
.setPositiveButton(R.string.remove) { _, _ ->
viewModel.deleteCategories(ids) viewModel.deleteCategories(ids)
mode.finish() mode.finish()
}.show() }
}.show()
} }
} }

View File

@@ -5,9 +5,8 @@ import android.view.Menu
import android.view.MenuInflater import android.view.MenuInflater
import android.view.MenuItem import android.view.MenuItem
import androidx.core.view.MenuProvider import androidx.core.view.MenuProvider
import com.google.android.material.dialog.MaterialAlertDialogBuilder
import org.koitharu.kotatsu.R import org.koitharu.kotatsu.R
import org.koitharu.kotatsu.core.util.ext.DIALOG_THEME_CENTERED import org.koitharu.kotatsu.core.ui.dialog.buildAlertDialog
import org.koitharu.kotatsu.favourites.ui.categories.edit.FavouritesCategoryEditActivity import org.koitharu.kotatsu.favourites.ui.categories.edit.FavouritesCategoryEditActivity
import org.koitharu.kotatsu.favourites.ui.list.FavouritesListFragment.Companion.NO_ID import org.koitharu.kotatsu.favourites.ui.list.FavouritesListFragment.Companion.NO_ID
@@ -41,13 +40,12 @@ class FavouriteTabPopupMenuProvider(
} }
private fun confirmDelete() { private fun confirmDelete() {
MaterialAlertDialogBuilder(context, DIALOG_THEME_CENTERED) buildAlertDialog(context, isCentered = true) {
.setMessage(R.string.categories_delete_confirm) setMessage(R.string.categories_delete_confirm)
.setTitle(R.string.remove_category) setTitle(R.string.remove_category)
.setIcon(R.drawable.ic_delete) setIcon(R.drawable.ic_delete)
.setNegativeButton(android.R.string.cancel, null) setNegativeButton(android.R.string.cancel, null)
.setPositiveButton(R.string.remove) { _, _ -> setPositiveButton(R.string.remove) { _, _ -> viewModel.deleteCategory(categoryId) }
viewModel.deleteCategory(categoryId) }.show()
}.show()
} }
} }

View File

@@ -6,16 +6,14 @@ import android.view.Menu
import android.view.MenuInflater import android.view.MenuInflater
import android.view.MenuItem import android.view.MenuItem
import androidx.core.view.MenuProvider import androidx.core.view.MenuProvider
import com.google.android.material.dialog.MaterialAlertDialogBuilder
import org.koitharu.kotatsu.R import org.koitharu.kotatsu.R
import org.koitharu.kotatsu.core.ui.dialog.RememberSelectionDialogListener import org.koitharu.kotatsu.core.ui.dialog.RememberSelectionDialogListener
import org.koitharu.kotatsu.core.util.ext.DIALOG_THEME_CENTERED import org.koitharu.kotatsu.core.ui.dialog.buildAlertDialog
import org.koitharu.kotatsu.stats.ui.StatsActivity import org.koitharu.kotatsu.stats.ui.StatsActivity
import java.time.Instant import java.time.Instant
import java.time.LocalDate import java.time.LocalDate
import java.time.ZoneId import java.time.ZoneId
import java.time.temporal.ChronoUnit import java.time.temporal.ChronoUnit
import com.google.android.material.R as materialR
class HistoryListMenuProvider( class HistoryListMenuProvider(
private val context: Context, private val context: Context,
@@ -49,9 +47,9 @@ class HistoryListMenuProvider(
private fun showClearHistoryDialog() { private fun showClearHistoryDialog() {
val selectionListener = RememberSelectionDialogListener(2) val selectionListener = RememberSelectionDialogListener(2)
MaterialAlertDialogBuilder(context, DIALOG_THEME_CENTERED) buildAlertDialog(context, isCentered = true) {
.setTitle(R.string.clear_history) setTitle(R.string.clear_history)
.setSingleChoiceItems( setSingleChoiceItems(
arrayOf( arrayOf(
context.getString(R.string.last_2_hours), context.getString(R.string.last_2_hours),
context.getString(R.string.today), context.getString(R.string.today),
@@ -60,9 +58,9 @@ class HistoryListMenuProvider(
selectionListener.selection, selectionListener.selection,
selectionListener, selectionListener,
) )
.setIcon(R.drawable.ic_delete) setIcon(R.drawable.ic_delete_all)
.setNegativeButton(android.R.string.cancel, null) setNegativeButton(android.R.string.cancel, null)
.setPositiveButton(R.string.clear) { _, _ -> setPositiveButton(R.string.clear) { _, _ ->
val minDate = when (selectionListener.selection) { val minDate = when (selectionListener.selection) {
0 -> Instant.now().minus(2, ChronoUnit.HOURS) 0 -> Instant.now().minus(2, ChronoUnit.HOURS)
1 -> LocalDate.now().atStartOfDay(ZoneId.systemDefault()).toInstant() 1 -> LocalDate.now().atStartOfDay(ZoneId.systemDefault()).toInstant()
@@ -70,6 +68,7 @@ class HistoryListMenuProvider(
else -> return@setPositiveButton else -> return@setPositiveButton
} }
viewModel.clearHistory(minDate) viewModel.clearHistory(minDate)
}.show() }
}.show()
} }
} }

View File

@@ -6,12 +6,10 @@ import android.view.MenuInflater
import android.view.MenuItem import android.view.MenuItem
import androidx.activity.result.ActivityResultLauncher import androidx.activity.result.ActivityResultLauncher
import androidx.core.view.MenuProvider import androidx.core.view.MenuProvider
import com.google.android.material.dialog.MaterialAlertDialogBuilder
import org.koitharu.kotatsu.R import org.koitharu.kotatsu.R
import org.koitharu.kotatsu.core.util.ext.DIALOG_THEME_CENTERED import org.koitharu.kotatsu.core.ui.dialog.buildAlertDialog
import org.koitharu.kotatsu.core.util.ext.resolve import org.koitharu.kotatsu.core.util.ext.resolve
import org.koitharu.kotatsu.core.util.ext.tryLaunch import org.koitharu.kotatsu.core.util.ext.tryLaunch
import com.google.android.material.R as materialR
class SearchSuggestionMenuProvider( class SearchSuggestionMenuProvider(
private val context: Context, private val context: Context,
@@ -44,13 +42,13 @@ class SearchSuggestionMenuProvider(
} }
private fun clearSearchHistory() { private fun clearSearchHistory() {
MaterialAlertDialogBuilder(context, DIALOG_THEME_CENTERED) buildAlertDialog(context, isCentered = true) {
.setTitle(R.string.clear_search_history) setTitle(R.string.clear_search_history)
.setIcon(R.drawable.ic_clear_all) setIcon(R.drawable.ic_clear_all)
.setMessage(R.string.text_clear_search_history_prompt) setCancelable(true)
.setNegativeButton(android.R.string.cancel, null) setMessage(R.string.text_clear_search_history_prompt)
.setPositiveButton(R.string.clear) { _, _ -> setNegativeButton(android.R.string.cancel, null)
viewModel.clearSearchHistory() setPositiveButton(R.string.clear) { _, _ -> viewModel.clearSearchHistory() }
}.show() }.show()
} }
} }

View File

@@ -15,7 +15,8 @@ import org.koitharu.kotatsu.R
import org.koitharu.kotatsu.core.prefs.NavItem import org.koitharu.kotatsu.core.prefs.NavItem
import org.koitharu.kotatsu.core.ui.BaseFragment import org.koitharu.kotatsu.core.ui.BaseFragment
import org.koitharu.kotatsu.core.ui.BaseListAdapter import org.koitharu.kotatsu.core.ui.BaseListAdapter
import org.koitharu.kotatsu.core.ui.dialog.RecyclerViewAlertDialog import org.koitharu.kotatsu.core.ui.dialog.buildAlertDialog
import org.koitharu.kotatsu.core.ui.dialog.setRecyclerViewList
import org.koitharu.kotatsu.core.ui.list.OnListItemClickListener import org.koitharu.kotatsu.core.ui.list.OnListItemClickListener
import org.koitharu.kotatsu.core.ui.util.RecyclerViewOwner import org.koitharu.kotatsu.core.ui.util.RecyclerViewOwner
import org.koitharu.kotatsu.core.util.ext.observe import org.koitharu.kotatsu.core.util.ext.observe
@@ -85,14 +86,12 @@ class NavConfigFragment : BaseFragment<FragmentSettingsSourcesBinding>(), Recycl
viewModel.addItem(item) viewModel.addItem(item)
dialog?.dismiss() dialog?.dismiss()
} }
dialog = RecyclerViewAlertDialog.Builder<NavItem>(v.context) dialog = buildAlertDialog(v.context) {
.setTitle(R.string.add) setTitle(R.string.add)
.addAdapterDelegate(navAvailableAD(listener)) setCancelable(true)
.setCancelable(true) setRecyclerViewList(viewModel.availableItems, navAvailableAD(listener))
.setItems(viewModel.availableItems) setNegativeButton(android.R.string.cancel, null)
.setNegativeButton(android.R.string.cancel, null) }.apply { show() }
.create()
.apply { show() }
} }
override fun onItemClick(item: NavItem, view: View) { override fun onItemClick(item: NavItem, view: View) {

View File

@@ -1,13 +1,11 @@
package org.koitharu.kotatsu.stats.ui package org.koitharu.kotatsu.stats.ui
import android.os.Bundle import android.os.Bundle
import android.view.Gravity
import android.view.Menu import android.view.Menu
import android.view.MenuItem import android.view.MenuItem
import android.view.View import android.view.View
import android.view.ViewStub import android.view.ViewStub
import android.widget.CompoundButton import android.widget.CompoundButton
import android.widget.Toast
import androidx.activity.viewModels import androidx.activity.viewModels
import androidx.appcompat.widget.PopupMenu import androidx.appcompat.widget.PopupMenu
import androidx.core.graphics.Insets import androidx.core.graphics.Insets
@@ -17,16 +15,15 @@ import androidx.recyclerview.widget.AsyncListDiffer
import coil.ImageLoader import coil.ImageLoader
import com.google.android.material.chip.Chip import com.google.android.material.chip.Chip
import com.google.android.material.chip.ChipDrawable import com.google.android.material.chip.ChipDrawable
import com.google.android.material.dialog.MaterialAlertDialogBuilder
import dagger.hilt.android.AndroidEntryPoint import dagger.hilt.android.AndroidEntryPoint
import org.koitharu.kotatsu.R import org.koitharu.kotatsu.R
import org.koitharu.kotatsu.core.model.FavouriteCategory import org.koitharu.kotatsu.core.model.FavouriteCategory
import org.koitharu.kotatsu.core.ui.BaseActivity import org.koitharu.kotatsu.core.ui.BaseActivity
import org.koitharu.kotatsu.core.ui.BaseListAdapter import org.koitharu.kotatsu.core.ui.BaseListAdapter
import org.koitharu.kotatsu.core.ui.dialog.buildAlertDialog
import org.koitharu.kotatsu.core.ui.list.OnListItemClickListener import org.koitharu.kotatsu.core.ui.list.OnListItemClickListener
import org.koitharu.kotatsu.core.ui.util.ReversibleActionObserver import org.koitharu.kotatsu.core.ui.util.ReversibleActionObserver
import org.koitharu.kotatsu.core.util.KotatsuColors import org.koitharu.kotatsu.core.util.KotatsuColors
import org.koitharu.kotatsu.core.util.ext.DIALOG_THEME_CENTERED
import org.koitharu.kotatsu.core.util.ext.enqueueWith import org.koitharu.kotatsu.core.util.ext.enqueueWith
import org.koitharu.kotatsu.core.util.ext.newImageRequest import org.koitharu.kotatsu.core.util.ext.newImageRequest
import org.koitharu.kotatsu.core.util.ext.observe import org.koitharu.kotatsu.core.util.ext.observe
@@ -167,14 +164,13 @@ class StatsActivity : BaseActivity<ActivityStatsBinding>(),
} }
private fun showClearConfirmDialog() { private fun showClearConfirmDialog() {
MaterialAlertDialogBuilder(this, DIALOG_THEME_CENTERED) buildAlertDialog(this, isCentered = true) {
.setMessage(R.string.clear_stats_confirm) setMessage(R.string.clear_stats_confirm)
.setTitle(R.string.clear_stats) setTitle(R.string.clear_stats)
.setIcon(R.drawable.ic_delete) setIcon(R.drawable.ic_delete_all)
.setNegativeButton(android.R.string.cancel, null) setNegativeButton(android.R.string.cancel, null)
.setPositiveButton(R.string.clear) { _, _ -> setPositiveButton(R.string.clear) { _, _ -> viewModel.clearStats() }
viewModel.clearStats() }.show()
}.show()
} }
private fun showPeriodSelector() { private fun showPeriodSelector() {

View File

@@ -7,7 +7,9 @@ import android.view.MenuItem
import android.view.View import android.view.View
import androidx.core.view.MenuProvider import androidx.core.view.MenuProvider
import org.koitharu.kotatsu.R import org.koitharu.kotatsu.R
import org.koitharu.kotatsu.core.ui.dialog.CheckBoxAlertDialog import org.koitharu.kotatsu.core.ui.dialog.RememberCheckListener
import org.koitharu.kotatsu.core.ui.dialog.buildAlertDialog
import org.koitharu.kotatsu.core.ui.dialog.setCheckbox
class FeedMenuProvider( class FeedMenuProvider(
private val snackbarHost: View, private val snackbarHost: View,
@@ -38,15 +40,17 @@ class FeedMenuProvider(
} }
R.id.action_clear_feed -> { R.id.action_clear_feed -> {
CheckBoxAlertDialog.Builder(context) val checkListener = RememberCheckListener(true)
.setTitle(R.string.clear_updates_feed) buildAlertDialog(context, isCentered = true) {
.setMessage(R.string.text_clear_updates_feed_prompt) setIcon(R.drawable.ic_clear_all)
.setNegativeButton(android.R.string.cancel, null) setTitle(R.string.clear_updates_feed)
.setCheckBoxChecked(true) setMessage(R.string.text_clear_updates_feed_prompt)
.setCheckBoxText(R.string.clear_new_chapters_counters) setNegativeButton(android.R.string.cancel, null)
.setPositiveButton(R.string.clear) { _, isChecked -> setCheckbox(R.string.clear_new_chapters_counters, true, checkListener)
viewModel.clearFeed(isChecked) setPositiveButton(R.string.clear) { _, _ ->
}.create().show() viewModel.clearFeed(checkListener.isChecked)
}
}.show()
true true
} }

View File

@@ -0,0 +1,11 @@
<vector
xmlns:android="http://schemas.android.com/apk/res/android"
android:width="24dp"
android:height="24dp"
android:tint="?colorControlNormal"
android:viewportWidth="24"
android:viewportHeight="24">
<path
android:fillColor="#000000"
android:pathData="M15,16H19V18H15V16M15,8H22V10H15V8M15,12H21V14H15V12M11,10V18H5V10H11M13,8H3V18A2,2 0 0,0 5,20H11A2,2 0 0,0 13,18V8M14,5H11L10,4H6L5,5H2V7H14V5Z" />
</vector>