chore: code refactor

This commit is contained in:
rebelonion 2024-02-06 02:16:10 -06:00
parent 8d7b86a667
commit a2e44da99d
334 changed files with 3550 additions and 3092 deletions

View file

@ -1,14 +1,16 @@
package ani.dantotsu.settings
import ani.dantotsu.settings.saving.PrefName
import ani.dantotsu.settings.saving.PrefManager
import ani.dantotsu.settings.saving.PrefName
import java.io.Serializable
data class CurrentNovelReaderSettings(
var currentThemeName: String = PrefManager.getVal(PrefName.CurrentThemeName),
var layout: Layouts = Layouts[PrefManager.getVal(PrefName.LayoutNovel)]
?: Layouts.PAGED,
var dualPageMode: CurrentReaderSettings.DualPageModes = CurrentReaderSettings.DualPageModes[PrefManager.getVal(PrefName.DualPageModeNovel)]
var dualPageMode: CurrentReaderSettings.DualPageModes = CurrentReaderSettings.DualPageModes[PrefManager.getVal(
PrefName.DualPageModeNovel
)]
?: CurrentReaderSettings.DualPageModes.Automatic,
var lineHeight: Float = PrefManager.getVal(PrefName.LineHeight),
var margin: Float = PrefManager.getVal(PrefName.Margin),

View file

@ -1,7 +1,7 @@
package ani.dantotsu.settings
import ani.dantotsu.settings.saving.PrefName
import ani.dantotsu.settings.saving.PrefManager
import ani.dantotsu.settings.saving.PrefName
import java.io.Serializable
data class CurrentReaderSettings(

View file

@ -18,8 +18,8 @@ import androidx.viewpager2.widget.ViewPager2
import ani.dantotsu.*
import ani.dantotsu.databinding.ActivityExtensionsBinding
import ani.dantotsu.others.LanguageMapper
import ani.dantotsu.settings.saving.PrefName
import ani.dantotsu.settings.saving.PrefManager
import ani.dantotsu.settings.saving.PrefName
import ani.dantotsu.themes.ThemeManager
import com.google.android.material.tabs.TabLayout
import com.google.android.material.tabs.TabLayoutMediator
@ -30,7 +30,7 @@ class ExtensionsActivity : AppCompatActivity() {
@SuppressLint("SetTextI18n")
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
ThemeManager(this).applyTheme()
binding = ActivityExtensionsBinding.inflate(layoutInflater)
setContentView(binding.root)
@ -65,7 +65,8 @@ class ExtensionsActivity : AppCompatActivity() {
searchView.setText("")
searchView.clearFocus()
tabLayout.clearFocus()
if (tab.text?.contains("Installed") == true) binding.languageselect.visibility = View.GONE
if (tab.text?.contains("Installed") == true) binding.languageselect.visibility =
View.GONE
else binding.languageselect.visibility = View.VISIBLE
viewPager.updateLayoutParams<ViewGroup.LayoutParams> {
height = ViewGroup.LayoutParams.MATCH_PARENT
@ -119,13 +120,18 @@ class ExtensionsActivity : AppCompatActivity() {
initActivity(this)
binding.languageselect.setOnClickListener {
val languageOptions = LanguageMapper.Companion.Language.entries.map{ it.name }.toTypedArray()
val languageOptions =
LanguageMapper.Companion.Language.entries.map { it.name }.toTypedArray()
val builder = AlertDialog.Builder(currContext(), R.style.MyPopup)
val listOrder: String = PrefManager.getVal(PrefName.LangSort)
val index = LanguageMapper.Companion.Language.entries.toTypedArray().indexOfFirst{it.code == listOrder}
val index = LanguageMapper.Companion.Language.entries.toTypedArray()
.indexOfFirst { it.code == listOrder }
builder.setTitle("Language")
builder.setSingleChoiceItems(languageOptions, index){ dialog, i ->
PrefManager.setVal(PrefName.LangSort, LanguageMapper.Companion.Language.entries[i].code)
builder.setSingleChoiceItems(languageOptions, index) { dialog, i ->
PrefManager.setVal(
PrefName.LangSort,
LanguageMapper.Companion.Language.entries[i].code
)
val currentFragment =
supportFragmentManager.findFragmentByTag("f${viewPager.currentItem}")
if (currentFragment is SearchQueryHandler) {

View file

@ -100,7 +100,7 @@ class FAQActivity : AppCompatActivity() {
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
ThemeManager(this).applyTheme()
binding = ActivityFaqBinding.inflate(layoutInflater)
setContentView(binding.root)

View file

@ -192,15 +192,20 @@ class InstalledAnimeExtensionsFragment : Fragment(), SearchQueryHandler {
extensionsRecyclerView.adapter = extensionsAdapter
val itemTouchHelperCallback = object : ItemTouchHelper.SimpleCallback(
ItemTouchHelper.UP or ItemTouchHelper.DOWN, 0) {
ItemTouchHelper.UP or ItemTouchHelper.DOWN, 0
) {
override fun onMove(
recyclerView: RecyclerView,
viewHolder: RecyclerView.ViewHolder,
target: RecyclerView.ViewHolder
): Boolean {
extensionsAdapter.onMove(viewHolder.absoluteAdapterPosition, target.absoluteAdapterPosition)
extensionsAdapter.onMove(
viewHolder.absoluteAdapterPosition,
target.absoluteAdapterPosition
)
return true
}
override fun onSwiped(viewHolder: RecyclerView.ViewHolder, direction: Int) {}
override fun onSelectedChanged(viewHolder: RecyclerView.ViewHolder?, actionState: Int) {
@ -211,7 +216,10 @@ class InstalledAnimeExtensionsFragment : Fragment(), SearchQueryHandler {
}
}
override fun clearView(recyclerView: RecyclerView, viewHolder: RecyclerView.ViewHolder) {
override fun clearView(
recyclerView: RecyclerView,
viewHolder: RecyclerView.ViewHolder
) {
super.clearView(recyclerView, viewHolder)
viewHolder.itemView.elevation = 0f
viewHolder.itemView.translationZ = 0f
@ -243,7 +251,10 @@ class InstalledAnimeExtensionsFragment : Fragment(), SearchQueryHandler {
}
override fun updateContentBasedOnQuery(query: String?) {
extensionsAdapter.filter(query ?: "", sortToAnimeSourcesList(animeExtensionManager.installedExtensionsFlow.value))
extensionsAdapter.filter(
query ?: "",
sortToAnimeSourcesList(animeExtensionManager.installedExtensionsFlow.value)
)
}
override fun notifyDataChanged() { // Do nothing

View file

@ -29,8 +29,8 @@ import ani.dantotsu.databinding.FragmentMangaExtensionsBinding
import ani.dantotsu.others.LanguageMapper
import ani.dantotsu.parsers.MangaSources
import ani.dantotsu.settings.extensionprefs.MangaSourcePreferencesFragment
import ani.dantotsu.settings.saving.PrefName
import ani.dantotsu.settings.saving.PrefManager
import ani.dantotsu.settings.saving.PrefName
import ani.dantotsu.snackString
import com.google.android.material.tabs.TabLayout
import com.google.android.material.textfield.TextInputLayout
@ -188,15 +188,20 @@ class InstalledMangaExtensionsFragment : Fragment(), SearchQueryHandler {
extensionsRecyclerView.adapter = extensionsAdapter
val itemTouchHelperCallback = object : ItemTouchHelper.SimpleCallback(
ItemTouchHelper.UP or ItemTouchHelper.DOWN, 0) {
ItemTouchHelper.UP or ItemTouchHelper.DOWN, 0
) {
override fun onMove(
recyclerView: RecyclerView,
viewHolder: RecyclerView.ViewHolder,
target: RecyclerView.ViewHolder
): Boolean {
extensionsAdapter.onMove(viewHolder.absoluteAdapterPosition, target.absoluteAdapterPosition)
extensionsAdapter.onMove(
viewHolder.absoluteAdapterPosition,
target.absoluteAdapterPosition
)
return true
}
override fun onSwiped(viewHolder: RecyclerView.ViewHolder, direction: Int) {}
override fun onSelectedChanged(viewHolder: RecyclerView.ViewHolder?, actionState: Int) {
@ -207,7 +212,10 @@ class InstalledMangaExtensionsFragment : Fragment(), SearchQueryHandler {
}
}
override fun clearView(recyclerView: RecyclerView, viewHolder: RecyclerView.ViewHolder) {
override fun clearView(
recyclerView: RecyclerView,
viewHolder: RecyclerView.ViewHolder
) {
super.clearView(recyclerView, viewHolder)
viewHolder.itemView.elevation = 0f
viewHolder.itemView.translationZ = 0f
@ -237,7 +245,10 @@ class InstalledMangaExtensionsFragment : Fragment(), SearchQueryHandler {
}
override fun updateContentBasedOnQuery(query: String?) {
extensionsAdapter.filter(query ?: "", sortToMangaSourcesList(mangaExtensionManager.installedExtensionsFlow.value))
extensionsAdapter.filter(
query ?: "",
sortToMangaSourcesList(mangaExtensionManager.installedExtensionsFlow.value)
)
}
override fun notifyDataChanged() { // Do nothing

View file

@ -27,8 +27,8 @@ import ani.dantotsu.others.LanguageMapper
import ani.dantotsu.parsers.NovelSources
import ani.dantotsu.parsers.novel.NovelExtension
import ani.dantotsu.parsers.novel.NovelExtensionManager
import ani.dantotsu.settings.saving.PrefName
import ani.dantotsu.settings.saving.PrefManager
import ani.dantotsu.settings.saving.PrefName
import ani.dantotsu.snackString
import eu.kanade.tachiyomi.data.notification.Notifications
import kotlinx.coroutines.launch
@ -117,15 +117,20 @@ class InstalledNovelExtensionsFragment : Fragment(), SearchQueryHandler {
extensionsRecyclerView.adapter = extensionsAdapter
val itemTouchHelperCallback = object : ItemTouchHelper.SimpleCallback(
ItemTouchHelper.UP or ItemTouchHelper.DOWN, 0) {
ItemTouchHelper.UP or ItemTouchHelper.DOWN, 0
) {
override fun onMove(
recyclerView: RecyclerView,
viewHolder: RecyclerView.ViewHolder,
target: RecyclerView.ViewHolder
): Boolean {
extensionsAdapter.onMove(viewHolder.absoluteAdapterPosition, target.absoluteAdapterPosition)
extensionsAdapter.onMove(
viewHolder.absoluteAdapterPosition,
target.absoluteAdapterPosition
)
return true
}
override fun onSwiped(viewHolder: RecyclerView.ViewHolder, direction: Int) {}
override fun onSelectedChanged(viewHolder: RecyclerView.ViewHolder?, actionState: Int) {
@ -136,7 +141,10 @@ class InstalledNovelExtensionsFragment : Fragment(), SearchQueryHandler {
}
}
override fun clearView(recyclerView: RecyclerView, viewHolder: RecyclerView.ViewHolder) {
override fun clearView(
recyclerView: RecyclerView,
viewHolder: RecyclerView.ViewHolder
) {
super.clearView(recyclerView, viewHolder)
viewHolder.itemView.elevation = 0f
viewHolder.itemView.translationZ = 0f
@ -167,7 +175,10 @@ class InstalledNovelExtensionsFragment : Fragment(), SearchQueryHandler {
}
override fun updateContentBasedOnQuery(query: String?) {
extensionsAdapter.filter(query ?: "", sortToNovelSourcesList(novelExtensionManager.installedExtensionsFlow.value))
extensionsAdapter.filter(
query ?: "",
sortToNovelSourcesList(novelExtensionManager.installedExtensionsFlow.value)
)
}
override fun notifyDataChanged() { // do nothing

View file

@ -18,8 +18,8 @@ import ani.dantotsu.media.Media
import ani.dantotsu.navBarHeight
import ani.dantotsu.others.getSerialized
import ani.dantotsu.parsers.Subtitle
import ani.dantotsu.settings.saving.PrefName
import ani.dantotsu.settings.saving.PrefManager
import ani.dantotsu.settings.saving.PrefName
import ani.dantotsu.snackString
import ani.dantotsu.statusBarHeight
import ani.dantotsu.themes.ThemeManager
@ -38,7 +38,7 @@ class PlayerSettingsActivity : AppCompatActivity() {
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
ThemeManager(this).applyTheme()
binding = ActivityPlayerSettingsBinding.inflate(layoutInflater)
setContentView(binding.root)
@ -88,12 +88,18 @@ class PlayerSettingsActivity : AppCompatActivity() {
var curSpeedArr = if (PrefManager.getVal(PrefName.CursedSpeeds)) cursedSpeeds else speeds
var speedsName = curSpeedArr.map { "${it}x" }.toTypedArray()
binding.playerSettingsSpeed.text =
getString(R.string.default_playback_speed, speedsName[PrefManager.getVal(PrefName.DefaultSpeed)])
getString(
R.string.default_playback_speed,
speedsName[PrefManager.getVal(PrefName.DefaultSpeed)]
)
val speedDialog = AlertDialog.Builder(this, R.style.MyPopup)
.setTitle(getString(R.string.default_speed))
binding.playerSettingsSpeed.setOnClickListener {
val dialog =
speedDialog.setSingleChoiceItems(speedsName, PrefManager.getVal(PrefName.DefaultSpeed)) { dialog, i ->
speedDialog.setSingleChoiceItems(
speedsName,
PrefManager.getVal(PrefName.DefaultSpeed)
) { dialog, i ->
PrefManager.setVal(PrefName.DefaultSpeed, i)
binding.playerSettingsSpeed.text =
getString(R.string.default_playback_speed, speedsName[i])
@ -110,7 +116,10 @@ class PlayerSettingsActivity : AppCompatActivity() {
PrefManager.setVal(PrefName.DefaultSpeed, newDefaultSpeed)
speedsName = curSpeedArr.map { "${it}x" }.toTypedArray()
binding.playerSettingsSpeed.text =
getString(R.string.default_playback_speed, speedsName[PrefManager.getVal(PrefName.DefaultSpeed)])
getString(
R.string.default_playback_speed,
speedsName[PrefManager.getVal(PrefName.DefaultSpeed)]
)
}
@ -120,12 +129,14 @@ class PlayerSettingsActivity : AppCompatActivity() {
PrefManager.setVal(PrefName.TimeStampsEnabled, isChecked)
}
binding.playerSettingsTimeStampsProxy.isChecked = PrefManager.getVal(PrefName.UseProxyForTimeStamps)
binding.playerSettingsTimeStampsProxy.isChecked =
PrefManager.getVal(PrefName.UseProxyForTimeStamps)
binding.playerSettingsTimeStampsProxy.setOnCheckedChangeListener { _, isChecked ->
PrefManager.setVal(PrefName.UseProxyForTimeStamps, isChecked)
}
binding.playerSettingsShowTimeStamp.isChecked = PrefManager.getVal(PrefName.ShowTimeStampButton)
binding.playerSettingsShowTimeStamp.isChecked =
PrefManager.getVal(PrefName.ShowTimeStampButton)
binding.playerSettingsShowTimeStamp.setOnCheckedChangeListener { _, isChecked ->
PrefManager.setVal(PrefName.ShowTimeStampButton, isChecked)
}
@ -147,16 +158,19 @@ class PlayerSettingsActivity : AppCompatActivity() {
}
//Update Progress
binding.playerSettingsAskUpdateProgress.isChecked = PrefManager.getVal(PrefName.AskIndividualPlayer)
binding.playerSettingsAskUpdateProgress.isChecked =
PrefManager.getVal(PrefName.AskIndividualPlayer)
binding.playerSettingsAskUpdateProgress.setOnCheckedChangeListener { _, isChecked ->
PrefManager.setVal(PrefName.AskIndividualPlayer, isChecked)
}
binding.playerSettingsAskUpdateHentai.isChecked = PrefManager.getVal(PrefName.UpdateForHPlayer)
binding.playerSettingsAskUpdateHentai.isChecked =
PrefManager.getVal(PrefName.UpdateForHPlayer)
binding.playerSettingsAskUpdateHentai.setOnCheckedChangeListener { _, isChecked ->
PrefManager.setVal(PrefName.UpdateForHPlayer, isChecked)
if (isChecked) snackString(getString(R.string.very_bold))
}
binding.playerSettingsCompletePercentage.value = (PrefManager.getVal<Float>(PrefName.WatchPercentage) * 100).roundToInt().toFloat()
binding.playerSettingsCompletePercentage.value =
(PrefManager.getVal<Float>(PrefName.WatchPercentage) * 100).roundToInt().toFloat()
binding.playerSettingsCompletePercentage.addOnChangeListener { _, value, _ ->
PrefManager.setVal(PrefName.WatchPercentage, value / 100)
}
@ -229,7 +243,10 @@ class PlayerSettingsActivity : AppCompatActivity() {
val resizeDialog = AlertDialog.Builder(this, R.style.MyPopup)
.setTitle(getString(R.string.default_resize_mode))
binding.playerResizeMode.setOnClickListener {
val dialog = resizeDialog.setSingleChoiceItems(resizeModes, PrefManager.getVal<Int>(PrefName.Resize)) { dialog, count ->
val dialog = resizeDialog.setSingleChoiceItems(
resizeModes,
PrefManager.getVal<Int>(PrefName.Resize)
) { dialog, count ->
PrefManager.setVal(PrefName.Resize, count)
dialog.dismiss()
}.show()
@ -425,7 +442,10 @@ class PlayerSettingsActivity : AppCompatActivity() {
val fontDialog = AlertDialog.Builder(this, R.style.MyPopup)
.setTitle(getString(R.string.subtitle_font))
binding.videoSubFont.setOnClickListener {
val dialog = fontDialog.setSingleChoiceItems(fonts, PrefManager.getVal(PrefName.Font)) { dialog, count ->
val dialog = fontDialog.setSingleChoiceItems(
fonts,
PrefManager.getVal(PrefName.Font)
) { dialog, count ->
PrefManager.setVal(PrefName.Font, count)
dialog.dismiss()
}.show()

View file

@ -8,8 +8,8 @@ import ani.dantotsu.R
import ani.dantotsu.databinding.ActivityReaderSettingsBinding
import ani.dantotsu.initActivity
import ani.dantotsu.navBarHeight
import ani.dantotsu.settings.saving.PrefName
import ani.dantotsu.settings.saving.PrefManager
import ani.dantotsu.settings.saving.PrefName
import ani.dantotsu.snackString
import ani.dantotsu.statusBarHeight
import ani.dantotsu.themes.ThemeManager
@ -20,7 +20,7 @@ class ReaderSettingsActivity : AppCompatActivity() {
private var defaultSettingsLN = CurrentNovelReaderSettings()
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
ThemeManager(this).applyTheme()
binding = ActivityReaderSettingsBinding.inflate(layoutInflater)
setContentView(binding.root)
@ -107,7 +107,10 @@ class ReaderSettingsActivity : AppCompatActivity() {
defaultSettings.dualPageMode = CurrentReaderSettings.DualPageModes[index]
?: CurrentReaderSettings.DualPageModes.Automatic
binding.readerSettingsDualPageText.text = defaultSettings.dualPageMode.toString()
PrefManager.setVal(PrefName.DualPageModeReader, defaultSettings.dualPageMode.ordinal)
PrefManager.setVal(
PrefName.DualPageModeReader,
defaultSettings.dualPageMode.ordinal
)
}
}
binding.readerSettingsTrueColors.isChecked = defaultSettings.trueColors
@ -215,7 +218,10 @@ class ReaderSettingsActivity : AppCompatActivity() {
defaultSettingsLN.dualPageMode = CurrentReaderSettings.DualPageModes[index]
?: CurrentReaderSettings.DualPageModes.Automatic
binding.LNdualPageText.text = defaultSettingsLN.dualPageMode.toString()
PrefManager.setVal(PrefName.DualPageModeNovel, defaultSettingsLN.dualPageMode.ordinal)
PrefManager.setVal(
PrefName.DualPageModeNovel,
defaultSettingsLN.dualPageMode.ordinal
)
}
}
@ -339,11 +345,13 @@ class ReaderSettingsActivity : AppCompatActivity() {
}
//Update Progress
binding.readerSettingsAskUpdateProgress.isChecked = PrefManager.getVal(PrefName.AskIndividualReader)
binding.readerSettingsAskUpdateProgress.isChecked =
PrefManager.getVal(PrefName.AskIndividualReader)
binding.readerSettingsAskUpdateProgress.setOnCheckedChangeListener { _, isChecked ->
PrefManager.setVal(PrefName.AskIndividualReader, isChecked)
}
binding.readerSettingsAskUpdateDoujins.isChecked = PrefManager.getVal(PrefName.UpdateForHReader)
binding.readerSettingsAskUpdateDoujins.isChecked =
PrefManager.getVal(PrefName.UpdateForHReader)
binding.readerSettingsAskUpdateDoujins.setOnCheckedChangeListener { _, isChecked ->
PrefManager.setVal(PrefName.UpdateForHReader, isChecked)
if (isChecked) snackString(getString(R.string.very_bold))

View file

@ -4,8 +4,12 @@ import android.annotation.SuppressLint
import android.app.AlertDialog
import android.content.Intent
import android.graphics.drawable.Animatable
import android.os.Build.*
import android.os.Build.VERSION.*
import android.os.Build.BRAND
import android.os.Build.DEVICE
import android.os.Build.SUPPORTED_ABIS
import android.os.Build.VERSION.CODENAME
import android.os.Build.VERSION.RELEASE
import android.os.Build.VERSION.SDK_INT
import android.os.Bundle
import android.view.LayoutInflater
import android.view.View
@ -14,9 +18,7 @@ import android.widget.ArrayAdapter
import android.widget.TextView
import android.widget.Toast
import androidx.activity.OnBackPressedCallback
import androidx.activity.result.ActivityResultLauncher
import androidx.activity.result.contract.ActivityResultContracts
import androidx.activity.result.contract.ActivityResultContracts.CreateDocument
import androidx.annotation.OptIn
import androidx.appcompat.app.AppCompatActivity
import androidx.core.content.ContextCompat
@ -25,34 +27,45 @@ import androidx.documentfile.provider.DocumentFile
import androidx.lifecycle.lifecycleScope
import androidx.media3.common.util.UnstableApi
import androidx.media3.exoplayer.offline.DownloadService
import ani.dantotsu.*
import ani.dantotsu.Mapper.json
import ani.dantotsu.BuildConfig
import ani.dantotsu.R
import ani.dantotsu.Refresh
import ani.dantotsu.connections.anilist.Anilist
import ani.dantotsu.connections.discord.Discord
import ani.dantotsu.connections.mal.MAL
import ani.dantotsu.copyToClipboard
import ani.dantotsu.currContext
import ani.dantotsu.databinding.ActivitySettingsBinding
import ani.dantotsu.download.DownloadedType
import ani.dantotsu.download.DownloadsManager
import ani.dantotsu.download.video.ExoplayerDownloadService
import ani.dantotsu.initActivity
import ani.dantotsu.loadImage
import ani.dantotsu.logger
import ani.dantotsu.navBarHeight
import ani.dantotsu.openLinkInBrowser
import ani.dantotsu.others.AppUpdater
import ani.dantotsu.others.CustomBottomDialog
import ani.dantotsu.parsers.AnimeSources
import ani.dantotsu.parsers.MangaSources
import ani.dantotsu.settings.saving.PrefName
import ani.dantotsu.pop
import ani.dantotsu.savePrefsToDownloads
import ani.dantotsu.setSafeOnClickListener
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.snackString
import ani.dantotsu.startMainActivity
import ani.dantotsu.statusBarHeight
import ani.dantotsu.subcriptions.Notifications
import ani.dantotsu.subcriptions.Notifications.Companion.openSettings
import ani.dantotsu.subcriptions.Subscription.Companion.defaultTime
import ani.dantotsu.subcriptions.Subscription.Companion.startSubscription
import ani.dantotsu.subcriptions.Subscription.Companion.timeMinutes
import ani.dantotsu.themes.ThemeManager
import ani.dantotsu.toast
import com.google.android.material.snackbar.Snackbar
import com.google.android.material.textfield.TextInputEditText
import com.google.gson.Gson
import com.google.gson.reflect.TypeToken
import eltos.simpledialogfragment.SimpleDialog
import eltos.simpledialogfragment.SimpleDialog.OnDialogResultListener.BUTTON_POSITIVE
import eltos.simpledialogfragment.color.SimpleColorDialog
@ -85,47 +98,48 @@ 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("Incorrect password")
return@passwordAlertDialog
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("Incorrect password")
return@passwordAlertDialog
}
if (PreferencePackager.unpack(decryptedJson))
restartApp()
} else {
toast("Password cannot be empty")
}
if(PreferencePackager.unpack(decryptedJson))
restartApp()
} else {
toast("Password cannot be empty")
}
} else if (name.endsWith(".ani")) {
val decryptedJson = jsonString.toString(Charsets.UTF_8)
if (PreferencePackager.unpack(decryptedJson))
restartApp()
} else {
toast("Unknown file type")
}
} else if (name.endsWith(".ani")) {
val decryptedJson = jsonString.toString(Charsets.UTF_8)
if(PreferencePackager.unpack(decryptedJson))
restartApp()
} else {
toast("Unknown file type")
} catch (e: Exception) {
e.printStackTrace()
toast("Error importing settings")
}
} catch (e: Exception) {
e.printStackTrace()
toast("Error importing settings")
}
}
}
binding.settingsVersion.text = getString(R.string.version_current, BuildConfig.VERSION_NAME)
binding.settingsVersion.setOnLongClickListener {
@ -244,7 +258,10 @@ class SettingsActivity : AppCompatActivity(), SimpleDialog.OnDialogResultListene
selectedArray.addAll(List(filteredLocations.size - 1) { false })
val dialog = AlertDialog.Builder(this, R.style.MyPopup)
.setTitle("Import/Export Settings")
.setMultiChoiceItems( filteredLocations.map { it.name }.toTypedArray(), selectedArray.toBooleanArray()) { _, which, isChecked ->
.setMultiChoiceItems(
filteredLocations.map { it.name }.toTypedArray(),
selectedArray.toBooleanArray()
) { _, which, isChecked ->
selectedArray[which] = isChecked
}
.setPositiveButton("Import...") { dialog, _ ->
@ -257,7 +274,8 @@ class SettingsActivity : AppCompatActivity(), SimpleDialog.OnDialogResultListene
return@setNegativeButton
}
dialog.dismiss()
val selected = filteredLocations.filterIndexed { index, _ -> selectedArray[index] }
val selected =
filteredLocations.filterIndexed { index, _ -> selectedArray[index] }
if (selected.contains(Location.Protected)) {
passwordAlertDialog(true) { password ->
if (password != null) {
@ -360,7 +378,7 @@ class SettingsActivity : AppCompatActivity(), SimpleDialog.OnDialogResultListene
}
binding.NSFWExtension.isChecked = PrefManager.getVal(PrefName.NSFWExtension)
binding.NSFWExtension.setOnCheckedChangeListener { _, isChecked ->
PrefManager.setVal(PrefName.NSFWExtension,isChecked)
PrefManager.setVal(PrefName.NSFWExtension, isChecked)
}
@ -847,7 +865,8 @@ class SettingsActivity : AppCompatActivity(), SimpleDialog.OnDialogResultListene
show()
}
}
private fun passwordAlertDialog(isExporting:Boolean, callback: (CharArray?) -> Unit) {
private fun passwordAlertDialog(isExporting: Boolean, callback: (CharArray?) -> Unit) {
val password = CharArray(16).apply { fill('0') }
// Inflate the dialog layout

View file

@ -3,8 +3,6 @@ package ani.dantotsu.settings
import android.content.Intent
import android.graphics.Color
import android.os.Bundle
import java.util.*
import kotlin.concurrent.schedule
import android.util.TypedValue
import android.view.LayoutInflater
import android.view.View
@ -27,9 +25,11 @@ import ani.dantotsu.offline.OfflineFragment
import ani.dantotsu.openLinkInBrowser
import ani.dantotsu.others.imagesearch.ImageSearchActivity
import ani.dantotsu.setSafeOnClickListener
import ani.dantotsu.settings.saving.PrefName
import ani.dantotsu.settings.saving.PrefManager
import ani.dantotsu.settings.saving.PrefName
import ani.dantotsu.startMainActivity
import java.util.Timer
import kotlin.concurrent.schedule
class SettingsDialogFragment : BottomSheetDialogFragment() {
private var _binding: BottomSheetSettingsBinding? = null
@ -103,58 +103,58 @@ class SettingsDialogFragment : BottomSheetDialogFragment() {
binding.settingsDownloads.isChecked = PrefManager.getVal(PrefName.OfflineMode)
binding.settingsDownloads.setOnCheckedChangeListener { _, isChecked ->
Timer().schedule(300){
when (pageType) {
PageType.MANGA -> {
val intent = Intent(activity, NoInternet::class.java)
intent.putExtra(
"FRAGMENT_CLASS_NAME",
OfflineMangaFragment::class.java.name
)
startActivity(intent)
Timer().schedule(300) {
when (pageType) {
PageType.MANGA -> {
val intent = Intent(activity, NoInternet::class.java)
intent.putExtra(
"FRAGMENT_CLASS_NAME",
OfflineMangaFragment::class.java.name
)
startActivity(intent)
}
PageType.ANIME -> {
val intent = Intent(activity, NoInternet::class.java)
intent.putExtra(
"FRAGMENT_CLASS_NAME",
OfflineAnimeFragment::class.java.name
)
startActivity(intent)
}
PageType.HOME -> {
val intent = Intent(activity, NoInternet::class.java)
intent.putExtra("FRAGMENT_CLASS_NAME", OfflineFragment::class.java.name)
startActivity(intent)
}
PageType.OfflineMANGA -> {
val intent = Intent(activity, MainActivity::class.java)
intent.putExtra("FRAGMENT_CLASS_NAME", MangaFragment::class.java.name)
startActivity(intent)
}
PageType.OfflineHOME -> {
val intent = Intent(activity, MainActivity::class.java)
intent.putExtra(
"FRAGMENT_CLASS_NAME",
if (Anilist.token != null) HomeFragment::class.java.name else LoginFragment::class.java.name
)
startActivity(intent)
}
PageType.OfflineANIME -> {
val intent = Intent(activity, MainActivity::class.java)
intent.putExtra("FRAGMENT_CLASS_NAME", AnimeFragment::class.java.name)
startActivity(intent)
}
}
PageType.ANIME -> {
val intent = Intent(activity, NoInternet::class.java)
intent.putExtra(
"FRAGMENT_CLASS_NAME",
OfflineAnimeFragment::class.java.name
)
startActivity(intent)
}
PageType.HOME -> {
val intent = Intent(activity, NoInternet::class.java)
intent.putExtra("FRAGMENT_CLASS_NAME", OfflineFragment::class.java.name)
startActivity(intent)
}
PageType.OfflineMANGA -> {
val intent = Intent(activity, MainActivity::class.java)
intent.putExtra("FRAGMENT_CLASS_NAME", MangaFragment::class.java.name)
startActivity(intent)
}
PageType.OfflineHOME -> {
val intent = Intent(activity, MainActivity::class.java)
intent.putExtra(
"FRAGMENT_CLASS_NAME",
if (Anilist.token != null) HomeFragment::class.java.name else LoginFragment::class.java.name
)
startActivity(intent)
}
PageType.OfflineANIME -> {
val intent = Intent(activity, MainActivity::class.java)
intent.putExtra("FRAGMENT_CLASS_NAME", AnimeFragment::class.java.name)
startActivity(intent)
}
dismiss()
PrefManager.setVal(PrefName.OfflineMode, isChecked)
}
dismiss()
PrefManager.setVal(PrefName.OfflineMode, isChecked)
}
}
}
override fun onDestroyView() {

View file

@ -10,8 +10,8 @@ import ani.dantotsu.R
import ani.dantotsu.databinding.ActivityUserInterfaceSettingsBinding
import ani.dantotsu.initActivity
import ani.dantotsu.navBarHeight
import ani.dantotsu.settings.saving.PrefName
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.snackbar.Snackbar
@ -21,7 +21,7 @@ class UserInterfaceSettingsActivity : AppCompatActivity() {
private val ui = "ui_settings"
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
ThemeManager(this).applyTheme()
binding = ActivityUserInterfaceSettingsBinding.inflate(layoutInflater)
setContentView(binding.root)
@ -44,7 +44,8 @@ class UserInterfaceSettingsActivity : AppCompatActivity() {
views,
PrefManager.getVal<List<Boolean>>(PrefName.HomeLayoutShow).toBooleanArray()
) { _, i, value ->
val set = PrefManager.getVal<List<Boolean>>(PrefName.HomeLayoutShow).toMutableList()
val set = PrefManager.getVal<List<Boolean>>(PrefName.HomeLayoutShow)
.toMutableList()
set[i] = value
PrefManager.setVal(PrefName.HomeLayoutShow, set)
}
@ -87,7 +88,8 @@ class UserInterfaceSettingsActivity : AppCompatActivity() {
0f to 0f
)
val mapReverse = map.map { it.value to it.key }.toMap()
binding.uiSettingsAnimationSpeed.value = mapReverse[PrefManager.getVal(PrefName.AnimationSpeed)] ?: 1f
binding.uiSettingsAnimationSpeed.value =
mapReverse[PrefManager.getVal(PrefName.AnimationSpeed)] ?: 1f
binding.uiSettingsAnimationSpeed.addOnChangeListener { _, value, _ ->
PrefManager.setVal(PrefName.AnimationSpeed, map[value] ?: 1f)
restartApp()

View file

@ -20,8 +20,8 @@ import androidx.recyclerview.widget.RecyclerView
import ani.dantotsu.R
import ani.dantotsu.databinding.ItemExtensionAllBinding
import ani.dantotsu.others.LanguageMapper
import ani.dantotsu.settings.saving.PrefName
import ani.dantotsu.settings.saving.PrefManager
import ani.dantotsu.settings.saving.PrefName
import com.bumptech.glide.Glide
import eu.kanade.tachiyomi.extension.anime.AnimeExtensionManager
import eu.kanade.tachiyomi.extension.anime.model.AnimeExtension
@ -103,7 +103,8 @@ class AnimeExtensionPagingSource(
availableExtensions.filter { it.name.contains(query, ignoreCase = true) }
}
val lang: String = PrefManager.getVal(PrefName.LangSort)
val langFilter = if (lang != "all") filteredExtensions.filter { it.lang == lang } else filteredExtensions
val langFilter =
if (lang != "all") filteredExtensions.filter { it.lang == lang } else filteredExtensions
val filternfsw = if (isNsfwEnabled) langFilter else langFilter.filterNot { it.isNsfw }
return try {
val sublist = filternfsw.subList(

View file

@ -20,8 +20,8 @@ import androidx.recyclerview.widget.RecyclerView
import ani.dantotsu.R
import ani.dantotsu.databinding.ItemExtensionAllBinding
import ani.dantotsu.others.LanguageMapper
import ani.dantotsu.settings.saving.PrefName
import ani.dantotsu.settings.saving.PrefManager
import ani.dantotsu.settings.saving.PrefName
import com.bumptech.glide.Glide
import eu.kanade.tachiyomi.extension.manga.MangaExtensionManager
import eu.kanade.tachiyomi.extension.manga.model.MangaExtension
@ -102,7 +102,8 @@ class MangaExtensionPagingSource(
availableExtensions.filter { it.name.contains(query, ignoreCase = true) }
}
val lang: String = PrefManager.getVal(PrefName.LangSort)
val langFilter = if (lang != "all") filteredExtensions.filter { it.lang == lang } else filteredExtensions
val langFilter =
if (lang != "all") filteredExtensions.filter { it.lang == lang } else filteredExtensions
val filternfsw = if (isNsfwEnabled) langFilter else langFilter.filterNot { it.isNsfw }
return try {
val sublist = filternfsw.subList(

View file

@ -21,8 +21,8 @@ import ani.dantotsu.databinding.ItemExtensionAllBinding
import ani.dantotsu.others.LanguageMapper
import ani.dantotsu.parsers.novel.NovelExtension
import ani.dantotsu.parsers.novel.NovelExtensionManager
import ani.dantotsu.settings.saving.PrefName
import ani.dantotsu.settings.saving.PrefManager
import ani.dantotsu.settings.saving.PrefName
import com.bumptech.glide.Glide
import kotlinx.coroutines.CoroutineScope
import kotlinx.coroutines.Dispatchers

View file

@ -22,12 +22,18 @@ object PrefManager {
private var protectedPreferences: SharedPreferences? = null
fun init(context: Context) { //must be called in Application class or will crash
generalPreferences = context.getSharedPreferences(Location.General.location, Context.MODE_PRIVATE)
playerPreferences = context.getSharedPreferences(Location.Player.location, Context.MODE_PRIVATE)
readerPreferences = context.getSharedPreferences(Location.Reader.location, Context.MODE_PRIVATE)
irrelevantPreferences = context.getSharedPreferences(Location.Irrelevant.location, Context.MODE_PRIVATE)
animeDownloadsPreferences = context.getSharedPreferences(Location.AnimeDownloads.location, Context.MODE_PRIVATE)
protectedPreferences = context.getSharedPreferences(Location.Protected.location, Context.MODE_PRIVATE)
generalPreferences =
context.getSharedPreferences(Location.General.location, Context.MODE_PRIVATE)
playerPreferences =
context.getSharedPreferences(Location.Player.location, Context.MODE_PRIVATE)
readerPreferences =
context.getSharedPreferences(Location.Reader.location, Context.MODE_PRIVATE)
irrelevantPreferences =
context.getSharedPreferences(Location.Irrelevant.location, Context.MODE_PRIVATE)
animeDownloadsPreferences =
context.getSharedPreferences(Location.AnimeDownloads.location, Context.MODE_PRIVATE)
protectedPreferences =
context.getSharedPreferences(Location.Protected.location, Context.MODE_PRIVATE)
Compat.importOldPrefs(context)
}
@ -49,7 +55,7 @@ object PrefManager {
}
@Suppress("UNCHECKED_CAST")
fun <T> getVal(prefName: PrefName, default: T) : T {
fun <T> getVal(prefName: PrefName, default: T): T {
return try {
val pref = getPrefLocation(prefName.data.prefLocation)
when (prefName.data.type) {
@ -58,8 +64,17 @@ object PrefManager {
Float::class -> pref.getFloat(prefName.name, default as Float) as T
Long::class -> pref.getLong(prefName.name, default as Long) as T
String::class -> pref.getString(prefName.name, default as String?) as T
Set::class -> convertFromStringSet(pref.getStringSet(prefName.name, null), default) as T
List::class -> deserializeClass(prefName.name, default, prefName.data.prefLocation) as T
Set::class -> convertFromStringSet(
pref.getStringSet(prefName.name, null),
default
) as T
List::class -> deserializeClass(
prefName.name,
default,
prefName.data.prefLocation
) as T
else -> throw IllegalArgumentException("Type not supported")
}
} catch (e: Exception) {
@ -68,17 +83,34 @@ object PrefManager {
}
@Suppress("UNCHECKED_CAST")
fun <T> getVal(prefName: PrefName) : T {
fun <T> getVal(prefName: PrefName): T {
return try {
val pref = getPrefLocation(prefName.data.prefLocation)
when (prefName.data.type) {
Boolean::class -> pref.getBoolean(prefName.name, prefName.data.default as Boolean) as T
Boolean::class -> pref.getBoolean(
prefName.name,
prefName.data.default as Boolean
) as T
Int::class -> pref.getInt(prefName.name, prefName.data.default as Int) as T
Float::class -> pref.getFloat(prefName.name, prefName.data.default as Float) as T
Long::class -> pref.getLong(prefName.name, prefName.data.default as Long) as T
String::class -> pref.getString(prefName.name, prefName.data.default as String?) as T
Set::class -> convertFromStringSet(pref.getStringSet(prefName.name, null), prefName.data.default) as T
List::class -> deserializeClass(prefName.name, prefName.data.default, prefName.data.prefLocation) as T
String::class -> pref.getString(
prefName.name,
prefName.data.default as String?
) as T
Set::class -> convertFromStringSet(
pref.getStringSet(prefName.name, null),
prefName.data.default
) as T
List::class -> deserializeClass(
prefName.name,
prefName.data.default,
prefName.data.prefLocation
) as T
else -> throw IllegalArgumentException("Type not supported")
}
} catch (e: Exception) {
@ -87,7 +119,10 @@ object PrefManager {
}
@Suppress("UNCHECKED_CAST")
fun <T> getNullableVal(prefName: PrefName, default: T?) : T? { //Strings don't necessarily need to use this one
fun <T> getNullableVal(
prefName: PrefName,
default: T?
): T? { //Strings don't necessarily need to use this one
return try {
val pref = getPrefLocation(prefName.data.prefLocation)
when (prefName.data.type) {
@ -96,7 +131,11 @@ object PrefManager {
Float::class -> pref.getFloat(prefName.name, default as Float) as T?
Long::class -> pref.getLong(prefName.name, default as Long) as T?
String::class -> pref.getString(prefName.name, default as String?) as T?
Set::class -> convertFromStringSet(pref.getStringSet(prefName.name, null), default) as T?
Set::class -> convertFromStringSet(
pref.getStringSet(prefName.name, null),
default
) as T?
else -> deserializeClass(prefName.name, default, prefName.data.prefLocation)
}
} catch (e: Exception) {
@ -113,7 +152,11 @@ object PrefManager {
is Float -> irrelevantPreferences!!.getFloat(key, default) as T
is Long -> irrelevantPreferences!!.getLong(key, default) as T
is String -> irrelevantPreferences!!.getString(key, default) as T
is Set<*> -> convertFromStringSet(irrelevantPreferences!!.getStringSet(key, null), default) as T
is Set<*> -> convertFromStringSet(
irrelevantPreferences!!.getStringSet(key, null),
default
) as T
else -> throw IllegalArgumentException("Type not supported")
}
} catch (e: Exception) {
@ -125,12 +168,36 @@ object PrefManager {
fun <T> getNullableCustomVal(key: String, default: T?, clazz: Class<T>): T? {
return try {
when {
clazz.isAssignableFrom(Boolean::class.java) -> irrelevantPreferences!!.getBoolean(key, default as? Boolean ?: false) as T?
clazz.isAssignableFrom(Int::class.java) -> irrelevantPreferences!!.getInt(key, default as? Int ?: 0) as T?
clazz.isAssignableFrom(Float::class.java) -> irrelevantPreferences!!.getFloat(key, default as? Float ?: 0f) as T?
clazz.isAssignableFrom(Long::class.java) -> irrelevantPreferences!!.getLong(key, default as? Long ?: 0L) as T?
clazz.isAssignableFrom(String::class.java) -> irrelevantPreferences!!.getString(key, default as? String) as T?
clazz.isAssignableFrom(Set::class.java) -> convertFromStringSet(irrelevantPreferences!!.getStringSet(key, null), default) as T?
clazz.isAssignableFrom(Boolean::class.java) -> irrelevantPreferences!!.getBoolean(
key,
default as? Boolean ?: false
) as T?
clazz.isAssignableFrom(Int::class.java) -> irrelevantPreferences!!.getInt(
key,
default as? Int ?: 0
) as T?
clazz.isAssignableFrom(Float::class.java) -> irrelevantPreferences!!.getFloat(
key,
default as? Float ?: 0f
) as T?
clazz.isAssignableFrom(Long::class.java) -> irrelevantPreferences!!.getLong(
key,
default as? Long ?: 0L
) as T?
clazz.isAssignableFrom(String::class.java) -> irrelevantPreferences!!.getString(
key,
default as? String
) as T?
clazz.isAssignableFrom(Set::class.java) -> convertFromStringSet(
irrelevantPreferences!!.getStringSet(key, null),
default
) as T?
else -> deserializeClass(key, default, Location.Irrelevant)
}
} catch (e: Exception) {
@ -173,7 +240,7 @@ object PrefManager {
}
@Suppress("UNCHECKED_CAST")
fun <T> getLiveVal(prefName: PrefName, default: T) : SharedPreferenceLiveData<T> {
fun <T> getLiveVal(prefName: PrefName, default: T): SharedPreferenceLiveData<T> {
val pref = getPrefLocation(prefName.data.prefLocation)
return when (prefName.data.type) {
Boolean::class -> SharedPreferenceBooleanLiveData(
@ -181,31 +248,37 @@ object PrefManager {
prefName.name,
default as Boolean
) as SharedPreferenceLiveData<T>
Int::class -> SharedPreferenceIntLiveData(
pref,
prefName.name,
default as Int
) as SharedPreferenceLiveData<T>
Float::class -> SharedPreferenceFloatLiveData(
pref,
prefName.name,
default as Float
) as SharedPreferenceLiveData<T>
Long::class -> SharedPreferenceLongLiveData(
pref,
prefName.name,
default as Long
) as SharedPreferenceLiveData<T>
String::class -> SharedPreferenceStringLiveData(
pref,
prefName.name,
default as String
) as SharedPreferenceLiveData<T>
Set::class -> SharedPreferenceStringSetLiveData(
pref,
prefName.name,
default as Set<String>
) as SharedPreferenceLiveData<T>
else -> throw IllegalArgumentException("Type not supported")
}
}
@ -234,7 +307,8 @@ object PrefManager {
this as? SharedPreferenceStringSetLiveData
?: throw ClassCastException("Cannot cast to SharedPreferenceLiveData<Set<String>>")
fun getAnimeDownloadPreferences(): SharedPreferences = animeDownloadsPreferences!! //needs to be used externally
fun getAnimeDownloadPreferences(): SharedPreferences =
animeDownloadsPreferences!! //needs to be used externally
fun exportAllPrefs(prefLocation: List<Location>): String {
return PreferencePackager.pack(
@ -272,7 +346,7 @@ object PrefManager {
return if (hadError) {
snackString("Error importing preferences")
false
} else {
} else {
snackString("Preferences imported")
true
}
@ -331,7 +405,7 @@ object PrefManager {
}
private fun <T> serializeClass(key: String, value: T, location: Location){
private fun <T> serializeClass(key: String, value: T, location: Location) {
val pref = getPrefLocation(location)
try {
val bos = ByteArrayOutputStream()

View file

@ -2,8 +2,8 @@ package ani.dantotsu.settings.saving
import android.graphics.Color
import ani.dantotsu.connections.mal.MAL
import ani.dantotsu.settings.saving.internal.Pref
import ani.dantotsu.settings.saving.internal.Location
import ani.dantotsu.settings.saving.internal.Pref
enum class PrefName(val data: Pref) { //TODO: Split this into multiple files
//General
@ -20,7 +20,13 @@ enum class PrefName(val data: Pref) { //TODO: Split this into multiple files
CheckUpdate(Pref(Location.General, Boolean::class, true)),
VerboseLogging(Pref(Location.General, Boolean::class, false)),
DohProvider(Pref(Location.General, Int::class, 0)),
DefaultUserAgent(Pref(Location.General, String::class, "Mozilla/5.0 (Windows NT 10.0; Win64; x64; rv:110.0) Gecko/20100101 Firefox/110.0")),
DefaultUserAgent(
Pref(
Location.General,
String::class,
"Mozilla/5.0 (Windows NT 10.0; Win64; x64; rv:110.0) Gecko/20100101 Firefox/110.0"
)
),
AnimeSourcesOrder(Pref(Location.General, List::class, listOf<String>())),
AnimeSearchHistory(Pref(Location.General, Set::class, setOf<String>())),
MangaSourcesOrder(Pref(Location.General, List::class, listOf<String>())),
@ -42,7 +48,13 @@ enum class PrefName(val data: Pref) { //TODO: Split this into multiple files
ImmersiveMode(Pref(Location.UI, Boolean::class, false)),
SmallView(Pref(Location.UI, Boolean::class, true)),
DefaultStartUpTab(Pref(Location.UI, Int::class, 1)),
HomeLayoutShow(Pref(Location.UI, List::class, listOf(true, false, false, true, false, false, true))),
HomeLayoutShow(
Pref(
Location.UI,
List::class,
listOf(true, false, false, true, false, false, true)
)
),
BannerAnimations(Pref(Location.UI, Boolean::class, true)),
LayoutAnimations(Pref(Location.UI, Boolean::class, true)),
AnimationSpeed(Pref(Location.UI, Float::class, 1f)),

View file

@ -1,8 +1,8 @@
package ani.dantotsu.settings.saving.internal
import android.content.Context
import ani.dantotsu.settings.saving.PrefName
import ani.dantotsu.settings.saving.PrefManager
import ani.dantotsu.settings.saving.PrefName
class Compat {
companion object {

View file

@ -8,6 +8,7 @@ data class Pref(
val type: KClass<*>,
val default: Any
)
enum class Location(val location: String, val exportable: Boolean) {
General("ani.dantotsu.general", true),
UI("ani.dantotsu.ui", true),

View file

@ -2,7 +2,6 @@ package ani.dantotsu.settings.saving.internal
import android.security.keystore.KeyGenParameterSpec
import android.security.keystore.KeyProperties
import java.security.KeyStore
import java.security.SecureRandom
import javax.crypto.Cipher
import javax.crypto.KeyGenerator
@ -15,7 +14,8 @@ import javax.crypto.spec.PBEKeySpec
class PreferenceKeystore {
companion object {
fun generateKey(alias: String) {
val keyGenerator = KeyGenerator.getInstance(KeyProperties.KEY_ALGORITHM_AES, "AndroidKeyStore")
val keyGenerator =
KeyGenerator.getInstance(KeyProperties.KEY_ALGORITHM_AES, "AndroidKeyStore")
keyGenerator.init(
KeyGenParameterSpec.Builder(
@ -30,17 +30,31 @@ class PreferenceKeystore {
keyGenerator.generateKey()
}
fun encryptWithPassword(password: CharArray, plaintext: String, salt: ByteArray): ByteArray {
fun encryptWithPassword(
password: CharArray,
plaintext: String,
salt: ByteArray
): ByteArray {
val secretKey = deriveKeyFromPassword(password, salt)
val cipher = Cipher.getInstance("${KeyProperties.KEY_ALGORITHM_AES}/${KeyProperties.BLOCK_MODE_CBC}/${KeyProperties.ENCRYPTION_PADDING_PKCS7}")
val cipher =
Cipher.getInstance("${KeyProperties.KEY_ALGORITHM_AES}/${KeyProperties.BLOCK_MODE_CBC}/${KeyProperties.ENCRYPTION_PADDING_PKCS7}")
cipher.init(Cipher.ENCRYPT_MODE, secretKey, IvParameterSpec(ByteArray(16)))
return cipher.doFinal(plaintext.toByteArray(Charsets.UTF_8))
}
fun decryptWithPassword(password: CharArray, ciphertext: ByteArray, salt: ByteArray): String {
fun decryptWithPassword(
password: CharArray,
ciphertext: ByteArray,
salt: ByteArray
): String {
val secretKey = deriveKeyFromPassword(password, salt)
val cipher = Cipher.getInstance("${KeyProperties.KEY_ALGORITHM_AES}/${KeyProperties.BLOCK_MODE_CBC}/${KeyProperties.ENCRYPTION_PADDING_PKCS7}")
cipher.init(Cipher.DECRYPT_MODE, secretKey, IvParameterSpec(ByteArray(16))) // Use the correct IV
val cipher =
Cipher.getInstance("${KeyProperties.KEY_ALGORITHM_AES}/${KeyProperties.BLOCK_MODE_CBC}/${KeyProperties.ENCRYPTION_PADDING_PKCS7}")
cipher.init(
Cipher.DECRYPT_MODE,
secretKey,
IvParameterSpec(ByteArray(16))
) // Use the correct IV
return cipher.doFinal(ciphertext).toString(Charsets.UTF_8)
}

View file

@ -1,11 +1,7 @@
package ani.dantotsu.settings.saving.internal
import android.content.SharedPreferences
import android.net.Uri
import androidx.documentfile.provider.DocumentFile
import ani.dantotsu.connections.discord.serializers.Activity
import ani.dantotsu.settings.saving.PrefManager
import ani.dantotsu.toast
import com.google.gson.Gson
import com.google.gson.reflect.TypeToken
@ -28,8 +24,10 @@ class PreferencePackager {
*/
fun unpack(decryptedJson: String): Boolean {
val gson = Gson()
val type = object : TypeToken<Map<String, Map<String, Map<String, Any>>>>() {}.type //oh god...
val rawPrefsMap: Map<String, Map<String, Map<String, Any>>> = gson.fromJson(decryptedJson, type)
val type = object :
TypeToken<Map<String, Map<String, Map<String, Any>>>>() {}.type //oh god...
val rawPrefsMap: Map<String, Map<String, Map<String, Any>>> =
gson.fromJson(decryptedJson, type)
val deserializedMap = mutableMapOf<String, Map<String, Any?>>()