diff --git a/app/src/main/AndroidManifest.xml b/app/src/main/AndroidManifest.xml
index 779c829f..f752bc76 100644
--- a/app/src/main/AndroidManifest.xml
+++ b/app/src/main/AndroidManifest.xml
@@ -132,6 +132,30 @@
+
+
+
+
+
+
+
+
{
+ topMargin = statusBarHeight
+ bottomMargin = navBarHeight
+ }
+ settingsAboutTitle.setOnClickListener { onBackPressedDispatcher.onBackPressed() }
+
+ settingsDev.setOnClickListener {
+ DevelopersDialogFragment().show(supportFragmentManager, "dialog")
+ }
+ settingsForks.setOnClickListener {
+ ForksDialogFragment().show(supportFragmentManager, "dialog")
+ }
+ settingsDisclaimer.setOnClickListener {
+ val text = TextView(context)
+ text.setText(R.string.full_disclaimer)
+
+ CustomBottomDialog.newInstance().apply {
+ setTitleText(getString(R.string.disclaimer))
+ addView(text)
+ setNegativeButton(getString(R.string.close)) {
+ dismiss()
+ }
+ show(supportFragmentManager, "dialog")
+ }
+ }
+
+ settingsFAQ.setOnClickListener {
+ startActivity(Intent(context, FAQActivity::class.java))
+ }
+
+ if (!BuildConfig.FLAVOR.contains("fdroid")) {
+
+ settingsCheckUpdate.apply {
+ isChecked = PrefManager.getVal(PrefName.CheckUpdate)
+
+ setOnCheckedChangeListener { _, isChecked ->
+ PrefManager.setVal(PrefName.CheckUpdate, isChecked)
+ if (!isChecked) {
+ snackString(getString(R.string.long_click_to_check_update))
+ }
+ }
+
+ setOnLongClickListener {
+ lifecycleScope.launch(Dispatchers.IO) {
+ AppUpdater.check(context, true)
+ }
+ true
+ }
+
+ }
+
+ settingsShareUsername.apply {
+ isChecked = PrefManager.getVal(PrefName.SharedUserID)
+ settingsShareUsername.setOnCheckedChangeListener { _, isChecked ->
+ PrefManager.setVal(PrefName.SharedUserID, isChecked)
+ }
+ }
+
+ } else {
+ settingsCheckUpdate.apply{
+ visibility = View.GONE
+ isEnabled = false
+ isChecked = false
+ }
+ settingsShareUsername.apply{
+ visibility = View.GONE
+ isEnabled = false
+ isChecked = false
+ }
+
+ }
+
+ settingsLogToFile.apply {
+ isChecked = PrefManager.getVal(PrefName.LogToFile)
+
+ setOnCheckedChangeListener { _, isChecked ->
+ PrefManager.setVal(PrefName.LogToFile, isChecked)
+ restartApp(binding.root)
+ }
+ }
+
+ settingsShareLog.setOnClickListener {
+ Logger.shareLog(context)
+ }
+ }
+ }
+}
\ No newline at end of file
diff --git a/app/src/main/java/ani/dantotsu/settings/SettingsAccountActivity.kt b/app/src/main/java/ani/dantotsu/settings/SettingsAccountActivity.kt
new file mode 100644
index 00000000..8344c1a5
--- /dev/null
+++ b/app/src/main/java/ani/dantotsu/settings/SettingsAccountActivity.kt
@@ -0,0 +1,201 @@
+package ani.dantotsu.settings
+
+import android.os.Bundle
+import android.view.HapticFeedbackConstants
+import android.view.View
+import android.view.ViewGroup
+import android.view.animation.AnimationUtils
+import android.widget.TextView
+import androidx.activity.OnBackPressedCallback
+import androidx.appcompat.app.AppCompatActivity
+import androidx.core.view.updateLayoutParams
+import ani.dantotsu.R
+import ani.dantotsu.connections.anilist.Anilist
+import ani.dantotsu.connections.discord.Discord
+import ani.dantotsu.connections.mal.MAL
+import ani.dantotsu.databinding.ActivitySettingsAboutBinding
+import ani.dantotsu.databinding.ActivitySettingsAccountsBinding
+import ani.dantotsu.initActivity
+import ani.dantotsu.loadImage
+import ani.dantotsu.navBarHeight
+import ani.dantotsu.openLinkInBrowser
+import ani.dantotsu.others.CustomBottomDialog
+import ani.dantotsu.settings.saving.PrefManager
+import ani.dantotsu.settings.saving.PrefName
+import ani.dantotsu.startMainActivity
+import ani.dantotsu.statusBarHeight
+import ani.dantotsu.themes.ThemeManager
+import io.noties.markwon.Markwon
+import io.noties.markwon.SoftBreakAddsNewLinePlugin
+
+class SettingsAccountActivity : AppCompatActivity() {
+ private lateinit var binding: ActivitySettingsAccountsBinding
+ private val restartMainActivity = object : OnBackPressedCallback(false) {
+ override fun handleOnBackPressed() = startMainActivity(this@SettingsAccountActivity)
+ }
+ override fun onCreate(savedInstanceState: Bundle?) {
+ super.onCreate(savedInstanceState)
+ ThemeManager(this).applyTheme()
+ initActivity(this)
+ val context = this
+
+ binding = ActivitySettingsAccountsBinding.inflate(layoutInflater)
+ setContentView(binding.root)
+
+ binding.apply {
+ settingsAccountsLayout.updateLayoutParams {
+ topMargin = statusBarHeight
+ bottomMargin = navBarHeight
+ }
+ settingsaccountTitle.setOnClickListener { onBackPressedDispatcher.onBackPressed() }
+
+ settingsAccountHelp.setOnClickListener {
+ CustomBottomDialog.newInstance().apply {
+ setTitleText(context.getString(R.string.account_help))
+ addView(
+ TextView(it.context).apply {
+ val markWon = Markwon.builder(it.context)
+ .usePlugin(SoftBreakAddsNewLinePlugin.create()).build()
+ markWon.setMarkdown(this, context.getString(R.string.full_account_help))
+ }
+ )
+ }.show(supportFragmentManager, "dialog")
+ }
+
+ fun reload() {
+ if (Anilist.token != null) {
+ settingsAnilistLogin.setText(R.string.logout)
+ settingsAnilistLogin.setOnClickListener {
+ Anilist.removeSavedToken()
+ restartMainActivity.isEnabled = true
+ reload()
+ }
+ settingsAnilistUsername.visibility = View.VISIBLE
+ settingsAnilistUsername.text = Anilist.username
+ settingsAnilistAvatar.loadImage(Anilist.avatar)
+ settingsAnilistAvatar.setOnClickListener {
+ it.performHapticFeedback(HapticFeedbackConstants.LONG_PRESS)
+ val anilistLink = getString(
+ R.string.anilist_link,
+ PrefManager.getVal(PrefName.AnilistUserName)
+ )
+ openLinkInBrowser(anilistLink)
+ }
+
+ settingsMALLoginRequired.visibility = View.GONE
+ settingsMALLogin.visibility = View.VISIBLE
+ settingsMALUsername.visibility = View.VISIBLE
+
+ if (MAL.token != null) {
+ settingsMALLogin.setText(R.string.logout)
+ settingsMALLogin.setOnClickListener {
+ MAL.removeSavedToken()
+ restartMainActivity.isEnabled = true
+ reload()
+ }
+ settingsMALUsername.visibility = View.VISIBLE
+ settingsMALUsername.text = MAL.username
+ settingsMALAvatar.loadImage(MAL.avatar)
+ settingsMALAvatar.setOnClickListener {
+ it.performHapticFeedback(HapticFeedbackConstants.LONG_PRESS)
+ openLinkInBrowser(getString(R.string.myanilist_link, MAL.username))
+ }
+ } else {
+ settingsMALAvatar.setImageResource(R.drawable.ic_round_person_24)
+ settingsMALUsername.visibility = View.GONE
+ settingsMALLogin.setText(R.string.login)
+ settingsMALLogin.setOnClickListener {
+ MAL.loginIntent(context)
+ }
+ }
+ } else {
+ settingsAnilistAvatar.setImageResource(R.drawable.ic_round_person_24)
+ settingsAnilistUsername.visibility = View.GONE
+ settingsAnilistLogin.setText(R.string.login)
+ settingsAnilistLogin.setOnClickListener {
+ Anilist.loginIntent(context)
+ }
+ settingsMALLoginRequired.visibility = View.VISIBLE
+ settingsMALLogin.visibility = View.GONE
+ settingsMALUsername.visibility = View.GONE
+ }
+
+ if (Discord.token != null) {
+ val id = PrefManager.getVal(PrefName.DiscordId, null as String?)
+ val avatar = PrefManager.getVal(PrefName.DiscordAvatar, null as String?)
+ val username = PrefManager.getVal(PrefName.DiscordUserName, null as String?)
+ if (id != null && avatar != null) {
+ settingsDiscordAvatar.loadImage("https://cdn.discordapp.com/avatars/$id/$avatar.png")
+ settingsDiscordAvatar.setOnClickListener {
+ it.performHapticFeedback(HapticFeedbackConstants.LONG_PRESS)
+ val discordLink = getString(R.string.discord_link, id)
+ openLinkInBrowser(discordLink)
+ }
+ }
+ settingsDiscordUsername.visibility = View.VISIBLE
+ settingsDiscordUsername.text =
+ username ?: Discord.token?.replace(Regex("."), "*")
+ settingsDiscordLogin.setText(R.string.logout)
+ settingsDiscordLogin.setOnClickListener {
+ Discord.removeSavedToken(context)
+ restartMainActivity.isEnabled = true
+ reload()
+ }
+
+ settingsImageSwitcher.visibility = View.VISIBLE
+ var initialStatus = when (PrefManager.getVal(PrefName.DiscordStatus)) {
+ "online" -> R.drawable.discord_status_online
+ "idle" -> R.drawable.discord_status_idle
+ "dnd" -> R.drawable.discord_status_dnd
+ else -> R.drawable.discord_status_online
+ }
+ settingsImageSwitcher.setImageResource(initialStatus)
+
+ val zoomInAnimation =
+ AnimationUtils.loadAnimation(context, R.anim.bounce_zoom)
+ settingsImageSwitcher.setOnClickListener {
+ var status = "online"
+ initialStatus = when (initialStatus) {
+ R.drawable.discord_status_online -> {
+ status = "idle"
+ R.drawable.discord_status_idle
+ }
+
+ R.drawable.discord_status_idle -> {
+ status = "dnd"
+ R.drawable.discord_status_dnd
+ }
+
+ R.drawable.discord_status_dnd -> {
+ status = "online"
+ R.drawable.discord_status_online
+ }
+
+ else -> R.drawable.discord_status_online
+ }
+
+ PrefManager.setVal(PrefName.DiscordStatus, status)
+ settingsImageSwitcher.setImageResource(initialStatus)
+ settingsImageSwitcher.startAnimation(zoomInAnimation)
+ }
+ settingsImageSwitcher.setOnLongClickListener {
+ it.performHapticFeedback(HapticFeedbackConstants.LONG_PRESS)
+ DiscordDialogFragment().show(supportFragmentManager, "dialog")
+ true
+ }
+ } else {
+ settingsImageSwitcher.visibility = View.GONE
+ settingsDiscordAvatar.setImageResource(R.drawable.ic_round_person_24)
+ settingsDiscordUsername.visibility = View.GONE
+ settingsDiscordLogin.setText(R.string.login)
+ settingsDiscordLogin.setOnClickListener {
+ Discord.warning(context)
+ .show(supportFragmentManager, "dialog")
+ }
+ }
+ }
+ reload()
+ }
+ }
+
+}
\ No newline at end of file
diff --git a/app/src/main/java/ani/dantotsu/settings/SettingsActivity.kt b/app/src/main/java/ani/dantotsu/settings/SettingsActivity.kt
index 81278580..301be833 100644
--- a/app/src/main/java/ani/dantotsu/settings/SettingsActivity.kt
+++ b/app/src/main/java/ani/dantotsu/settings/SettingsActivity.kt
@@ -19,7 +19,6 @@ import android.view.KeyEvent
import android.view.LayoutInflater
import android.view.View
import android.view.ViewGroup
-import android.view.animation.AnimationUtils
import android.view.inputmethod.EditorInfo
import android.widget.ArrayAdapter
import android.widget.EditText
@@ -35,14 +34,8 @@ import androidx.lifecycle.lifecycleScope
import androidx.media3.common.util.UnstableApi
import ani.dantotsu.BuildConfig
import ani.dantotsu.R
-import ani.dantotsu.connections.anilist.Anilist
import ani.dantotsu.connections.anilist.api.NotificationType
-import ani.dantotsu.connections.discord.Discord
-import ani.dantotsu.connections.mal.MAL
import ani.dantotsu.copyToClipboard
-import ani.dantotsu.currContext
-import ani.dantotsu.databinding.ActivitySettingsAboutBinding
-import ani.dantotsu.databinding.ActivitySettingsAccountsBinding
import ani.dantotsu.databinding.ActivitySettingsAnimeBinding
import ani.dantotsu.databinding.ActivitySettingsBinding
import ani.dantotsu.databinding.ActivitySettingsCommonBinding
@@ -53,7 +46,6 @@ import ani.dantotsu.databinding.ActivitySettingsThemeBinding
import ani.dantotsu.databinding.ItemRepositoryBinding
import ani.dantotsu.download.DownloadsManager
import ani.dantotsu.initActivity
-import ani.dantotsu.loadImage
import ani.dantotsu.media.MediaType
import ani.dantotsu.navBarHeight
import ani.dantotsu.notifications.TaskScheduler
@@ -90,8 +82,6 @@ import eltos.simpledialogfragment.color.SimpleColorDialog
import eu.kanade.domain.base.BasePreferences
import eu.kanade.tachiyomi.extension.anime.AnimeExtensionManager
import eu.kanade.tachiyomi.extension.manga.MangaExtensionManager
-import io.noties.markwon.Markwon
-import io.noties.markwon.SoftBreakAddsNewLinePlugin
import kotlinx.coroutines.CoroutineScope
import kotlinx.coroutines.DelicateCoroutinesApi
import kotlinx.coroutines.Dispatchers
@@ -109,21 +99,9 @@ class SettingsActivity : AppCompatActivity(), SimpleDialog.OnDialogResultListene
override fun handleOnBackPressed() = startMainActivity(this@SettingsActivity)
}
lateinit var binding: ActivitySettingsBinding
- private lateinit var launcher: LauncherWrapper
- private lateinit var bindingAccounts: ActivitySettingsAccountsBinding
- private lateinit var bindingTheme: ActivitySettingsThemeBinding
- private lateinit var bindingExtensions: ActivitySettingsExtensionsBinding
- private lateinit var bindingCommon: ActivitySettingsCommonBinding
- private lateinit var bindingAnime: ActivitySettingsAnimeBinding
- private lateinit var bindingManga: ActivitySettingsMangaBinding
- private lateinit var bindingNotifications: ActivitySettingsNotificationsBinding
- private lateinit var bindingAbout: ActivitySettingsAboutBinding
- private val extensionInstaller = Injekt.get().extensionInstaller()
private var cursedCounter = 0
- private val animeExtensionManager: AnimeExtensionManager by injectLazy()
- private val mangaExtensionManager: MangaExtensionManager by injectLazy()
- @kotlin.OptIn(DelicateCoroutinesApi::class)
+
@OptIn(UnstableApi::class)
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
@@ -133,51 +111,6 @@ class SettingsActivity : AppCompatActivity(), SimpleDialog.OnDialogResultListene
initActivity(this)
- val openDocumentLauncher =
- registerForActivityResult(ActivityResultContracts.OpenDocument()) { uri ->
- if (uri != null) {
- try {
- val jsonString = contentResolver.openInputStream(uri)?.readBytes()
- ?: throw Exception("Error reading file")
- val name = DocumentFile.fromSingleUri(this, uri)?.name ?: "settings"
- //.sani is encrypted, .ani is not
- if (name.endsWith(".sani")) {
- passwordAlertDialog(false) { password ->
- if (password != null) {
- val salt = jsonString.copyOfRange(0, 16)
- val encrypted = jsonString.copyOfRange(16, jsonString.size)
- val decryptedJson = try {
- PreferenceKeystore.decryptWithPassword(
- password,
- encrypted,
- salt
- )
- } catch (e: Exception) {
- toast(getString(R.string.incorrect_password))
- return@passwordAlertDialog
- }
- if (PreferencePackager.unpack(decryptedJson))
- restartApp(binding.root)
- } else {
- toast(getString(R.string.password_cannot_be_empty))
- }
- }
- } else if (name.endsWith(".ani")) {
- val decryptedJson = jsonString.toString(Charsets.UTF_8)
- if (PreferencePackager.unpack(decryptedJson))
- restartApp(binding.root)
- } else {
- toast(getString(R.string.unknown_file_type))
- }
- } catch (e: Exception) {
- e.printStackTrace()
- toast(getString(R.string.error_importing_settings))
- }
- }
- }
- val contract = ActivityResultContracts.OpenDocumentTree()
- launcher = LauncherWrapper(this, contract)
-
binding.settingsVersion.text = getString(R.string.version_current, BuildConfig.VERSION_NAME)
binding.settingsVersion.setOnLongClickListener {
copyToClipboard(getDeviceInfo(), false)
@@ -196,1018 +129,40 @@ class SettingsActivity : AppCompatActivity(), SimpleDialog.OnDialogResultListene
onBackPressedDispatcher.onBackPressed()
}
- bindingAccounts = ActivitySettingsAccountsBinding.bind(binding.root).apply {
- settingsAccountHelp.setOnClickListener {
- val title = getString(R.string.account_help)
- val full = getString(R.string.full_account_help)
- CustomBottomDialog.newInstance().apply {
- setTitleText(title)
- addView(
- TextView(it.context).apply {
- val markWon = Markwon.builder(it.context)
- .usePlugin(SoftBreakAddsNewLinePlugin.create()).build()
- markWon.setMarkdown(this, full)
- }
- )
- }.show(supportFragmentManager, "dialog")
+ binding.apply {
+ settingsAbout.setOnClickListener {
+ startActivity(Intent(this@SettingsActivity, SettingsAboutActivity::class.java))
}
-
- fun reload() {
- if (Anilist.token != null) {
- settingsAnilistLogin.setText(R.string.logout)
- settingsAnilistLogin.setOnClickListener {
- Anilist.removeSavedToken()
- restartMainActivity.isEnabled = true
- reload()
- }
- settingsAnilistUsername.visibility = View.VISIBLE
- settingsAnilistUsername.text = Anilist.username
- settingsAnilistAvatar.loadImage(Anilist.avatar)
- settingsAnilistAvatar.setOnClickListener {
- it.performHapticFeedback(HapticFeedbackConstants.LONG_PRESS)
- val anilistLink = getString(
- R.string.anilist_link,
- PrefManager.getVal(PrefName.AnilistUserName)
- )
- openLinkInBrowser(anilistLink)
- }
-
- settingsMALLoginRequired.visibility = View.GONE
- settingsMALLogin.visibility = View.VISIBLE
- settingsMALUsername.visibility = View.VISIBLE
-
- if (MAL.token != null) {
- settingsMALLogin.setText(R.string.logout)
- settingsMALLogin.setOnClickListener {
- MAL.removeSavedToken()
- restartMainActivity.isEnabled = true
- reload()
- }
- settingsMALUsername.visibility = View.VISIBLE
- settingsMALUsername.text = MAL.username
- settingsMALAvatar.loadImage(MAL.avatar)
- settingsMALAvatar.setOnClickListener {
- it.performHapticFeedback(HapticFeedbackConstants.LONG_PRESS)
- val myanilistLink = getString(R.string.myanilist_link, MAL.username)
- openLinkInBrowser(myanilistLink)
- }
- } else {
- settingsMALAvatar.setImageResource(R.drawable.ic_round_person_24)
- settingsMALUsername.visibility = View.GONE
- settingsMALLogin.setText(R.string.login)
- settingsMALLogin.setOnClickListener {
- MAL.loginIntent(this@SettingsActivity)
- }
- }
- } else {
- settingsAnilistAvatar.setImageResource(R.drawable.ic_round_person_24)
- settingsAnilistUsername.visibility = View.GONE
- settingsAnilistLogin.setText(R.string.login)
- settingsAnilistLogin.setOnClickListener {
- Anilist.loginIntent(this@SettingsActivity)
- }
- settingsMALLoginRequired.visibility = View.VISIBLE
- settingsMALLogin.visibility = View.GONE
- settingsMALUsername.visibility = View.GONE
- }
-
- if (Discord.token != null) {
- val id = PrefManager.getVal(PrefName.DiscordId, null as String?)
- val avatar = PrefManager.getVal(PrefName.DiscordAvatar, null as String?)
- val username = PrefManager.getVal(PrefName.DiscordUserName, null as String?)
- if (id != null && avatar != null) {
- settingsDiscordAvatar.loadImage("https://cdn.discordapp.com/avatars/$id/$avatar.png")
- settingsDiscordAvatar.setOnClickListener {
- it.performHapticFeedback(HapticFeedbackConstants.LONG_PRESS)
- val discordLink = getString(R.string.discord_link, id)
- openLinkInBrowser(discordLink)
- }
- }
- settingsDiscordUsername.visibility = View.VISIBLE
- settingsDiscordUsername.text =
- username ?: Discord.token?.replace(Regex("."), "*")
- settingsDiscordLogin.setText(R.string.logout)
- settingsDiscordLogin.setOnClickListener {
- Discord.removeSavedToken(this@SettingsActivity)
- restartMainActivity.isEnabled = true
- reload()
- }
-
- settingsImageSwitcher.visibility = View.VISIBLE
- var initialStatus = when (PrefManager.getVal(PrefName.DiscordStatus)) {
- "online" -> R.drawable.discord_status_online
- "idle" -> R.drawable.discord_status_idle
- "dnd" -> R.drawable.discord_status_dnd
- else -> R.drawable.discord_status_online
- }
- settingsImageSwitcher.setImageResource(initialStatus)
-
- val zoomInAnimation =
- AnimationUtils.loadAnimation(this@SettingsActivity, R.anim.bounce_zoom)
- settingsImageSwitcher.setOnClickListener {
- var status = "online"
- initialStatus = when (initialStatus) {
- R.drawable.discord_status_online -> {
- status = "idle"
- R.drawable.discord_status_idle
- }
-
- R.drawable.discord_status_idle -> {
- status = "dnd"
- R.drawable.discord_status_dnd
- }
-
- R.drawable.discord_status_dnd -> {
- status = "online"
- R.drawable.discord_status_online
- }
-
- else -> R.drawable.discord_status_online
- }
-
- PrefManager.setVal(PrefName.DiscordStatus, status)
- settingsImageSwitcher.setImageResource(initialStatus)
- settingsImageSwitcher.startAnimation(zoomInAnimation)
- }
- settingsImageSwitcher.setOnLongClickListener {
- it.performHapticFeedback(HapticFeedbackConstants.LONG_PRESS)
- DiscordDialogFragment().show(supportFragmentManager, "dialog")
- true
- }
- } else {
- settingsImageSwitcher.visibility = View.GONE
- settingsDiscordAvatar.setImageResource(R.drawable.ic_round_person_24)
- settingsDiscordUsername.visibility = View.GONE
- settingsDiscordLogin.setText(R.string.login)
- settingsDiscordLogin.setOnClickListener {
- Discord.warning(this@SettingsActivity)
- .show(supportFragmentManager, "dialog")
- }
- }
+ settingsAccount.setOnClickListener {
+ startActivity(Intent(this@SettingsActivity, SettingsAccountActivity::class.java))
}
- reload()
- }
-
- bindingTheme = ActivitySettingsThemeBinding.bind(binding.root).apply {
- settingsUseMaterialYou.isChecked =
- PrefManager.getVal(PrefName.UseMaterialYou)
- settingsUseMaterialYou.setOnCheckedChangeListener { _, isChecked ->
- PrefManager.setVal(PrefName.UseMaterialYou, isChecked)
- if (isChecked) settingsUseCustomTheme.isChecked = false
- restartApp(binding.root)
+ settingsAnime.setOnClickListener {
+ startActivity(Intent(this@SettingsActivity, SettingsAnimeActivity::class.java))
}
-
- settingsUseCustomTheme.isChecked =
- PrefManager.getVal(PrefName.UseCustomTheme)
- settingsUseCustomTheme.setOnCheckedChangeListener { _, isChecked ->
- PrefManager.setVal(PrefName.UseCustomTheme, isChecked)
- if (isChecked) {
- settingsUseMaterialYou.isChecked = false
- }
-
- restartApp(binding.root)
+ settingsManga.setOnClickListener {
+ startActivity(Intent(this@SettingsActivity, SettingsMangaActivity::class.java))
}
-
- settingsUseSourceTheme.isChecked =
- PrefManager.getVal(PrefName.UseSourceTheme)
- settingsUseSourceTheme.setOnCheckedChangeListener { _, isChecked ->
- PrefManager.setVal(PrefName.UseSourceTheme, isChecked)
- restartApp(binding.root)
+ settingsCommon.setOnClickListener {
+ startActivity(Intent(this@SettingsActivity, SettingsCommonActivity::class.java))
}
-
- settingsUseOLED.isChecked = PrefManager.getVal(PrefName.UseOLED)
- settingsUseOLED.setOnCheckedChangeListener { _, isChecked ->
- PrefManager.setVal(PrefName.UseOLED, isChecked)
- restartApp(binding.root)
+ settingsExtension.setOnClickListener {
+ startActivity(Intent(this@SettingsActivity, SettingsExtensionsActivity::class.java))
}
-
- val themeString: String = PrefManager.getVal(PrefName.Theme)
- val themeText = themeString.substring(0, 1) + themeString.substring(1).lowercase()
- themeSwitcher.setText(themeText)
-
- themeSwitcher.setAdapter(
- ArrayAdapter(
- this@SettingsActivity,
- R.layout.item_dropdown,
- ThemeManager.Companion.Theme.entries
- .map { it.theme.substring(0, 1) + it.theme.substring(1).lowercase() })
- )
-
- themeSwitcher.setOnItemClickListener { _, _, i, _ ->
- PrefManager.setVal(PrefName.Theme, ThemeManager.Companion.Theme.entries[i].theme)
- //ActivityHelper.shouldRefreshMainActivity = true
- themeSwitcher.clearFocus()
- restartApp(binding.root)
+ settingsNotification.setOnClickListener {
+ startActivity(Intent(this@SettingsActivity, SettingsNotificationActivity::class.java))
}
-
- customTheme.setOnClickListener {
- val originalColor: Int = PrefManager.getVal(PrefName.CustomThemeInt)
-
- class CustomColorDialog : SimpleColorDialog() { //idk where to put it
- override fun onPositiveButtonClick() {
- restartApp(binding.root)
- super.onPositiveButtonClick()
- }
- }
-
- val tag = "colorPicker"
- CustomColorDialog().title(R.string.custom_theme)
- .colorPreset(originalColor)
- .colors(this@SettingsActivity, SimpleColorDialog.MATERIAL_COLOR_PALLET)
- .allowCustom(true)
- .showOutline(0x46000000)
- .gridNumColumn(5)
- .choiceMode(SimpleColorDialog.SINGLE_CHOICE)
- .neg()
- .show(this@SettingsActivity, tag)
- }
-
- var previous: View = when (PrefManager.getVal(PrefName.DarkMode)) {
- 0 -> settingsUiAuto
- 1 -> settingsUiLight
- 2 -> settingsUiDark
- else -> settingsUiAuto
- }
- previous.alpha = 1f
- fun uiTheme(mode: Int, current: View) {
- previous.alpha = 0.33f
- previous = current
- current.alpha = 1f
- PrefManager.setVal(PrefName.DarkMode, mode)
- reloadActivity()
- }
-
- settingsUiAuto.setOnClickListener {
- uiTheme(0, it)
- }
-
- settingsUiLight.setOnClickListener {
- settingsUseOLED.isChecked = false
- uiTheme(1, it)
- }
-
- settingsUiDark.setOnClickListener {
- uiTheme(2, it)
+ settingsTheme.setOnClickListener {
+ startActivity(Intent(this@SettingsActivity, SettingsThemeActivity::class.java))
}
}
- val managers = arrayOf("Default", "1DM", "ADM")
- val downloadManagerDialog =
- AlertDialog.Builder(this, R.style.MyPopup).setTitle(R.string.download_manager)
- var downloadManager: Int = PrefManager.getVal(PrefName.DownloadManager)
-
- bindingAnime = ActivitySettingsAnimeBinding.bind(binding.root).apply {
- settingsPlayer.setOnClickListener {
- startActivity(Intent(this@SettingsActivity, PlayerSettingsActivity::class.java))
- }
-
- purgeAnimeDownloads.setOnClickListener {
- val dialog = AlertDialog.Builder(this@SettingsActivity, R.style.MyPopup)
- .setTitle(R.string.purge_anime_downloads)
- .setMessage(getString(R.string.purge_confirm, getString(R.string.anime)))
- .setPositiveButton(R.string.yes) { dialog, _ ->
- val downloadsManager = Injekt.get()
- downloadsManager.purgeDownloads(MediaType.ANIME)
- dialog.dismiss()
- }
- .setNegativeButton(R.string.no) { dialog, _ ->
- dialog.dismiss()
- }
- .create()
- dialog.window?.setDimAmount(0.8f)
- dialog.show()
- }
-
- settingsPreferDub.isChecked = PrefManager.getVal(PrefName.SettingsPreferDub)
- settingsPreferDub.setOnCheckedChangeListener { _, isChecked ->
- PrefManager.setVal(PrefName.SettingsPreferDub, isChecked)
- }
-
-
- settingsShowYt.isChecked = PrefManager.getVal(PrefName.ShowYtButton)
- settingsShowYt.setOnCheckedChangeListener { _, isChecked ->
- PrefManager.setVal(PrefName.ShowYtButton, isChecked)
- }
- settingsIncludeAnimeList.isChecked = PrefManager.getVal(PrefName.IncludeAnimeList)
- settingsIncludeAnimeList.setOnCheckedChangeListener { _, isChecked ->
- PrefManager.setVal(PrefName.IncludeAnimeList, isChecked)
- restartApp(binding.root)
- }
-
- var previousEp: View = when (PrefManager.getVal(PrefName.AnimeDefaultView)) {
- 0 -> settingsEpList
- 1 -> settingsEpGrid
- 2 -> settingsEpCompact
- else -> settingsEpList
- }
- previousEp.alpha = 1f
- fun uiEp(mode: Int, current: View) {
- previousEp.alpha = 0.33f
- previousEp = current
- current.alpha = 1f
- PrefManager.setVal(PrefName.AnimeDefaultView, mode)
- }
-
- settingsEpList.setOnClickListener {
- uiEp(0, it)
- }
-
- settingsEpGrid.setOnClickListener {
- uiEp(1, it)
- }
-
- settingsEpCompact.setOnClickListener {
- uiEp(2, it)
- }
- }
-
- bindingManga = ActivitySettingsMangaBinding.bind(binding.root).apply {
- purgeMangaDownloads.setOnClickListener {
- val dialog = AlertDialog.Builder(this@SettingsActivity, R.style.MyPopup)
- .setTitle(R.string.purge_manga_downloads)
- .setMessage(getString(R.string.purge_confirm, getString(R.string.manga)))
- .setPositiveButton(R.string.yes) { dialog, _ ->
- 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()
- }
-
- purgeNovelDownloads.setOnClickListener {
- val dialog = AlertDialog.Builder(this@SettingsActivity, R.style.MyPopup)
- .setTitle(R.string.purge_novel_downloads)
- .setMessage(getString(R.string.purge_confirm, getString(R.string.novels)))
- .setPositiveButton(R.string.yes) { dialog, _ ->
- 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()
- }
-
- settingsReader.setOnClickListener {
- startActivity(Intent(this@SettingsActivity, ReaderSettingsActivity::class.java))
- }
-
- var previousChp: View = when (PrefManager.getVal(PrefName.MangaDefaultView)) {
- 0 -> settingsChpList
- 1 -> settingsChpCompact
- else -> settingsChpList
- }
- previousChp.alpha = 1f
- fun uiChp(mode: Int, current: View) {
- previousChp.alpha = 0.33f
- previousChp = current
- current.alpha = 1f
- PrefManager.setVal(PrefName.MangaDefaultView, mode)
- }
-
- settingsChpList.setOnClickListener {
- uiChp(0, it)
- }
-
- settingsChpCompact.setOnClickListener {
- uiChp(1, it)
- }
-
- settingsIncludeMangaList.isChecked = PrefManager.getVal(PrefName.IncludeMangaList)
- settingsIncludeMangaList.setOnCheckedChangeListener { _, isChecked ->
- PrefManager.setVal(PrefName.IncludeMangaList, isChecked)
- restartApp(binding.root)
- }
- }
-
- bindingExtensions = ActivitySettingsExtensionsBinding.bind(binding.root).apply {
-
- fun setExtensionOutput(repoInventory: ViewGroup, type: MediaType) {
- repoInventory.removeAllViews()
- val prefName: PrefName? = when (type) {
- MediaType.ANIME -> { PrefName.AnimeExtensionRepos }
- MediaType.MANGA -> { PrefName.MangaExtensionRepos }
- else -> { null }
+ if (!BuildConfig.FLAVOR.contains("fdroid")) {
+ binding.settingsLogo.setOnLongClickListener {
+ lifecycleScope.launch(Dispatchers.IO) {
+ AppUpdater.check(this@SettingsActivity, true)
}
- prefName?.let { repoList ->
- PrefManager.getVal>(repoList).forEach { item ->
- val view = ItemRepositoryBinding.inflate(
- LayoutInflater.from(repoInventory.context), repoInventory, true
- )
- view.repositoryItem.text = item.removePrefix("https://raw.githubusercontent.com")
- view.repositoryItem.setOnClickListener {
- AlertDialog.Builder(this@SettingsActivity, R.style.MyPopup)
- .setTitle(R.string.rem_repository)
- .setMessage(item)
- .setPositiveButton(getString(R.string.ok)) { dialog, _ ->
- val repos = PrefManager.getVal>(repoList).minus(item)
- PrefManager.setVal(repoList, repos)
- setExtensionOutput(repoInventory, type)
- CoroutineScope(Dispatchers.IO).launch {
- when (type) {
- MediaType.ANIME -> { animeExtensionManager.findAvailableExtensions() }
- MediaType.MANGA -> { mangaExtensionManager.findAvailableExtensions() }
- else -> { }
- }
- }
- dialog.dismiss()
- }
- .setNegativeButton(getString(R.string.cancel)) { dialog, _ ->
- dialog.dismiss()
- }
- .create()
- .show()
- }
- view.repositoryItem.setOnLongClickListener {
- it.performHapticFeedback(HapticFeedbackConstants.LONG_PRESS)
- copyToClipboard(item, true)
- true
- }
- }
- repoInventory.isVisible = repoInventory.childCount > 0
- }
- }
-
- fun processUserInput(input: String, mediaType: MediaType) {
- val entry = if (input.endsWith("/") || input.endsWith("index.min.json"))
- input.substring(0, input.lastIndexOf("/")) else input
- if (mediaType == MediaType.ANIME) {
- val anime =
- PrefManager.getVal>(PrefName.AnimeExtensionRepos).plus(entry)
- PrefManager.setVal(PrefName.AnimeExtensionRepos, anime)
- CoroutineScope(Dispatchers.IO).launch {
- animeExtensionManager.findAvailableExtensions()
- }
- setExtensionOutput(animeRepoInventory, MediaType.ANIME)
- }
- if (mediaType == MediaType.MANGA) {
- val manga =
- PrefManager.getVal>(PrefName.MangaExtensionRepos).plus(entry)
- PrefManager.setVal(PrefName.MangaExtensionRepos, manga)
- CoroutineScope(Dispatchers.IO).launch {
- mangaExtensionManager.findAvailableExtensions()
- }
- setExtensionOutput(mangaRepoInventory, MediaType.MANGA)
- }
- }
-
- fun processEditorAction(dialog: AlertDialog, editText: EditText, mediaType: MediaType) {
- editText.setOnEditorActionListener { textView, action, keyEvent ->
- if (action == EditorInfo.IME_ACTION_SEARCH || action == EditorInfo.IME_ACTION_DONE ||
- (keyEvent?.action == KeyEvent.ACTION_UP
- && keyEvent.keyCode == KeyEvent.KEYCODE_ENTER)
- ) {
- return@setOnEditorActionListener if (textView.text.isNullOrBlank()) {
- false
- } else {
- processUserInput(textView.text.toString(), mediaType)
- dialog.dismiss()
- true
- }
- }
- false
- }
- }
-
- setExtensionOutput(animeRepoInventory, MediaType.ANIME)
- setExtensionOutput(mangaRepoInventory, MediaType.MANGA)
- animeAddRepository.setOnClickListener {
- val dialogView = layoutInflater.inflate(R.layout.dialog_user_agent, null)
- val editText =
- dialogView.findViewById(R.id.userAgentTextBox).apply {
- hint = getString(R.string.anime_add_repository)
- }
- val alertDialog = AlertDialog.Builder(this@SettingsActivity, R.style.MyPopup)
- .setTitle(R.string.anime_add_repository)
- .setView(dialogView)
- .setPositiveButton(getString(R.string.ok)) { dialog, _ ->
- if (!editText.text.isNullOrBlank())
- processUserInput(editText.text.toString(), MediaType.ANIME)
- dialog.dismiss()
- }
- .setNegativeButton(getString(R.string.cancel)) { dialog, _ ->
- dialog.dismiss()
- }
- .create()
-
- processEditorAction(alertDialog, editText, MediaType.ANIME)
- alertDialog.show()
- alertDialog.window?.setDimAmount(0.8f)
- }
-
- mangaAddRepository.setOnClickListener {
- val dialogView = layoutInflater.inflate(R.layout.dialog_user_agent, null)
- val editText =
- dialogView.findViewById(R.id.userAgentTextBox).apply {
- hint = getString(R.string.manga_add_repository)
- }
- val alertDialog = AlertDialog.Builder(this@SettingsActivity, R.style.MyPopup)
- .setTitle(R.string.manga_add_repository)
- .setView(dialogView)
- .setPositiveButton(getString(R.string.ok)) { dialog, _ ->
- if (!editText.text.isNullOrBlank())
- processUserInput(editText.text.toString(), MediaType.MANGA)
- dialog.dismiss()
- }
- .setNegativeButton(getString(R.string.cancel)) { dialog, _ ->
- dialog.dismiss()
- }
- .create()
-
- processEditorAction(alertDialog, editText, MediaType.MANGA)
- alertDialog.show()
- alertDialog.window?.setDimAmount(0.8f)
- }
-
- settingsForceLegacyInstall.isChecked =
- extensionInstaller.get() == BasePreferences.ExtensionInstaller.LEGACY
- settingsForceLegacyInstall.setOnCheckedChangeListener { _, isChecked ->
- if (isChecked) {
- extensionInstaller.set(BasePreferences.ExtensionInstaller.LEGACY)
- } else {
- extensionInstaller.set(BasePreferences.ExtensionInstaller.PACKAGEINSTALLER)
- }
- }
-
- skipExtensionIcons.isChecked =
- PrefManager.getVal(PrefName.SkipExtensionIcons)
- skipExtensionIcons.setOnCheckedChangeListener { _, isChecked ->
- PrefManager.getVal(PrefName.SkipExtensionIcons, isChecked)
- }
- NSFWExtension.isChecked = PrefManager.getVal(PrefName.NSFWExtension)
- NSFWExtension.setOnCheckedChangeListener { _, isChecked ->
- PrefManager.setVal(PrefName.NSFWExtension, isChecked)
-
- }
-
- userAgent.setOnClickListener {
- val dialogView = layoutInflater.inflate(R.layout.dialog_user_agent, null)
- val editText = dialogView.findViewById(R.id.userAgentTextBox)
- editText.setText(PrefManager.getVal(PrefName.DefaultUserAgent))
- val alertDialog = AlertDialog.Builder(this@SettingsActivity, R.style.MyPopup)
- .setTitle(R.string.user_agent)
- .setView(dialogView)
- .setPositiveButton(getString(R.string.ok)) { dialog, _ ->
- PrefManager.setVal(PrefName.DefaultUserAgent, editText.text.toString())
- dialog.dismiss()
- }
- .setNeutralButton(getString(R.string.reset)) { dialog, _ ->
- PrefManager.removeVal(PrefName.DefaultUserAgent)
- editText.setText("")
- dialog.dismiss()
- }
- .setNegativeButton(getString(R.string.cancel)) { dialog, _ ->
- dialog.dismiss()
- }
- .create()
-
- alertDialog.show()
- alertDialog.window?.setDimAmount(0.8f)
- }
- }
-
-
- val exDns = listOf(
- "None",
- "Cloudflare",
- "Google",
- "AdGuard",
- "Quad9",
- "AliDNS",
- "DNSPod",
- "360",
- "Quad101",
- "Mullvad",
- "Controld",
- "Njalla",
- "Shecan",
- "Libre"
- )
-
- bindingCommon = ActivitySettingsCommonBinding.bind(binding.root).apply {
- settingsDownloadManager.setOnClickListener {
- val dialog = downloadManagerDialog.setSingleChoiceItems(
- managers,
- downloadManager
- ) { dialog, count ->
- downloadManager = count
- PrefManager.setVal(PrefName.DownloadManager, downloadManager)
- dialog.dismiss()
- }.show()
- dialog.window?.setDimAmount(0.8f)
- }
-
- importExportSettings.setOnClickListener {
- downloadsPermission(this@SettingsActivity)
- val selectedArray = mutableListOf(false)
- val filteredLocations = Location.entries.filter { it.exportable }
- selectedArray.addAll(List(filteredLocations.size - 1) { false })
- val dialog = AlertDialog.Builder(this@SettingsActivity, R.style.MyPopup)
- .setTitle(R.string.backup_restore)
- .setMultiChoiceItems(
- filteredLocations.map { it.name }.toTypedArray(),
- selectedArray.toBooleanArray()
- ) { _, which, isChecked ->
- selectedArray[which] = isChecked
- }
- .setPositiveButton(R.string.button_restore) { dialog, _ ->
- openDocumentLauncher.launch(arrayOf("*/*"))
- dialog.dismiss()
- }
- .setNegativeButton(R.string.button_backup) { dialog, _ ->
- if (!selectedArray.contains(true)) {
- toast(R.string.no_location_selected)
- return@setNegativeButton
- }
- dialog.dismiss()
- val selected =
- filteredLocations.filterIndexed { index, _ -> selectedArray[index] }
- if (selected.contains(Location.Protected)) {
- passwordAlertDialog(true) { password ->
- if (password != null) {
- savePrefsToDownloads(
- "DantotsuSettings",
- PrefManager.exportAllPrefs(selected),
- this@SettingsActivity,
- password
- )
- } else {
- toast(R.string.password_cannot_be_empty)
- }
- }
- } else {
- savePrefsToDownloads(
- "DantotsuSettings",
- PrefManager.exportAllPrefs(selected),
- this@SettingsActivity,
- null
- )
- }
- }
- .setNeutralButton(R.string.cancel) { dialog, _ ->
- dialog.dismiss()
- }
- .create()
- dialog.window?.setDimAmount(0.8f)
- dialog.show()
- }
-
- settingsExtensionDns.setText(exDns[PrefManager.getVal(PrefName.DohProvider)])
- settingsExtensionDns.setAdapter(
- ArrayAdapter(
- this@SettingsActivity,
- R.layout.item_dropdown,
- exDns
- )
- )
- settingsExtensionDns.setOnItemClickListener { _, _, i, _ ->
- PrefManager.setVal(PrefName.DohProvider, i)
- settingsExtensionDns.clearFocus()
- restartApp(binding.root)
- }
-
- settingsContinueMedia.isChecked = PrefManager.getVal(PrefName.ContinueMedia)
- settingsContinueMedia.setOnCheckedChangeListener { _, isChecked ->
- PrefManager.setVal(PrefName.ContinueMedia, isChecked)
- }
-
- settingsSearchSources.isChecked = PrefManager.getVal(PrefName.SearchSources)
- settingsSearchSources.setOnCheckedChangeListener { _, isChecked ->
- PrefManager.setVal(PrefName.SearchSources, isChecked)
- }
-
- settingsRecentlyListOnly.isChecked = PrefManager.getVal(PrefName.RecentlyListOnly)
- settingsRecentlyListOnly.setOnCheckedChangeListener { _, isChecked ->
- PrefManager.setVal(PrefName.RecentlyListOnly, isChecked)
- }
- settingsAdultAnimeOnly.isChecked = PrefManager.getVal(PrefName.AdultOnly)
- settingsAdultAnimeOnly.setOnCheckedChangeListener { _, isChecked ->
- PrefManager.setVal(PrefName.AdultOnly, isChecked)
- restartApp(binding.root)
- }
-
- settingsDownloadLocation.setOnClickListener {
- val dialog = AlertDialog.Builder(this@SettingsActivity, R.style.MyPopup)
- .setTitle(R.string.change_download_location)
- .setMessage(R.string.download_location_msg)
- .setPositiveButton(R.string.ok) { dialog, _ ->
- val oldUri = PrefManager.getVal(PrefName.DownloadsDir)
- launcher.registerForCallback { success ->
- if (success) {
- toast(getString(R.string.please_wait))
- val newUri = PrefManager.getVal(PrefName.DownloadsDir)
- GlobalScope.launch(Dispatchers.IO) {
- Injekt.get().moveDownloadsDir(
- this@SettingsActivity,
- Uri.parse(oldUri), Uri.parse(newUri)
- ) { finished, message ->
- if (finished) {
- toast(getString(R.string.success))
- } else {
- toast(message)
- }
- }
- }
- } else {
- toast(getString(R.string.error))
- }
- }
- launcher.launch()
- dialog.dismiss()
- }
- .setNeutralButton(R.string.cancel) { dialog, _ ->
- dialog.dismiss()
- }
- .create()
- dialog.window?.setDimAmount(0.8f)
- dialog.show()
- }
-
- var previousStart: View = when (PrefManager.getVal(PrefName.DefaultStartUpTab)) {
- 0 -> uiSettingsAnime
- 1 -> uiSettingsHome
- 2 -> uiSettingsManga
- else -> uiSettingsHome
- }
- previousStart.alpha = 1f
- fun uiDefault(mode: Int, current: View) {
- previousStart.alpha = 0.33f
- previousStart = current
- current.alpha = 1f
- PrefManager.setVal(PrefName.DefaultStartUpTab, mode)
- initActivity(this@SettingsActivity)
- }
-
- uiSettingsAnime.setOnClickListener {
- uiDefault(0, it)
- }
-
- uiSettingsHome.setOnClickListener {
- uiDefault(1, it)
- }
-
- uiSettingsManga.setOnClickListener {
- uiDefault(2, it)
- }
-
- settingsUi.setOnClickListener {
- startActivity(
- Intent(
- this@SettingsActivity,
- UserInterfaceSettingsActivity::class.java
- )
- )
- }
- }
-
- bindingNotifications = ActivitySettingsNotificationsBinding.bind(binding.root).apply {
- var curTime = PrefManager.getVal(PrefName.SubscriptionNotificationInterval)
- val timeNames = checkIntervals.map {
- val mins = it % 60
- val hours = it / 60
- if (it > 0) "${if (hours > 0) "$hours hrs " else ""}${if (mins > 0) "$mins mins" else ""}"
- else getString(R.string.do_not_update)
- }.toTypedArray()
-
- settingsSubscriptionsTime.text =
- getString(R.string.subscriptions_checking_time_s, timeNames[curTime])
- val speedDialog = AlertDialog.Builder(this@SettingsActivity, R.style.MyPopup)
- .setTitle(R.string.subscriptions_checking_time)
- settingsSubscriptionsTime.setOnClickListener {
- val dialog = speedDialog.setSingleChoiceItems(timeNames, curTime) { dialog, i ->
- curTime = i
- settingsSubscriptionsTime.text =
- getString(R.string.subscriptions_checking_time_s, timeNames[i])
- PrefManager.setVal(PrefName.SubscriptionNotificationInterval, curTime)
- dialog.dismiss()
- TaskScheduler.create(
- this@SettingsActivity,
- PrefManager.getVal(PrefName.UseAlarmManager)
- ).scheduleAllTasks(this@SettingsActivity)
- }.show()
- dialog.window?.setDimAmount(0.8f)
- }
-
- settingsSubscriptionsTime.setOnLongClickListener {
- TaskScheduler.create(
- this@SettingsActivity,
- PrefManager.getVal(PrefName.UseAlarmManager)
- ).scheduleAllTasks(this@SettingsActivity)
true
}
-
- val aTimeNames = AnilistNotificationWorker.checkIntervals.map { it.toInt() }
- val aItems = aTimeNames.map {
- val mins = it % 60
- val hours = it / 60
- if (it > 0) "${if (hours > 0) "$hours hrs " else ""}${if (mins > 0) "$mins mins" else ""}"
- else getString(R.string.do_not_update)
- }
- settingsAnilistSubscriptionsTime.text =
- getString(
- R.string.anilist_notifications_checking_time,
- aItems[PrefManager.getVal(PrefName.AnilistNotificationInterval)]
- )
- settingsAnilistSubscriptionsTime.setOnClickListener {
-
- val selected = PrefManager.getVal(PrefName.AnilistNotificationInterval)
- val dialog = AlertDialog.Builder(this@SettingsActivity, R.style.MyPopup)
- .setTitle(R.string.subscriptions_checking_time)
- .setSingleChoiceItems(aItems.toTypedArray(), selected) { dialog, i ->
- PrefManager.setVal(PrefName.AnilistNotificationInterval, i)
- settingsAnilistSubscriptionsTime.text =
- getString(R.string.anilist_notifications_checking_time, aItems[i])
- dialog.dismiss()
- TaskScheduler.create(
- this@SettingsActivity,
- PrefManager.getVal(PrefName.UseAlarmManager)
- ).scheduleAllTasks(this@SettingsActivity)
- }
- .create()
- dialog.window?.setDimAmount(0.8f)
- dialog.show()
- }
-
- settingsAnilistNotifications.setOnClickListener {
- val types = NotificationType.entries.map { it.name }
- val filteredTypes =
- PrefManager.getVal>(PrefName.AnilistFilteredTypes).toMutableSet()
- val selected = types.map { filteredTypes.contains(it) }.toBooleanArray()
- val dialog = AlertDialog.Builder(this@SettingsActivity, R.style.MyPopup)
- .setTitle(R.string.anilist_notification_filters)
- .setMultiChoiceItems(types.toTypedArray(), selected) { _, which, isChecked ->
- val type = types[which]
- if (isChecked) {
- filteredTypes.add(type)
- } else {
- filteredTypes.remove(type)
- }
- PrefManager.setVal(PrefName.AnilistFilteredTypes, filteredTypes)
- }
- .create()
- dialog.window?.setDimAmount(0.8f)
- dialog.show()
- }
-
- val cTimeNames = CommentNotificationWorker.checkIntervals.map { it.toInt() }
- val cItems = cTimeNames.map {
- val mins = it % 60
- val hours = it / 60
- if (it > 0) "${if (hours > 0) "$hours hrs " else ""}${if (mins > 0) "$mins mins" else ""}"
- else getString(R.string.do_not_update)
- }
-
- settingsCommentSubscriptionsTime.text =
- getString(
- R.string.comment_notification_checking_time,
- cItems[PrefManager.getVal(PrefName.CommentNotificationInterval)]
- )
- settingsCommentSubscriptionsTime.setOnClickListener {
- val selected = PrefManager.getVal(PrefName.CommentNotificationInterval)
- val dialog = AlertDialog.Builder(this@SettingsActivity, R.style.MyPopup)
- .setTitle(R.string.subscriptions_checking_time)
- .setSingleChoiceItems(cItems.toTypedArray(), selected) { dialog, i ->
- PrefManager.setVal(PrefName.CommentNotificationInterval, i)
- settingsCommentSubscriptionsTime.text =
- getString(R.string.comment_notification_checking_time, cItems[i])
- dialog.dismiss()
- TaskScheduler.create(
- this@SettingsActivity,
- PrefManager.getVal(PrefName.UseAlarmManager)
- ).scheduleAllTasks(this@SettingsActivity)
- }
- .create()
- dialog.window?.setDimAmount(0.8f)
- dialog.show()
- }
-
- settingsNotificationsCheckingSubscriptions.isChecked =
- PrefManager.getVal(PrefName.SubscriptionCheckingNotifications)
- settingsNotificationsCheckingSubscriptions.setOnCheckedChangeListener { _, isChecked ->
- PrefManager.setVal(PrefName.SubscriptionCheckingNotifications, isChecked)
- }
-
- settingsNotificationsCheckingSubscriptions.setOnLongClickListener {
- openSettings(this@SettingsActivity, null)
- }
-
- settingsNotificationsUseAlarmManager.isChecked =
- PrefManager.getVal(PrefName.UseAlarmManager)
-
- settingsNotificationsUseAlarmManager.setOnCheckedChangeListener { _, isChecked ->
- if (isChecked) {
- val alertDialog = AlertDialog.Builder(this@SettingsActivity, R.style.MyPopup)
- .setTitle(R.string.use_alarm_manager)
- .setMessage(R.string.use_alarm_manager_confirm)
- .setPositiveButton(R.string.use) { dialog, _ ->
- PrefManager.setVal(PrefName.UseAlarmManager, true)
- if (SDK_INT >= Build.VERSION_CODES.S) {
- if (!(getSystemService(Context.ALARM_SERVICE) as AlarmManager).canScheduleExactAlarms()) {
- val intent =
- Intent("android.settings.REQUEST_SCHEDULE_EXACT_ALARM")
- startActivity(intent)
- settingsNotificationsCheckingSubscriptions.isChecked = true
- }
- }
- dialog.dismiss()
- }
- .setNegativeButton(R.string.cancel) { dialog, _ ->
- settingsNotificationsCheckingSubscriptions.isChecked = false
- PrefManager.setVal(PrefName.UseAlarmManager, false)
- dialog.dismiss()
- }
- .create()
- alertDialog.window?.setDimAmount(0.8f)
- alertDialog.show()
- } else {
- PrefManager.setVal(PrefName.UseAlarmManager, false)
- TaskScheduler.create(this@SettingsActivity, true).cancelAllTasks()
- TaskScheduler.create(this@SettingsActivity, false)
- .scheduleAllTasks(this@SettingsActivity)
- }
- }
- }
-
- bindingAbout = ActivitySettingsAboutBinding.bind(binding.root).apply {
- settingsDev.setOnClickListener {
- DevelopersDialogFragment().show(supportFragmentManager, "dialog")
- }
- settingsForks.setOnClickListener {
- ForksDialogFragment().show(supportFragmentManager, "dialog")
- }
- settingsDisclaimer.setOnClickListener {
- val title = getString(R.string.disclaimer)
- val text = TextView(this@SettingsActivity)
- text.setText(R.string.full_disclaimer)
-
- CustomBottomDialog.newInstance().apply {
- setTitleText(title)
- addView(text)
- setNegativeButton(currContext()!!.getString(R.string.close)) {
- dismiss()
- }
- show(supportFragmentManager, "dialog")
- }
- }
-
- settingsFAQ.setOnClickListener {
- startActivity(Intent(this@SettingsActivity, FAQActivity::class.java))
- }
-
- if (!BuildConfig.FLAVOR.contains("fdroid")) {
- binding.settingsLogo.setOnLongClickListener {
- lifecycleScope.launch(Dispatchers.IO) {
- AppUpdater.check(this@SettingsActivity, true)
- }
- true
- }
-
- settingsCheckUpdate.isChecked = PrefManager.getVal(PrefName.CheckUpdate)
- settingsCheckUpdate.setOnCheckedChangeListener { _, isChecked ->
- PrefManager.setVal(PrefName.CheckUpdate, isChecked)
- if (!isChecked) {
- snackString(getString(R.string.long_click_to_check_update))
- }
- }
-
- settingsCheckUpdate.setOnLongClickListener {
- lifecycleScope.launch(Dispatchers.IO) {
- AppUpdater.check(this@SettingsActivity, true)
- }
- true
- }
-
- settingsShareUsername.isChecked = PrefManager.getVal(PrefName.SharedUserID)
- settingsShareUsername.setOnCheckedChangeListener { _, isChecked ->
- PrefManager.setVal(PrefName.SharedUserID, isChecked)
- }
-
- } else {
- settingsCheckUpdate.visibility = View.GONE
- settingsShareUsername.visibility = View.GONE
- settingsCheckUpdate.isEnabled = false
- settingsShareUsername.isEnabled = false
- settingsCheckUpdate.isChecked = false
- settingsShareUsername.isChecked = false
- }
-
- settingsLogToFile.isChecked = PrefManager.getVal(PrefName.LogToFile)
- settingsLogToFile.setOnCheckedChangeListener { _, isChecked ->
- PrefManager.setVal(PrefName.LogToFile, isChecked)
- restartApp(binding.root)
- }
-
- settingsShareLog.setOnClickListener {
- Logger.shareLog(this@SettingsActivity)
- }
}
binding.settingBuyMeCoffee.setOnClickListener {
@@ -1284,60 +239,6 @@ class SettingsActivity : AppCompatActivity(), SimpleDialog.OnDialogResultListene
return true
}
- private fun passwordAlertDialog(isExporting: Boolean, callback: (CharArray?) -> Unit) {
- val password = CharArray(16).apply { fill('0') }
-
- // Inflate the dialog layout
- val dialogView = LayoutInflater.from(this).inflate(R.layout.dialog_user_agent, null)
- val box = dialogView.findViewById(R.id.userAgentTextBox)
- box?.hint = getString(R.string.password)
- box?.setSingleLine()
-
- val dialog = AlertDialog.Builder(this, R.style.MyPopup)
- .setTitle(getString(R.string.enter_password))
- .setView(dialogView)
- .setPositiveButton(R.string.ok, null)
- .setNegativeButton(R.string.cancel) { dialog, _ ->
- password.fill('0')
- dialog.dismiss()
- callback(null)
- }
- .create()
-
- fun handleOkAction() {
- val editText = dialog.findViewById(R.id.userAgentTextBox)
- if (editText?.text?.isNotBlank() == true) {
- editText.text?.toString()?.trim()?.toCharArray(password)
- dialog.dismiss()
- callback(password)
- } else {
- toast(getString(R.string.password_cannot_be_empty))
- }
- }
- box?.setOnEditorActionListener { _, actionId, _ ->
- if (actionId == EditorInfo.IME_ACTION_DONE) {
- handleOkAction()
- true
- } else {
- false
- }
- }
- val subtitleTextView = dialogView.findViewById(R.id.subtitle)
- subtitleTextView?.visibility = View.VISIBLE
- if (!isExporting)
- subtitleTextView?.text = getString(R.string.enter_password_to_decrypt_file)
-
-
- dialog.window?.setDimAmount(0.8f)
- dialog.show()
-
- // Override the positive button here
- dialog.getButton(AlertDialog.BUTTON_POSITIVE).setOnClickListener {
- handleOkAction()
- }
-
- }
-
companion object {
fun getDeviceInfo(): String {
diff --git a/app/src/main/java/ani/dantotsu/settings/SettingsAnimeActivity.kt b/app/src/main/java/ani/dantotsu/settings/SettingsAnimeActivity.kt
new file mode 100644
index 00000000..5c517843
--- /dev/null
+++ b/app/src/main/java/ani/dantotsu/settings/SettingsAnimeActivity.kt
@@ -0,0 +1,104 @@
+package ani.dantotsu.settings
+
+import android.app.AlertDialog
+import android.content.Intent
+import android.os.Bundle
+import android.view.View
+import android.view.ViewGroup
+import androidx.appcompat.app.AppCompatActivity
+import androidx.core.view.updateLayoutParams
+import ani.dantotsu.R
+import ani.dantotsu.databinding.ActivitySettingsAnimeBinding
+import ani.dantotsu.databinding.ActivitySettingsMangaBinding
+import ani.dantotsu.download.DownloadsManager
+import ani.dantotsu.initActivity
+import ani.dantotsu.media.MediaType
+import ani.dantotsu.navBarHeight
+import ani.dantotsu.restartApp
+import ani.dantotsu.settings.saving.PrefManager
+import ani.dantotsu.settings.saving.PrefName
+import ani.dantotsu.statusBarHeight
+import ani.dantotsu.themes.ThemeManager
+import uy.kohesive.injekt.Injekt
+import uy.kohesive.injekt.api.get
+
+class SettingsAnimeActivity: AppCompatActivity(){
+ private lateinit var binding: ActivitySettingsAnimeBinding
+ override fun onCreate(savedInstanceState: Bundle?) {
+ super.onCreate(savedInstanceState)
+ ThemeManager(this).applyTheme()
+ initActivity(this)
+ val context = this
+ binding = ActivitySettingsAnimeBinding.inflate(layoutInflater)
+ setContentView(binding.root)
+ binding.apply {
+
+ settingsAnimeLayout.updateLayoutParams {
+ topMargin = statusBarHeight
+ bottomMargin = navBarHeight
+ }
+ settingsPlayer.setOnClickListener {
+ startActivity(Intent(context, PlayerSettingsActivity::class.java))
+ }
+ settingsAnimeTitle.setOnClickListener {
+ onBackPressedDispatcher.onBackPressed()
+ }
+ purgeAnimeDownloads.setOnClickListener {
+ val dialog = AlertDialog.Builder(context, R.style.MyPopup)
+ .setTitle(R.string.purge_anime_downloads)
+ .setMessage(getString(R.string.purge_confirm, getString(R.string.anime)))
+ .setPositiveButton(R.string.yes) { dialog, _ ->
+ val downloadsManager = Injekt.get()
+ downloadsManager.purgeDownloads(MediaType.ANIME)
+ dialog.dismiss()
+ }.setNegativeButton(R.string.no) { dialog, _ ->
+ dialog.dismiss()
+ }.create()
+ dialog.window?.setDimAmount(0.8f)
+ dialog.show()
+ }
+
+ settingsPreferDub.isChecked = PrefManager.getVal(PrefName.SettingsPreferDub)
+ settingsPreferDub.setOnCheckedChangeListener { _, isChecked ->
+ PrefManager.setVal(PrefName.SettingsPreferDub, isChecked)
+ }
+
+
+ settingsShowYt.isChecked = PrefManager.getVal(PrefName.ShowYtButton)
+ settingsShowYt.setOnCheckedChangeListener { _, isChecked ->
+ PrefManager.setVal(PrefName.ShowYtButton, isChecked)
+ }
+ settingsIncludeAnimeList.isChecked = PrefManager.getVal(PrefName.IncludeAnimeList)
+ settingsIncludeAnimeList.setOnCheckedChangeListener { _, isChecked ->
+ PrefManager.setVal(PrefName.IncludeAnimeList, isChecked)
+ restartApp(binding.root)
+ }
+
+ var previousEp: View = when (PrefManager.getVal(PrefName.AnimeDefaultView)) {
+ 0 -> settingsEpList
+ 1 -> settingsEpGrid
+ 2 -> settingsEpCompact
+ else -> settingsEpList
+ }
+ previousEp.alpha = 1f
+ fun uiEp(mode: Int, current: View) {
+ previousEp.alpha = 0.33f
+ previousEp = current
+ current.alpha = 1f
+ PrefManager.setVal(PrefName.AnimeDefaultView, mode)
+ }
+
+ settingsEpList.setOnClickListener {
+ uiEp(0, it)
+ }
+
+ settingsEpGrid.setOnClickListener {
+ uiEp(1, it)
+ }
+
+ settingsEpCompact.setOnClickListener {
+ uiEp(2, it)
+ }
+ }
+ }
+}
\ No newline at end of file
diff --git a/app/src/main/java/ani/dantotsu/settings/SettingsCommonActivity.kt b/app/src/main/java/ani/dantotsu/settings/SettingsCommonActivity.kt
new file mode 100644
index 00000000..d75ed217
--- /dev/null
+++ b/app/src/main/java/ani/dantotsu/settings/SettingsCommonActivity.kt
@@ -0,0 +1,334 @@
+package ani.dantotsu.settings
+
+import android.app.AlertDialog
+import android.content.Intent
+import android.net.Uri
+import android.os.Bundle
+import android.view.LayoutInflater
+import android.view.View
+import android.view.ViewGroup
+import android.view.inputmethod.EditorInfo
+import android.widget.ArrayAdapter
+import android.widget.TextView
+import androidx.activity.result.contract.ActivityResultContracts
+import androidx.appcompat.app.AppCompatActivity
+import androidx.core.view.updateLayoutParams
+import androidx.documentfile.provider.DocumentFile
+import ani.dantotsu.R
+import ani.dantotsu.databinding.ActivitySettingsCommonBinding
+import ani.dantotsu.download.DownloadsManager
+import ani.dantotsu.initActivity
+import ani.dantotsu.navBarHeight
+import ani.dantotsu.restartApp
+import ani.dantotsu.savePrefsToDownloads
+import ani.dantotsu.settings.saving.PrefManager
+import ani.dantotsu.settings.saving.PrefName
+import ani.dantotsu.settings.saving.internal.Location
+import ani.dantotsu.settings.saving.internal.PreferenceKeystore
+import ani.dantotsu.settings.saving.internal.PreferencePackager
+import ani.dantotsu.statusBarHeight
+import ani.dantotsu.themes.ThemeManager
+import ani.dantotsu.toast
+import ani.dantotsu.util.LauncherWrapper
+import ani.dantotsu.util.StoragePermissions
+import com.google.android.material.textfield.TextInputEditText
+import kotlinx.coroutines.Dispatchers
+import kotlinx.coroutines.GlobalScope
+import kotlinx.coroutines.launch
+import uy.kohesive.injekt.Injekt
+import uy.kohesive.injekt.api.get
+
+class SettingsCommonActivity: AppCompatActivity(){
+ private lateinit var binding: ActivitySettingsCommonBinding
+ private lateinit var launcher: LauncherWrapper
+ override fun onCreate(savedInstanceState: Bundle?) {
+ super.onCreate(savedInstanceState)
+ ThemeManager(this).applyTheme()
+ initActivity(this)
+ val context = this
+ binding = ActivitySettingsCommonBinding.inflate(layoutInflater)
+ setContentView(binding.root)
+ val openDocumentLauncher =
+ registerForActivityResult(ActivityResultContracts.OpenDocument()) { uri ->
+ if (uri != null) {
+ try {
+ val jsonString = contentResolver.openInputStream(uri)?.readBytes()
+ ?: throw Exception("Error reading file")
+ val name = DocumentFile.fromSingleUri(this, uri)?.name ?: "settings"
+ //.sani is encrypted, .ani is not
+ if (name.endsWith(".sani")) {
+ passwordAlertDialog(false) { password ->
+ if (password != null) {
+ val salt = jsonString.copyOfRange(0, 16)
+ val encrypted = jsonString.copyOfRange(16, jsonString.size)
+ val decryptedJson = try {
+ PreferenceKeystore.decryptWithPassword(
+ password, encrypted, salt
+ )
+ } catch (e: Exception) {
+ toast(getString(R.string.incorrect_password))
+ return@passwordAlertDialog
+ }
+ if (PreferencePackager.unpack(decryptedJson)) restartApp(binding.root)
+ } else {
+ toast(getString(R.string.password_cannot_be_empty))
+ }
+ }
+ } else if (name.endsWith(".ani")) {
+ val decryptedJson = jsonString.toString(Charsets.UTF_8)
+ if (PreferencePackager.unpack(decryptedJson)) restartApp(binding.root)
+ } else {
+ toast(getString(R.string.unknown_file_type))
+ }
+ } catch (e: Exception) {
+ e.printStackTrace()
+ toast(getString(R.string.error_importing_settings))
+ }
+ }
+ }
+ val contract = ActivityResultContracts.OpenDocumentTree()
+ launcher = LauncherWrapper(this, contract)
+ val managers = arrayOf("Default", "1DM", "ADM")
+ val downloadManagerDialog =
+ AlertDialog.Builder(this, R.style.MyPopup).setTitle(R.string.download_manager)
+ var downloadManager: Int = PrefManager.getVal(PrefName.DownloadManager)
+ binding.apply {
+
+ settingsCommonLayout.updateLayoutParams {
+ topMargin = statusBarHeight
+ bottomMargin = navBarHeight
+ }
+ settingsCommonTitle.setOnClickListener {
+ onBackPressedDispatcher.onBackPressed()
+ }
+ settingsDownloadManager.setOnClickListener {
+ val dialog = downloadManagerDialog.setSingleChoiceItems(
+ managers, downloadManager
+ ) { dialog, count ->
+ downloadManager = count
+ PrefManager.setVal(PrefName.DownloadManager, downloadManager)
+ dialog.dismiss()
+ }.show()
+ dialog.window?.setDimAmount(0.8f)
+ }
+
+ importExportSettings.setOnClickListener {
+ StoragePermissions.downloadsPermission(context)
+ val selectedArray = mutableListOf(false)
+ val filteredLocations = Location.entries.filter { it.exportable }
+ selectedArray.addAll(List(filteredLocations.size - 1) { false })
+ val dialog = AlertDialog.Builder(context, R.style.MyPopup)
+ .setTitle(R.string.backup_restore).setMultiChoiceItems(
+ filteredLocations.map { it.name }.toTypedArray(),
+ selectedArray.toBooleanArray()
+ ) { _, which, isChecked ->
+ selectedArray[which] = isChecked
+ }.setPositiveButton(R.string.button_restore) { dialog, _ ->
+ openDocumentLauncher.launch(arrayOf("*/*"))
+ dialog.dismiss()
+ }.setNegativeButton(R.string.button_backup) { dialog, _ ->
+ if (!selectedArray.contains(true)) {
+ toast(R.string.no_location_selected)
+ return@setNegativeButton
+ }
+ dialog.dismiss()
+ val selected =
+ filteredLocations.filterIndexed { index, _ -> selectedArray[index] }
+ if (selected.contains(Location.Protected)) {
+ passwordAlertDialog(true) { password ->
+ if (password != null) {
+ savePrefsToDownloads(
+ "DantotsuSettings",
+ PrefManager.exportAllPrefs(selected),
+ context,
+ password
+ )
+ } else {
+ toast(R.string.password_cannot_be_empty)
+ }
+ }
+ } else {
+ savePrefsToDownloads(
+ "DantotsuSettings",
+ PrefManager.exportAllPrefs(selected),
+ context,
+ null
+ )
+ }
+ }.setNeutralButton(R.string.cancel) { dialog, _ ->
+ dialog.dismiss()
+ }.create()
+ dialog.window?.setDimAmount(0.8f)
+ dialog.show()
+ }
+ val exDns = listOf(
+ "None",
+ "Cloudflare",
+ "Google",
+ "AdGuard",
+ "Quad9",
+ "AliDNS",
+ "DNSPod",
+ "360",
+ "Quad101",
+ "Mullvad",
+ "Controld",
+ "Njalla",
+ "Shecan",
+ "Libre"
+ )
+ settingsExtensionDns.setText(exDns[PrefManager.getVal(PrefName.DohProvider)])
+ settingsExtensionDns.setAdapter(
+ ArrayAdapter(
+ context, R.layout.item_dropdown, exDns
+ )
+ )
+ settingsExtensionDns.setOnItemClickListener { _, _, i, _ ->
+ PrefManager.setVal(PrefName.DohProvider, i)
+ settingsExtensionDns.clearFocus()
+ restartApp(binding.root)
+ }
+
+ settingsContinueMedia.isChecked = PrefManager.getVal(PrefName.ContinueMedia)
+ settingsContinueMedia.setOnCheckedChangeListener { _, isChecked ->
+ PrefManager.setVal(PrefName.ContinueMedia, isChecked)
+ }
+
+ settingsSearchSources.isChecked = PrefManager.getVal(PrefName.SearchSources)
+ settingsSearchSources.setOnCheckedChangeListener { _, isChecked ->
+ PrefManager.setVal(PrefName.SearchSources, isChecked)
+ }
+
+ settingsRecentlyListOnly.isChecked = PrefManager.getVal(PrefName.RecentlyListOnly)
+ settingsRecentlyListOnly.setOnCheckedChangeListener { _, isChecked ->
+ PrefManager.setVal(PrefName.RecentlyListOnly, isChecked)
+ }
+ settingsAdultAnimeOnly.isChecked = PrefManager.getVal(PrefName.AdultOnly)
+ settingsAdultAnimeOnly.setOnCheckedChangeListener { _, isChecked ->
+ PrefManager.setVal(PrefName.AdultOnly, isChecked)
+ restartApp(binding.root)
+ }
+
+ settingsDownloadLocation.setOnClickListener {
+ val dialog = AlertDialog.Builder(context, R.style.MyPopup)
+ .setTitle(R.string.change_download_location)
+ .setMessage(R.string.download_location_msg)
+ .setPositiveButton(R.string.ok) { dialog, _ ->
+ val oldUri = PrefManager.getVal(PrefName.DownloadsDir)
+ launcher.registerForCallback { success ->
+ if (success) {
+ toast(getString(R.string.please_wait))
+ val newUri = PrefManager.getVal(PrefName.DownloadsDir)
+ GlobalScope.launch(Dispatchers.IO) {
+ Injekt.get().moveDownloadsDir(
+ context, Uri.parse(oldUri), Uri.parse(newUri)
+ ) { finished, message ->
+ if (finished) {
+ toast(getString(R.string.success))
+ } else {
+ toast(message)
+ }
+ }
+ }
+ } else {
+ toast(getString(R.string.error))
+ }
+ }
+ launcher.launch()
+ dialog.dismiss()
+ }.setNeutralButton(R.string.cancel) { dialog, _ ->
+ dialog.dismiss()
+ }.create()
+ dialog.window?.setDimAmount(0.8f)
+ dialog.show()
+ }
+
+ var previousStart: View = when (PrefManager.getVal(PrefName.DefaultStartUpTab)) {
+ 0 -> uiSettingsAnime
+ 1 -> uiSettingsHome
+ 2 -> uiSettingsManga
+ else -> uiSettingsHome
+ }
+ previousStart.alpha = 1f
+ fun uiDefault(mode: Int, current: View) {
+ previousStart.alpha = 0.33f
+ previousStart = current
+ current.alpha = 1f
+ PrefManager.setVal(PrefName.DefaultStartUpTab, mode)
+ initActivity(context)
+ }
+
+ uiSettingsAnime.setOnClickListener {
+ uiDefault(0, it)
+ }
+
+ uiSettingsHome.setOnClickListener {
+ uiDefault(1, it)
+ }
+
+ uiSettingsManga.setOnClickListener {
+ uiDefault(2, it)
+ }
+
+ settingsUi.setOnClickListener {
+ startActivity(
+ Intent(
+ context, UserInterfaceSettingsActivity::class.java
+ )
+ )
+ }
+ }
+ }
+ private fun passwordAlertDialog(isExporting: Boolean, callback: (CharArray?) -> Unit) {
+ val password = CharArray(16).apply { fill('0') }
+
+ // Inflate the dialog layout
+ val dialogView = LayoutInflater.from(this).inflate(R.layout.dialog_user_agent, null)
+ val box = dialogView.findViewById(R.id.userAgentTextBox)
+ box?.hint = getString(R.string.password)
+ box?.setSingleLine()
+
+ val dialog =
+ AlertDialog.Builder(this, R.style.MyPopup).setTitle(getString(R.string.enter_password))
+ .setView(dialogView).setPositiveButton(R.string.ok, null)
+ .setNegativeButton(R.string.cancel) { dialog, _ ->
+ password.fill('0')
+ dialog.dismiss()
+ callback(null)
+ }.create()
+
+ fun handleOkAction() {
+ val editText = dialog.findViewById(R.id.userAgentTextBox)
+ if (editText?.text?.isNotBlank() == true) {
+ editText.text?.toString()?.trim()?.toCharArray(password)
+ dialog.dismiss()
+ callback(password)
+ } else {
+ toast(getString(R.string.password_cannot_be_empty))
+ }
+ }
+ box?.setOnEditorActionListener { _, actionId, _ ->
+ if (actionId == EditorInfo.IME_ACTION_DONE) {
+ handleOkAction()
+ true
+ } else {
+ false
+ }
+ }
+ val subtitleTextView = dialogView.findViewById(R.id.subtitle)
+ subtitleTextView?.visibility = View.VISIBLE
+ if (!isExporting) subtitleTextView?.text =
+ getString(R.string.enter_password_to_decrypt_file)
+
+
+ dialog.window?.setDimAmount(0.8f)
+ dialog.show()
+
+ // Override the positive button here
+ dialog.getButton(AlertDialog.BUTTON_POSITIVE).setOnClickListener {
+ handleOkAction()
+ }
+
+ }
+
+}
\ No newline at end of file
diff --git a/app/src/main/java/ani/dantotsu/settings/SettingsExtensionsActivity.kt b/app/src/main/java/ani/dantotsu/settings/SettingsExtensionsActivity.kt
new file mode 100644
index 00000000..501d2fd9
--- /dev/null
+++ b/app/src/main/java/ani/dantotsu/settings/SettingsExtensionsActivity.kt
@@ -0,0 +1,246 @@
+package ani.dantotsu.settings
+
+import android.app.AlertDialog
+import android.os.Bundle
+import android.view.HapticFeedbackConstants
+import android.view.KeyEvent
+import android.view.LayoutInflater
+import android.view.ViewGroup
+import android.view.inputmethod.EditorInfo
+import android.widget.EditText
+import androidx.appcompat.app.AppCompatActivity
+import androidx.core.view.isVisible
+import androidx.core.view.updateLayoutParams
+import ani.dantotsu.R
+import ani.dantotsu.copyToClipboard
+import ani.dantotsu.databinding.ActivitySettingsExtensionsBinding
+import ani.dantotsu.databinding.ItemRepositoryBinding
+import ani.dantotsu.initActivity
+import ani.dantotsu.media.MediaType
+import ani.dantotsu.navBarHeight
+import ani.dantotsu.settings.saving.PrefManager
+import ani.dantotsu.settings.saving.PrefName
+import ani.dantotsu.statusBarHeight
+import ani.dantotsu.themes.ThemeManager
+import com.google.android.material.textfield.TextInputEditText
+import eu.kanade.domain.base.BasePreferences
+import eu.kanade.tachiyomi.extension.anime.AnimeExtensionManager
+import eu.kanade.tachiyomi.extension.manga.MangaExtensionManager
+import kotlinx.coroutines.CoroutineScope
+import kotlinx.coroutines.Dispatchers
+import kotlinx.coroutines.launch
+import uy.kohesive.injekt.Injekt
+import uy.kohesive.injekt.api.get
+import uy.kohesive.injekt.injectLazy
+
+class SettingsExtensionsActivity: AppCompatActivity() {
+ private lateinit var binding: ActivitySettingsExtensionsBinding
+ private val extensionInstaller = Injekt.get().extensionInstaller()
+ private val animeExtensionManager: AnimeExtensionManager by injectLazy()
+ private val mangaExtensionManager: MangaExtensionManager by injectLazy()
+ override fun onCreate(savedInstanceState: Bundle?) {
+ super.onCreate(savedInstanceState)
+ ThemeManager(this).applyTheme()
+ initActivity(this)
+ val context = this
+ binding = ActivitySettingsExtensionsBinding.inflate(layoutInflater)
+ setContentView(binding.root)
+ binding.apply {
+
+ fun setExtensionOutput(repoInventory: ViewGroup, type: MediaType) {
+ repoInventory.removeAllViews()
+ val prefName: PrefName? = when (type) {
+ MediaType.ANIME -> {
+ PrefName.AnimeExtensionRepos
+ }
+
+ MediaType.MANGA -> {
+ PrefName.MangaExtensionRepos
+ }
+
+ else -> {
+ null
+ }
+ }
+ prefName?.let { repoList ->
+ PrefManager.getVal>(repoList).forEach { item ->
+ val view = ItemRepositoryBinding.inflate(
+ LayoutInflater.from(repoInventory.context), repoInventory, true
+ )
+ 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)
+ PrefManager.setVal(repoList, repos)
+ setExtensionOutput(repoInventory, type)
+ CoroutineScope(Dispatchers.IO).launch {
+ when (type) {
+ MediaType.ANIME -> {
+ animeExtensionManager.findAvailableExtensions()
+ }
+
+ MediaType.MANGA -> {
+ mangaExtensionManager.findAvailableExtensions()
+ }
+
+ else -> {}
+ }
+ }
+ dialog.dismiss()
+ }.setNegativeButton(getString(R.string.cancel)) { dialog, _ ->
+ dialog.dismiss()
+ }.create().show()
+ }
+ view.repositoryItem.setOnLongClickListener {
+ it.performHapticFeedback(HapticFeedbackConstants.LONG_PRESS)
+ copyToClipboard(item, true)
+ true
+ }
+ }
+ repoInventory.isVisible = repoInventory.childCount > 0
+ }
+ }
+
+ fun processUserInput(input: String, mediaType: MediaType) {
+ val entry =
+ if (input.endsWith("/") || input.endsWith("index.min.json")) input.substring(
+ 0,
+ input.lastIndexOf("/")
+ ) else input
+ if (mediaType == MediaType.ANIME) {
+ val anime =
+ PrefManager.getVal>(PrefName.AnimeExtensionRepos).plus(entry)
+ PrefManager.setVal(PrefName.AnimeExtensionRepos, anime)
+ CoroutineScope(Dispatchers.IO).launch {
+ animeExtensionManager.findAvailableExtensions()
+ }
+ setExtensionOutput(animeRepoInventory, MediaType.ANIME)
+ }
+ if (mediaType == MediaType.MANGA) {
+ val manga =
+ PrefManager.getVal>(PrefName.MangaExtensionRepos).plus(entry)
+ PrefManager.setVal(PrefName.MangaExtensionRepos, manga)
+ CoroutineScope(Dispatchers.IO).launch {
+ mangaExtensionManager.findAvailableExtensions()
+ }
+ setExtensionOutput(mangaRepoInventory, MediaType.MANGA)
+ }
+ }
+
+ fun processEditorAction(dialog: AlertDialog, editText: EditText, mediaType: MediaType) {
+ editText.setOnEditorActionListener { textView, action, keyEvent ->
+ if (action == EditorInfo.IME_ACTION_SEARCH || action == EditorInfo.IME_ACTION_DONE || (keyEvent?.action == KeyEvent.ACTION_UP && keyEvent.keyCode == KeyEvent.KEYCODE_ENTER)) {
+ return@setOnEditorActionListener if (textView.text.isNullOrBlank()) {
+ false
+ } else {
+ processUserInput(textView.text.toString(), mediaType)
+ dialog.dismiss()
+ true
+ }
+ }
+ false
+ }
+ }
+ settingsExtensionsLayout.updateLayoutParams {
+ topMargin = statusBarHeight
+ bottomMargin = navBarHeight
+ }
+ settingsExtensionsTitle.setOnClickListener{
+ onBackPressedDispatcher.onBackPressed()
+ }
+ setExtensionOutput(animeRepoInventory, MediaType.ANIME)
+ setExtensionOutput(mangaRepoInventory, MediaType.MANGA)
+ animeAddRepository.setOnClickListener {
+ val dialogView = layoutInflater.inflate(R.layout.dialog_user_agent, null)
+ val editText =
+ dialogView.findViewById(R.id.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)
+ .setPositiveButton(getString(R.string.ok)) { dialog, _ ->
+ if (!editText.text.isNullOrBlank()) processUserInput(
+ editText.text.toString(),
+ MediaType.ANIME
+ )
+ dialog.dismiss()
+ }.setNegativeButton(getString(R.string.cancel)) { dialog, _ ->
+ dialog.dismiss()
+ }.create()
+
+ processEditorAction(alertDialog, editText, MediaType.ANIME)
+ alertDialog.show()
+ alertDialog.window?.setDimAmount(0.8f)
+ }
+
+ mangaAddRepository.setOnClickListener {
+ val dialogView = layoutInflater.inflate(R.layout.dialog_user_agent, null)
+ val editText =
+ dialogView.findViewById(R.id.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)
+ .setPositiveButton(getString(R.string.ok)) { dialog, _ ->
+ if (!editText.text.isNullOrBlank()) processUserInput(
+ editText.text.toString(),
+ MediaType.MANGA
+ )
+ dialog.dismiss()
+ }.setNegativeButton(getString(R.string.cancel)) { dialog, _ ->
+ dialog.dismiss()
+ }.create()
+
+ processEditorAction(alertDialog, editText, MediaType.MANGA)
+ alertDialog.show()
+ alertDialog.window?.setDimAmount(0.8f)
+ }
+
+ settingsForceLegacyInstall.isChecked =
+ extensionInstaller.get() == BasePreferences.ExtensionInstaller.LEGACY
+ settingsForceLegacyInstall.setOnCheckedChangeListener { _, isChecked ->
+ if (isChecked) {
+ extensionInstaller.set(BasePreferences.ExtensionInstaller.LEGACY)
+ } else {
+ extensionInstaller.set(BasePreferences.ExtensionInstaller.PACKAGEINSTALLER)
+ }
+ }
+
+ skipExtensionIcons.isChecked = PrefManager.getVal(PrefName.SkipExtensionIcons)
+ skipExtensionIcons.setOnCheckedChangeListener { _, isChecked ->
+ PrefManager.getVal(PrefName.SkipExtensionIcons, isChecked)
+ }
+ NSFWExtension.isChecked = PrefManager.getVal(PrefName.NSFWExtension)
+ NSFWExtension.setOnCheckedChangeListener { _, isChecked ->
+ PrefManager.setVal(PrefName.NSFWExtension, isChecked)
+
+ }
+
+ userAgent.setOnClickListener {
+ val dialogView = layoutInflater.inflate(R.layout.dialog_user_agent, null)
+ val editText = dialogView.findViewById(R.id.userAgentTextBox)
+ editText.setText(PrefManager.getVal(PrefName.DefaultUserAgent))
+ val alertDialog = AlertDialog.Builder(context, R.style.MyPopup)
+ .setTitle(R.string.user_agent).setView(dialogView)
+ .setPositiveButton(getString(R.string.ok)) { dialog, _ ->
+ PrefManager.setVal(PrefName.DefaultUserAgent, editText.text.toString())
+ dialog.dismiss()
+ }.setNeutralButton(getString(R.string.reset)) { dialog, _ ->
+ PrefManager.removeVal(PrefName.DefaultUserAgent)
+ editText.setText("")
+ dialog.dismiss()
+ }.setNegativeButton(getString(R.string.cancel)) { dialog, _ ->
+ dialog.dismiss()
+ }.create()
+
+ alertDialog.show()
+ alertDialog.window?.setDimAmount(0.8f)
+ }
+ }
+ }
+
+}
\ No newline at end of file
diff --git a/app/src/main/java/ani/dantotsu/settings/SettingsMangaActivity.kt b/app/src/main/java/ani/dantotsu/settings/SettingsMangaActivity.kt
new file mode 100644
index 00000000..c4b08d40
--- /dev/null
+++ b/app/src/main/java/ani/dantotsu/settings/SettingsMangaActivity.kt
@@ -0,0 +1,104 @@
+package ani.dantotsu.settings
+
+import android.app.AlertDialog
+import android.content.Intent
+import android.os.Bundle
+import android.view.View
+import android.view.ViewGroup
+import androidx.appcompat.app.AppCompatActivity
+import androidx.core.view.updateLayoutParams
+import ani.dantotsu.R
+import ani.dantotsu.databinding.ActivitySettingsMangaBinding
+import ani.dantotsu.download.DownloadsManager
+import ani.dantotsu.initActivity
+import ani.dantotsu.media.MediaType
+import ani.dantotsu.navBarHeight
+import ani.dantotsu.restartApp
+import ani.dantotsu.settings.saving.PrefManager
+import ani.dantotsu.settings.saving.PrefName
+import ani.dantotsu.statusBarHeight
+import ani.dantotsu.themes.ThemeManager
+import uy.kohesive.injekt.Injekt
+import uy.kohesive.injekt.api.get
+
+class SettingsMangaActivity: AppCompatActivity(){
+ private lateinit var binding: ActivitySettingsMangaBinding
+
+ override fun onCreate(savedInstanceState: Bundle?) {
+ super.onCreate(savedInstanceState)
+ ThemeManager(this).applyTheme()
+ initActivity(this)
+ val context = this
+ binding = ActivitySettingsMangaBinding.inflate(layoutInflater)
+ setContentView(binding.root)
+ binding.apply {
+ settingsMangaLayout.updateLayoutParams {
+ topMargin = statusBarHeight
+ bottomMargin = navBarHeight
+ }
+ settingsMangaTitle.setOnClickListener {
+ onBackPressedDispatcher.onBackPressed()
+ }
+ purgeMangaDownloads.setOnClickListener {
+ 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, _ ->
+ 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()
+ }
+
+ purgeNovelDownloads.setOnClickListener {
+ 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, _ ->
+ 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()
+ }
+
+ settingsReader.setOnClickListener {
+ startActivity(Intent(context, ReaderSettingsActivity::class.java))
+ }
+
+ var previousChp: View = when (PrefManager.getVal(PrefName.MangaDefaultView)) {
+ 0 -> settingsChpList
+ 1 -> settingsChpCompact
+ else -> settingsChpList
+ }
+ previousChp.alpha = 1f
+ fun uiChp(mode: Int, current: View) {
+ previousChp.alpha = 0.33f
+ previousChp = current
+ current.alpha = 1f
+ PrefManager.setVal(PrefName.MangaDefaultView, mode)
+ }
+
+ settingsChpList.setOnClickListener {
+ uiChp(0, it)
+ }
+
+ settingsChpCompact.setOnClickListener {
+ uiChp(1, it)
+ }
+
+ settingsIncludeMangaList.isChecked = PrefManager.getVal(PrefName.IncludeMangaList)
+ settingsIncludeMangaList.setOnCheckedChangeListener { _, isChecked ->
+ PrefManager.setVal(PrefName.IncludeMangaList, isChecked)
+ restartApp(binding.root)
+ }
+ }
+ }
+}
\ No newline at end of file
diff --git a/app/src/main/java/ani/dantotsu/settings/SettingsNotificationActivity.kt b/app/src/main/java/ani/dantotsu/settings/SettingsNotificationActivity.kt
new file mode 100644
index 00000000..f9ca378f
--- /dev/null
+++ b/app/src/main/java/ani/dantotsu/settings/SettingsNotificationActivity.kt
@@ -0,0 +1,200 @@
+package ani.dantotsu.settings
+
+import android.app.AlarmManager
+import android.app.AlertDialog
+import android.content.Context
+import android.content.Intent
+import android.os.Build
+import android.os.Bundle
+import android.view.ViewGroup
+import androidx.appcompat.app.AppCompatActivity
+import androidx.core.view.updateLayoutParams
+import ani.dantotsu.R
+import ani.dantotsu.connections.anilist.api.NotificationType
+import ani.dantotsu.databinding.ActivitySettingsNotificationsBinding
+import ani.dantotsu.initActivity
+import ani.dantotsu.navBarHeight
+import ani.dantotsu.notifications.TaskScheduler
+import ani.dantotsu.notifications.anilist.AnilistNotificationWorker
+import ani.dantotsu.notifications.comment.CommentNotificationWorker
+import ani.dantotsu.notifications.subscription.SubscriptionNotificationWorker
+import ani.dantotsu.openSettings
+import ani.dantotsu.settings.saving.PrefManager
+import ani.dantotsu.settings.saving.PrefName
+import ani.dantotsu.statusBarHeight
+import ani.dantotsu.themes.ThemeManager
+
+class SettingsNotificationActivity: AppCompatActivity(){
+ private lateinit var binding: ActivitySettingsNotificationsBinding
+
+ override fun onCreate(savedInstanceState: Bundle?) {
+ super.onCreate(savedInstanceState)
+ ThemeManager(this).applyTheme()
+ initActivity(this)
+ val context = this
+ binding = ActivitySettingsNotificationsBinding.inflate(layoutInflater)
+ setContentView(binding.root)
+ binding.apply {
+ var curTime = PrefManager.getVal(PrefName.SubscriptionNotificationInterval)
+ val timeNames = SubscriptionNotificationWorker.checkIntervals.map {
+ val mins = it % 60
+ val hours = it / 60
+ if (it > 0) "${if (hours > 0) "$hours hrs " else ""}${if (mins > 0) "$mins mins" else ""}"
+ else getString(R.string.do_not_update)
+ }.toTypedArray()
+ settingsNotificationsLayout.updateLayoutParams {
+ topMargin = statusBarHeight
+ bottomMargin = navBarHeight
+ }
+ settingsNotificationsTitle.setOnClickListener {
+ onBackPressedDispatcher.onBackPressed()
+ }
+ settingsSubscriptionsTime.text =
+ getString(R.string.subscriptions_checking_time_s, timeNames[curTime])
+ val speedDialog = AlertDialog.Builder(context, R.style.MyPopup)
+ .setTitle(R.string.subscriptions_checking_time)
+ settingsSubscriptionsTime.setOnClickListener {
+ val dialog = speedDialog.setSingleChoiceItems(timeNames, curTime) { dialog, i ->
+ curTime = i
+ settingsSubscriptionsTime.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)
+ }
+
+ settingsSubscriptionsTime.setOnLongClickListener {
+ TaskScheduler.create(
+ context, PrefManager.getVal(PrefName.UseAlarmManager)
+ ).scheduleAllTasks(context)
+ true
+ }
+
+ val aTimeNames = AnilistNotificationWorker.checkIntervals.map { it.toInt() }
+ val aItems = aTimeNames.map {
+ val mins = it % 60
+ val hours = it / 60
+ if (it > 0) "${if (hours > 0) "$hours hrs " else ""}${if (mins > 0) "$mins mins" else ""}"
+ else getString(R.string.do_not_update)
+ }
+ settingsAnilistSubscriptionsTime.text = getString(
+ R.string.anilist_notifications_checking_time,
+ aItems[PrefManager.getVal(PrefName.AnilistNotificationInterval)]
+ )
+ settingsAnilistSubscriptionsTime.setOnClickListener {
+
+ val selected = PrefManager.getVal(PrefName.AnilistNotificationInterval)
+ val dialog = AlertDialog.Builder(context, R.style.MyPopup)
+ .setTitle(R.string.subscriptions_checking_time)
+ .setSingleChoiceItems(aItems.toTypedArray(), selected) { dialog, i ->
+ PrefManager.setVal(PrefName.AnilistNotificationInterval, i)
+ settingsAnilistSubscriptionsTime.text =
+ getString(R.string.anilist_notifications_checking_time, aItems[i])
+ dialog.dismiss()
+ TaskScheduler.create(
+ context, PrefManager.getVal(PrefName.UseAlarmManager)
+ ).scheduleAllTasks(context)
+ }.create()
+ dialog.window?.setDimAmount(0.8f)
+ dialog.show()
+ }
+
+ settingsAnilistNotifications.setOnClickListener {
+ val types = NotificationType.entries.map { it.name }
+ val filteredTypes =
+ PrefManager.getVal>(PrefName.AnilistFilteredTypes).toMutableSet()
+ val selected = types.map { filteredTypes.contains(it) }.toBooleanArray()
+ val dialog = AlertDialog.Builder(context, R.style.MyPopup)
+ .setTitle(R.string.anilist_notification_filters)
+ .setMultiChoiceItems(types.toTypedArray(), selected) { _, which, isChecked ->
+ val type = types[which]
+ if (isChecked) {
+ filteredTypes.add(type)
+ } else {
+ filteredTypes.remove(type)
+ }
+ PrefManager.setVal(PrefName.AnilistFilteredTypes, filteredTypes)
+ }.create()
+ dialog.window?.setDimAmount(0.8f)
+ dialog.show()
+ }
+
+ val cTimeNames = CommentNotificationWorker.checkIntervals.map { it.toInt() }
+ val cItems = cTimeNames.map {
+ val mins = it % 60
+ val hours = it / 60
+ if (it > 0) "${if (hours > 0) "$hours hrs " else ""}${if (mins > 0) "$mins mins" else ""}"
+ else getString(R.string.do_not_update)
+ }
+
+ settingsCommentSubscriptionsTime.text = getString(
+ R.string.comment_notification_checking_time,
+ cItems[PrefManager.getVal(PrefName.CommentNotificationInterval)]
+ )
+ settingsCommentSubscriptionsTime.setOnClickListener {
+ val selected = PrefManager.getVal(PrefName.CommentNotificationInterval)
+ val dialog = AlertDialog.Builder(context, R.style.MyPopup)
+ .setTitle(R.string.subscriptions_checking_time)
+ .setSingleChoiceItems(cItems.toTypedArray(), selected) { dialog, i ->
+ PrefManager.setVal(PrefName.CommentNotificationInterval, i)
+ settingsCommentSubscriptionsTime.text =
+ getString(R.string.comment_notification_checking_time, cItems[i])
+ dialog.dismiss()
+ TaskScheduler.create(
+ context, PrefManager.getVal(PrefName.UseAlarmManager)
+ ).scheduleAllTasks(context)
+ }.create()
+ dialog.window?.setDimAmount(0.8f)
+ dialog.show()
+ }
+
+ settingsNotificationsCheckingSubscriptions.isChecked =
+ PrefManager.getVal(PrefName.SubscriptionCheckingNotifications)
+ settingsNotificationsCheckingSubscriptions.setOnCheckedChangeListener { _, isChecked ->
+ PrefManager.setVal(PrefName.SubscriptionCheckingNotifications, isChecked)
+ }
+
+ settingsNotificationsCheckingSubscriptions.setOnLongClickListener {
+ openSettings(context, null)
+ }
+
+ settingsNotificationsUseAlarmManager.isChecked =
+ PrefManager.getVal(PrefName.UseAlarmManager)
+
+ settingsNotificationsUseAlarmManager.setOnCheckedChangeListener { _, isChecked ->
+ if (isChecked) {
+ val alertDialog = AlertDialog.Builder(context, R.style.MyPopup)
+ .setTitle(R.string.use_alarm_manager)
+ .setMessage(R.string.use_alarm_manager_confirm)
+ .setPositiveButton(R.string.use) { dialog, _ ->
+ PrefManager.setVal(PrefName.UseAlarmManager, true)
+ if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.S) {
+ if (!(getSystemService(Context.ALARM_SERVICE) as AlarmManager).canScheduleExactAlarms()) {
+ val intent =
+ Intent("android.settings.REQUEST_SCHEDULE_EXACT_ALARM")
+ startActivity(intent)
+ settingsNotificationsCheckingSubscriptions.isChecked = true
+ }
+ }
+ dialog.dismiss()
+ }.setNegativeButton(R.string.cancel) { dialog, _ ->
+ settingsNotificationsCheckingSubscriptions.isChecked = false
+ PrefManager.setVal(PrefName.UseAlarmManager, false)
+ dialog.dismiss()
+ }.create()
+ alertDialog.window?.setDimAmount(0.8f)
+ alertDialog.show()
+ } else {
+ PrefManager.setVal(PrefName.UseAlarmManager, false)
+ TaskScheduler.create(context, true).cancelAllTasks()
+ TaskScheduler.create(context, false)
+ .scheduleAllTasks(context)
+ }
+ }
+ }
+ }
+}
\ No newline at end of file
diff --git a/app/src/main/java/ani/dantotsu/settings/SettingsThemeActivity.kt b/app/src/main/java/ani/dantotsu/settings/SettingsThemeActivity.kt
new file mode 100644
index 00000000..c4d629b8
--- /dev/null
+++ b/app/src/main/java/ani/dantotsu/settings/SettingsThemeActivity.kt
@@ -0,0 +1,139 @@
+package ani.dantotsu.settings
+
+import android.os.Bundle
+import android.view.View
+import android.view.ViewGroup
+import android.widget.ArrayAdapter
+import androidx.appcompat.app.AppCompatActivity
+import androidx.core.view.updateLayoutParams
+import ani.dantotsu.R
+import ani.dantotsu.databinding.ActivitySettingsThemeBinding
+import ani.dantotsu.initActivity
+import ani.dantotsu.navBarHeight
+import ani.dantotsu.reloadActivity
+import ani.dantotsu.restartApp
+import ani.dantotsu.settings.saving.PrefManager
+import ani.dantotsu.settings.saving.PrefName
+import ani.dantotsu.statusBarHeight
+import ani.dantotsu.themes.ThemeManager
+import eltos.simpledialogfragment.color.SimpleColorDialog
+
+class SettingsThemeActivity : AppCompatActivity() {
+ private lateinit var binding: ActivitySettingsThemeBinding
+
+ override fun onCreate(savedInstanceState: Bundle?) {
+ super.onCreate(savedInstanceState)
+ ThemeManager(this).applyTheme()
+ initActivity(this)
+ val context = this
+ binding = ActivitySettingsThemeBinding.inflate(layoutInflater)
+ setContentView(binding.root)
+ binding.apply {
+ settingsThemeLayout.updateLayoutParams {
+ topMargin = statusBarHeight
+ bottomMargin = navBarHeight
+ }
+ settingsThemeTitle.setOnClickListener { onBackPressedDispatcher.onBackPressed() }
+
+ settingsUseMaterialYou.apply {
+ isChecked = PrefManager.getVal(PrefName.UseMaterialYou)
+
+ setOnCheckedChangeListener { _, isChecked ->
+ PrefManager.setVal(PrefName.UseMaterialYou, isChecked)
+ if (isChecked) settingsUseCustomTheme.isChecked = false
+ restartApp(binding.root)
+ }
+ }
+
+ settingsUseCustomTheme.isChecked = PrefManager.getVal(PrefName.UseCustomTheme)
+ settingsUseCustomTheme.setOnCheckedChangeListener { _, isChecked ->
+ PrefManager.setVal(PrefName.UseCustomTheme, isChecked)
+ if (isChecked) {
+ settingsUseMaterialYou.isChecked = false
+ }
+
+ restartApp(binding.root)
+ }
+
+ settingsUseSourceTheme.isChecked = PrefManager.getVal(PrefName.UseSourceTheme)
+ settingsUseSourceTheme.setOnCheckedChangeListener { _, isChecked ->
+ PrefManager.setVal(PrefName.UseSourceTheme, isChecked)
+ restartApp(binding.root)
+ }
+
+ settingsUseOLED.isChecked = PrefManager.getVal(PrefName.UseOLED)
+ settingsUseOLED.setOnCheckedChangeListener { _, isChecked ->
+ PrefManager.setVal(PrefName.UseOLED, isChecked)
+ restartApp(binding.root)
+ }
+
+ val themeString: String = PrefManager.getVal(PrefName.Theme)
+ val themeText = themeString.substring(0, 1) + themeString.substring(1).lowercase()
+ themeSwitcher.setText(themeText)
+
+ themeSwitcher.setAdapter(
+ ArrayAdapter(context,
+ R.layout.item_dropdown,
+ ThemeManager.Companion.Theme.entries.map {
+ it.theme.substring(
+ 0,
+ 1
+ ) + it.theme.substring(1).lowercase()
+ })
+ )
+
+ themeSwitcher.setOnItemClickListener { _, _, i, _ ->
+ PrefManager.setVal(PrefName.Theme, ThemeManager.Companion.Theme.entries[i].theme)
+ //ActivityHelper.shouldRefreshMainActivity = true
+ themeSwitcher.clearFocus()
+ restartApp(binding.root)
+ }
+
+ customTheme.setOnClickListener {
+ val originalColor: Int = PrefManager.getVal(PrefName.CustomThemeInt)
+
+ class CustomColorDialog : SimpleColorDialog() { //idk where to put it
+ override fun onPositiveButtonClick() {
+ restartApp(binding.root)
+ super.onPositiveButtonClick()
+ }
+ }
+
+ val tag = "colorPicker"
+ CustomColorDialog().title(R.string.custom_theme).colorPreset(originalColor)
+ .colors(context, SimpleColorDialog.MATERIAL_COLOR_PALLET)
+ .allowCustom(true).showOutline(0x46000000).gridNumColumn(5)
+ .choiceMode(SimpleColorDialog.SINGLE_CHOICE).neg()
+ .show(context, tag)
+ }
+
+ var previous: View = when (PrefManager.getVal(PrefName.DarkMode)) {
+ 0 -> settingsUiAuto
+ 1 -> settingsUiLight
+ 2 -> settingsUiDark
+ else -> settingsUiAuto
+ }
+ previous.alpha = 1f
+ fun uiTheme(mode: Int, current: View) {
+ previous.alpha = 0.33f
+ previous = current
+ current.alpha = 1f
+ PrefManager.setVal(PrefName.DarkMode, mode)
+ reloadActivity()
+ }
+
+ settingsUiAuto.setOnClickListener {
+ uiTheme(0, it)
+ }
+
+ settingsUiLight.setOnClickListener {
+ settingsUseOLED.isChecked = false
+ uiTheme(1, it)
+ }
+
+ settingsUiDark.setOnClickListener {
+ uiTheme(2, it)
+ }
+ }
+ }
+}
\ No newline at end of file
diff --git a/app/src/main/res/layout/activity_settings.xml b/app/src/main/res/layout/activity_settings.xml
index 2a14a9ec..e21aa2df 100644
--- a/app/src/main/res/layout/activity_settings.xml
+++ b/app/src/main/res/layout/activity_settings.xml
@@ -74,19 +74,117 @@
android:paddingStart="31dp"
android:paddingEnd="31dp">
-
-
-
-
-
-
-
-
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
-
-
+
+
+
+
+
+ android:checked="true"
+ android:drawableStart="@drawable/ic_round_new_releases_24"
+ android:drawablePadding="16dp"
+ android:elegantTextHeight="true"
+ android:fontFamily="@font/poppins_bold"
+ android:minHeight="64dp"
+ android:text="@string/check_app_updates"
+ android:textAlignment="viewStart"
+ android:textColor="?attr/colorOnBackground"
+ app:cornerRadius="0dp"
+ app:drawableTint="?attr/colorPrimary"
+ app:showText="false"
+ app:thumbTint="@color/button_switch_track" />
+
+
+
+
+
+
-
-
-
-
-
-
-
+ android:text="@string/logging_warning" />
-
-
-
-
-
-
-
+
-
+
-
+
-
+
-
+
-
-
\ No newline at end of file
+
\ No newline at end of file
diff --git a/app/src/main/res/layout/activity_settings_accounts.xml b/app/src/main/res/layout/activity_settings_accounts.xml
index 08cbbb98..31aa1a63 100644
--- a/app/src/main/res/layout/activity_settings_accounts.xml
+++ b/app/src/main/res/layout/activity_settings_accounts.xml
@@ -1,29 +1,27 @@
-
-
+
-
-
-
-
+ android:layout_height="64dp"
+ android:layout_marginTop="16dp"
+ android:fontFamily="@font/poppins"
+ android:gravity="center"
+ android:paddingEnd="28dp"
+ android:text="@string/accounts"
+ android:textSize="20sp"
+ android:textStyle="bold"
+ app:drawableStartCompat="@drawable/ic_round_arrow_back_ios_new_24"
+ app:drawableTint="?attr/colorOnBackground"
+ tools:ignore="RtlSymmetry" />
-
-
-
\ No newline at end of file
+
\ No newline at end of file
diff --git a/app/src/main/res/layout/activity_settings_anime.xml b/app/src/main/res/layout/activity_settings_anime.xml
index dd044ca3..7b1c59e4 100644
--- a/app/src/main/res/layout/activity_settings_anime.xml
+++ b/app/src/main/res/layout/activity_settings_anime.xml
@@ -1,33 +1,32 @@
-
-
+
+
-
-
-
-
+ android:layout_height="64dp"
+ android:layout_marginTop="16dp"
+ android:fontFamily="@font/poppins"
+ android:gravity="center"
+ android:paddingEnd="28dp"
+ android:text="@string/anime"
+ android:textSize="20sp"
+ android:textStyle="bold"
+ app:drawableStartCompat="@drawable/ic_round_arrow_back_ios_new_24"
+ app:drawableTint="?attr/colorOnBackground"
+ tools:ignore="RtlSymmetry" />
@@ -197,13 +196,4 @@
app:showText="false"
app:thumbTint="@color/button_switch_track" />
-
-
-
\ No newline at end of file
+
\ No newline at end of file
diff --git a/app/src/main/res/layout/activity_settings_common.xml b/app/src/main/res/layout/activity_settings_common.xml
index 5e873166..f03e52bd 100644
--- a/app/src/main/res/layout/activity_settings_common.xml
+++ b/app/src/main/res/layout/activity_settings_common.xml
@@ -1,34 +1,32 @@
-
+ xmlns:tools="http://schemas.android.com/tools"
+ android:id="@+id/settingsCommonLayout"
+ android:layout_width="match_parent"
+ android:layout_height="match_parent"
+ android:orientation="vertical"
+ android:paddingStart="31dp"
+ android:paddingEnd="31dp">
-
-
-
-
-
+ android:layout_height="64dp"
+ android:layout_marginTop="16dp"
+ android:fontFamily="@font/poppins"
+ android:gravity="center"
+ android:paddingEnd="28dp"
+ android:text="@string/common"
+ android:textSize="20sp"
+ android:textStyle="bold"
+ app:drawableStartCompat="@drawable/ic_round_arrow_back_ios_new_24"
+ app:drawableTint="?attr/colorOnBackground"
+ tools:ignore="RtlSymmetry" />
@@ -185,7 +183,7 @@
-
-
-
-
\ No newline at end of file
+
+
\ No newline at end of file
diff --git a/app/src/main/res/layout/activity_settings_extensions.xml b/app/src/main/res/layout/activity_settings_extensions.xml
index 6929b3f1..465f5d24 100644
--- a/app/src/main/res/layout/activity_settings_extensions.xml
+++ b/app/src/main/res/layout/activity_settings_extensions.xml
@@ -1,31 +1,29 @@
-
+ xmlns:tools="http://schemas.android.com/tools"
+ android:id="@+id/settingsExtensionsLayout"
+ android:layout_width="match_parent"
+ android:layout_height="match_parent"
+ android:orientation="vertical"
+ android:paddingStart="31dp"
+ android:paddingEnd="31dp">
-
+ android:layout_height="64dp"
+ android:layout_marginTop="16dp"
+ android:fontFamily="@font/poppins"
+ android:gravity="center"
+ android:paddingEnd="28dp"
+ android:text="@string/extensions"
+ android:textSize="20sp"
+ android:textStyle="bold"
+ app:drawableStartCompat="@drawable/ic_round_arrow_back_ios_new_24"
+ app:drawableTint="?attr/colorOnBackground"
+ tools:ignore="RtlSymmetry" />
-
-
-
-
-
-
+
diff --git a/app/src/main/res/layout/activity_settings_manga.xml b/app/src/main/res/layout/activity_settings_manga.xml
index 7d0b980c..353850fd 100644
--- a/app/src/main/res/layout/activity_settings_manga.xml
+++ b/app/src/main/res/layout/activity_settings_manga.xml
@@ -1,33 +1,33 @@
-
-
+
+
+ android:layout_height="64dp"
+ android:layout_marginTop="16dp"
+ android:fontFamily="@font/poppins"
+ android:gravity="center"
+ android:paddingEnd="28dp"
+ android:text="@string/manga"
+ android:textSize="20sp"
+ android:textStyle="bold"
+ app:drawableStartCompat="@drawable/ic_round_arrow_back_ios_new_24"
+ app:drawableTint="?attr/colorOnBackground"
+ tools:ignore="RtlSymmetry" />
-
-
-
@@ -160,13 +160,5 @@
app:drawableTint="?attr/colorPrimary"
app:showText="false"
app:thumbTint="@color/button_switch_track" />
-
-
-
\ No newline at end of file
+
\ No newline at end of file
diff --git a/app/src/main/res/layout/activity_settings_notifications.xml b/app/src/main/res/layout/activity_settings_notifications.xml
index 49be52f5..4e682013 100644
--- a/app/src/main/res/layout/activity_settings_notifications.xml
+++ b/app/src/main/res/layout/activity_settings_notifications.xml
@@ -1,30 +1,28 @@
-
-
+
+
-
-
-
-
-
+ android:layout_height="64dp"
+ android:layout_marginTop="16dp"
+ android:fontFamily="@font/poppins"
+ android:gravity="center"
+ android:paddingEnd="28dp"
+ android:text="@string/notifications"
+ android:textSize="20sp"
+ android:textStyle="bold"
+ app:drawableStartCompat="@drawable/ic_round_arrow_back_ios_new_24"
+ app:drawableTint="?attr/colorOnBackground"
+ tools:ignore="RtlSymmetry" />
-
-
-
\ No newline at end of file
+
\ No newline at end of file
diff --git a/app/src/main/res/layout/activity_settings_theme.xml b/app/src/main/res/layout/activity_settings_theme.xml
index fa409152..e9d4ab20 100644
--- a/app/src/main/res/layout/activity_settings_theme.xml
+++ b/app/src/main/res/layout/activity_settings_theme.xml
@@ -1,260 +1,250 @@
-
-
+
+
+
+
+
+ android:layout_marginTop="8dp"
+ android:gravity="center"
+ android:orientation="horizontal">
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
+ android:text="@string/theme" />
-
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ android:freezesText="false"
+ android:inputType="none"
+ android:padding="8dp"
+ android:text="@string/watch"
+ android:textAllCaps="true"
+ android:textColor="?android:attr/textColorSecondary"
+ android:textSize="14sp"
+ tools:ignore="LabelFor,TextContrastCheck,DuplicateSpeakableTextCheck" />
+
-
+
-
+
-
-
\ No newline at end of file
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file