feat: optimize Alert Dialogs

This commit is contained in:
aayush262 2024-06-13 19:15:55 +05:30
parent 1670383619
commit 124c8f5ed7
31 changed files with 739 additions and 837 deletions

View file

@ -39,6 +39,7 @@ import ani.dantotsu.settings.FAQActivity
import ani.dantotsu.settings.saving.PrefManager
import ani.dantotsu.settings.saving.PrefName
import ani.dantotsu.toast
import ani.dantotsu.util.customAlertDialog
import com.google.android.material.chip.Chip
import eu.kanade.tachiyomi.animesource.online.AnimeHttpSource
import eu.kanade.tachiyomi.data.notification.Notifications.CHANNEL_SUBSCRIPTION_CHECK
@ -61,9 +62,6 @@ class AnimeWatchAdapter(
return ViewHolder(bind)
}
private var nestedDialog: AlertDialog? = null
override fun onBindViewHolder(holder: ViewHolder, position: Int) {
val binding = holder.binding
_binding = binding
@ -201,104 +199,102 @@ class AnimeWatchAdapter(
//Nested Button
binding.animeNestedButton.setOnClickListener {
val dialogView =
LayoutInflater.from(fragment.requireContext()).inflate(R.layout.dialog_layout, null)
val dialogBinding = DialogLayoutBinding.bind(dialogView)
var refresh = false
var run = false
var reversed = media.selected!!.recyclerReversed
var style =
media.selected!!.recyclerStyle ?: PrefManager.getVal(PrefName.AnimeDefaultView)
dialogBinding.animeSourceTop.rotation = if (reversed) -90f else 90f
dialogBinding.sortText.text = if (reversed) "Down to Up" else "Up to Down"
dialogBinding.animeSourceTop.setOnClickListener {
reversed = !reversed
dialogBinding.animeSourceTop.rotation = if (reversed) -90f else 90f
dialogBinding.sortText.text = if (reversed) "Down to Up" else "Up to Down"
run = true
}
//Grids
var selected = when (style) {
0 -> dialogBinding.animeSourceList
1 -> dialogBinding.animeSourceGrid
2 -> dialogBinding.animeSourceCompact
else -> dialogBinding.animeSourceList
}
when (style) {
0 -> dialogBinding.layoutText.setText(R.string.list)
1 -> dialogBinding.layoutText.setText(R.string.grid)
2 -> dialogBinding.layoutText.setText(R.string.compact)
else -> dialogBinding.animeSourceList
}
selected.alpha = 1f
fun selected(it: ImageButton) {
selected.alpha = 0.33f
selected = it
selected.alpha = 1f
}
dialogBinding.animeSourceList.setOnClickListener {
selected(it as ImageButton)
style = 0
dialogBinding.layoutText.setText(R.string.list)
run = true
}
dialogBinding.animeSourceGrid.setOnClickListener {
selected(it as ImageButton)
style = 1
dialogBinding.layoutText.setText(R.string.grid)
run = true
}
dialogBinding.animeSourceCompact.setOnClickListener {
selected(it as ImageButton)
style = 2
dialogBinding.layoutText.setText(R.string.compact)
run = true
}
dialogBinding.animeWebviewContainer.setOnClickListener {
if (!WebViewUtil.supportsWebView(fragment.requireContext())) {
toast(R.string.webview_not_installed)
val dialogBinding = DialogLayoutBinding.inflate(fragment.layoutInflater)
dialogBinding.apply {
var refresh = false
var run = false
var reversed = media.selected!!.recyclerReversed
var style =
media.selected!!.recyclerStyle ?: PrefManager.getVal(PrefName.AnimeDefaultView)
animeSourceTop.rotation = if (reversed) -90f else 90f
sortText.text = if (reversed) "Down to Up" else "Up to Down"
animeSourceTop.setOnClickListener {
reversed = !reversed
animeSourceTop.rotation = if (reversed) -90f else 90f
sortText.text = if (reversed) "Down to Up" else "Up to Down"
run = true
}
//start CookieCatcher activity
if (watchSources.names.isNotEmpty() && source in 0 until watchSources.names.size) {
val sourceAHH = watchSources[source] as? DynamicAnimeParser
val sourceHttp =
sourceAHH?.extension?.sources?.firstOrNull() as? AnimeHttpSource
val url = sourceHttp?.baseUrl
url?.let {
refresh = true
val headersMap = try {
sourceHttp.headers.toMultimap()
.mapValues { it.value.getOrNull(0) ?: "" }
} catch (e: Exception) {
emptyMap()
//Grids
var selected = when (style) {
0 -> animeSourceList
1 -> animeSourceGrid
2 -> animeSourceCompact
else -> animeSourceList
}
when (style) {
0 -> layoutText.setText(R.string.list)
1 -> layoutText.setText(R.string.grid)
2 -> layoutText.setText(R.string.compact)
else -> animeSourceList
}
selected.alpha = 1f
fun selected(it: ImageButton) {
selected.alpha = 0.33f
selected = it
selected.alpha = 1f
}
animeSourceList.setOnClickListener {
selected(it as ImageButton)
style = 0
layoutText.setText(R.string.list)
run = true
}
animeSourceGrid.setOnClickListener {
selected(it as ImageButton)
style = 1
layoutText.setText(R.string.grid)
run = true
}
animeSourceCompact.setOnClickListener {
selected(it as ImageButton)
style = 2
layoutText.setText(R.string.compact)
run = true
}
animeWebviewContainer.setOnClickListener {
if (!WebViewUtil.supportsWebView(fragment.requireContext())) {
toast(R.string.webview_not_installed)
}
//start CookieCatcher activity
if (watchSources.names.isNotEmpty() && source in 0 until watchSources.names.size) {
val sourceAHH = watchSources[source] as? DynamicAnimeParser
val sourceHttp =
sourceAHH?.extension?.sources?.firstOrNull() as? AnimeHttpSource
val url = sourceHttp?.baseUrl
url?.let {
refresh = true
val headersMap = try {
sourceHttp.headers.toMultimap()
.mapValues { it.value.getOrNull(0) ?: "" }
} catch (e: Exception) {
emptyMap()
}
val intent =
Intent(fragment.requireContext(), CookieCatcher::class.java)
.putExtra("url", url)
.putExtra("headers", headersMap as HashMap<String, String>)
startActivity(fragment.requireContext(), intent, null)
}
val intent = Intent(fragment.requireContext(), CookieCatcher::class.java)
.putExtra("url", url)
.putExtra("headers", headersMap as HashMap<String, String>)
startActivity(fragment.requireContext(), intent, null)
}
}
//hidden
animeScanlatorContainer.visibility = View.GONE
animeDownloadContainer.visibility = View.GONE
fragment.requireContext().customAlertDialog().apply {
setTitle("Options")
setCustomView(dialogBinding.root)
setPosButton("OK") {
if (run) fragment.onIconPressed(style, reversed)
if (refresh) fragment.loadEpisodes(source, true)
}
setNegButton("Cancel") {
if (refresh) fragment.loadEpisodes(source, true)
}
show()
}
}
//hidden
dialogBinding.animeScanlatorContainer.visibility = View.GONE
dialogBinding.animeDownloadContainer.visibility = View.GONE
nestedDialog = AlertDialog.Builder(fragment.requireContext(), R.style.MyPopup)
.setTitle("Options")
.setView(dialogView)
.setPositiveButton("OK") { _, _ ->
if (run) fragment.onIconPressed(style, reversed)
if (refresh) fragment.loadEpisodes(source, true)
}
.setNegativeButton("Cancel") { _, _ ->
if (refresh) fragment.loadEpisodes(source, true)
}
.setOnCancelListener {
if (refresh) fragment.loadEpisodes(source, true)
}
.create()
nestedDialog?.show()
}
//Episode Handling
handleEpisodes()

View file

@ -63,6 +63,7 @@ import ani.dantotsu.toast
import ani.dantotsu.util.Logger
import ani.dantotsu.util.StoragePermissions.Companion.accessAlertDialog
import ani.dantotsu.util.StoragePermissions.Companion.hasDirAccess
import ani.dantotsu.util.customAlertDialog
import com.anggrayudi.storage.file.extension
import com.google.android.material.appbar.AppBarLayout
import eu.kanade.tachiyomi.animesource.ConfigurableAnimeSource
@ -396,20 +397,18 @@ class AnimeWatchFragment : Fragment() {
if (allSettings.size > 1) {
val names =
allSettings.map { LanguageMapper.getLanguageName(it.lang) }.toTypedArray()
val dialog = AlertDialog.Builder(requireContext(), R.style.MyPopup)
.setTitle("Select a Source")
.setSingleChoiceItems(names, -1) { dialog, which ->
requireContext()
.customAlertDialog()
.apply {
setTitle("Select a Source")
singleChoiceItems(names) { which ->
selectedSetting = allSettings[which]
itemSelected = true
dialog.dismiss()
// Move the fragment transaction here
requireActivity().runOnUiThread {
val fragment =
AnimeSourcePreferencesFragment().getInstance(selectedSetting.id) {
changeUIVisibility(true)
loadEpisodes(media.selected!!.sourceIndex, true)
}
val fragment = AnimeSourcePreferencesFragment().getInstance(selectedSetting.id) {
changeUIVisibility(true)
loadEpisodes(media.selected!!.sourceIndex, true)
}
parentFragmentManager.beginTransaction()
.setCustomAnimations(R.anim.slide_up, R.anim.slide_down)
.replace(R.id.fragmentExtensionsContainer, fragment)
@ -417,13 +416,13 @@ class AnimeWatchFragment : Fragment() {
.commit()
}
}
.setOnDismissListener {
onDismiss {
if (!itemSelected) {
changeUIVisibility(true)
}
}
.show()
dialog.window?.setDimAmount(0.8f)
show()
}
} else {
// If there's only one setting, proceed with the fragment transaction
requireActivity().runOnUiThread {
@ -432,11 +431,12 @@ class AnimeWatchFragment : Fragment() {
changeUIVisibility(true)
loadEpisodes(media.selected!!.sourceIndex, true)
}
parentFragmentManager.beginTransaction()
.setCustomAnimations(R.anim.slide_up, R.anim.slide_down)
.replace(R.id.fragmentExtensionsContainer, fragment)
.addToBackStack(null)
.commit()
parentFragmentManager.beginTransaction().apply {
setCustomAnimations(R.anim.slide_up, R.anim.slide_down)
replace(R.id.fragmentExtensionsContainer, fragment)
addToBackStack(null)
commit()
}
}
}

View file

@ -23,6 +23,7 @@ import ani.dantotsu.media.MediaNameAdapter
import ani.dantotsu.media.MediaType
import ani.dantotsu.setAnimation
import ani.dantotsu.settings.saving.PrefManager
import ani.dantotsu.util.customAlertDialog
import com.bumptech.glide.Glide
import com.bumptech.glide.load.model.GlideUrl
import kotlinx.coroutines.delay
@ -318,16 +319,14 @@ class EpisodeAdapter(
fragment.onAnimeEpisodeStopDownloadClick(episodeNumber)
return@setOnClickListener
} else if (downloadedEpisodes.contains(episodeNumber)) {
val builder = AlertDialog.Builder(currContext(), R.style.MyPopup)
builder.setTitle("Delete Episode")
builder.setMessage("Are you sure you want to delete Episode ${episodeNumber}?")
builder.setPositiveButton("Yes") { _, _ ->
fragment.onAnimeEpisodeRemoveDownloadClick(episodeNumber)
}
builder.setNegativeButton("No") { _, _ ->
}
val dialog = builder.show()
dialog.window?.setDimAmount(0.8f)
binding.root.context.customAlertDialog().apply {
setTitle("Delete Episode")
setMessage("Are you sure you want to delete Episode $episodeNumber?")
setPosButton(R.string.yes) {
fragment.onAnimeEpisodeRemoveDownloadClick(episodeNumber)
}
setNegButton(R.string.no)
}.show()
return@setOnClickListener
} else {
fragment.onAnimeEpisodeDownloadClick(episodeNumber)

View file

@ -444,15 +444,12 @@ class SelectorDialogFragment : BottomSheetDialogFragment() {
if (subtitles.isNotEmpty()) {
val subtitleNames = subtitles.map { it.language }
var subtitleToDownload: Subtitle? = null
val alertDialog = AlertDialog.Builder(context, R.style.MyPopup)
.setTitle(R.string.download_subtitle)
.setSingleChoiceItems(
subtitleNames.toTypedArray(),
-1
) { _, which ->
requireActivity().customAlertDialog().apply {
setTitle(R.string.download_subtitle)
singleChoiceItems(subtitleNames.toTypedArray()) {which ->
subtitleToDownload = subtitles[which]
}
.setPositiveButton(R.string.download) { dialog, _ ->
setPosButton(R.string.download) {
scope.launch {
if (subtitleToDownload != null) {
SubtitleDownloader.downloadSubtitle(
@ -466,13 +463,9 @@ class SelectorDialogFragment : BottomSheetDialogFragment() {
)
}
}
dialog.dismiss()
}
.setNegativeButton(R.string.cancel) { dialog, _ ->
dialog.dismiss()
}
.show()
alertDialog.window?.setDimAmount(0.8f)
setNegButton(R.string.cancel) {}
}.show()
} else {
snackString(R.string.no_subtitles_available)
}
@ -576,65 +569,63 @@ class SelectorDialogFragment : BottomSheetDialogFragment() {
if (audioTracks.isNotEmpty()) {
val audioNamesArray = audioTracks.toTypedArray()
val checkedItems = BooleanArray(audioNamesArray.size) { false }
val alertDialog = AlertDialog.Builder(currContext, R.style.MyPopup)
.setTitle(R.string.download_audio_tracks)
.setMultiChoiceItems(audioNamesArray, checkedItems) { _, which, isChecked ->
val audioPair = Pair(extractor.audioTracks[which].url, extractor.audioTracks[which].lang)
if (isChecked) {
selectedAudioTracks.add(audioPair)
} else {
selectedAudioTracks.remove(audioPair)
currContext.customAlertDialog().apply{ // ToTest
setTitle(R.string.download_audio_tracks)
multiChoiceItems(audioNamesArray, checkedItems) {
it.forEachIndexed { index, isChecked ->
val audioPair = Pair(extractor.audioTracks[index].url, extractor.audioTracks[index].lang)
if (isChecked) {
selectedAudioTracks.add(audioPair)
} else {
selectedAudioTracks.remove(audioPair)
}
}
}
.setPositiveButton(R.string.download) { _, _ ->
dialog?.dismiss()
setPosButton(R.string.download) {
go()
}
.setNegativeButton(R.string.skip) { dialog, _ ->
setNegButton(R.string.skip) {
selectedAudioTracks = mutableListOf()
go()
dialog.dismiss()
}
.setNeutralButton(R.string.cancel) { dialog, _ ->
setNeutralButton(R.string.cancel) {
selectedAudioTracks = mutableListOf()
dialog.dismiss()
}
.show()
alertDialog.window?.setDimAmount(0.8f)
show()
}
} else {
go()
}
}
if (subtitles.isNotEmpty()) {
if (subtitles.isNotEmpty()) { // ToTest
val subtitleNamesArray = subtitleNames.toTypedArray()
val checkedItems = BooleanArray(subtitleNamesArray.size) { false }
val alertDialog = AlertDialog.Builder(currContext, R.style.MyPopup)
.setTitle(R.string.download_subtitle)
.setMultiChoiceItems(subtitleNamesArray, checkedItems) { _, which, isChecked ->
val subtitlePair = Pair(subtitles[which].file.url, subtitles[which].language)
if (isChecked) {
selectedSubtitles.add(subtitlePair)
} else {
selectedSubtitles.remove(subtitlePair)
currContext.customAlertDialog().apply {
setTitle(R.string.download_subtitle)
multiChoiceItems(subtitleNamesArray, checkedItems) {
it.forEachIndexed { index, isChecked ->
val subtitlePair = Pair(subtitles[index].file.url, subtitles[index].language)
if (isChecked) {
selectedSubtitles.add(subtitlePair)
} else {
selectedSubtitles.remove(subtitlePair)
}
}
}
.setPositiveButton(R.string.download) { _, _ ->
dialog?.dismiss()
setPosButton(R.string.download) {
checkAudioTracks()
}
.setNegativeButton(R.string.skip) { dialog, _ ->
setNegButton(R.string.skip) {
selectedSubtitles = mutableListOf()
checkAudioTracks()
dialog.dismiss()
}
.setNeutralButton(R.string.cancel) { dialog, _ ->
setNeutralButton(R.string.cancel) {
selectedSubtitles = mutableListOf()
dialog.dismiss()
}
.show()
alertDialog.window?.setDimAmount(0.8f)
show()
}
} else {
checkAudioTracks()
}

View file

@ -21,6 +21,7 @@ import ani.dantotsu.setAnimation
import ani.dantotsu.snackString
import ani.dantotsu.util.ColorEditor.Companion.adjustColorForContrast
import ani.dantotsu.util.ColorEditor.Companion.getContrastRatio
import ani.dantotsu.util.customAlertDialog
import com.xwray.groupie.GroupieAdapter
import com.xwray.groupie.Section
import com.xwray.groupie.viewbinding.BindableItem
@ -385,19 +386,14 @@ class CommentItem(
* @param callback the callback to call when the user clicks yes
*/
private fun dialogBuilder(title: String, message: String, callback: () -> Unit) {
val alertDialog =
android.app.AlertDialog.Builder(commentsFragment.activity, R.style.MyPopup)
.setTitle(title)
.setMessage(message)
.setPositiveButton("Yes") { dialog, _ ->
callback()
dialog.dismiss()
}
.setNegativeButton("No") { dialog, _ ->
dialog.dismiss()
}
val dialog = alertDialog.show()
dialog?.window?.setDimAmount(0.8f)
commentsFragment.activity.customAlertDialog().apply {
setTitle(title)
setMessage(message)
setPosButton("Yes") {
callback()
}
setNegButton("No") {}
}.show()
}
private val usernameColors: Array<String> = arrayOf(

View file

@ -25,6 +25,7 @@ import ani.dantotsu.connections.anilist.Anilist
import ani.dantotsu.connections.comments.Comment
import ani.dantotsu.connections.comments.CommentResponse
import ani.dantotsu.connections.comments.CommentsAPI
import ani.dantotsu.databinding.DialogEdittextBinding
import ani.dantotsu.databinding.FragmentCommentsBinding
import ani.dantotsu.loadImage
import ani.dantotsu.media.MediaDetailsActivity
@ -34,6 +35,7 @@ import ani.dantotsu.settings.saving.PrefName
import ani.dantotsu.snackString
import ani.dantotsu.toast
import ani.dantotsu.util.Logger
import ani.dantotsu.util.customAlertDialog
import com.xwray.groupie.GroupieAdapter
import com.xwray.groupie.Section
import io.noties.markwon.editor.MarkwonEditor
@ -162,33 +164,26 @@ class CommentsFragment : Fragment() {
}
binding.commentFilter.setOnClickListener {
val alertDialog = AlertDialog.Builder(activity, R.style.MyPopup)
.setTitle("Enter a chapter/episode number tag")
.setView(R.layout.dialog_edittext)
.setPositiveButton("OK") { dialog, _ ->
val editText =
(dialog as AlertDialog).findViewById<EditText>(R.id.dialogEditText)
val text = editText?.text.toString()
activity.customAlertDialog().apply {
val customView = DialogEdittextBinding.inflate(layoutInflater)
setTitle("Enter a chapter/episode number tag")
setCustomView(customView.root)
setPosButton("OK") {
val text = customView.dialogEditText.text.toString()
filterTag = text.toIntOrNull()
lifecycleScope.launch {
loadAndDisplayComments()
}
dialog.dismiss()
}
.setNeutralButton("Clear") { dialog, _ ->
setNeutralButton("Clear") {
filterTag = null
lifecycleScope.launch {
loadAndDisplayComments()
}
dialog.dismiss()
}
.setNegativeButton("Cancel") { dialog, _ ->
filterTag = null
dialog.dismiss()
}
val dialog = alertDialog.show()
dialog?.window?.setDimAmount(0.8f)
setNegButton("Cancel") { filterTag = null }
show()
}
}
var isFetching = false
@ -303,13 +298,12 @@ class CommentsFragment : Fragment() {
activity.binding.commentLabel.setOnClickListener {
//alert dialog to enter a number, with a cancel and ok button
val alertDialog = AlertDialog.Builder(activity, R.style.MyPopup)
.setTitle("Enter a chapter/episode number tag")
.setView(R.layout.dialog_edittext)
.setPositiveButton("OK") { dialog, _ ->
val editText =
(dialog as AlertDialog).findViewById<EditText>(R.id.dialogEditText)
val text = editText?.text.toString()
activity.customAlertDialog().apply {
val customView = DialogEdittextBinding.inflate(layoutInflater)
setTitle("Enter a chapter/episode number tag")
setCustomView(customView.root)
setPosButton("OK") {
val text = customView.dialogEditText.text.toString()
tag = text.toIntOrNull()
if (tag == null) {
activity.binding.commentLabel.background = ResourcesCompat.getDrawable(
@ -324,28 +318,25 @@ class CommentsFragment : Fragment() {
null
)
}
dialog.dismiss()
}
.setNeutralButton("Clear") { dialog, _ ->
setNeutralButton("Clear") {
tag = null
activity.binding.commentLabel.background = ResourcesCompat.getDrawable(
resources,
R.drawable.ic_label_off_24,
null
)
dialog.dismiss()
}
.setNegativeButton("Cancel") { dialog, _ ->
setNegButton("Cancel") {
tag = null
activity.binding.commentLabel.background = ResourcesCompat.getDrawable(
resources,
R.drawable.ic_label_off_24,
null
)
dialog.dismiss()
}
val dialog = alertDialog.show()
dialog?.window?.setDimAmount(0.8f)
show()
}
}
}
@ -362,12 +353,6 @@ class CommentsFragment : Fragment() {
}
}
}
@SuppressLint("NotifyDataSetChanged")
override fun onStart() {
super.onStart()
}
@SuppressLint("NotifyDataSetChanged")
override fun onResume() {
super.onResume()
@ -579,9 +564,9 @@ class CommentsFragment : Fragment() {
* Called when the user tries to comment for the first time
*/
private fun showCommentRulesDialog() {
val alertDialog = AlertDialog.Builder(activity, R.style.MyPopup)
.setTitle("Commenting Rules")
.setMessage(
activity.customAlertDialog().apply{
setTitle("Commenting Rules")
setMessage(
"I WILL BAN YOU WITHOUT HESITATION\n" +
"1. No racism\n" +
"2. No hate speech\n" +
@ -594,16 +579,13 @@ class CommentsFragment : Fragment() {
"10. No illegal content\n" +
"11. Anything you know you shouldn't comment\n"
)
.setPositiveButton("I Understand") { dialog, _ ->
dialog.dismiss()
setPosButton("I Understand") {
PrefManager.setVal(PrefName.FirstComment, false)
processComment()
}
.setNegativeButton("Cancel") { dialog, _ ->
dialog.dismiss()
}
val dialog = alertDialog.show()
dialog?.window?.setDimAmount(0.8f)
setNegButton(R.string.cancel)
show()
}
}
private fun processComment() {

View file

@ -19,6 +19,7 @@ import androidx.recyclerview.widget.RecyclerView
import ani.dantotsu.R
import ani.dantotsu.currActivity
import ani.dantotsu.currContext
import ani.dantotsu.databinding.CustomDialogLayoutBinding
import ani.dantotsu.databinding.DialogLayoutBinding
import ani.dantotsu.databinding.ItemAnimeWatchBinding
import ani.dantotsu.databinding.ItemChipBinding
@ -40,6 +41,7 @@ import ani.dantotsu.settings.FAQActivity
import ani.dantotsu.settings.saving.PrefManager
import ani.dantotsu.settings.saving.PrefName
import ani.dantotsu.toast
import ani.dantotsu.util.customAlertDialog
import com.google.android.material.chip.Chip
import eu.kanade.tachiyomi.data.notification.Notifications.CHANNEL_SUBSCRIPTION_CHECK
import eu.kanade.tachiyomi.source.online.HttpSource
@ -65,8 +67,6 @@ class MangaReadAdapter(
return ViewHolder(bind)
}
private var nestedDialog: AlertDialog? = null
override fun onBindViewHolder(holder: ViewHolder, position: Int) {
val binding = holder.binding
_binding = binding
@ -171,194 +171,179 @@ class MangaReadAdapter(
}
binding.animeNestedButton.setOnClickListener {
val dialogView =
LayoutInflater.from(fragment.requireContext()).inflate(R.layout.dialog_layout, null)
val dialogBinding = DialogLayoutBinding.bind(dialogView)
val dialogBinding = DialogLayoutBinding.inflate(fragment.layoutInflater)
var refresh = false
var run = false
var reversed = media.selected!!.recyclerReversed
var style =
media.selected!!.recyclerStyle ?: PrefManager.getVal(PrefName.MangaDefaultView)
dialogBinding.animeSourceTop.rotation = if (reversed) -90f else 90f
dialogBinding.sortText.text = if (reversed) "Down to Up" else "Up to Down"
dialogBinding.animeSourceTop.setOnClickListener {
reversed = !reversed
dialogBinding.animeSourceTop.rotation = if (reversed) -90f else 90f
dialogBinding.sortText.text = if (reversed) "Down to Up" else "Up to Down"
run = true
}
dialogBinding.apply {
animeSourceTop.rotation = if (reversed) -90f else 90f
sortText.text = if (reversed) "Down to Up" else "Up to Down"
animeSourceTop.setOnClickListener {
reversed = !reversed
animeSourceTop.rotation = if (reversed) -90f else 90f
sortText.text = if (reversed) "Down to Up" else "Up to Down"
run = true
}
//Grids
dialogBinding.animeSourceGrid.visibility = View.GONE
var selected = when (style) {
0 -> dialogBinding.animeSourceList
1 -> dialogBinding.animeSourceCompact
else -> dialogBinding.animeSourceList
}
when (style) {
0 -> dialogBinding.layoutText.setText(R.string.list)
1 -> dialogBinding.layoutText.setText(R.string.compact)
else -> dialogBinding.animeSourceList
}
selected.alpha = 1f
fun selected(it: ImageButton) {
selected.alpha = 0.33f
selected = it
//Grids
animeSourceGrid.visibility = View.GONE
var selected = when (style) {
0 -> animeSourceList
1 -> animeSourceCompact
else -> animeSourceList
}
when (style) {
0 -> layoutText.setText(R.string.list)
1 -> layoutText.setText(R.string.compact)
else -> animeSourceList
}
selected.alpha = 1f
}
dialogBinding.animeSourceList.setOnClickListener {
selected(it as ImageButton)
style = 0
dialogBinding.layoutText.setText(R.string.list)
run = true
}
dialogBinding.animeSourceCompact.setOnClickListener {
selected(it as ImageButton)
style = 1
dialogBinding.layoutText.setText(R.string.compact)
run = true
}
dialogBinding.animeWebviewContainer.setOnClickListener {
if (!WebViewUtil.supportsWebView(fragment.requireContext())) {
toast(R.string.webview_not_installed)
fun selected(it: ImageButton) {
selected.alpha = 0.33f
selected = it
selected.alpha = 1f
}
//start CookieCatcher activity
if (mangaReadSources.names.isNotEmpty() && source in 0 until mangaReadSources.names.size) {
val sourceAHH = mangaReadSources[source] as? DynamicMangaParser
val sourceHttp = sourceAHH?.extension?.sources?.firstOrNull() as? HttpSource
val url = sourceHttp?.baseUrl
url?.let {
refresh = true
val intent = Intent(fragment.requireContext(), CookieCatcher::class.java)
.putExtra("url", url)
startActivity(fragment.requireContext(), intent, null)
animeSourceList.setOnClickListener {
selected(it as ImageButton)
style = 0
layoutText.setText(R.string.list)
run = true
}
animeSourceCompact.setOnClickListener {
selected(it as ImageButton)
style = 1
layoutText.setText(R.string.compact)
run = true
}
animeWebviewContainer.setOnClickListener {
if (!WebViewUtil.supportsWebView(fragment.requireContext())) {
toast(R.string.webview_not_installed)
}
}
}
//Multi download
dialogBinding.downloadNo.text = "0"
dialogBinding.animeDownloadTop.setOnClickListener {
//Alert dialog asking for the number of chapters to download
val alertDialog = AlertDialog.Builder(currContext(), R.style.MyPopup)
alertDialog.setTitle("Multi Chapter Downloader")
alertDialog.setMessage("Enter the number of chapters to download")
val input = NumberPicker(currContext())
input.minValue = 1
input.maxValue = 20
input.value = 1
alertDialog.setView(input)
alertDialog.setPositiveButton("OK") { _, _ ->
dialogBinding.downloadNo.text = "${input.value}"
}
alertDialog.setNegativeButton("Cancel") { dialog, _ -> dialog.cancel() }
val dialog = alertDialog.show()
dialog.window?.setDimAmount(0.8f)
}
//Scanlator
dialogBinding.animeScanlatorContainer.isVisible = options.count() > 1
dialogBinding.scanlatorNo.text = "${options.count()}"
dialogBinding.animeScanlatorTop.setOnClickListener {
val dialogView2 =
LayoutInflater.from(currContext()).inflate(R.layout.custom_dialog_layout, null)
val checkboxContainer =
dialogView2.findViewById<LinearLayout>(R.id.checkboxContainer)
val tickAllButton = dialogView2.findViewById<ImageButton>(R.id.toggleButton)
// Function to get the right image resource for the toggle button
fun getToggleImageResource(container: ViewGroup): Int {
var allChecked = true
var allUnchecked = true
for (i in 0 until container.childCount) {
val checkBox = container.getChildAt(i) as CheckBox
if (!checkBox.isChecked) {
allChecked = false
} else {
allUnchecked = false
//start CookieCatcher activity
if (mangaReadSources.names.isNotEmpty() && source in 0 until mangaReadSources.names.size) {
val sourceAHH = mangaReadSources[source] as? DynamicMangaParser
val sourceHttp = sourceAHH?.extension?.sources?.firstOrNull() as? HttpSource
val url = sourceHttp?.baseUrl
url?.let {
refresh = true
val intent =
Intent(fragment.requireContext(), CookieCatcher::class.java)
.putExtra("url", url)
startActivity(fragment.requireContext(), intent, null)
}
}
return when {
allChecked -> R.drawable.untick_all_boxes
allUnchecked -> R.drawable.tick_all_boxes
else -> R.drawable.invert_all_boxes
}
}
// Dynamically add checkboxes
options.forEach { option ->
val checkBox = CheckBox(currContext()).apply {
text = option
setOnCheckedChangeListener { _, _ ->
// Update image resource when you change a checkbox
tickAllButton.setImageResource(getToggleImageResource(checkboxContainer))
//Multi download
downloadNo.text = "0"
animeDownloadTop.setOnClickListener {
//Alert dialog asking for the number of chapters to download
fragment.requireContext().customAlertDialog().apply {
setTitle("Multi Chapter Downloader")
setMessage("Enter the number of chapters to download")
val input = NumberPicker(currContext())
input.minValue = 1
input.maxValue = 20
input.value = 1
setCustomView(input)
setPosButton(R.string.ok) {
downloadNo.text = "${input.value}"
}
setNegButton(R.string.cancel)
show()
}
// Set checked if its already selected
if (media.selected!!.scanlators != null) {
checkBox.isChecked = media.selected!!.scanlators?.contains(option) != true
scanlatorSelectionListener?.onScanlatorsSelected()
} else {
checkBox.isChecked = true
}
checkboxContainer.addView(checkBox)
}
// Create AlertDialog
val dialog = AlertDialog.Builder(currContext(), R.style.MyPopup)
.setView(dialogView2)
.setPositiveButton("OK") { _, _ ->
hiddenScanlators.clear()
for (i in 0 until checkboxContainer.childCount) {
val checkBox = checkboxContainer.getChildAt(i) as CheckBox
//Scanlator
animeScanlatorContainer.isVisible = options.count() > 1
scanlatorNo.text = "${options.count()}"
animeScanlatorTop.setOnClickListener {
CustomDialogLayoutBinding.inflate(fragment.layoutInflater)
val dialogView = CustomDialogLayoutBinding.inflate(fragment.layoutInflater)
val checkboxContainer = dialogView.checkboxContainer
val tickAllButton = dialogView.toggleButton
fun getToggleImageResource(container: ViewGroup): Int {
var allChecked = true
var allUnchecked = true
for (i in 0 until container.childCount) {
val checkBox = container.getChildAt(i) as CheckBox
if (!checkBox.isChecked) {
hiddenScanlators.add(checkBox.text.toString())
allChecked = false
} else {
allUnchecked = false
}
}
fragment.onScanlatorChange(hiddenScanlators)
scanlatorSelectionListener?.onScanlatorsSelected()
}
.setNegativeButton("Cancel", null)
.show()
dialog.window?.setDimAmount(0.8f)
// Standard image resource
tickAllButton.setImageResource(getToggleImageResource(checkboxContainer))
// Listens to ticked checkboxes and changes image resource accordingly
tickAllButton.setOnClickListener {
// Toggle checkboxes
for (i in 0 until checkboxContainer.childCount) {
val checkBox = checkboxContainer.getChildAt(i) as CheckBox
checkBox.isChecked = !checkBox.isChecked
return when {
allChecked -> R.drawable.untick_all_boxes
allUnchecked -> R.drawable.tick_all_boxes
else -> R.drawable.invert_all_boxes
}
}
// Update image resource
options.forEach { option ->
val checkBox = CheckBox(currContext()).apply {
text = option
setOnCheckedChangeListener { _, _ ->
tickAllButton.setImageResource(getToggleImageResource(checkboxContainer))
}
}
if (media.selected!!.scanlators != null) {
checkBox.isChecked = media.selected!!.scanlators?.contains(option) != true
scanlatorSelectionListener?.onScanlatorsSelected()
} else {
checkBox.isChecked = true
}
checkboxContainer.addView(checkBox)
}
fragment.requireContext().customAlertDialog().apply {
setCustomView(dialogView.root)
setPosButton("OK") {
hiddenScanlators.clear()
for (i in 0 until checkboxContainer.childCount) {
val checkBox = checkboxContainer.getChildAt(i) as CheckBox
if (!checkBox.isChecked) {
hiddenScanlators.add(checkBox.text.toString())
}
}
fragment.onScanlatorChange(hiddenScanlators)
scanlatorSelectionListener?.onScanlatorsSelected()
}
setNegButton("Cancel")
}.show()
tickAllButton.setImageResource(getToggleImageResource(checkboxContainer))
tickAllButton.setOnClickListener {
for (i in 0 until checkboxContainer.childCount) {
val checkBox = checkboxContainer.getChildAt(i) as CheckBox
checkBox.isChecked = !checkBox.isChecked
}
tickAllButton.setImageResource(getToggleImageResource(checkboxContainer))
}
}
fragment.requireContext().customAlertDialog().apply {
setTitle("Options")
setCustomView(root)
setPosButton("OK") {
if (run) fragment.onIconPressed(style, reversed)
if (downloadNo.text != "0") {
fragment.multiDownload(downloadNo.text.toString().toInt())
}
if (refresh) fragment.loadChapters(source, true)
}
setNegButton("Cancel") {
if (refresh) fragment.loadChapters(source, true)
}
show()
}
}
nestedDialog = AlertDialog.Builder(fragment.requireContext(), R.style.MyPopup)
.setTitle("Options")
.setView(dialogView)
.setPositiveButton("OK") { _, _ ->
if (run) fragment.onIconPressed(style, reversed)
if (dialogBinding.downloadNo.text != "0") {
fragment.multiDownload(dialogBinding.downloadNo.text.toString().toInt())
}
if (refresh) fragment.loadChapters(source, true)
}
.setNegativeButton("Cancel") { _, _ ->
if (refresh) fragment.loadChapters(source, true)
}
.setOnCancelListener {
if (refresh) fragment.loadChapters(source, true)
}
.create()
nestedDialog?.show()
}
//Chapter Handling
handleChapters()

View file

@ -60,6 +60,7 @@ import ani.dantotsu.settings.saving.PrefName
import ani.dantotsu.snackString
import ani.dantotsu.util.StoragePermissions.Companion.accessAlertDialog
import ani.dantotsu.util.StoragePermissions.Companion.hasDirAccess
import ani.dantotsu.util.customAlertDialog
import com.google.android.material.appbar.AppBarLayout
import eu.kanade.tachiyomi.extension.manga.model.MangaExtension
import eu.kanade.tachiyomi.source.ConfigurableSource
@ -386,32 +387,30 @@ open class MangaReadFragment : Fragment(), ScanlatorSelectionListener {
if (allSettings.size > 1) {
val names =
allSettings.map { LanguageMapper.getLanguageName(it.lang) }.toTypedArray()
val dialog = AlertDialog.Builder(requireContext(), R.style.MyPopup)
.setTitle("Select a Source")
.setSingleChoiceItems(names, -1) { dialog, which ->
requireContext().customAlertDialog().apply {
setTitle("Select a Source")
singleChoiceItems(names) { which ->
selectedSetting = allSettings[which]
itemSelected = true
dialog.dismiss()
// Move the fragment transaction here
val fragment =
MangaSourcePreferencesFragment().getInstance(selectedSetting.id) {
changeUIVisibility(true)
loadChapters(media.selected!!.sourceIndex, true)
}
val fragment = MangaSourcePreferencesFragment().getInstance(selectedSetting.id) {
changeUIVisibility(true)
loadChapters(media.selected!!.sourceIndex, true)
}
parentFragmentManager.beginTransaction()
.setCustomAnimations(R.anim.slide_up, R.anim.slide_down)
.replace(R.id.fragmentExtensionsContainer, fragment)
.addToBackStack(null)
.commit()
}
.setOnDismissListener {
onDismiss{
if (!itemSelected) {
changeUIVisibility(true)
}
}
.show()
dialog.window?.setDimAmount(0.8f)
show()
}
} else {
// If there's only one setting, proceed with the fragment transaction
val fragment = MangaSourcePreferencesFragment().getInstance(selectedSetting.id) {

View file

@ -83,6 +83,7 @@ import ani.dantotsu.showSystemBarsRetractView
import ani.dantotsu.snackString
import ani.dantotsu.themes.ThemeManager
import ani.dantotsu.tryWith
import ani.dantotsu.util.customAlertDialog
import com.alexvasilkov.gestures.views.GestureFrameLayout
import com.bumptech.glide.load.resource.bitmap.BitmapTransformation
import com.davemorrissey.labs.subscaleview.SubsamplingScaleImageView
@ -1013,28 +1014,27 @@ class MangaReaderActivity : AppCompatActivity() {
PrefManager.setCustomVal("${media.id}_progressDialog", !isChecked)
showProgressDialog = !isChecked
}
AlertDialog.Builder(this, R.style.MyPopup)
.setTitle(getString(R.string.title_update_progress))
.setView(dialogView)
.setCancelable(false)
.setPositiveButton(getString(R.string.yes)) { dialog, _ ->
customAlertDialog().apply {
setTitle(R.string.title_update_progress)
setCustomView(dialogView)
setCancelable(false)
setPosButton(R.string.yes) {
PrefManager.setCustomVal("${media.id}_save_progress", true)
updateProgress(
media,
MediaNameAdapter.findChapterNumber(media.manga!!.selectedChapter!!)
.toString()
)
dialog.dismiss()
runnable.run()
}
.setNegativeButton(getString(R.string.no)) { dialog, _ ->
setNegButton(R.string.no) {
PrefManager.setCustomVal("${media.id}_save_progress", false)
dialog.dismiss()
runnable.run()
}
.setOnCancelListener { hideSystemBars() }
.create()
.show()
setOnCancelListener { hideSystemBars() }
show()
}
} else {
if (!incognito && PrefManager.getCustomVal(
"${media.id}_save_progress",

View file

@ -13,6 +13,7 @@ import ani.dantotsu.parsers.ShowResponse
import ani.dantotsu.setAnimation
import ani.dantotsu.snackString
import ani.dantotsu.util.Logger
import ani.dantotsu.util.customAlertDialog
import com.bumptech.glide.Glide
import com.bumptech.glide.load.model.GlideUrl
@ -93,27 +94,22 @@ class NovelResponseAdapter(
}
binding.root.setOnLongClickListener {
val builder = androidx.appcompat.app.AlertDialog.Builder(
fragment.requireContext(),
R.style.MyPopup
)
builder.setTitle("Delete ${novel.name}?")
builder.setMessage("Are you sure you want to delete ${novel.name}?")
builder.setPositiveButton("Yes") { _, _ ->
downloadedCheckCallback.deleteDownload(novel)
deleteDownload(novel.link)
snackString("Deleted ${novel.name}")
if (binding.itemEpisodeFiller.text.toString()
.contains("Download", ignoreCase = true)
) {
binding.itemEpisodeFiller.text = ""
it.context.customAlertDialog().apply {
setTitle("Delete ${novel.name}?")
setMessage("Are you sure you want to delete ${novel.name}?")
setPosButton(R.string.yes) {
downloadedCheckCallback.deleteDownload(novel)
deleteDownload(novel.link)
snackString("Deleted ${novel.name}")
if (binding.itemEpisodeFiller.text.toString()
.contains("Download", ignoreCase = true)
) {
binding.itemEpisodeFiller.text = ""
}
}
setNegButton(R.string.no)
show()
}
builder.setNegativeButton("No") { _, _ ->
// Do nothing
}
val dialog = builder.show()
dialog.window?.setDimAmount(0.8f)
true
}
}