From 124c8f5ed74de017c0dd85da63114c9776847521 Mon Sep 17 00:00:00 2001 From: aayush262 Date: Thu, 13 Jun 2024 19:15:55 +0530 Subject: [PATCH] feat: optimize Alert Dialogs --- .../main/java/ani/dantotsu/MainActivity.kt | 46 ++- .../download/anime/OfflineAnimeFragment.kt | 32 +- .../download/manga/OfflineMangaFragment.kt | 23 +- .../ani/dantotsu/download/video/Helper.kt | 22 +- .../java/ani/dantotsu/home/LoginFragment.kt | 47 ++- .../java/ani/dantotsu/home/status/Stories.kt | 3 +- .../dantotsu/media/anime/AnimeWatchAdapter.kt | 184 +++++------ .../media/anime/AnimeWatchFragment.kt | 38 +-- .../dantotsu/media/anime/EpisodeAdapters.kt | 19 +- .../media/anime/SelectorDialogFragment.kt | 85 +++-- .../dantotsu/media/comments/CommentItem.kt | 22 +- .../media/comments/CommentsFragment.kt | 76 ++--- .../dantotsu/media/manga/MangaReadAdapter.kt | 307 +++++++++--------- .../dantotsu/media/manga/MangaReadFragment.kt | 25 +- .../manga/mangareader/MangaReaderActivity.kt | 22 +- .../media/novel/NovelResponseAdapter.kt | 34 +- .../dantotsu/profile/activity/ActivityItem.kt | 1 - .../activity}/RepliesBottomDialog.kt | 15 +- .../dantotsu/settings/ExtensionsActivity.kt | 63 ++-- .../InstalledAnimeExtensionsFragment.kt | 21 +- .../InstalledMangaExtensionsFragment.kt | 14 +- .../settings/PlayerSettingsActivity.kt | 168 +++++----- .../settings/SettingsCommonActivity.kt | 105 +++--- .../settings/SettingsExtensionsActivity.kt | 76 ++--- .../settings/SettingsNotificationActivity.kt | 29 +- .../settings/UserInterfaceSettingsActivity.kt | 12 +- .../dantotsu/settings/saving/Preferences.kt | 1 + .../dantotsu/util/ActivityMarkdownCreator.kt | 13 +- .../ani/dantotsu/util/AlertDialogBuilder.kt | 32 +- .../ani/dantotsu/util/StoragePermissions.kt | 25 +- app/src/main/res/values/strings.xml | 2 + 31 files changed, 732 insertions(+), 830 deletions(-) rename app/src/main/java/ani/dantotsu/{home/status => profile/activity}/RepliesBottomDialog.kt (90%) diff --git a/app/src/main/java/ani/dantotsu/MainActivity.kt b/app/src/main/java/ani/dantotsu/MainActivity.kt index 2562ce93af..68f429222a 100644 --- a/app/src/main/java/ani/dantotsu/MainActivity.kt +++ b/app/src/main/java/ani/dantotsu/MainActivity.kt @@ -61,6 +61,7 @@ import ani.dantotsu.settings.saving.internal.PreferenceKeystore import ani.dantotsu.settings.saving.internal.PreferencePackager import ani.dantotsu.themes.ThemeManager import ani.dantotsu.util.Logger +import ani.dantotsu.util.customAlertDialog import com.google.android.material.snackbar.BaseTransientBottomBar import com.google.android.material.snackbar.Snackbar import com.google.android.material.textfield.TextInputEditText @@ -494,35 +495,28 @@ class MainActivity : AppCompatActivity() { val password = CharArray(16).apply { fill('0') } // Inflate the dialog layout - val dialogView = DialogUserAgentBinding.inflate(layoutInflater) - dialogView.userAgentTextBox.hint = "Password" - dialogView.subtitle.visibility = View.VISIBLE - dialogView.subtitle.text = getString(R.string.enter_password_to_decrypt_file) - - val dialog = AlertDialog.Builder(this, R.style.MyPopup) - .setTitle("Enter Password") - .setView(dialogView.root) - .setPositiveButton("OK", null) - .setNegativeButton("Cancel") { dialog, _ -> + val dialogView = DialogUserAgentBinding.inflate(layoutInflater).apply { + userAgentTextBox.hint = "Password" + subtitle.visibility = View.VISIBLE + subtitle.text = getString(R.string.enter_password_to_decrypt_file) + } + customAlertDialog().apply { + setTitle("Enter Password") + setCustomView(dialogView.root) + setPosButton(R.string.yes) { + val editText = dialogView.userAgentTextBox + if (editText.text?.isNotBlank() == true) { + editText.text?.toString()?.trim()?.toCharArray(password) + callback(password) + } else { + toast("Password cannot be empty") + } + } + setNegButton(R.string.cancel) { password.fill('0') - dialog.dismiss() callback(null) } - .create() - - dialog.window?.setDimAmount(0.8f) - dialog.show() - - // Override the positive button here - dialog.getButton(AlertDialog.BUTTON_POSITIVE).setOnClickListener { - val editText = dialog.findViewById(R.id.userAgentTextBox) - if (editText?.text?.isNotBlank() == true) { - editText.text?.toString()?.trim()?.toCharArray(password) - dialog.dismiss() - callback(password) - } else { - toast("Password cannot be empty") - } + show() } } diff --git a/app/src/main/java/ani/dantotsu/download/anime/OfflineAnimeFragment.kt b/app/src/main/java/ani/dantotsu/download/anime/OfflineAnimeFragment.kt index 3bcdffe1ee..4f3876fe51 100644 --- a/app/src/main/java/ani/dantotsu/download/anime/OfflineAnimeFragment.kt +++ b/app/src/main/java/ani/dantotsu/download/anime/OfflineAnimeFragment.kt @@ -49,6 +49,7 @@ import ani.dantotsu.settings.saving.PrefManager import ani.dantotsu.settings.saving.PrefName import ani.dantotsu.snackString import ani.dantotsu.util.Logger +import ani.dantotsu.util.customAlertDialog import com.anggrayudi.storage.file.openInputStream import com.google.android.material.card.MaterialCardView import com.google.android.material.imageview.ShapeableImageView @@ -203,25 +204,22 @@ class OfflineAnimeFragment : Fragment(), OfflineAnimeSearchListener { val type: MediaType = MediaType.ANIME // Alert dialog to confirm deletion - val builder = - androidx.appcompat.app.AlertDialog.Builder(requireContext(), R.style.MyPopup) - builder.setTitle("Delete ${item.title}?") - builder.setMessage("Are you sure you want to delete ${item.title}?") - builder.setPositiveButton("Yes") { _, _ -> - downloadManager.removeMedia(item.title, type) - val mediaIds = - PrefManager.getAnimeDownloadPreferences().all?.filter { it.key.contains(item.title) }?.values - ?: emptySet() - if (mediaIds.isEmpty()) { - snackString("No media found") // if this happens, terrible things have happened + requireContext().customAlertDialog().apply { + setTitle("Delete ${item.title}?") + setMessage("Are you sure you want to delete ${item.title}?") + setPosButton(R.string.yes) { + downloadManager.removeMedia(item.title, type) + val mediaIds = PrefManager.getAnimeDownloadPreferences().all?.filter { it.key.contains(item.title) }?.values ?: emptySet() + if (mediaIds.isEmpty()) { + snackString("No media found") // if this happens, terrible things have happened + } + getDownloads() } - getDownloads() - } - builder.setNegativeButton("No") { _, _ -> - // Do nothing + setNegButton(R.string.no) { + // Do nothing + } + show() } - val dialog = builder.show() - dialog.window?.setDimAmount(0.8f) true } } diff --git a/app/src/main/java/ani/dantotsu/download/manga/OfflineMangaFragment.kt b/app/src/main/java/ani/dantotsu/download/manga/OfflineMangaFragment.kt index 6d88918e6c..dcb462e80f 100644 --- a/app/src/main/java/ani/dantotsu/download/manga/OfflineMangaFragment.kt +++ b/app/src/main/java/ani/dantotsu/download/manga/OfflineMangaFragment.kt @@ -46,6 +46,7 @@ import ani.dantotsu.settings.saving.PrefManager import ani.dantotsu.settings.saving.PrefName import ani.dantotsu.snackString import ani.dantotsu.util.Logger +import ani.dantotsu.util.customAlertDialog import com.anggrayudi.storage.file.openInputStream import com.google.android.material.card.MaterialCardView import com.google.android.material.imageview.ShapeableImageView @@ -201,19 +202,15 @@ class OfflineMangaFragment : Fragment(), OfflineMangaSearchListener { MediaType.NOVEL } // Alert dialog to confirm deletion - val builder = - androidx.appcompat.app.AlertDialog.Builder(requireContext(), R.style.MyPopup) - builder.setTitle("Delete ${item.title}?") - builder.setMessage("Are you sure you want to delete ${item.title}?") - builder.setPositiveButton("Yes") { _, _ -> - downloadManager.removeMedia(item.title, type) - getDownloads() - } - builder.setNegativeButton("No") { _, _ -> - // Do nothing - } - val dialog = builder.show() - dialog.window?.setDimAmount(0.8f) + requireContext().customAlertDialog().apply { + setTitle("Delete ${item.title}?") + setMessage("Are you sure you want to delete ${item.title}?") + setPosButton(R.string.yes) { + downloadManager.removeMedia(item.title, type) + getDownloads() + } + setNegButton(R.string.no) + }.show() true } } diff --git a/app/src/main/java/ani/dantotsu/download/video/Helper.kt b/app/src/main/java/ani/dantotsu/download/video/Helper.kt index b207d63461..ab8dd73d4d 100644 --- a/app/src/main/java/ani/dantotsu/download/video/Helper.kt +++ b/app/src/main/java/ani/dantotsu/download/video/Helper.kt @@ -3,7 +3,6 @@ package ani.dantotsu.download.video import android.Manifest import android.annotation.SuppressLint import android.app.Activity -import android.app.AlertDialog import android.content.Context import android.content.Intent import android.content.pm.PackageManager @@ -29,10 +28,10 @@ import ani.dantotsu.download.anime.AnimeDownloaderService import ani.dantotsu.download.anime.AnimeServiceDataSingleton import ani.dantotsu.media.Media import ani.dantotsu.media.MediaType -import ani.dantotsu.parsers.Subtitle import ani.dantotsu.parsers.Video import ani.dantotsu.settings.saving.PrefManager import ani.dantotsu.util.Logger +import ani.dantotsu.util.customAlertDialog import eu.kanade.tachiyomi.network.NetworkHelper import uy.kohesive.injekt.Injekt import uy.kohesive.injekt.api.get @@ -72,19 +71,19 @@ object Helper { episodeImage ) - val downloadsManger = Injekt.get() - val downloadCheck = downloadsManger + val downloadsManager = Injekt.get() + val downloadCheck = downloadsManager .queryDownload(title, episode, MediaType.ANIME) if (downloadCheck) { - AlertDialog.Builder(context, R.style.MyPopup) - .setTitle("Download Exists") - .setMessage("A download for this episode already exists. Do you want to overwrite it?") - .setPositiveButton("Yes") { _, _ -> + context.customAlertDialog().apply { + setTitle("Download Exists") + setMessage("A download for this episode already exists. Do you want to overwrite it?") + setPosButton(R.string.yes) { PrefManager.getAnimeDownloadPreferences().edit() .remove(animeDownloadTask.getTaskName()) .apply() - downloadsManger.removeDownload( + downloadsManager.removeDownload( DownloadedType( title, episode, @@ -99,8 +98,9 @@ object Helper { } } } - .setNegativeButton("No") { _, _ -> } - .show() + setNegButton(R.string.no) + show() + } } else { AnimeServiceDataSingleton.downloadQueue.offer(animeDownloadTask) if (!AnimeServiceDataSingleton.isServiceRunning) { diff --git a/app/src/main/java/ani/dantotsu/home/LoginFragment.kt b/app/src/main/java/ani/dantotsu/home/LoginFragment.kt index 5f89464e3c..13fde1e547 100644 --- a/app/src/main/java/ani/dantotsu/home/LoginFragment.kt +++ b/app/src/main/java/ani/dantotsu/home/LoginFragment.kt @@ -12,12 +12,14 @@ import androidx.documentfile.provider.DocumentFile import androidx.fragment.app.Fragment import ani.dantotsu.R import ani.dantotsu.connections.anilist.Anilist +import ani.dantotsu.databinding.DialogUserAgentBinding import ani.dantotsu.databinding.FragmentLoginBinding import ani.dantotsu.openLinkInBrowser import ani.dantotsu.settings.saving.internal.PreferenceKeystore import ani.dantotsu.settings.saving.internal.PreferencePackager import ani.dantotsu.toast import ani.dantotsu.util.Logger +import ani.dantotsu.util.customAlertDialog import com.google.android.material.textfield.TextInputEditText class LoginFragment : Fragment() { @@ -94,38 +96,31 @@ class LoginFragment : Fragment() { val password = CharArray(16).apply { fill('0') } // Inflate the dialog layout - val dialogView = - LayoutInflater.from(requireActivity()).inflate(R.layout.dialog_user_agent, null) - dialogView.findViewById(R.id.userAgentTextBox)?.hint = "Password" - val subtitleTextView = dialogView.findViewById(R.id.subtitle) - subtitleTextView?.visibility = View.VISIBLE - subtitleTextView?.text = "Enter your password to decrypt the file" + val dialogView = DialogUserAgentBinding.inflate(layoutInflater).apply { + userAgentTextBox.hint = "Password" + subtitle.visibility = View.VISIBLE + subtitle.text = getString(R.string.enter_password_to_decrypt_file) + } - val dialog = AlertDialog.Builder(requireActivity(), R.style.MyPopup) - .setTitle("Enter Password") - .setView(dialogView) - .setPositiveButton("OK", null) - .setNegativeButton("Cancel") { dialog, _ -> + requireActivity().customAlertDialog().apply { + setTitle("Enter Password") + setCustomView(dialogView.root) + setPosButton(R.string.ok){ + val editText = dialogView.userAgentTextBox + if (editText.text?.isNotBlank() == true) { + editText.text?.toString()?.trim()?.toCharArray(password) + callback(password) + } else { + toast("Password cannot be empty") + } + } + setNegButton(R.string.cancel) { password.fill('0') - dialog.dismiss() callback(null) } - .create() + }.show() - dialog.window?.setDimAmount(0.8f) - dialog.show() - // Override the positive button here - dialog.getButton(AlertDialog.BUTTON_POSITIVE).setOnClickListener { - val editText = dialog.findViewById(R.id.userAgentTextBox) - if (editText?.text?.isNotBlank() == true) { - editText.text?.toString()?.trim()?.toCharArray(password) - dialog.dismiss() - callback(password) - } else { - toast("Password cannot be empty") - } - } } private fun restartApp() { diff --git a/app/src/main/java/ani/dantotsu/home/status/Stories.kt b/app/src/main/java/ani/dantotsu/home/status/Stories.kt index d65228442a..a017b7ab46 100644 --- a/app/src/main/java/ani/dantotsu/home/status/Stories.kt +++ b/app/src/main/java/ani/dantotsu/home/status/Stories.kt @@ -5,7 +5,6 @@ import android.content.Context import android.content.Intent import android.content.res.ColorStateList import android.util.AttributeSet -import android.view.Gravity import android.view.LayoutInflater import android.view.MotionEvent import android.view.View @@ -16,7 +15,6 @@ import androidx.core.app.ActivityOptionsCompat import androidx.core.content.ContextCompat import androidx.core.view.ViewCompat import androidx.core.view.isVisible -import androidx.core.widget.NestedScrollView import androidx.fragment.app.FragmentActivity import ani.dantotsu.R import ani.dantotsu.blurImage @@ -32,6 +30,7 @@ import ani.dantotsu.profile.ProfileActivity import ani.dantotsu.profile.User import ani.dantotsu.profile.UsersDialogFragment import ani.dantotsu.profile.activity.ActivityItemBuilder +import ani.dantotsu.profile.activity.RepliesBottomDialog import ani.dantotsu.settings.saving.PrefManager import ani.dantotsu.settings.saving.PrefName import ani.dantotsu.snackString diff --git a/app/src/main/java/ani/dantotsu/media/anime/AnimeWatchAdapter.kt b/app/src/main/java/ani/dantotsu/media/anime/AnimeWatchAdapter.kt index a2406a21be..4f71089649 100644 --- a/app/src/main/java/ani/dantotsu/media/anime/AnimeWatchAdapter.kt +++ b/app/src/main/java/ani/dantotsu/media/anime/AnimeWatchAdapter.kt @@ -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 + 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 + } + //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 - } - 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) + fun selected(it: ImageButton) { + selected.alpha = 0.33f + selected = it + selected.alpha = 1f } - //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() + 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) + startActivity(fragment.requireContext(), intent, null) } - val intent = Intent(fragment.requireContext(), CookieCatcher::class.java) - .putExtra("url", url) - .putExtra("headers", headersMap as HashMap) - startActivity(fragment.requireContext(), intent, null) } } - } - - //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) + //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() } - .create() - nestedDialog?.show() + } } //Episode Handling handleEpisodes() diff --git a/app/src/main/java/ani/dantotsu/media/anime/AnimeWatchFragment.kt b/app/src/main/java/ani/dantotsu/media/anime/AnimeWatchFragment.kt index ecd8ee7312..a9dc9b7e8e 100644 --- a/app/src/main/java/ani/dantotsu/media/anime/AnimeWatchFragment.kt +++ b/app/src/main/java/ani/dantotsu/media/anime/AnimeWatchFragment.kt @@ -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() + } } } diff --git a/app/src/main/java/ani/dantotsu/media/anime/EpisodeAdapters.kt b/app/src/main/java/ani/dantotsu/media/anime/EpisodeAdapters.kt index 14be291aa1..1ee5c88127 100644 --- a/app/src/main/java/ani/dantotsu/media/anime/EpisodeAdapters.kt +++ b/app/src/main/java/ani/dantotsu/media/anime/EpisodeAdapters.kt @@ -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) diff --git a/app/src/main/java/ani/dantotsu/media/anime/SelectorDialogFragment.kt b/app/src/main/java/ani/dantotsu/media/anime/SelectorDialogFragment.kt index e93267e218..febd93ec41 100644 --- a/app/src/main/java/ani/dantotsu/media/anime/SelectorDialogFragment.kt +++ b/app/src/main/java/ani/dantotsu/media/anime/SelectorDialogFragment.kt @@ -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() } diff --git a/app/src/main/java/ani/dantotsu/media/comments/CommentItem.kt b/app/src/main/java/ani/dantotsu/media/comments/CommentItem.kt index 6c55209065..0a4bed3356 100644 --- a/app/src/main/java/ani/dantotsu/media/comments/CommentItem.kt +++ b/app/src/main/java/ani/dantotsu/media/comments/CommentItem.kt @@ -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 = arrayOf( diff --git a/app/src/main/java/ani/dantotsu/media/comments/CommentsFragment.kt b/app/src/main/java/ani/dantotsu/media/comments/CommentsFragment.kt index ff861dbe4c..fc21805e67 100644 --- a/app/src/main/java/ani/dantotsu/media/comments/CommentsFragment.kt +++ b/app/src/main/java/ani/dantotsu/media/comments/CommentsFragment.kt @@ -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(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(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() { diff --git a/app/src/main/java/ani/dantotsu/media/manga/MangaReadAdapter.kt b/app/src/main/java/ani/dantotsu/media/manga/MangaReadAdapter.kt index 177d36845c..4cd856a1c7 100644 --- a/app/src/main/java/ani/dantotsu/media/manga/MangaReadAdapter.kt +++ b/app/src/main/java/ani/dantotsu/media/manga/MangaReadAdapter.kt @@ -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 } - } - - //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}" + animeSourceCompact.setOnClickListener { + selected(it as ImageButton) + style = 1 + layoutText.setText(R.string.compact) + run = true } - 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(R.id.checkboxContainer) - val tickAllButton = dialogView2.findViewById(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 - } + animeWebviewContainer.setOnClickListener { + if (!WebViewUtil.supportsWebView(fragment.requireContext())) { + toast(R.string.webview_not_installed) } - return when { - allChecked -> R.drawable.untick_all_boxes - allUnchecked -> R.drawable.tick_all_boxes - else -> R.drawable.invert_all_boxes + //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) + } } } - // 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() + return when { + allChecked -> R.drawable.untick_all_boxes + allUnchecked -> R.drawable.tick_all_boxes + else -> R.drawable.invert_all_boxes + } } - .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 + + 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) } - // Update image resource + 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)) - } - } - 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()) + tickAllButton.setOnClickListener { + for (i in 0 until checkboxContainer.childCount) { + val checkBox = checkboxContainer.getChildAt(i) as CheckBox + checkBox.isChecked = !checkBox.isChecked + } + tickAllButton.setImageResource(getToggleImageResource(checkboxContainer)) } - if (refresh) fragment.loadChapters(source, true) - } - .setNegativeButton("Cancel") { _, _ -> - if (refresh) fragment.loadChapters(source, true) } - .setOnCancelListener { - if (refresh) fragment.loadChapters(source, true) + + 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() } - .create() - nestedDialog?.show() + } } //Chapter Handling handleChapters() diff --git a/app/src/main/java/ani/dantotsu/media/manga/MangaReadFragment.kt b/app/src/main/java/ani/dantotsu/media/manga/MangaReadFragment.kt index bce5f31283..7430bafa51 100644 --- a/app/src/main/java/ani/dantotsu/media/manga/MangaReadFragment.kt +++ b/app/src/main/java/ani/dantotsu/media/manga/MangaReadFragment.kt @@ -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) { diff --git a/app/src/main/java/ani/dantotsu/media/manga/mangareader/MangaReaderActivity.kt b/app/src/main/java/ani/dantotsu/media/manga/mangareader/MangaReaderActivity.kt index 86085f58d7..bb28d7aaee 100644 --- a/app/src/main/java/ani/dantotsu/media/manga/mangareader/MangaReaderActivity.kt +++ b/app/src/main/java/ani/dantotsu/media/manga/mangareader/MangaReaderActivity.kt @@ -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", diff --git a/app/src/main/java/ani/dantotsu/media/novel/NovelResponseAdapter.kt b/app/src/main/java/ani/dantotsu/media/novel/NovelResponseAdapter.kt index 92ddc7399a..cade2abd8e 100644 --- a/app/src/main/java/ani/dantotsu/media/novel/NovelResponseAdapter.kt +++ b/app/src/main/java/ani/dantotsu/media/novel/NovelResponseAdapter.kt @@ -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 } } diff --git a/app/src/main/java/ani/dantotsu/profile/activity/ActivityItem.kt b/app/src/main/java/ani/dantotsu/profile/activity/ActivityItem.kt index 26c886c914..bca8609818 100644 --- a/app/src/main/java/ani/dantotsu/profile/activity/ActivityItem.kt +++ b/app/src/main/java/ani/dantotsu/profile/activity/ActivityItem.kt @@ -11,7 +11,6 @@ import ani.dantotsu.buildMarkwon import ani.dantotsu.connections.anilist.Anilist import ani.dantotsu.connections.anilist.api.Activity import ani.dantotsu.databinding.ItemActivityBinding -import ani.dantotsu.home.status.RepliesBottomDialog import ani.dantotsu.loadImage import ani.dantotsu.profile.User import ani.dantotsu.profile.UsersDialogFragment diff --git a/app/src/main/java/ani/dantotsu/home/status/RepliesBottomDialog.kt b/app/src/main/java/ani/dantotsu/profile/activity/RepliesBottomDialog.kt similarity index 90% rename from app/src/main/java/ani/dantotsu/home/status/RepliesBottomDialog.kt rename to app/src/main/java/ani/dantotsu/profile/activity/RepliesBottomDialog.kt index 44a11baf6e..184c7af9b4 100644 --- a/app/src/main/java/ani/dantotsu/home/status/RepliesBottomDialog.kt +++ b/app/src/main/java/ani/dantotsu/profile/activity/RepliesBottomDialog.kt @@ -1,4 +1,4 @@ -package ani.dantotsu.home.status +package ani.dantotsu.profile.activity import android.content.Intent import android.os.Bundle @@ -14,7 +14,6 @@ import ani.dantotsu.connections.anilist.Anilist import ani.dantotsu.connections.anilist.api.ActivityReply import ani.dantotsu.databinding.BottomSheetRecyclerBinding import ani.dantotsu.profile.ProfileActivity -import ani.dantotsu.profile.activity.ActivityReplyItem import ani.dantotsu.snackString import ani.dantotsu.util.ActivityMarkdownCreator import com.xwray.groupie.GroupieAdapter @@ -72,14 +71,10 @@ class RepliesBottomDialog : BottomSheetDialogFragment() { adapter.update( replies.map { ActivityReplyItem( - it, - activityId, - requireActivity(), - adapter, - clickCallback = { int, _ -> - onClick(int) - } - ) + it, activityId, requireActivity(), adapter, + ) { i, _ -> + onClick(i) + } } ) } else { diff --git a/app/src/main/java/ani/dantotsu/settings/ExtensionsActivity.kt b/app/src/main/java/ani/dantotsu/settings/ExtensionsActivity.kt index 748e476e5f..46d42eb9f0 100644 --- a/app/src/main/java/ani/dantotsu/settings/ExtensionsActivity.kt +++ b/app/src/main/java/ani/dantotsu/settings/ExtensionsActivity.kt @@ -35,6 +35,7 @@ import ani.dantotsu.settings.saving.PrefManager import ani.dantotsu.settings.saving.PrefName import ani.dantotsu.statusBarHeight import ani.dantotsu.themes.ThemeManager +import ani.dantotsu.util.customAlertDialog import com.google.android.material.tabs.TabLayout import com.google.android.material.tabs.TabLayoutMediator import eu.kanade.tachiyomi.extension.anime.AnimeExtensionManager @@ -178,25 +179,20 @@ class ExtensionsActivity : AppCompatActivity() { entry.name.lowercase().replace("_", " ") .replaceFirstChar { if (it.isLowerCase()) it.titlecase(Locale.ROOT) else it.toString() } }.toTypedArray() - val builder = AlertDialog.Builder(this, R.style.MyPopup) val listOrder: String = PrefManager.getVal(PrefName.LangSort) val index = LanguageMapper.Companion.Language.entries.toTypedArray() .indexOfFirst { it.code == listOrder } - builder.setTitle("Language") - builder.setSingleChoiceItems(languageOptions, index) { dialog, i -> - PrefManager.setVal( - PrefName.LangSort, - LanguageMapper.Companion.Language.entries[i].code - ) - val currentFragment = - supportFragmentManager.findFragmentByTag("f${viewPager.currentItem}") - if (currentFragment is SearchQueryHandler) { - currentFragment.notifyDataChanged() + customAlertDialog().apply { + setTitle("Language") + singleChoiceItems(languageOptions, index) { selected -> + PrefManager.setVal(PrefName.LangSort, LanguageMapper.Companion.Language.entries[selected].code) + val currentFragment = supportFragmentManager.findFragmentByTag("f${viewPager.currentItem}") + if (currentFragment is SearchQueryHandler) { + currentFragment.notifyDataChanged() + } } - dialog.dismiss() + show() } - val dialog = builder.show() - dialog.window?.setDimAmount(0.8f) } binding.settingsContainer.updateLayoutParams { topMargin = statusBarHeight @@ -247,10 +243,10 @@ class ExtensionsActivity : AppCompatActivity() { ) view.repositoryItem.text = item.removePrefix("https://raw.githubusercontent.com") view.repositoryItem.setOnClickListener { - AlertDialog.Builder(this@ExtensionsActivity, R.style.MyPopup) - .setTitle(R.string.rem_repository) - .setMessage(item) - .setPositiveButton(getString(R.string.ok)) { dialog, _ -> + customAlertDialog().apply { + setTitle(R.string.rem_repository) + setMessage(item) + setPosButton(R.string.ok) { val repos = PrefManager.getVal>(prefName).minus(item) PrefManager.setVal(prefName, repos) repoInventory.removeView(view.root) @@ -267,13 +263,10 @@ class ExtensionsActivity : AppCompatActivity() { else -> {} } } - dialog.dismiss() - } - .setNegativeButton(getString(R.string.cancel)) { dialog, _ -> - dialog.dismiss() } - .create() - .show() + setNegButton(R.string.cancel) + show() + } } view.repositoryItem.setOnLongClickListener { it.performHapticFeedback(HapticFeedbackConstants.LONG_PRESS) @@ -324,20 +317,18 @@ class ExtensionsActivity : AppCompatActivity() { dialogView.repoInventory.apply { getSavedRepositories(this, type) } - val alertDialog = AlertDialog.Builder(this@ExtensionsActivity, R.style.MyPopup) - .setTitle(R.string.edit_repositories) - .setView(dialogView.root) - .setPositiveButton(getString(R.string.add)) { _, _ -> - if (!dialogView.repositoryTextBox.text.isNullOrBlank()) + processEditorAction(dialogView.repositoryTextBox, type) + customAlertDialog().apply { + setTitle(R.string.edit_repositories) + setCustomView(dialogView.root) + setPosButton(R.string.add) { + if (!dialogView.repositoryTextBox.text.isNullOrBlank()) { processUserInput(dialogView.repositoryTextBox.text.toString(), type) + } } - .setNegativeButton(getString(R.string.close)) { dialog, _ -> - dialog.dismiss() - } - .create() - processEditorAction(dialogView.repositoryTextBox, type) - alertDialog.show() - alertDialog.window?.setDimAmount(0.8f) + setNegButton(R.string.close) + show() + } } } } diff --git a/app/src/main/java/ani/dantotsu/settings/InstalledAnimeExtensionsFragment.kt b/app/src/main/java/ani/dantotsu/settings/InstalledAnimeExtensionsFragment.kt index 2e6d650cac..4d3350e3aa 100644 --- a/app/src/main/java/ani/dantotsu/settings/InstalledAnimeExtensionsFragment.kt +++ b/app/src/main/java/ani/dantotsu/settings/InstalledAnimeExtensionsFragment.kt @@ -25,13 +25,15 @@ import androidx.viewpager2.widget.ViewPager2 import ani.dantotsu.R import ani.dantotsu.connections.crashlytics.CrashlyticsInterface import ani.dantotsu.databinding.FragmentExtensionsBinding -import ani.dantotsu.others.LanguageMapper +import ani.dantotsu.others.LanguageMapper.Companion.getLanguageName import ani.dantotsu.parsers.AnimeSources import ani.dantotsu.settings.extensionprefs.AnimeSourcePreferencesFragment import ani.dantotsu.settings.saving.PrefManager import ani.dantotsu.settings.saving.PrefName import ani.dantotsu.snackString import ani.dantotsu.util.Logger +import ani.dantotsu.util.customAlertDialog + import com.google.android.material.tabs.TabLayout import com.google.android.material.textfield.TextInputLayout import eu.kanade.tachiyomi.animesource.ConfigurableAnimeSource @@ -72,16 +74,15 @@ class InstalledAnimeExtensionsFragment : Fragment(), SearchQueryHandler { if (allSettings.isNotEmpty()) { var selectedSetting = allSettings[0] if (allSettings.size > 1) { - val names = allSettings.map { LanguageMapper.getLanguageName(it.lang) } + val names = allSettings.map { getLanguageName(it.lang) } .toTypedArray() var selectedIndex = 0 - val dialog = AlertDialog.Builder(requireContext(), R.style.MyPopup) - .setTitle("Select a Source") - .setSingleChoiceItems(names, selectedIndex) { dialog, which -> + requireContext().customAlertDialog().apply { + setTitle("Select a Source") + singleChoiceItems(names, selectedIndex) { which -> itemSelected = true selectedIndex = which selectedSetting = allSettings[selectedIndex] - dialog.dismiss() val fragment = AnimeSourcePreferencesFragment().getInstance(selectedSetting.id) { @@ -93,13 +94,13 @@ class InstalledAnimeExtensionsFragment : Fragment(), SearchQueryHandler { .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 = @@ -295,7 +296,7 @@ class InstalledAnimeExtensionsFragment : Fragment(), SearchQueryHandler { override fun onBindViewHolder(holder: ViewHolder, position: Int) { val extension = getItem(position) val nsfw = if (extension.isNsfw) "(18+)" else "" - val lang = LanguageMapper.getLanguageName(extension.lang) + val lang = getLanguageName(extension.lang) holder.extensionNameTextView.text = extension.name val versionText = "$lang ${extension.versionName} $nsfw" holder.extensionVersionTextView.text = versionText diff --git a/app/src/main/java/ani/dantotsu/settings/InstalledMangaExtensionsFragment.kt b/app/src/main/java/ani/dantotsu/settings/InstalledMangaExtensionsFragment.kt index 0a66c64886..c11ec2233c 100644 --- a/app/src/main/java/ani/dantotsu/settings/InstalledMangaExtensionsFragment.kt +++ b/app/src/main/java/ani/dantotsu/settings/InstalledMangaExtensionsFragment.kt @@ -34,6 +34,7 @@ import ani.dantotsu.settings.saving.PrefManager import ani.dantotsu.settings.saving.PrefName import ani.dantotsu.snackString import ani.dantotsu.util.Logger +import ani.dantotsu.util.customAlertDialog import com.google.android.material.tabs.TabLayout import com.google.android.material.textfield.TextInputLayout import eu.kanade.tachiyomi.data.notification.Notifications @@ -74,13 +75,12 @@ class InstalledMangaExtensionsFragment : Fragment(), SearchQueryHandler { val names = allSettings.map { LanguageMapper.getLanguageName(it.lang) } .toTypedArray() var selectedIndex = 0 - val dialog = AlertDialog.Builder(requireContext(), R.style.MyPopup) - .setTitle("Select a Source") - .setSingleChoiceItems(names, selectedIndex) { dialog, which -> + requireContext().customAlertDialog().apply { + setTitle("Select a Source") + singleChoiceItems(names, selectedIndex) { which -> itemSelected = true selectedIndex = which selectedSetting = allSettings[selectedIndex] - dialog.dismiss() // Move the fragment transaction here val fragment = @@ -93,13 +93,13 @@ class InstalledMangaExtensionsFragment : Fragment(), SearchQueryHandler { .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 = diff --git a/app/src/main/java/ani/dantotsu/settings/PlayerSettingsActivity.kt b/app/src/main/java/ani/dantotsu/settings/PlayerSettingsActivity.kt index 9006228a44..e3999509ba 100644 --- a/app/src/main/java/ani/dantotsu/settings/PlayerSettingsActivity.kt +++ b/app/src/main/java/ani/dantotsu/settings/PlayerSettingsActivity.kt @@ -28,6 +28,7 @@ import ani.dantotsu.snackString import ani.dantotsu.statusBarHeight import ani.dantotsu.themes.ThemeManager import ani.dantotsu.toast +import ani.dantotsu.util.customAlertDialog import com.google.android.material.slider.Slider.OnChangeListener import kotlin.math.roundToInt @@ -100,20 +101,19 @@ class PlayerSettingsActivity : AppCompatActivity() { R.string.default_playback_speed, speedsName[PrefManager.getVal(PrefName.DefaultSpeed)] ) - val speedDialog = AlertDialog.Builder(this, R.style.MyPopup) - .setTitle(getString(R.string.default_speed)) binding.playerSettingsSpeed.setOnClickListener { - val dialog = - speedDialog.setSingleChoiceItems( + customAlertDialog().apply { + setTitle(getString(R.string.default_speed)) + singleChoiceItems( speedsName, PrefManager.getVal(PrefName.DefaultSpeed) - ) { dialog, i -> + ) { i -> PrefManager.setVal(PrefName.DefaultSpeed, i) binding.playerSettingsSpeed.text = getString(R.string.default_playback_speed, speedsName[i]) - dialog.dismiss() - }.show() - dialog.window?.setDimAmount(0.8f) + } + show() + } } binding.playerSettingsCursedSpeeds.isChecked = PrefManager.getVal(PrefName.CursedSpeeds) @@ -278,17 +278,17 @@ class PlayerSettingsActivity : AppCompatActivity() { } val resizeModes = arrayOf("Original", "Zoom", "Stretch") - val resizeDialog = AlertDialog.Builder(this, R.style.MyPopup) - .setTitle(getString(R.string.default_resize_mode)) binding.playerResizeMode.setOnClickListener { - val dialog = resizeDialog.setSingleChoiceItems( - resizeModes, - PrefManager.getVal(PrefName.Resize) - ) { dialog, count -> - PrefManager.setVal(PrefName.Resize, count) - dialog.dismiss() - }.show() - dialog.window?.setDimAmount(0.8f) + customAlertDialog().apply { + setTitle(getString(R.string.default_resize_mode)) + singleChoiceItems( + resizeModes, + PrefManager.getVal(PrefName.Resize) + ) { count -> + PrefManager.setVal(PrefName.Resize, count) + } + show() + } } fun toggleSubOptions(isChecked: Boolean) { @@ -332,18 +332,18 @@ class PlayerSettingsActivity : AppCompatActivity() { "Blue", "Magenta" ) - val primaryColorDialog = AlertDialog.Builder(this, R.style.MyPopup) - .setTitle(getString(R.string.primary_sub_color)) binding.videoSubColorPrimary.setOnClickListener { - val dialog = primaryColorDialog.setSingleChoiceItems( - colorsPrimary, - PrefManager.getVal(PrefName.PrimaryColor) - ) { dialog, count -> - PrefManager.setVal(PrefName.PrimaryColor, count) - dialog.dismiss() - updateSubPreview() - }.show() - dialog.window?.setDimAmount(0.8f) + customAlertDialog().apply { + setTitle(getString(R.string.primary_sub_color)) + singleChoiceItems( + colorsPrimary, + PrefManager.getVal(PrefName.PrimaryColor) + ) { count -> + PrefManager.setVal(PrefName.PrimaryColor, count) + updateSubPreview() + } + show() + } } val colorsSecondary = arrayOf( "Black", @@ -359,32 +359,32 @@ class PlayerSettingsActivity : AppCompatActivity() { "Magenta", "Transparent" ) - val secondaryColorDialog = AlertDialog.Builder(this, R.style.MyPopup) - .setTitle(getString(R.string.outline_sub_color)) binding.videoSubColorSecondary.setOnClickListener { - val dialog = secondaryColorDialog.setSingleChoiceItems( - colorsSecondary, - PrefManager.getVal(PrefName.SecondaryColor) - ) { dialog, count -> - PrefManager.setVal(PrefName.SecondaryColor, count) - dialog.dismiss() - updateSubPreview() - }.show() - dialog.window?.setDimAmount(0.8f) + customAlertDialog().apply { + setTitle(getString(R.string.outline_sub_color)) + singleChoiceItems( + colorsSecondary, + PrefManager.getVal(PrefName.SecondaryColor) + ) { count -> + PrefManager.setVal(PrefName.SecondaryColor, count) + updateSubPreview() + } + show() + } } val typesOutline = arrayOf("Outline", "Shine", "Drop Shadow", "None") - val outlineDialog = AlertDialog.Builder(this, R.style.MyPopup) - .setTitle(getString(R.string.outline_type)) binding.videoSubOutline.setOnClickListener { - val dialog = outlineDialog.setSingleChoiceItems( - typesOutline, - PrefManager.getVal(PrefName.Outline) - ) { dialog, count -> - PrefManager.setVal(PrefName.Outline, count) - dialog.dismiss() - updateSubPreview() - }.show() - dialog.window?.setDimAmount(0.8f) + customAlertDialog().apply { + setTitle(getString(R.string.outline_type)) + singleChoiceItems( + typesOutline, + PrefManager.getVal(PrefName.Outline) + ) { count -> + PrefManager.setVal(PrefName.Outline, count) + updateSubPreview() + } + show() + } } val colorsSubBackground = arrayOf( "Transparent", @@ -400,18 +400,18 @@ class PlayerSettingsActivity : AppCompatActivity() { "Blue", "Magenta" ) - val subBackgroundDialog = AlertDialog.Builder(this, R.style.MyPopup) - .setTitle(getString(R.string.sub_background_color_select)) binding.videoSubColorBackground.setOnClickListener { - val dialog = subBackgroundDialog.setSingleChoiceItems( - colorsSubBackground, - PrefManager.getVal(PrefName.SubBackground) - ) { dialog, count -> - PrefManager.setVal(PrefName.SubBackground, count) - dialog.dismiss() - updateSubPreview() - }.show() - dialog.window?.setDimAmount(0.8f) + customAlertDialog().apply { + setTitle(getString(R.string.sub_background_color_select)) + singleChoiceItems( + colorsSubBackground, + PrefManager.getVal(PrefName.SubBackground) + ) { count -> + PrefManager.setVal(PrefName.SubBackground, count) + updateSubPreview() + } + show() + } } val colorsSubWindow = arrayOf( @@ -428,18 +428,18 @@ class PlayerSettingsActivity : AppCompatActivity() { "Blue", "Magenta" ) - val subWindowDialog = AlertDialog.Builder(this, R.style.MyPopup) - .setTitle(getString(R.string.sub_window_color_select)) binding.videoSubColorWindow.setOnClickListener { - val dialog = subWindowDialog.setSingleChoiceItems( - colorsSubWindow, - PrefManager.getVal(PrefName.SubWindow) - ) { dialog, count -> - PrefManager.setVal(PrefName.SubWindow, count) - dialog.dismiss() - updateSubPreview() - }.show() - dialog.window?.setDimAmount(0.8f) + customAlertDialog().apply { + setTitle(getString(R.string.sub_window_color_select)) + singleChoiceItems( + colorsSubWindow, + PrefManager.getVal(PrefName.SubWindow) + ) { count -> + PrefManager.setVal(PrefName.SubWindow, count) + updateSubPreview() + } + show() + } } binding.videoSubAlpha.value = PrefManager.getVal(PrefName.SubAlpha) @@ -459,18 +459,18 @@ class PlayerSettingsActivity : AppCompatActivity() { "Levenim MT Bold", "Blocky" ) - val fontDialog = AlertDialog.Builder(this, R.style.MyPopup) - .setTitle(getString(R.string.subtitle_font)) binding.videoSubFont.setOnClickListener { - val dialog = fontDialog.setSingleChoiceItems( - fonts, - PrefManager.getVal(PrefName.Font) - ) { dialog, count -> - PrefManager.setVal(PrefName.Font, count) - dialog.dismiss() - updateSubPreview() - }.show() - dialog.window?.setDimAmount(0.8f) + customAlertDialog().apply { + setTitle(getString(R.string.subtitle_font)) + singleChoiceItems( + fonts, + PrefManager.getVal(PrefName.Font) + ) { count -> + PrefManager.setVal(PrefName.Font, count) + updateSubPreview() + } + show() + } } binding.subtitleFontSize.setText(PrefManager.getVal(PrefName.FontSize).toString()) binding.subtitleFontSize.setOnEditorActionListener { _, actionId, _ -> diff --git a/app/src/main/java/ani/dantotsu/settings/SettingsCommonActivity.kt b/app/src/main/java/ani/dantotsu/settings/SettingsCommonActivity.kt index 0bcf356d75..a9c839e713 100644 --- a/app/src/main/java/ani/dantotsu/settings/SettingsCommonActivity.kt +++ b/app/src/main/java/ani/dantotsu/settings/SettingsCommonActivity.kt @@ -20,6 +20,7 @@ import androidx.recyclerview.widget.LinearLayoutManager import ani.dantotsu.R import ani.dantotsu.connections.anilist.Anilist import ani.dantotsu.databinding.ActivitySettingsCommonBinding +import ani.dantotsu.databinding.DialogSetPasswordBinding import ani.dantotsu.databinding.DialogUserAgentBinding import ani.dantotsu.download.DownloadsManager import ani.dantotsu.initActivity @@ -37,6 +38,7 @@ import ani.dantotsu.themes.ThemeManager import ani.dantotsu.toast import ani.dantotsu.util.LauncherWrapper import ani.dantotsu.util.StoragePermissions +import ani.dantotsu.util.customAlertDialog import kotlinx.coroutines.DelicateCoroutinesApi import kotlinx.coroutines.Dispatchers import kotlinx.coroutines.GlobalScope @@ -160,18 +162,16 @@ class SettingsCommonActivity : AppCompatActivity() { icon = R.drawable.ic_download_24, onClick = { val managers = arrayOf("Default", "1DM", "ADM") - val downloadManagerDialog = - AlertDialog.Builder(context, R.style.MyPopup) - .setTitle(R.string.download_manager) - var downloadManager: Int = PrefManager.getVal(PrefName.DownloadManager) - val dialog = downloadManagerDialog.setSingleChoiceItems( - managers, downloadManager - ) { dialog, count -> - downloadManager = count - PrefManager.setVal(PrefName.DownloadManager, downloadManager) - dialog.dismiss() - }.show() - dialog.window?.setDimAmount(0.8f) + customAlertDialog().apply { + setTitle(getString(R.string.download_manager)) + singleChoiceItems( + managers, + PrefManager.getVal(PrefName.DownloadManager) + ) { count -> + PrefManager.setVal(PrefName.DownloadManager, count) + } + show() + } } ), Settings( @@ -180,90 +180,67 @@ class SettingsCommonActivity : AppCompatActivity() { desc = getString(R.string.app_lock_desc), icon = R.drawable.ic_round_lock_open_24, onClick = { - val passwordDialog = AlertDialog.Builder(context, R.style.MyPopup) - .setTitle(R.string.app_lock) - .setView(R.layout.dialog_set_password) - .setPositiveButton(R.string.ok) { dialog, _ -> - val passwordInput = - (dialog as AlertDialog).findViewById(R.id.passwordInput) - val confirmPasswordInput = - dialog.findViewById(R.id.confirmPasswordInput) - val forgotPasswordCheckbox = - dialog.findViewById(R.id.forgotPasswordCheckbox) - if (forgotPasswordCheckbox?.isChecked == true) { + customAlertDialog().apply { + val view = DialogSetPasswordBinding.inflate(layoutInflater) + setTitle(R.string.app_lock) + setCustomView(view.root) + setPosButton(R.string.ok) { + if (view.forgotPasswordCheckbox.isChecked) { PrefManager.setVal(PrefName.OverridePassword, true) } - - val password = passwordInput?.text.toString() - val confirmPassword = confirmPasswordInput?.text.toString() - + val password = view.passwordInput.text.toString() + val confirmPassword = view.confirmPasswordInput.text.toString() if (password == confirmPassword && password.isNotEmpty()) { PrefManager.setVal(PrefName.AppPassword, password) - if (dialog.findViewById(R.id.biometricCheckbox)?.isChecked == true) { + if (view.biometricCheckbox.isChecked) { val canBiometricPrompt = BiometricManager.from(applicationContext) - .canAuthenticate( - BiometricManager.Authenticators.BIOMETRIC_WEAK - ) == BiometricManager.BIOMETRIC_SUCCESS + .canAuthenticate(BiometricManager.Authenticators.BIOMETRIC_WEAK) == BiometricManager.BIOMETRIC_SUCCESS + if (canBiometricPrompt) { val biometricPrompt = - BiometricPromptUtils.createBiometricPrompt( - this@SettingsCommonActivity - ) { _ -> + BiometricPromptUtils.createBiometricPrompt(this@SettingsCommonActivity) { _ -> val token = UUID.randomUUID().toString() PrefManager.setVal( PrefName.BiometricToken, token ) toast(R.string.success) - dialog.dismiss() } val promptInfo = - BiometricPromptUtils.createPromptInfo( - this@SettingsCommonActivity - ) + BiometricPromptUtils.createPromptInfo(this@SettingsCommonActivity) biometricPrompt.authenticate(promptInfo) } + } else { PrefManager.setVal(PrefName.BiometricToken, "") toast(R.string.success) - dialog.dismiss() } } else { toast(R.string.password_mismatch) } } - .setNegativeButton(R.string.cancel) { dialog, _ -> - dialog.dismiss() - } - .setNeutralButton(R.string.remove) { dialog, _ -> + setNegButton(R.string.cancel) + setNeutralButton(R.string.remove){ PrefManager.setVal(PrefName.AppPassword, "") PrefManager.setVal(PrefName.BiometricToken, "") PrefManager.setVal(PrefName.OverridePassword, false) toast(R.string.success) - dialog.dismiss() } - .create() - - passwordDialog.window?.setDimAmount(0.8f) - passwordDialog.setOnShowListener { - passwordDialog.findViewById(R.id.passwordInput) - ?.requestFocus() - val biometricCheckbox = - passwordDialog.findViewById(R.id.biometricCheckbox) - val forgotPasswordCheckbox = - passwordDialog.findViewById(R.id.forgotPasswordCheckbox) - val canAuthenticate = - BiometricManager.from(applicationContext).canAuthenticate( - BiometricManager.Authenticators.BIOMETRIC_WEAK - ) == BiometricManager.BIOMETRIC_SUCCESS - biometricCheckbox?.isVisible = canAuthenticate - biometricCheckbox?.isChecked = - PrefManager.getVal(PrefName.BiometricToken, "").isNotEmpty() - forgotPasswordCheckbox?.isChecked = - PrefManager.getVal(PrefName.OverridePassword) + setOnShowListener { + view.passwordInput.requestFocus() + val canAuthenticate = + BiometricManager.from(applicationContext).canAuthenticate( + BiometricManager.Authenticators.BIOMETRIC_WEAK + ) == BiometricManager.BIOMETRIC_SUCCESS + view.biometricCheckbox.isVisible = canAuthenticate + view.biometricCheckbox.isChecked = + PrefManager.getVal(PrefName.BiometricToken, "").isNotEmpty() + view.forgotPasswordCheckbox.isChecked = + PrefManager.getVal(PrefName.OverridePassword) + } + show() } - passwordDialog.show() } ), diff --git a/app/src/main/java/ani/dantotsu/settings/SettingsExtensionsActivity.kt b/app/src/main/java/ani/dantotsu/settings/SettingsExtensionsActivity.kt index abf742ba39..a054b89aee 100644 --- a/app/src/main/java/ani/dantotsu/settings/SettingsExtensionsActivity.kt +++ b/app/src/main/java/ani/dantotsu/settings/SettingsExtensionsActivity.kt @@ -81,11 +81,11 @@ class SettingsExtensionsActivity : AppCompatActivity() { view.repositoryItem.text = item.removePrefix("https://raw.githubusercontent.com/") view.repositoryItem.setOnClickListener { - AlertDialog.Builder(context, R.style.MyPopup) - .setTitle(R.string.rem_repository).setMessage(item) - .setPositiveButton(getString(R.string.ok)) { dialog, _ -> - val repos = - PrefManager.getVal>(repoList).minus(item) + context.customAlertDialog().apply { + setTitle(R.string.rem_repository) + setMessage(item) + setPosButton(R.string.ok) { + val repos = PrefManager.getVal>(repoList).minus(item) PrefManager.setVal(repoList, repos) setExtensionOutput(repoInventory, type) CoroutineScope(Dispatchers.IO).launch { @@ -93,18 +93,16 @@ class SettingsExtensionsActivity : AppCompatActivity() { MediaType.ANIME -> { animeExtensionManager.findAvailableExtensions() } - MediaType.MANGA -> { mangaExtensionManager.findAvailableExtensions() } - else -> {} } } - dialog.dismiss() - }.setNegativeButton(getString(R.string.cancel)) { dialog, _ -> - dialog.dismiss() - }.create().show() + } + setNegButton(R.string.cancel) + show() + } } view.repositoryItem.setOnLongClickListener { it.performHapticFeedback(HapticFeedbackConstants.LONG_PRESS) @@ -209,27 +207,27 @@ class SettingsExtensionsActivity : AppCompatActivity() { val editText = dialogView.userAgentTextBox.apply { hint = getString(R.string.manga_add_repository) } - val alertDialog = AlertDialog.Builder(context, R.style.MyPopup) - .setTitle(R.string.manga_add_repository).setView(dialogView.root) - .setPositiveButton(getString(R.string.ok)) { dialog, _ -> + context.customAlertDialog().apply { + setTitle(R.string.manga_add_repository) + setCustomView(dialogView.root) + setPosButton(R.string.ok) { if (!editText.text.isNullOrBlank()) processUserInput( editText.text.toString(), MediaType.MANGA, it.attachView ) - dialog.dismiss() - }.setNegativeButton(getString(R.string.cancel)) { dialog, _ -> - dialog.dismiss() - }.create() + } + setNegButton(R.string.cancel) + attach { dialog -> + processEditorAction( + dialog, + editText, + MediaType.MANGA, + it.attachView + ) + } + }.show() - processEditorAction( - alertDialog, - editText, - MediaType.MANGA, - it.attachView - ) - alertDialog.show() - alertDialog.window?.setDimAmount(0.8f) }, attach = { setExtensionOutput(it.attachView, MediaType.MANGA) @@ -258,24 +256,18 @@ class SettingsExtensionsActivity : AppCompatActivity() { val dialogView = DialogUserAgentBinding.inflate(layoutInflater) val editText = dialogView.userAgentTextBox editText.setText(PrefManager.getVal(PrefName.DefaultUserAgent)) - val alertDialog = AlertDialog.Builder(context, R.style.MyPopup) - .setTitle(R.string.user_agent).setView(dialogView.root) - .setPositiveButton(getString(R.string.ok)) { dialog, _ -> - PrefManager.setVal( - PrefName.DefaultUserAgent, - editText.text.toString() - ) - dialog.dismiss() - }.setNeutralButton(getString(R.string.reset)) { dialog, _ -> + context.customAlertDialog().apply { + setTitle(R.string.user_agent) + setCustomView(dialogView.root) + setPosButton(R.string.ok) { + PrefManager.setVal(PrefName.DefaultUserAgent, editText.text.toString()) + } + setNeutralButton(R.string.reset) { PrefManager.removeVal(PrefName.DefaultUserAgent) editText.setText("") - dialog.dismiss() - }.setNegativeButton(getString(R.string.cancel)) { dialog, _ -> - dialog.dismiss() - }.create() - - alertDialog.show() - alertDialog.window?.setDimAmount(0.8f) + } + setNegButton(R.string.cancel) + }.show() } ), Settings( diff --git a/app/src/main/java/ani/dantotsu/settings/SettingsNotificationActivity.kt b/app/src/main/java/ani/dantotsu/settings/SettingsNotificationActivity.kt index b97dfa4cd4..c7a9b1e63c 100644 --- a/app/src/main/java/ani/dantotsu/settings/SettingsNotificationActivity.kt +++ b/app/src/main/java/ani/dantotsu/settings/SettingsNotificationActivity.kt @@ -25,6 +25,7 @@ import ani.dantotsu.settings.saving.PrefManager import ani.dantotsu.settings.saving.PrefName import ani.dantotsu.statusBarHeight import ani.dantotsu.themes.ThemeManager +import ani.dantotsu.util.customAlertDialog import java.util.Locale class SettingsNotificationActivity : AppCompatActivity() { @@ -77,26 +78,16 @@ class SettingsNotificationActivity : AppCompatActivity() { desc = getString(R.string.subscriptions_info), icon = R.drawable.ic_round_notifications_none_24, onClick = { - val speedDialog = AlertDialog.Builder(context, R.style.MyPopup) - .setTitle(R.string.subscriptions_checking_time) - val dialog = - speedDialog.setSingleChoiceItems(timeNames, curTime) { dialog, i -> + context.customAlertDialog().apply { + setTitle(R.string.subscriptions_checking_time) + singleChoiceItems(timeNames, curTime) { i -> curTime = i - it.settingsTitle.text = - getString( - R.string.subscriptions_checking_time_s, - timeNames[i] - ) - PrefManager.setVal( - PrefName.SubscriptionNotificationInterval, - curTime - ) - dialog.dismiss() - TaskScheduler.create( - context, PrefManager.getVal(PrefName.UseAlarmManager) - ).scheduleAllTasks(context) - }.show() - dialog.window?.setDimAmount(0.8f) + it.settingsTitle.text = getString(R.string.subscriptions_checking_time_s, timeNames[i]) + PrefManager.setVal(PrefName.SubscriptionNotificationInterval, curTime) + TaskScheduler.create(context, PrefManager.getVal(PrefName.UseAlarmManager)).scheduleAllTasks(context) + } + show() + } }, onLongClick = { TaskScheduler.create( diff --git a/app/src/main/java/ani/dantotsu/settings/UserInterfaceSettingsActivity.kt b/app/src/main/java/ani/dantotsu/settings/UserInterfaceSettingsActivity.kt index fd6bfde602..08b6345e5e 100644 --- a/app/src/main/java/ani/dantotsu/settings/UserInterfaceSettingsActivity.kt +++ b/app/src/main/java/ani/dantotsu/settings/UserInterfaceSettingsActivity.kt @@ -39,9 +39,9 @@ class UserInterfaceSettingsActivity : AppCompatActivity() { binding.uiSettingsHomeLayout.setOnClickListener { val set = PrefManager.getVal>(PrefName.HomeLayout).toMutableList() val views = resources.getStringArray(R.array.home_layouts) - customAlertDialog() - .setTitle(getString(R.string.home_layout_show)) - .multiChoiceItems( + customAlertDialog().apply { + setTitle(getString(R.string.home_layout_show)) + multiChoiceItems( items = views, checkedItems = PrefManager.getVal>(PrefName.HomeLayout).toBooleanArray() ) { selectedItems -> @@ -49,11 +49,13 @@ class UserInterfaceSettingsActivity : AppCompatActivity() { set[i] = selectedItems[i] } } - .setPosButton("Done") { + setPosButton(R.string.ok) { PrefManager.setVal(PrefName.HomeLayout, set) restartApp() } - .show() + show() + } + } binding.uiSettingsSmallView.isChecked = PrefManager.getVal(PrefName.SmallView) diff --git a/app/src/main/java/ani/dantotsu/settings/saving/Preferences.kt b/app/src/main/java/ani/dantotsu/settings/saving/Preferences.kt index b4e43ac872..6f188b854c 100644 --- a/app/src/main/java/ani/dantotsu/settings/saving/Preferences.kt +++ b/app/src/main/java/ani/dantotsu/settings/saving/Preferences.kt @@ -22,6 +22,7 @@ enum class PrefName(val data: Pref) { //TODO: Split this into multiple files CheckUpdate(Pref(Location.General, Boolean::class, true)), VerboseLogging(Pref(Location.General, Boolean::class, false)), DohProvider(Pref(Location.General, Int::class, 0)), + HidePrivate(Pref(Location.General, Boolean::class, false)), DefaultUserAgent( Pref( Location.General, diff --git a/app/src/main/java/ani/dantotsu/util/ActivityMarkdownCreator.kt b/app/src/main/java/ani/dantotsu/util/ActivityMarkdownCreator.kt index 1a3e9f1889..ccddfbab33 100644 --- a/app/src/main/java/ani/dantotsu/util/ActivityMarkdownCreator.kt +++ b/app/src/main/java/ani/dantotsu/util/ActivityMarkdownCreator.kt @@ -120,12 +120,11 @@ class ActivityMarkdownCreator : AppCompatActivity() { toast(getString(R.string.cannot_be_empty)) return@setOnClickListener } - AlertDialog.Builder(this, R.style.MyPopup).apply { + customAlertDialog().apply { setTitle(R.string.warning) setMessage(R.string.post_to_anilist_warning) - setPositiveButton(R.string.ok) { _, _ -> + setPosButton(R.string.ok) { launchIO { - val isEdit = editId != -1 val success = when (type) { "activity" -> if (isEdit) { @@ -139,7 +138,6 @@ class ActivityMarkdownCreator : AppCompatActivity() { } else { Anilist.mutation.postReply(parentId, text) } - "message" -> if (isEdit) { Anilist.mutation.postMessage(userId, text, editId) } else { @@ -152,11 +150,12 @@ class ActivityMarkdownCreator : AppCompatActivity() { finish() } } - setNeutralButton(R.string.open_rules) { _, _ -> + setNeutralButton(R.string.open_rules) { openLinkInBrowser("https://anilist.co/forum/thread/14") } - setNegativeButton(R.string.cancel, null) - }.show() + setNegButton(R.string.cancel) + show() + } } binding.previewCheckbox.setOnClickListener { diff --git a/app/src/main/java/ani/dantotsu/util/AlertDialogBuilder.kt b/app/src/main/java/ani/dantotsu/util/AlertDialogBuilder.kt index 5bda5a18fe..374eb3d142 100644 --- a/app/src/main/java/ani/dantotsu/util/AlertDialogBuilder.kt +++ b/app/src/main/java/ani/dantotsu/util/AlertDialogBuilder.kt @@ -21,8 +21,23 @@ class AlertDialogBuilder(private val context: Context) { private var selectedItemIndex: Int = -1 private var onItemSelected: ((Int) -> Unit)? = null private var customView: View? = null + private var onShow: (() -> Unit)? = null private var attach: ((dialog: AlertDialog) -> Unit)? = null private var onDismiss: (() -> Unit)? = null + private var onCancel: (() -> Unit)? = null + private var cancelable: Boolean = true + fun setCancelable(cancelable: Boolean): AlertDialogBuilder { + this.cancelable = cancelable + return this + } + fun setOnShowListener(onShow: () -> Unit): AlertDialogBuilder { + this.onShow = onShow + return this + } + fun setOnCancelListener(onCancel: () -> Unit): AlertDialogBuilder { + this.onCancel = onCancel + return this + } fun setTitle(title: String?): AlertDialogBuilder { this.title = title @@ -48,6 +63,10 @@ class AlertDialogBuilder(private val context: Context) { this.customView = view return this } + fun setCustomView(layoutResId: Int): AlertDialogBuilder { + this.customView = View.inflate(context, layoutResId, null) + return this + } fun setPosButton(title: String?, onClick: (() -> Unit)? = null): AlertDialogBuilder { this.posButtonTitle = title @@ -118,9 +137,10 @@ class AlertDialogBuilder(private val context: Context) { if (customView != null) builder.setView(customView) if (items != null) { if (onItemSelected != null) { - builder.setSingleChoiceItems(items, selectedItemIndex) { _, which -> + builder.setSingleChoiceItems(items, selectedItemIndex) { dialog, which -> selectedItemIndex = which onItemSelected?.invoke(which) + dialog.dismiss() } } else if (checkedItems != null && onItemsSelected != null) { builder.setMultiChoiceItems(items, checkedItems) { _, which, isChecked -> @@ -147,12 +167,20 @@ class AlertDialogBuilder(private val context: Context) { dialog.dismiss() } } - builder.setCancelable(false) + if (onCancel != null) { + builder.setOnCancelListener { + onCancel?.invoke() + } + } + builder.setCancelable(cancelable) val dialog = builder.create() attach?.invoke(dialog) dialog.setOnDismissListener { onDismiss?.invoke() } + dialog.setOnShowListener { + onShow?.invoke() + } dialog.window?.setDimAmount(0.8f) dialog.show() } diff --git a/app/src/main/java/ani/dantotsu/util/StoragePermissions.kt b/app/src/main/java/ani/dantotsu/util/StoragePermissions.kt index 8291c567a8..ee2a9aa85a 100644 --- a/app/src/main/java/ani/dantotsu/util/StoragePermissions.kt +++ b/app/src/main/java/ani/dantotsu/util/StoragePermissions.kt @@ -71,20 +71,17 @@ class StoragePermissions { complete(true) return } - val builder = AlertDialog.Builder(this, R.style.MyPopup) - builder.setTitle(getString(R.string.dir_access)) - builder.setMessage(getString(R.string.dir_access_msg)) - builder.setPositiveButton(getString(R.string.ok)) { dialog, _ -> - launcher.registerForCallback(complete) - launcher.launch() - dialog.dismiss() - } - builder.setNegativeButton(getString(R.string.cancel)) { dialog, _ -> - dialog.dismiss() - complete(false) - } - val dialog = builder.show() - dialog.window?.setDimAmount(0.8f) + customAlertDialog().apply { + setTitle(getString(R.string.dir_access)) + setMessage(getString(R.string.dir_access_msg)) + setPosButton(getString(R.string.ok)) { + launcher.registerForCallback(complete) + launcher.launch() + } + setNegButton(getString(R.string.cancel)) { + complete(false) + } + }.show() } private fun pathToUri(path: String): Uri { diff --git a/app/src/main/res/values/strings.xml b/app/src/main/res/values/strings.xml index 3660dae981..c6cb384470 100644 --- a/app/src/main/res/values/strings.xml +++ b/app/src/main/res/values/strings.xml @@ -948,6 +948,8 @@ Non quae tempore quo provident laudantium qui illo dolor vel quia dolor et exerc Use color from media\'s banner Use your own color for the theme Choose a color + Hide private Media from home screen + Long click "Continue Watching" to access Torrent Add-on Enable Torrent Anime Downloader Add-on