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 5b883b4aa3..cfdd7e1d9b 100644 --- a/app/src/main/java/ani/dantotsu/home/status/Stories.kt +++ b/app/src/main/java/ani/dantotsu/home/status/Stories.kt @@ -14,7 +14,9 @@ import android.view.animation.LinearInterpolator import android.widget.ProgressBar import androidx.constraintlayout.widget.ConstraintLayout import androidx.constraintlayout.widget.ConstraintSet +import androidx.core.app.ActivityOptionsCompat import androidx.core.content.ContextCompat +import androidx.core.view.ViewCompat import androidx.fragment.app.FragmentActivity import ani.dantotsu.R import ani.dantotsu.blurImage @@ -363,7 +365,6 @@ constructor( .putExtra("userId", story.userId), null) } - fun visible(isList: Boolean){ val visible = if (isList) View.VISIBLE else View.GONE val gone = if (isList) View.GONE else View.VISIBLE @@ -400,7 +401,13 @@ constructor( binding.coverImage.setOnClickListener{ ContextCompat.startActivity(context, Intent(context, MediaDetailsActivity::class.java) .putExtra("mediaId", story.media?.id), - null) + ActivityOptionsCompat.makeSceneTransitionAnimation( + activity, + binding.coverImage, + ViewCompat.getTransitionName(binding.coverImage)!! + ).toBundle() + ) + } } diff --git a/app/src/main/java/ani/dantotsu/media/manga/MangaChapterAdapter.kt b/app/src/main/java/ani/dantotsu/media/manga/MangaChapterAdapter.kt index 18d0765405..933928e085 100644 --- a/app/src/main/java/ani/dantotsu/media/manga/MangaChapterAdapter.kt +++ b/app/src/main/java/ani/dantotsu/media/manga/MangaChapterAdapter.kt @@ -16,6 +16,7 @@ import ani.dantotsu.databinding.ItemEpisodeCompactBinding import ani.dantotsu.media.Media import ani.dantotsu.media.MediaNameAdapter import ani.dantotsu.setAnimation +import ani.dantotsu.util.customAlertDialog import kotlinx.coroutines.delay import kotlinx.coroutines.launch import java.text.SimpleDateFormat @@ -209,16 +210,15 @@ class MangaChapterAdapter( fragment.onMangaChapterStopDownloadClick(chapterNumber) return@setOnClickListener } else if (downloadedChapters.contains(chapterNumber)) { - val builder = AlertDialog.Builder(currContext(), R.style.MyPopup) - builder.setTitle("Delete Chapter") - builder.setMessage("Are you sure you want to delete ${chapterNumber}?") - builder.setPositiveButton("Yes") { _, _ -> - fragment.onMangaChapterRemoveDownloadClick(chapterNumber) + it.context.customAlertDialog().apply { + setTitle("Delete Chapter") + setMessage("Are you sure you want to delete ${chapterNumber}?") + setPosButton(R.string.delete) { + fragment.onMangaChapterRemoveDownloadClick(chapterNumber) + } + setNegButton(R.string.cancel) + show() } - builder.setNegativeButton("No") { _, _ -> - } - val dialog = builder.show() - dialog.window?.setDimAmount(0.8f) return@setOnClickListener } else { fragment.onMangaChapterDownloadClick(chapterNumber) @@ -228,20 +228,20 @@ class MangaChapterAdapter( } binding.itemDownload.setOnLongClickListener { //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 = itemCount - bindingAdapterPosition - input.value = 1 - alertDialog.setView(input) - alertDialog.setPositiveButton("OK") { _, _ -> - downloadNChaptersFrom(bindingAdapterPosition, input.value) + it.context.customAlertDialog().apply { + setTitle("Multi Chapter Downloader") + setMessage("Enter the number of chapters to download") + val input = NumberPicker(currContext()) + input.minValue = 1 + input.maxValue = itemCount - bindingAdapterPosition + input.value = 1 + setCustomView(input) + setPosButton("OK") { + downloadNChaptersFrom(bindingAdapterPosition, input.value) + } + setNegButton("Cancel") + show() } - alertDialog.setNegativeButton("Cancel") { dialog, _ -> dialog.cancel() } - val dialog = alertDialog.show() - dialog.window?.setDimAmount(0.8f) true } diff --git a/app/src/main/java/ani/dantotsu/offline/OfflineFragment.kt b/app/src/main/java/ani/dantotsu/offline/OfflineFragment.kt index 5807cb4886..4702130c0c 100644 --- a/app/src/main/java/ani/dantotsu/offline/OfflineFragment.kt +++ b/app/src/main/java/ani/dantotsu/offline/OfflineFragment.kt @@ -4,6 +4,7 @@ import android.os.Bundle import android.view.LayoutInflater import android.view.View import android.view.ViewGroup +import androidx.core.view.isVisible import androidx.core.view.updateLayoutParams import androidx.fragment.app.Fragment import ani.dantotsu.R @@ -30,10 +31,15 @@ class OfflineFragment : Fragment() { offline = PrefManager.getVal(PrefName.OfflineMode) binding.noInternet.text = if (offline) "Offline Mode" else getString(R.string.no_internet) - binding.refreshButton.visibility = if (offline) View.GONE else View.VISIBLE + binding.refreshButton.text = if (offline) "Go Online" else getString(R.string.refresh) binding.refreshButton.setOnClickListener { - if (isOnline(requireContext())) { + if (offline && isOnline(requireContext())) { + PrefManager.setVal(PrefName.OfflineMode, false) startMainActivity(requireActivity()) + } else { + if (isOnline(requireContext()) ) { + startMainActivity(requireActivity()) + } } } return binding.root diff --git a/app/src/main/java/ani/dantotsu/settings/SettingsDialogFragment.kt b/app/src/main/java/ani/dantotsu/settings/SettingsDialogFragment.kt index 078c179e91..70da38d4ab 100644 --- a/app/src/main/java/ani/dantotsu/settings/SettingsDialogFragment.kt +++ b/app/src/main/java/ani/dantotsu/settings/SettingsDialogFragment.kt @@ -4,7 +4,6 @@ import android.app.AlertDialog import android.content.Intent import android.graphics.Color import android.os.Bundle -import android.util.TypedValue import android.view.LayoutInflater import android.view.View import android.view.ViewGroup @@ -17,6 +16,8 @@ import ani.dantotsu.connections.anilist.Anilist import ani.dantotsu.databinding.BottomSheetSettingsBinding import ani.dantotsu.download.anime.OfflineAnimeFragment import ani.dantotsu.download.manga.OfflineMangaFragment +import ani.dantotsu.getAppString +import ani.dantotsu.getThemeColor import ani.dantotsu.home.AnimeFragment import ani.dantotsu.home.HomeFragment import ani.dantotsu.home.LoginFragment @@ -32,6 +33,7 @@ import ani.dantotsu.setSafeOnClickListener import ani.dantotsu.settings.saving.PrefManager import ani.dantotsu.settings.saving.PrefName import ani.dantotsu.startMainActivity +import ani.dantotsu.util.customAlertDialog import eu.kanade.tachiyomi.util.system.getSerializableCompat import java.util.Timer import kotlin.concurrent.schedule @@ -59,10 +61,7 @@ class SettingsDialogFragment : BottomSheetDialogFragment() { super.onViewCreated(view, savedInstanceState) val window = dialog?.window window?.statusBarColor = Color.CYAN - val typedValue = TypedValue() - val theme = requireContext().theme - theme.resolveAttribute(com.google.android.material.R.attr.colorSurface, typedValue, true) - window?.navigationBarColor = typedValue.data + window?.navigationBarColor = requireContext().getThemeColor(com.google.android.material.R.attr.colorSurface) val notificationIcon = if (Anilist.unreadNotificationCount > 0) { R.drawable.ic_round_notifications_active_24 } else { @@ -73,18 +72,16 @@ class SettingsDialogFragment : BottomSheetDialogFragment() { if (Anilist.token != null) { binding.settingsLogin.setText(R.string.logout) binding.settingsLogin.setOnClickListener { - val alertDialog = AlertDialog.Builder(requireContext(), R.style.MyPopup) - .setTitle("Logout") - .setMessage("Are you sure you want to logout?") - .setPositiveButton("Yes") { _, _ -> + requireContext().customAlertDialog().apply{ + setTitle(R.string.logout) + setMessage(R.string.logout_confirm) + setPosButton(R.string.yes) { Anilist.removeSavedToken() - dismiss() startMainActivity(requireActivity()) } - .setNegativeButton("No") { _, _ -> } - .create() - alertDialog.window?.setDimAmount(0.8f) - alertDialog.show() + setNegButton(R.string.no) + show() + } } binding.settingsUsername.text = Anilist.username binding.settingsUserAvatar.loadImage(Anilist.avatar) diff --git a/app/src/main/java/ani/dantotsu/settings/SettingsExtensionsActivity.kt b/app/src/main/java/ani/dantotsu/settings/SettingsExtensionsActivity.kt index 1f38a491d5..078d7b380b 100644 --- a/app/src/main/java/ani/dantotsu/settings/SettingsExtensionsActivity.kt +++ b/app/src/main/java/ani/dantotsu/settings/SettingsExtensionsActivity.kt @@ -24,6 +24,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 eu.kanade.domain.base.BasePreferences import eu.kanade.tachiyomi.extension.anime.AnimeExtensionManager import eu.kanade.tachiyomi.extension.manga.MangaExtensionManager @@ -169,27 +170,27 @@ class SettingsExtensionsActivity : AppCompatActivity() { val editText = dialogView.userAgentTextBox.apply { hint = getString(R.string.anime_add_repository) } - val alertDialog = AlertDialog.Builder(context, R.style.MyPopup) - .setTitle(R.string.anime_add_repository).setView(dialogView.root) - .setPositiveButton(getString(R.string.ok)) { dialog, _ -> + context.customAlertDialog().apply { + setTitle(R.string.anime_add_repository) + setCustomView(dialogView.root) + setPosButton(getString(R.string.ok)) { if (!editText.text.isNullOrBlank()) processUserInput( editText.text.toString(), MediaType.ANIME, it.attachView ) - dialog.dismiss() - }.setNegativeButton(getString(R.string.cancel)) { dialog, _ -> - dialog.dismiss() - }.create() - - processEditorAction( - alertDialog, - editText, - MediaType.ANIME, - it.attachView - ) - alertDialog.show() - alertDialog.window?.setDimAmount(0.8f) + } + setNegButton(getString(R.string.cancel)) + attach { dialog -> + processEditorAction( + dialog, + editText, + MediaType.ANIME, + it.attachView + ) + } + show() + } }, attach = { setExtensionOutput(it.attachView, MediaType.ANIME) diff --git a/app/src/main/java/ani/dantotsu/settings/SettingsMangaActivity.kt b/app/src/main/java/ani/dantotsu/settings/SettingsMangaActivity.kt index 7322f3ef9d..1842d147fb 100644 --- a/app/src/main/java/ani/dantotsu/settings/SettingsMangaActivity.kt +++ b/app/src/main/java/ani/dantotsu/settings/SettingsMangaActivity.kt @@ -19,6 +19,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 uy.kohesive.injekt.Injekt import uy.kohesive.injekt.api.get @@ -80,23 +81,16 @@ class SettingsMangaActivity : AppCompatActivity() { desc = getString(R.string.purge_manga_downloads_desc), icon = R.drawable.ic_round_delete_24, onClick = { - val dialog = AlertDialog.Builder(context, R.style.MyPopup) - .setTitle(R.string.purge_manga_downloads) - .setMessage( - getString( - R.string.purge_confirm, - getString(R.string.manga) - ) - ) - .setPositiveButton(R.string.yes) { dialog, _ -> + context.customAlertDialog().apply { + setTitle(R.string.purge_manga_downloads) + setMessage(R.string.purge_confirm, getString(R.string.manga)) + setPosButton(R.string.yes, onClick = { val downloadsManager = Injekt.get() downloadsManager.purgeDownloads(MediaType.MANGA) - dialog.dismiss() - }.setNegativeButton(R.string.no) { dialog, _ -> - dialog.dismiss() - }.create() - dialog.window?.setDimAmount(0.8f) - dialog.show() + }) + setNegButton(R.string.no) + show() + } } ), @@ -106,23 +100,16 @@ class SettingsMangaActivity : AppCompatActivity() { desc = getString(R.string.purge_novel_downloads_desc), icon = R.drawable.ic_round_delete_24, onClick = { - val dialog = AlertDialog.Builder(context, R.style.MyPopup) - .setTitle(R.string.purge_novel_downloads) - .setMessage( - getString( - R.string.purge_confirm, - getString(R.string.novels) - ) - ) - .setPositiveButton(R.string.yes) { dialog, _ -> + context.customAlertDialog().apply { + setTitle(R.string.purge_novel_downloads) + setMessage(R.string.purge_confirm, getString(R.string.novels)) + setPosButton(R.string.yes) { val downloadsManager = Injekt.get() downloadsManager.purgeDownloads(MediaType.NOVEL) - dialog.dismiss() - }.setNegativeButton(R.string.no) { dialog, _ -> - dialog.dismiss() - }.create() - dialog.window?.setDimAmount(0.8f) - dialog.show() + } + setNegButton(R.string.no) + show() + } } ), Settings( diff --git a/app/src/main/java/ani/dantotsu/util/AlertDialogBuilder.kt b/app/src/main/java/ani/dantotsu/util/AlertDialogBuilder.kt new file mode 100644 index 0000000000..31ddad263c --- /dev/null +++ b/app/src/main/java/ani/dantotsu/util/AlertDialogBuilder.kt @@ -0,0 +1,170 @@ +package ani.dantotsu.util + +import android.app.AlertDialog +import android.content.Context +import android.view.View +import ani.dantotsu.R + +class AlertDialogBuilder(private val context: Context) { + private var title: String? = null + private var message: String? = null + private var posButtonTitle: String? = null + private var negButtonTitle: String? = null + private var neutralButtonTitle: String? = null + private var onPositiveButtonClick: (() -> Unit)? = null + private var onNegativeButtonClick: (() -> Unit)? = null + private var onNeutralButtonClick: (() -> Unit)? = null + private var items: Array? = null + private var checkedItems: BooleanArray? = null + private var onItemsSelected: ((BooleanArray) -> Unit)? = null + private var selectedItemIndex: Int = -1 + private var onItemSelected: ((Int) -> Unit)? = null + private var customView: View? = null + private var attach: ((dialog: AlertDialog) -> Unit)? = null + fun setTitle(title: String?): AlertDialogBuilder { + this.title = title + return this + } + + fun setTitle(int: Int, formatArgs: Int? = null): AlertDialogBuilder { + this.title = context.getString(int, formatArgs) + return this + } + + fun setMessage(message: String?): AlertDialogBuilder { + this.message = message + return this + } + + fun setMessage(stringInt: Int, vararg formatArgs: Any): AlertDialogBuilder { + this.message = context.getString(stringInt, *formatArgs) + return this + } + + fun setCustomView(view: View): AlertDialogBuilder { + this.customView = view + return this + } + + fun setPosButton(title: String?, onClick: (() -> Unit)? = null): AlertDialogBuilder { + this.posButtonTitle = title + this.onPositiveButtonClick = onClick + return this + } + + fun setPosButton( + int: Int, + formatArgs: Int? = null, + onClick: (() -> Unit)? = null + ): AlertDialogBuilder { + this.posButtonTitle = context.getString(int, formatArgs) + this.onPositiveButtonClick = onClick + return this + } + + fun setNegButton(title: String?, onClick: (() -> Unit)? = null): AlertDialogBuilder { + this.negButtonTitle = title + this.onNegativeButtonClick = onClick + return this + } + + fun setNegButton( + int: Int, + formatArgs: Int? = null, + onClick: (() -> Unit)? = null + ): AlertDialogBuilder { + this.negButtonTitle = context.getString(int, formatArgs) + this.onNegativeButtonClick = onClick + return this + } + + fun setNeutralButton(title: String?, onClick: (() -> Unit)? = null): AlertDialogBuilder { + this.negButtonTitle = title + this.onNegativeButtonClick = onClick + return this + } + + fun setNeutralButton( + int: Int, + formatArgs: Int? = null, + onClick: (() -> Unit)? = null + ): AlertDialogBuilder { + this.negButtonTitle = context.getString(int, formatArgs) + this.onNegativeButtonClick = onClick + return this + } + + fun attach(attach: ((dialog: AlertDialog) -> Unit)?): AlertDialogBuilder { + this.attach = attach + return this + } + + fun singleChoiceItems( + items: Array, + selectedItemIndex: Int = -1, + onItemSelected: (Int) -> Unit + ): AlertDialogBuilder { + this.items = items + this.selectedItemIndex = selectedItemIndex + this.onItemSelected = onItemSelected + return this + } + + fun multiChoiceItems( + items: Array, + checkedItems: BooleanArray? = null, + onItemsSelected: (BooleanArray) -> Unit + ): AlertDialogBuilder { + this.items = items + this.checkedItems = checkedItems ?: BooleanArray(items.size) { false } + this.onItemsSelected = onItemsSelected + return this + } + + fun show() { + val builder = AlertDialog.Builder(context, R.style.MyPopup) + if (title != null) builder.setTitle(title) + if (message != null) builder.setMessage(message) + if (customView != null) builder.setView(customView) + if (items != null) { + if (onItemSelected != null) { + builder.setSingleChoiceItems(items, selectedItemIndex) { _, which -> + selectedItemIndex = which + onItemSelected?.invoke(which) + } + } else if (checkedItems != null && onItemsSelected != null) { + builder.setMultiChoiceItems(items, checkedItems) { _, which, isChecked -> + checkedItems?.set(which, isChecked) + } + } + } + if (posButtonTitle != null) { + builder.setPositiveButton(posButtonTitle) { dialog, _ -> + onPositiveButtonClick?.invoke() + dialog.dismiss() + } + } + if (negButtonTitle != null) { + builder.setNegativeButton(negButtonTitle) { dialog, _ -> + onNegativeButtonClick?.invoke() + dialog.dismiss() + } + } + if (neutralButtonTitle != null) { + builder.setNeutralButton(neutralButtonTitle) { dialog, _ -> + onNeutralButtonClick?.invoke() + dialog.dismiss() + } + } + builder.setCancelable(false) + val dialog = builder.create() + attach?.invoke(dialog) + dialog.window?.setDimAmount(0.8f) + dialog.show() + } + +} + +fun Context.customAlertDialog(): AlertDialogBuilder { + return AlertDialogBuilder(this) +} \ No newline at end of file diff --git a/app/src/main/res/layout/fragment_offline.xml b/app/src/main/res/layout/fragment_offline.xml index 9514a06351..20fe567530 100644 --- a/app/src/main/res/layout/fragment_offline.xml +++ b/app/src/main/res/layout/fragment_offline.xml @@ -64,7 +64,7 @@