import/export settings

This commit is contained in:
rebelonion 2024-02-02 02:04:46 -06:00
parent b559a13bab
commit 49e90a27b8
97 changed files with 1721 additions and 1441 deletions

View file

@ -29,7 +29,7 @@ android {
debug { debug {
applicationIdSuffix ".beta" applicationIdSuffix ".beta"
manifestPlaceholders = [icon_placeholder: "@mipmap/ic_launcher_beta", icon_placeholder_round: "@mipmap/ic_launcher_beta_round"] manifestPlaceholders = [icon_placeholder: "@mipmap/ic_launcher_beta", icon_placeholder_round: "@mipmap/ic_launcher_beta_round"]
debuggable System.getenv("CI") == null debuggable false
} }
release { release {
manifestPlaceholders = [icon_placeholder: "@mipmap/ic_launcher", icon_placeholder_round: "@mipmap/ic_launcher_round"] manifestPlaceholders = [icon_placeholder: "@mipmap/ic_launcher", icon_placeholder_round: "@mipmap/ic_launcher_round"]

View file

@ -15,7 +15,7 @@ import ani.dantotsu.parsers.NovelSources
import ani.dantotsu.parsers.novel.NovelExtensionManager import ani.dantotsu.parsers.novel.NovelExtensionManager
import ani.dantotsu.settings.SettingsActivity import ani.dantotsu.settings.SettingsActivity
import ani.dantotsu.settings.saving.PrefName import ani.dantotsu.settings.saving.PrefName
import ani.dantotsu.settings.saving.PrefWrapper import ani.dantotsu.settings.saving.PrefManager
import com.google.android.material.color.DynamicColors import com.google.android.material.color.DynamicColors
import com.google.firebase.crashlytics.FirebaseCrashlytics import com.google.firebase.crashlytics.FirebaseCrashlytics
import com.google.firebase.crashlytics.ktx.crashlytics import com.google.firebase.crashlytics.ktx.crashlytics
@ -54,9 +54,9 @@ class App : MultiDexApplication() {
override fun onCreate() { override fun onCreate() {
super.onCreate() super.onCreate()
PrefWrapper.init(this) PrefManager.init(this)
val useMaterialYou = PrefWrapper.getVal(PrefName.UseMaterialYou, false) val useMaterialYou: Boolean = PrefManager.getVal(PrefName.UseMaterialYou)
if (useMaterialYou) { if (useMaterialYou) {
DynamicColors.applyToActivitiesIfAvailable(this) DynamicColors.applyToActivitiesIfAvailable(this)
//TODO: HarmonizedColors //TODO: HarmonizedColors
@ -64,10 +64,10 @@ class App : MultiDexApplication() {
registerActivityLifecycleCallbacks(mFTActivityLifecycleCallbacks) registerActivityLifecycleCallbacks(mFTActivityLifecycleCallbacks)
Firebase.crashlytics.setCrashlyticsCollectionEnabled(!DisabledReports) Firebase.crashlytics.setCrashlyticsCollectionEnabled(!DisabledReports)
PrefWrapper.getVal(PrefName.SharedUserID, true).let { (PrefManager.getVal(PrefName.SharedUserID) as Boolean).let {
if (!it) return@let if (!it) return@let
val dUsername = PrefWrapper.getVal(PrefName.DiscordUserName, null as String?) val dUsername = PrefManager.getVal(PrefName.DiscordUserName, null as String?)
val aUsername = PrefWrapper.getVal(PrefName.AnilistUserName, null as String?) val aUsername = PrefManager.getVal(PrefName.AnilistUserName, null as String?)
if (dUsername != null || aUsername != null) { if (dUsername != null || aUsername != null) {
Firebase.crashlytics.setUserId("$dUsername - $aUsername") Firebase.crashlytics.setUserId("$dUsername - $aUsername")
} }

View file

@ -47,9 +47,8 @@ import ani.dantotsu.connections.anilist.api.FuzzyDate
import ani.dantotsu.databinding.ItemCountDownBinding import ani.dantotsu.databinding.ItemCountDownBinding
import ani.dantotsu.media.Media import ani.dantotsu.media.Media
import ani.dantotsu.parsers.ShowResponse import ani.dantotsu.parsers.ShowResponse
import ani.dantotsu.settings.UserInterfaceSettings
import ani.dantotsu.settings.saving.PrefName import ani.dantotsu.settings.saving.PrefName
import ani.dantotsu.settings.saving.PrefWrapper import ani.dantotsu.settings.saving.PrefManager
import ani.dantotsu.subcriptions.NotificationClickReceiver import ani.dantotsu.subcriptions.NotificationClickReceiver
import com.bumptech.glide.Glide import com.bumptech.glide.Glide
import com.bumptech.glide.load.model.GlideUrl import com.bumptech.glide.load.model.GlideUrl
@ -61,6 +60,7 @@ import com.google.android.material.bottomsheet.BottomSheetDialogFragment
import com.google.android.material.internal.ViewUtils import com.google.android.material.internal.ViewUtils
import com.google.android.material.snackbar.Snackbar import com.google.android.material.snackbar.Snackbar
import com.google.firebase.crashlytics.FirebaseCrashlytics import com.google.firebase.crashlytics.FirebaseCrashlytics
import com.google.gson.Gson
import eu.kanade.tachiyomi.data.notification.Notifications import eu.kanade.tachiyomi.data.notification.Notifications
import kotlinx.coroutines.* import kotlinx.coroutines.*
import nl.joery.animatedbottombar.AnimatedBottomBar import nl.joery.animatedbottombar.AnimatedBottomBar
@ -109,11 +109,9 @@ fun logger(e: Any?, print: Boolean = true) {
fun initActivity(a: Activity) { fun initActivity(a: Activity) {
val window = a.window val window = a.window
WindowCompat.setDecorFitsSystemWindows(window, false) WindowCompat.setDecorFitsSystemWindows(window, false)
val uiSettings = loadData<UserInterfaceSettings>("ui_settings", toast = false) val darkMode = PrefManager.getNullableVal(PrefName.DarkMode, null as Boolean?)
?: UserInterfaceSettings().apply { val immersiveMode: Boolean = PrefManager.getVal(PrefName.ImmersiveMode)
saveData("ui_settings", this) darkMode.apply {
}
uiSettings.darkMode.apply {
AppCompatDelegate.setDefaultNightMode( AppCompatDelegate.setDefaultNightMode(
when (this) { when (this) {
true -> AppCompatDelegate.MODE_NIGHT_YES true -> AppCompatDelegate.MODE_NIGHT_YES
@ -122,7 +120,7 @@ fun initActivity(a: Activity) {
} }
) )
} }
if (uiSettings.immersiveMode) { if (immersiveMode) {
if (navBarHeight == 0) { if (navBarHeight == 0) {
ViewCompat.getRootWindowInsets(window.decorView.findViewById(android.R.id.content)) ViewCompat.getRootWindowInsets(window.decorView.findViewById(android.R.id.content))
?.apply { ?.apply {
@ -290,20 +288,19 @@ class InputFilterMinMax(
} }
class ZoomOutPageTransformer(private val uiSettings: UserInterfaceSettings) : class ZoomOutPageTransformer() :
ViewPager2.PageTransformer { ViewPager2.PageTransformer {
override fun transformPage(view: View, position: Float) { override fun transformPage(view: View, position: Float) {
if (position == 0.0f && uiSettings.layoutAnimations) { if (position == 0.0f && PrefManager.getVal(PrefName.LayoutAnimations)) {
setAnimation( setAnimation(
view.context, view.context,
view, view,
uiSettings,
300, 300,
floatArrayOf(1.3f, 1f, 1.3f, 1f), floatArrayOf(1.3f, 1f, 1.3f, 1f),
0.5f to 0f 0.5f to 0f
) )
ObjectAnimator.ofFloat(view, "alpha", 0f, 1.0f) ObjectAnimator.ofFloat(view, "alpha", 0f, 1.0f)
.setDuration((200 * uiSettings.animationSpeed).toLong()).start() .setDuration((200 * (PrefManager.getVal(PrefName.AnimationSpeed) as Float)).toLong()).start()
} }
} }
} }
@ -311,12 +308,11 @@ class ZoomOutPageTransformer(private val uiSettings: UserInterfaceSettings) :
fun setAnimation( fun setAnimation(
context: Context, context: Context,
viewToAnimate: View, viewToAnimate: View,
uiSettings: UserInterfaceSettings,
duration: Long = 150, duration: Long = 150,
list: FloatArray = floatArrayOf(0.0f, 1.0f, 0.0f, 1.0f), list: FloatArray = floatArrayOf(0.0f, 1.0f, 0.0f, 1.0f),
pivot: Pair<Float, Float> = 0.5f to 0.5f pivot: Pair<Float, Float> = 0.5f to 0.5f
) { ) {
if (uiSettings.layoutAnimations) { if (PrefManager.getVal(PrefName.LayoutAnimations)) {
val anim = ScaleAnimation( val anim = ScaleAnimation(
list[0], list[0],
list[1], list[1],
@ -327,7 +323,7 @@ fun setAnimation(
Animation.RELATIVE_TO_SELF, Animation.RELATIVE_TO_SELF,
pivot.second pivot.second
) )
anim.duration = (duration * uiSettings.animationSpeed).toLong() anim.duration = (duration * (PrefManager.getVal(PrefName.AnimationSpeed) as Float)).toLong()
anim.setInterpolator(context, R.anim.over_shoot) anim.setInterpolator(context, R.anim.over_shoot)
viewToAnimate.startAnimation(anim) viewToAnimate.startAnimation(anim)
} }
@ -592,6 +588,34 @@ fun saveImageToDownloads(title: String, bitmap: Bitmap, context: Context) {
) )
} }
fun savePrefsToDownloads(title: String, map: Map<String, *>, context: Context) {
FileProvider.getUriForFile(
context,
"$APPLICATION_ID.provider",
savePrefs(
map,
Environment.getExternalStoragePublicDirectory(Environment.DIRECTORY_DOWNLOADS).absolutePath,
title,
context
) ?: return
)
}
fun savePrefs(map: Map<String, *>, path: String, title: String, context: Context): File? {
val file = File(path, "$title.ani")
return try {
val gson = Gson()
val json = gson.toJson(map)
file.writeText(json)
scanFile(file.absolutePath, context)
toast(String.format(context.getString(R.string.saved_to_path, path)))
file
} catch (e: Exception) {
snackString("Failed to save settings: ${e.localizedMessage}")
null
}
}
fun shareImage(title: String, bitmap: Bitmap, context: Context) { fun shareImage(title: String, bitmap: Bitmap, context: Context) {
val contentUri = FileProvider.getUriForFile( val contentUri = FileProvider.getUriForFile(
@ -708,10 +732,11 @@ fun MutableMap<String, Genre>.checkGenreTime(genre: String): Boolean {
return true return true
} }
fun setSlideIn(uiSettings: UserInterfaceSettings) = AnimationSet(false).apply { fun setSlideIn() = AnimationSet(false).apply {
if (uiSettings.layoutAnimations) { if (PrefManager.getVal(PrefName.LayoutAnimations)) {
var animation: Animation = AlphaAnimation(0.0f, 1.0f) var animation: Animation = AlphaAnimation(0.0f, 1.0f)
animation.duration = (500 * uiSettings.animationSpeed).toLong() val animationSpeed: Float = PrefManager.getVal(PrefName.AnimationSpeed)
animation.duration = (500 * animationSpeed).toLong()
animation.interpolator = AccelerateDecelerateInterpolator() animation.interpolator = AccelerateDecelerateInterpolator()
addAnimation(animation) addAnimation(animation)
@ -722,16 +747,17 @@ fun setSlideIn(uiSettings: UserInterfaceSettings) = AnimationSet(false).apply {
Animation.RELATIVE_TO_SELF, 0f Animation.RELATIVE_TO_SELF, 0f
) )
animation.duration = (750 * uiSettings.animationSpeed).toLong() animation.duration = (750 * animationSpeed).toLong()
animation.interpolator = OvershootInterpolator(1.1f) animation.interpolator = OvershootInterpolator(1.1f)
addAnimation(animation) addAnimation(animation)
} }
} }
fun setSlideUp(uiSettings: UserInterfaceSettings) = AnimationSet(false).apply { fun setSlideUp() = AnimationSet(false).apply {
if (uiSettings.layoutAnimations) { if (PrefManager.getVal(PrefName.LayoutAnimations)) {
var animation: Animation = AlphaAnimation(0.0f, 1.0f) var animation: Animation = AlphaAnimation(0.0f, 1.0f)
animation.duration = (500 * uiSettings.animationSpeed).toLong() val animationSpeed: Float = PrefManager.getVal(PrefName.AnimationSpeed)
animation.duration = (500 * animationSpeed).toLong()
animation.interpolator = AccelerateDecelerateInterpolator() animation.interpolator = AccelerateDecelerateInterpolator()
addAnimation(animation) addAnimation(animation)
@ -742,7 +768,7 @@ fun setSlideUp(uiSettings: UserInterfaceSettings) = AnimationSet(false).apply {
Animation.RELATIVE_TO_SELF, 0f Animation.RELATIVE_TO_SELF, 0f
) )
animation.duration = (750 * uiSettings.animationSpeed).toLong() animation.duration = (750 * animationSpeed).toLong()
animation.interpolator = OvershootInterpolator(1.1f) animation.interpolator = OvershootInterpolator(1.1f)
addAnimation(animation) addAnimation(animation)
} }
@ -929,7 +955,7 @@ const val INCOGNITO_CHANNEL_ID = 26
fun incognitoNotification(context: Context) { fun incognitoNotification(context: Context) {
val notificationManager = val notificationManager =
context.getSystemService(Context.NOTIFICATION_SERVICE) as NotificationManager context.getSystemService(Context.NOTIFICATION_SERVICE) as NotificationManager
val incognito = PrefWrapper.getVal(PrefName.Incognito, false) val incognito: Boolean = PrefManager.getVal(PrefName.Incognito)
if (incognito) { if (incognito) {
val intent = Intent(context, NotificationClickReceiver::class.java) val intent = Intent(context, NotificationClickReceiver::class.java)
val pendingIntent = PendingIntent.getBroadcast( val pendingIntent = PendingIntent.getBroadcast(

View file

@ -44,11 +44,11 @@ import ani.dantotsu.home.MangaFragment
import ani.dantotsu.home.NoInternet import ani.dantotsu.home.NoInternet
import ani.dantotsu.media.MediaDetailsActivity import ani.dantotsu.media.MediaDetailsActivity
import ani.dantotsu.others.CustomBottomDialog import ani.dantotsu.others.CustomBottomDialog
import ani.dantotsu.settings.UserInterfaceSettings
import ani.dantotsu.settings.saving.PrefName import ani.dantotsu.settings.saving.PrefName
import ani.dantotsu.settings.saving.PrefWrapper import ani.dantotsu.settings.saving.PrefManager
import ani.dantotsu.settings.saving.PrefWrapper.asLiveBool import ani.dantotsu.settings.saving.PrefManager.asLiveBool
import ani.dantotsu.settings.saving.SharedPreferenceBooleanLiveData import ani.dantotsu.settings.saving.SharedPreferenceBooleanLiveData
import ani.dantotsu.settings.saving.internal.Location
import ani.dantotsu.subcriptions.Subscription.Companion.startSubscription import ani.dantotsu.subcriptions.Subscription.Companion.startSubscription
import ani.dantotsu.themes.ThemeManager import ani.dantotsu.themes.ThemeManager
import eu.kanade.domain.source.service.SourcePreferences import eu.kanade.domain.source.service.SourcePreferences
@ -71,8 +71,6 @@ class MainActivity : AppCompatActivity() {
private val scope = lifecycleScope private val scope = lifecycleScope
private var load = false private var load = false
private var uiSettings = UserInterfaceSettings()
@SuppressLint("InternalInsetResource", "DiscouragedApi") @SuppressLint("InternalInsetResource", "DiscouragedApi")
@OptIn(UnstableApi::class) @OptIn(UnstableApi::class)
@ -108,7 +106,7 @@ class MainActivity : AppCompatActivity() {
val layoutParams = binding.incognito.layoutParams as ViewGroup.MarginLayoutParams val layoutParams = binding.incognito.layoutParams as ViewGroup.MarginLayoutParams
layoutParams.topMargin = 11 * offset / 12 layoutParams.topMargin = 11 * offset / 12
binding.incognito.layoutParams = layoutParams binding.incognito.layoutParams = layoutParams
incognitoLiveData = PrefWrapper.getLiveVal( incognitoLiveData = PrefManager.getLiveVal(
PrefName.Incognito, PrefName.Incognito,
false false
).asLiveBool() ).asLiveBool()
@ -208,7 +206,6 @@ class MainActivity : AppCompatActivity() {
binding.root.doOnAttach { binding.root.doOnAttach {
initActivity(this) initActivity(this)
uiSettings = loadData("ui_settings") ?: uiSettings
selectedOption = if (fragment != null) { selectedOption = if (fragment != null) {
when (fragment) { when (fragment) {
AnimeFragment::class.java.name -> 0 AnimeFragment::class.java.name -> 0
@ -217,14 +214,14 @@ class MainActivity : AppCompatActivity() {
else -> 1 else -> 1
} }
} else { } else {
uiSettings.defaultStartUpTab PrefManager.getVal(PrefName.DefaultStartUpTab)
} }
binding.includedNavbar.navbarContainer.updateLayoutParams<ViewGroup.MarginLayoutParams> { binding.includedNavbar.navbarContainer.updateLayoutParams<ViewGroup.MarginLayoutParams> {
bottomMargin = navBarHeight bottomMargin = navBarHeight
} }
} }
val offlineMode = PrefWrapper.getVal(PrefName.OfflineMode, false) val offlineMode: Boolean = PrefManager.getVal(PrefName.OfflineMode)
if (!isOnline(this)) { if (!isOnline(this)) {
snackString(this@MainActivity.getString(R.string.no_internet_connection)) snackString(this@MainActivity.getString(R.string.no_internet_connection))
startActivity(Intent(this, NoInternet::class.java)) startActivity(Intent(this, NoInternet::class.java))
@ -245,7 +242,7 @@ class MainActivity : AppCompatActivity() {
mainViewPager.isUserInputEnabled = false mainViewPager.isUserInputEnabled = false
mainViewPager.adapter = mainViewPager.adapter =
ViewPagerAdapter(supportFragmentManager, lifecycle) ViewPagerAdapter(supportFragmentManager, lifecycle)
mainViewPager.setPageTransformer(ZoomOutPageTransformer(uiSettings)) mainViewPager.setPageTransformer(ZoomOutPageTransformer())
navbar.setOnTabSelectListener(object : navbar.setOnTabSelectListener(object :
AnimatedBottomBar.OnTabSelectListener { AnimatedBottomBar.OnTabSelectListener {
override fun onTabSelected( override fun onTabSelected(
@ -299,7 +296,7 @@ class MainActivity : AppCompatActivity() {
} }
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.S) { if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.S) {
if (!PrefWrapper.getVal(PrefName.AllowOpeningLinks, false)) { if (!(PrefManager.getVal(PrefName.AllowOpeningLinks) as Boolean)) {
CustomBottomDialog.newInstance().apply { CustomBottomDialog.newInstance().apply {
title = "Allow Dantotsu to automatically open Anilist & MAL Links?" title = "Allow Dantotsu to automatically open Anilist & MAL Links?"
val md = "Open settings & click +Add Links & select Anilist & Mal urls" val md = "Open settings & click +Add Links & select Anilist & Mal urls"
@ -311,12 +308,12 @@ class MainActivity : AppCompatActivity() {
}) })
setNegativeButton(this@MainActivity.getString(R.string.no)) { setNegativeButton(this@MainActivity.getString(R.string.no)) {
PrefWrapper.setVal(PrefName.AllowOpeningLinks, true) PrefManager.setVal(PrefName.AllowOpeningLinks, true)
dismiss() dismiss()
} }
setPositiveButton(this@MainActivity.getString(R.string.yes)) { setPositiveButton(this@MainActivity.getString(R.string.yes)) {
PrefWrapper.setVal(PrefName.AllowOpeningLinks, true) PrefManager.setVal(PrefName.AllowOpeningLinks, true)
tryWith(true) { tryWith(true) {
startActivity( startActivity(
Intent(Settings.ACTION_APP_OPEN_BY_DEFAULT_SETTINGS) Intent(Settings.ACTION_APP_OPEN_BY_DEFAULT_SETTINGS)

View file

@ -16,7 +16,6 @@ import eu.kanade.tachiyomi.core.preference.AndroidPreferenceStore
import eu.kanade.tachiyomi.extension.anime.AnimeExtensionManager import eu.kanade.tachiyomi.extension.anime.AnimeExtensionManager
import eu.kanade.tachiyomi.extension.manga.MangaExtensionManager import eu.kanade.tachiyomi.extension.manga.MangaExtensionManager
import eu.kanade.tachiyomi.network.NetworkHelper import eu.kanade.tachiyomi.network.NetworkHelper
import eu.kanade.tachiyomi.network.NetworkPreferences
import eu.kanade.tachiyomi.source.anime.AndroidAnimeSourceManager import eu.kanade.tachiyomi.source.anime.AndroidAnimeSourceManager
import eu.kanade.tachiyomi.source.manga.AndroidMangaSourceManager import eu.kanade.tachiyomi.source.manga.AndroidMangaSourceManager
import kotlinx.serialization.json.Json import kotlinx.serialization.json.Json
@ -36,7 +35,7 @@ class AppModule(val app: Application) : InjektModule {
addSingletonFactory { DownloadsManager(app) } addSingletonFactory { DownloadsManager(app) }
addSingletonFactory { NetworkHelper(app, get()) } addSingletonFactory { NetworkHelper(app) }
addSingletonFactory { AnimeExtensionManager(app) } addSingletonFactory { AnimeExtensionManager(app) }
addSingletonFactory { MangaExtensionManager(app) } addSingletonFactory { MangaExtensionManager(app) }
@ -69,13 +68,6 @@ class PreferenceModule(val application: Application) : InjektModule {
AndroidPreferenceStore(application) AndroidPreferenceStore(application)
} }
addSingletonFactory {
NetworkPreferences(
preferenceStore = get(),
verboseLogging = false,
)
}
addSingletonFactory { addSingletonFactory {
SourcePreferences(get()) SourcePreferences(get())
} }

View file

@ -7,14 +7,14 @@ import ani.dantotsu.connections.mal.MAL
import ani.dantotsu.currContext import ani.dantotsu.currContext
import ani.dantotsu.media.Media import ani.dantotsu.media.Media
import ani.dantotsu.settings.saving.PrefName import ani.dantotsu.settings.saving.PrefName
import ani.dantotsu.settings.saving.PrefWrapper import ani.dantotsu.settings.saving.PrefManager
import ani.dantotsu.toast import ani.dantotsu.toast
import kotlinx.coroutines.CoroutineScope import kotlinx.coroutines.CoroutineScope
import kotlinx.coroutines.Dispatchers import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.launch import kotlinx.coroutines.launch
fun updateProgress(media: Media, number: String) { fun updateProgress(media: Media, number: String) {
val incognito = PrefWrapper.getVal(PrefName.Incognito, false) val incognito: Boolean = PrefManager.getVal(PrefName.Incognito)
if (!incognito) { if (!incognito) {
if (Anilist.userid != null) { if (Anilist.userid != null) {
CoroutineScope(Dispatchers.IO).launch { CoroutineScope(Dispatchers.IO).launch {

View file

@ -11,20 +11,24 @@ import ani.dantotsu.connections.anilist.api.Page
import ani.dantotsu.connections.anilist.api.Query import ani.dantotsu.connections.anilist.api.Query
import ani.dantotsu.currContext import ani.dantotsu.currContext
import ani.dantotsu.isOnline import ani.dantotsu.isOnline
import ani.dantotsu.loadData
import ani.dantotsu.logError import ani.dantotsu.logError
import ani.dantotsu.media.Author import ani.dantotsu.media.Author
import ani.dantotsu.media.Character import ani.dantotsu.media.Character
import ani.dantotsu.media.Media import ani.dantotsu.media.Media
import ani.dantotsu.media.Studio import ani.dantotsu.media.Studio
import ani.dantotsu.others.MalScraper import ani.dantotsu.others.MalScraper
import ani.dantotsu.saveData
import ani.dantotsu.settings.saving.PrefName import ani.dantotsu.settings.saving.PrefName
import ani.dantotsu.settings.saving.PrefWrapper import ani.dantotsu.settings.saving.PrefManager
import ani.dantotsu.snackString import ani.dantotsu.snackString
import kotlinx.coroutines.async import kotlinx.coroutines.async
import kotlinx.coroutines.awaitAll import kotlinx.coroutines.awaitAll
import kotlinx.coroutines.runBlocking import kotlinx.coroutines.runBlocking
import java.io.ByteArrayOutputStream
import java.io.ObjectOutputStream
import java.io.Serializable
import android.util.Base64
import java.io.ByteArrayInputStream
import java.io.ObjectInputStream
import kotlin.system.measureTimeMillis import kotlin.system.measureTimeMillis
class AnilistQueries { class AnilistQueries {
@ -36,7 +40,7 @@ class AnilistQueries {
}.also { println("time : $it") } }.also { println("time : $it") }
val user = response?.data?.user ?: return false val user = response?.data?.user ?: return false
PrefWrapper.setVal(PrefName.AnilistUserName, user.name) PrefManager.setVal(PrefName.AnilistUserName, user.name)
Anilist.userid = user.id Anilist.userid = user.id
Anilist.username = user.name Anilist.username = user.name
@ -277,8 +281,8 @@ class AnilistQueries {
} }
statuses.forEach { repeat(it) } statuses.forEach { repeat(it) }
val set = loadData<MutableSet<Int>>("continue_$type") val set = PrefManager.getCustomVal<Set<Int>>("continue_$type", setOf()).toMutableSet()
if (set != null) { if (set.isNotEmpty()) {
set.reversed().forEach { set.reversed().forEach {
if (map.containsKey(it)) returnArray.add(map[it]!!) if (map.containsKey(it)) returnArray.add(map[it]!!)
} }
@ -351,7 +355,11 @@ class AnilistQueries {
} }
private suspend fun bannerImage(type: String): String? { private suspend fun bannerImage(type: String): String? {
var image = loadData<BannerImage>("banner_$type") //var image = loadData<BannerImage>("banner_$type")
val image: BannerImage? = BannerImage(
PrefManager.getCustomVal("banner_${type}_url", null),
PrefManager.getCustomVal("banner_${type}_time", 0L)
)
if (image == null || image.checkTime()) { if (image == null || image.checkTime()) {
val response = val response =
executeQuery<Query.MediaListCollection>("""{ MediaListCollection(userId: ${Anilist.userid}, type: $type, chunk:1,perChunk:25, sort: [SCORE_DESC,UPDATED_TIME_DESC]) { lists { entries{ media { id bannerImage } } } } } """) executeQuery<Query.MediaListCollection>("""{ MediaListCollection(userId: ${Anilist.userid}, type: $type, chunk:1,perChunk:25, sort: [SCORE_DESC,UPDATED_TIME_DESC]) { lists { entries{ media { id bannerImage } } } } } """)
@ -362,13 +370,9 @@ class AnilistQueries {
else null else null
} }
}?.flatten()?.randomOrNull() ?: return null }?.flatten()?.randomOrNull() ?: return null
PrefManager.setCustomVal("banner_${type}_url", random)
image = BannerImage( PrefManager.setCustomVal("banner_${type}_time", System.currentTimeMillis())
random, return random
System.currentTimeMillis()
)
saveData("banner_$type", image)
return image.url
} else return image.url } else return image.url
} }
@ -417,8 +421,8 @@ class AnilistQueries {
sorted["Favourites"]?.sortWith(compareBy { it.userFavOrder }) sorted["Favourites"]?.sortWith(compareBy { it.userFavOrder })
sorted["All"] = all sorted["All"] = all
val listSort = if (anime) PrefWrapper.getVal(PrefName.AnimeListSortOrder, "score") val listSort: String = if (anime) PrefManager.getVal(PrefName.AnimeListSortOrder)
else PrefWrapper.getVal(PrefName.MangaListSortOrder, "score") else PrefManager.getVal(PrefName.MangaListSortOrder)
val sort = listSort ?: sortOrder ?: options?.rowOrder val sort = listSort ?: sortOrder ?: options?.rowOrder
for (i in sorted.keys) { for (i in sorted.keys) {
when (sort) { when (sort) {
@ -441,10 +445,16 @@ class AnilistQueries {
suspend fun getGenresAndTags(activity: Activity): Boolean { suspend fun getGenresAndTags(activity: Activity): Boolean {
var genres: ArrayList<String>? = loadData("genres_list", activity) var genres: ArrayList<String>? = PrefManager.getVal<Set<String>>(PrefName.GenresList).toMutableList() as ArrayList<String>?
var tags: Map<Boolean, List<String>>? = loadData("tags_map", activity) val adultTags = PrefManager.getVal<Set<String>>(PrefName.TagsListIsAdult).toMutableList()
val nonAdultTags = PrefManager.getVal<Set<String>>(PrefName.TagsListNonAdult).toMutableList()
var tags = if (adultTags.isEmpty() || nonAdultTags.isEmpty()) null else
mapOf(
true to adultTags,
false to nonAdultTags
)
if (genres == null) { if (genres.isNullOrEmpty()) {
executeQuery<Query.GenreCollection>( executeQuery<Query.GenreCollection>(
"""{GenreCollection}""", """{GenreCollection}""",
force = true, force = true,
@ -454,7 +464,7 @@ class AnilistQueries {
forEach { forEach {
genres?.add(it) genres?.add(it)
} }
saveData("genres_list", genres!!) PrefManager.setVal(PrefName.GenresList, genres?.toSet())
} }
} }
if (tags == null) { if (tags == null) {
@ -472,10 +482,11 @@ class AnilistQueries {
true to adult, true to adult,
false to good false to good
) )
saveData("tags_map", tags) PrefManager.setVal(PrefName.TagsListIsAdult, adult.toSet())
PrefManager.setVal(PrefName.TagsListNonAdult, good.toSet())
} }
} }
return if (genres != null && tags != null) { return if (!genres.isNullOrEmpty() && tags != null) {
Anilist.genres = genres Anilist.genres = genres
Anilist.tags = tags Anilist.tags = tags
true true
@ -492,8 +503,36 @@ class AnilistQueries {
} }
} }
private suspend fun getGenreThumbnail(genre: String): Genre? { private fun <K, V : Serializable> saveSerializableMap(prefKey: String, map: Map<K, V>) {
val genres = loadData<MutableMap<String, Genre>>("genre_thumb") ?: mutableMapOf() val byteStream = ByteArrayOutputStream()
ObjectOutputStream(byteStream).use { outputStream ->
outputStream.writeObject(map)
}
val serializedMap = Base64.encodeToString(byteStream.toByteArray(), Base64.DEFAULT)
PrefManager.setCustomVal(prefKey, serializedMap)
}
@Suppress("UNCHECKED_CAST")
private fun <K, V : Serializable> loadSerializableMap(prefKey: String): Map<K, V>? {
try {
val serializedMap = PrefManager.getCustomVal(prefKey, "")
if (serializedMap.isEmpty()) return null
val bytes = Base64.decode(serializedMap, Base64.DEFAULT)
val byteArrayStream = ByteArrayInputStream(bytes)
return ObjectInputStream(byteArrayStream).use { inputStream ->
inputStream.readObject() as? Map<K, V>
}
} catch (e: Exception) {
return null
}
}
private suspend fun getGenreThumbnail(genre: String): Genre? {
val genres: MutableMap<String, Genre> = loadSerializableMap<String, Genre>("genre_thumb")?.toMutableMap()
?: mutableMapOf()
if (genres.checkGenreTime(genre)) { if (genres.checkGenreTime(genre)) {
try { try {
val genreQuery = val genreQuery =
@ -506,7 +545,7 @@ class AnilistQueries {
it.bannerImage!!, it.bannerImage!!,
System.currentTimeMillis() System.currentTimeMillis()
) )
saveData("genre_thumb", genres) saveSerializableMap("genre_thumb", genres)
return genres[genre] return genres[genre]
} }
} }
@ -719,7 +758,7 @@ Page(page:$page,perPage:50) {
if (smaller) { if (smaller) {
val response = execute()?.airingSchedules ?: return null val response = execute()?.airingSchedules ?: return null
val idArr = mutableListOf<Int>() val idArr = mutableListOf<Int>()
val listOnly = PrefWrapper.getVal(PrefName.RecentlyListOnly, false) val listOnly: Boolean = PrefManager.getVal(PrefName.RecentlyListOnly)
return response.mapNotNull { i -> return response.mapNotNull { i ->
i.media?.let { i.media?.let {
if (!idArr.contains(it.id)) if (!idArr.contains(it.id))

View file

@ -8,11 +8,10 @@ import androidx.lifecycle.ViewModel
import ani.dantotsu.R import ani.dantotsu.R
import ani.dantotsu.connections.discord.Discord import ani.dantotsu.connections.discord.Discord
import ani.dantotsu.connections.mal.MAL import ani.dantotsu.connections.mal.MAL
import ani.dantotsu.loadData
import ani.dantotsu.media.Media import ani.dantotsu.media.Media
import ani.dantotsu.others.AppUpdater import ani.dantotsu.others.AppUpdater
import ani.dantotsu.settings.saving.PrefName import ani.dantotsu.settings.saving.PrefName
import ani.dantotsu.settings.saving.PrefWrapper import ani.dantotsu.settings.saving.PrefManager
import ani.dantotsu.snackString import ani.dantotsu.snackString
import ani.dantotsu.tryWithSuspend import ani.dantotsu.tryWithSuspend
import kotlinx.coroutines.CoroutineScope import kotlinx.coroutines.CoroutineScope
@ -21,8 +20,8 @@ import kotlinx.coroutines.launch
suspend fun getUserId(context: Context, block: () -> Unit) { suspend fun getUserId(context: Context, block: () -> Unit) {
CoroutineScope(Dispatchers.IO).launch { CoroutineScope(Dispatchers.IO).launch {
val token = PrefWrapper.getVal(PrefName.DiscordToken, null as String?) val token = PrefManager.getVal(PrefName.DiscordToken, null as String?)
val userid = PrefWrapper.getVal(PrefName.DiscordId, null as String?) val userid = PrefManager.getVal(PrefName.DiscordId, null as String?)
if (userid == null && token != null) { if (userid == null && token != null) {
/*if (!Discord.getUserData()) /*if (!Discord.getUserData())
snackString(context.getString(R.string.error_loading_discord_user_data))*/ snackString(context.getString(R.string.error_loading_discord_user_data))*/
@ -101,7 +100,7 @@ class AnilistHomeViewModel : ViewModel() {
Anilist.getSavedToken(context) Anilist.getSavedToken(context)
MAL.getSavedToken(context) MAL.getSavedToken(context)
Discord.getSavedToken(context) Discord.getSavedToken(context)
if (PrefWrapper.getVal(PrefName.CheckUpdate, false)) AppUpdater.check(context) if (PrefManager.getVal(PrefName.CheckUpdate)) AppUpdater.check(context)
genres.postValue(Anilist.query.getGenresAndTags(context)) genres.postValue(Anilist.query.getGenresAndTags(context))
} }

View file

@ -3,11 +3,10 @@ package ani.dantotsu.connections.discord
import android.content.Context import android.content.Context
import android.content.Intent import android.content.Intent
import android.widget.TextView import android.widget.TextView
import androidx.core.content.edit
import ani.dantotsu.R import ani.dantotsu.R
import ani.dantotsu.others.CustomBottomDialog import ani.dantotsu.others.CustomBottomDialog
import ani.dantotsu.settings.saving.PrefName import ani.dantotsu.settings.saving.PrefName
import ani.dantotsu.settings.saving.PrefWrapper import ani.dantotsu.settings.saving.PrefManager
import ani.dantotsu.toast import ani.dantotsu.toast
import ani.dantotsu.tryWith import ani.dantotsu.tryWith
import io.noties.markwon.Markwon import io.noties.markwon.Markwon
@ -22,17 +21,17 @@ object Discord {
fun getSavedToken(context: Context): Boolean { fun getSavedToken(context: Context): Boolean {
token = PrefWrapper.getVal( token = PrefManager.getVal(
PrefName.DiscordToken, null as String?) PrefName.DiscordToken, null as String?)
return token != null return token != null
} }
fun saveToken(context: Context, token: String) { fun saveToken(context: Context, token: String) {
PrefWrapper.setVal(PrefName.DiscordToken, token) PrefManager.setVal(PrefName.DiscordToken, token)
} }
fun removeSavedToken(context: Context) { fun removeSavedToken(context: Context) {
PrefWrapper.removeVal(PrefName.DiscordToken) PrefManager.removeVal(PrefName.DiscordToken)
tryWith(true) { tryWith(true) {
val dir = File(context.filesDir?.parentFile, "app_webview") val dir = File(context.filesDir?.parentFile, "app_webview")

View file

@ -25,7 +25,7 @@ import ani.dantotsu.connections.discord.serializers.Presence
import ani.dantotsu.connections.discord.serializers.User import ani.dantotsu.connections.discord.serializers.User
import ani.dantotsu.isOnline import ani.dantotsu.isOnline
import ani.dantotsu.settings.saving.PrefName import ani.dantotsu.settings.saving.PrefName
import ani.dantotsu.settings.saving.PrefWrapper import ani.dantotsu.settings.saving.PrefManager
import com.google.gson.JsonArray import com.google.gson.JsonArray
import com.google.gson.JsonObject import com.google.gson.JsonObject
import com.google.gson.JsonParser import com.google.gson.JsonParser
@ -153,9 +153,9 @@ class DiscordService : Service() {
fun saveProfile(response: String) { fun saveProfile(response: String) {
val user = json.decodeFromString<User.Response>(response).d.user val user = json.decodeFromString<User.Response>(response).d.user
log("User data: $user") log("User data: $user")
PrefWrapper.setVal(PrefName.DiscordUserName, user.username) PrefManager.setVal(PrefName.DiscordUserName, user.username)
PrefWrapper.setVal(PrefName.DiscordId, user.id) PrefManager.setVal(PrefName.DiscordId, user.id)
PrefWrapper.setVal(PrefName.DiscordAvatar, user.avatar) PrefManager.setVal(PrefName.DiscordAvatar, user.avatar)
} }
override fun onBind(p0: Intent?): IBinder? = null override fun onBind(p0: Intent?): IBinder? = null
@ -312,7 +312,7 @@ class DiscordService : Service() {
} }
fun getToken(context: Context): String { fun getToken(context: Context): String {
val token = PrefWrapper.getVal(PrefName.DiscordToken, null as String?) val token = PrefManager.getVal(PrefName.DiscordToken, null as String?)
return if (token == null) { return if (token == null) {
log("WebSocket: Token not found") log("WebSocket: Token not found")
errorNotification("Could not set the presence", "token not found") errorNotification("Could not set the presence", "token not found")

View file

@ -8,8 +8,9 @@ import ani.dantotsu.R
import ani.dantotsu.client import ani.dantotsu.client
import ani.dantotsu.connections.mal.MAL.clientId import ani.dantotsu.connections.mal.MAL.clientId
import ani.dantotsu.connections.mal.MAL.saveResponse import ani.dantotsu.connections.mal.MAL.saveResponse
import ani.dantotsu.loadData
import ani.dantotsu.logError import ani.dantotsu.logError
import ani.dantotsu.settings.saving.PrefName
import ani.dantotsu.settings.saving.PrefManager
import ani.dantotsu.snackString import ani.dantotsu.snackString
import ani.dantotsu.startMainActivity import ani.dantotsu.startMainActivity
import ani.dantotsu.themes.ThemeManager import ani.dantotsu.themes.ThemeManager
@ -25,7 +26,7 @@ class Login : AppCompatActivity() {
try { try {
val data: Uri = intent?.data val data: Uri = intent?.data
?: throw Exception(getString(R.string.mal_login_uri_not_found)) ?: throw Exception(getString(R.string.mal_login_uri_not_found))
val codeChallenge: String = loadData("malCodeChallenge", this) val codeChallenge = PrefManager.getVal(PrefName.MALCodeChallenge, null as String?)
?: throw Exception(getString(R.string.mal_login_code_challenge_not_found)) ?: throw Exception(getString(R.string.mal_login_code_challenge_not_found))
val code = data.getQueryParameter("code") val code = data.getQueryParameter("code")
?: throw Exception(getString(R.string.mal_login_code_not_present)) ?: throw Exception(getString(R.string.mal_login_code_not_present))

View file

@ -9,13 +9,12 @@ import androidx.fragment.app.FragmentActivity
import ani.dantotsu.R import ani.dantotsu.R
import ani.dantotsu.client import ani.dantotsu.client
import ani.dantotsu.currContext import ani.dantotsu.currContext
import ani.dantotsu.loadData
import ani.dantotsu.openLinkInBrowser import ani.dantotsu.openLinkInBrowser
import ani.dantotsu.saveData import ani.dantotsu.settings.saving.PrefName
import ani.dantotsu.settings.saving.PrefManager
import ani.dantotsu.tryWithSuspend import ani.dantotsu.tryWithSuspend
import kotlinx.serialization.SerialName import kotlinx.serialization.SerialName
import kotlinx.serialization.Serializable import kotlinx.serialization.Serializable
import java.io.File
import java.security.SecureRandom import java.security.SecureRandom
object MAL { object MAL {
@ -34,7 +33,7 @@ object MAL {
.replace("/", "_") .replace("/", "_")
.replace("\n", "") .replace("\n", "")
saveData("malCodeChallenge", codeChallenge, context) PrefManager.setVal(PrefName.MALCodeChallenge, codeChallenge)
val request = val request =
"https://myanimelist.net/v1/oauth2/authorize?response_type=code&client_id=$clientId&code_challenge=$codeChallenge" "https://myanimelist.net/v1/oauth2/authorize?response_type=code&client_id=$clientId&code_challenge=$codeChallenge"
try { try {
@ -47,11 +46,9 @@ object MAL {
} }
} }
private const val MAL_TOKEN = "malToken"
private suspend fun refreshToken(): ResponseToken? { private suspend fun refreshToken(): ResponseToken? {
return tryWithSuspend { return tryWithSuspend {
val token = loadData<ResponseToken>(MAL_TOKEN) val token = PrefManager.getNullableVal<ResponseToken?>(PrefName.MALToken, null)
?: throw Exception(currContext()?.getString(R.string.refresh_token_load_failed)) ?: throw Exception(currContext()?.getString(R.string.refresh_token_load_failed))
val res = client.post( val res = client.post(
"https://myanimelist.net/v1/oauth2/token", "https://myanimelist.net/v1/oauth2/token",
@ -69,7 +66,7 @@ object MAL {
suspend fun getSavedToken(context: FragmentActivity): Boolean { suspend fun getSavedToken(context: FragmentActivity): Boolean {
return tryWithSuspend(false) { return tryWithSuspend(false) {
var res: ResponseToken = loadData(MAL_TOKEN, context) var res: ResponseToken = PrefManager.getNullableVal<ResponseToken?>(PrefName.MALToken, null)
?: return@tryWithSuspend false ?: return@tryWithSuspend false
if (System.currentTimeMillis() > res.expiresIn) if (System.currentTimeMillis() > res.expiresIn)
res = refreshToken() res = refreshToken()
@ -84,14 +81,12 @@ object MAL {
username = null username = null
userid = null userid = null
avatar = null avatar = null
if (MAL_TOKEN in context.fileList()) { PrefManager.removeVal(PrefName.MALToken)
File(context.filesDir, MAL_TOKEN).delete()
}
} }
fun saveResponse(res: ResponseToken) { fun saveResponse(res: ResponseToken) {
res.expiresIn += System.currentTimeMillis() res.expiresIn += System.currentTimeMillis()
saveData(MAL_TOKEN, res) PrefManager.setVal(PrefName.MALToken, res)
} }
@Serializable @Serializable

View file

@ -4,7 +4,7 @@ import android.content.Context
import android.os.Environment import android.os.Environment
import android.widget.Toast import android.widget.Toast
import ani.dantotsu.settings.saving.PrefName import ani.dantotsu.settings.saving.PrefName
import ani.dantotsu.settings.saving.PrefWrapper import ani.dantotsu.settings.saving.PrefManager
import com.google.gson.Gson import com.google.gson.Gson
import com.google.gson.reflect.TypeToken import com.google.gson.reflect.TypeToken
import java.io.File import java.io.File
@ -23,11 +23,11 @@ class DownloadsManager(private val context: Context) {
private fun saveDownloads() { private fun saveDownloads() {
val jsonString = gson.toJson(downloadsList) val jsonString = gson.toJson(downloadsList)
PrefWrapper.setVal(PrefName.DownloadsKeys, jsonString) PrefManager.setVal(PrefName.DownloadsKeys, jsonString)
} }
private fun loadDownloads(): List<DownloadedType> { private fun loadDownloads(): List<DownloadedType> {
val jsonString = PrefWrapper.getVal(PrefName.DownloadsKeys, null as String?) val jsonString = PrefManager.getVal(PrefName.DownloadsKeys, null as String?)
return if (jsonString != null) { return if (jsonString != null) {
val type = object : TypeToken<List<DownloadedType>>() {}.type val type = object : TypeToken<List<DownloadedType>>() {}.type
gson.fromJson(jsonString, type) gson.fromJson(jsonString, type)

View file

@ -32,7 +32,7 @@ import ani.dantotsu.media.SubtitleDownloader
import ani.dantotsu.media.anime.AnimeWatchFragment import ani.dantotsu.media.anime.AnimeWatchFragment
import ani.dantotsu.parsers.Subtitle import ani.dantotsu.parsers.Subtitle
import ani.dantotsu.parsers.Video import ani.dantotsu.parsers.Video
import ani.dantotsu.settings.saving.PrefWrapper import ani.dantotsu.settings.saving.PrefManager
import ani.dantotsu.snackString import ani.dantotsu.snackString
import com.google.firebase.crashlytics.FirebaseCrashlytics import com.google.firebase.crashlytics.FirebaseCrashlytics
import com.google.gson.GsonBuilder import com.google.gson.GsonBuilder
@ -295,7 +295,7 @@ class AnimeDownloaderService : Service() {
builder.setContentText("${task.title} - ${task.episode} Download completed") builder.setContentText("${task.title} - ${task.episode} Download completed")
notificationManager.notify(NOTIFICATION_ID, builder.build()) notificationManager.notify(NOTIFICATION_ID, builder.build())
snackString("${task.title} - ${task.episode} Download completed") snackString("${task.title} - ${task.episode} Download completed")
PrefWrapper.getAnimeDownloadPreferences().edit().putString( PrefManager.getAnimeDownloadPreferences().edit().putString(
task.getTaskName(), task.getTaskName(),
task.video.file.url task.video.file.url
).apply() ).apply()

View file

@ -13,7 +13,7 @@ import android.widget.TextView
import androidx.cardview.widget.CardView import androidx.cardview.widget.CardView
import ani.dantotsu.R import ani.dantotsu.R
import ani.dantotsu.settings.saving.PrefName import ani.dantotsu.settings.saving.PrefName
import ani.dantotsu.settings.saving.PrefWrapper import ani.dantotsu.settings.saving.PrefManager
class OfflineAnimeAdapter( class OfflineAnimeAdapter(
@ -24,7 +24,7 @@ class OfflineAnimeAdapter(
private val inflater: LayoutInflater = private val inflater: LayoutInflater =
context.getSystemService(Context.LAYOUT_INFLATER_SERVICE) as LayoutInflater context.getSystemService(Context.LAYOUT_INFLATER_SERVICE) as LayoutInflater
private var originalItems: List<OfflineAnimeModel> = items private var originalItems: List<OfflineAnimeModel> = items
private var style = PrefWrapper.getVal(PrefName.OfflineView, 0) private var style: Int = PrefManager.getVal(PrefName.OfflineView)
override fun getCount(): Int { override fun getCount(): Int {
return items.size return items.size
@ -106,7 +106,7 @@ class OfflineAnimeAdapter(
} }
fun notifyNewGrid() { fun notifyNewGrid() {
style = PrefWrapper.getVal(PrefName.OfflineView, 0) style = PrefManager.getVal(PrefName.OfflineView)
notifyDataSetChanged() notifyDataSetChanged()
} }
} }

View file

@ -1,7 +1,6 @@
package ani.dantotsu.download.anime package ani.dantotsu.download.anime
import android.content.Context
import android.content.Intent import android.content.Intent
import android.net.Uri import android.net.Uri
import android.os.Bundle import android.os.Bundle
@ -36,16 +35,14 @@ import ani.dantotsu.currContext
import ani.dantotsu.download.DownloadedType import ani.dantotsu.download.DownloadedType
import ani.dantotsu.download.DownloadsManager import ani.dantotsu.download.DownloadsManager
import ani.dantotsu.initActivity import ani.dantotsu.initActivity
import ani.dantotsu.loadData
import ani.dantotsu.logger import ani.dantotsu.logger
import ani.dantotsu.media.Media import ani.dantotsu.media.Media
import ani.dantotsu.media.MediaDetailsActivity import ani.dantotsu.media.MediaDetailsActivity
import ani.dantotsu.navBarHeight import ani.dantotsu.navBarHeight
import ani.dantotsu.setSafeOnClickListener import ani.dantotsu.setSafeOnClickListener
import ani.dantotsu.settings.SettingsDialogFragment import ani.dantotsu.settings.SettingsDialogFragment
import ani.dantotsu.settings.UserInterfaceSettings
import ani.dantotsu.settings.saving.PrefName import ani.dantotsu.settings.saving.PrefName
import ani.dantotsu.settings.saving.PrefWrapper import ani.dantotsu.settings.saving.PrefManager
import ani.dantotsu.snackString import ani.dantotsu.snackString
import com.google.android.material.card.MaterialCardView import com.google.android.material.card.MaterialCardView
import com.google.android.material.imageview.ShapeableImageView import com.google.android.material.imageview.ShapeableImageView
@ -70,8 +67,6 @@ class OfflineAnimeFragment : Fragment(), OfflineAnimeSearchListener {
private lateinit var gridView: GridView private lateinit var gridView: GridView
private lateinit var adapter: OfflineAnimeAdapter private lateinit var adapter: OfflineAnimeAdapter
private lateinit var total: TextView private lateinit var total: TextView
private var uiSettings: UserInterfaceSettings =
loadData("ui_settings") ?: UserInterfaceSettings()
override fun onCreateView( override fun onCreateView(
inflater: LayoutInflater, inflater: LayoutInflater,
@ -97,7 +92,7 @@ class OfflineAnimeFragment : Fragment(), OfflineAnimeSearchListener {
SettingsDialogFragment.newInstance(SettingsDialogFragment.Companion.PageType.OfflineANIME) SettingsDialogFragment.newInstance(SettingsDialogFragment.Companion.PageType.OfflineANIME)
dialogFragment.show((it.context as AppCompatActivity).supportFragmentManager, "dialog") dialogFragment.show((it.context as AppCompatActivity).supportFragmentManager, "dialog")
} }
if (!uiSettings.immersiveMode) { if (!(PrefManager.getVal(PrefName.ImmersiveMode) as Boolean)) {
view.rootView.fitsSystemWindows = true view.rootView.fitsSystemWindows = true
} }
@ -116,7 +111,7 @@ class OfflineAnimeFragment : Fragment(), OfflineAnimeSearchListener {
onSearchQuery(s.toString()) onSearchQuery(s.toString())
} }
}) })
var style = PrefWrapper.getVal(PrefName.OfflineView, 0) var style: Int = PrefManager.getVal(PrefName.OfflineView)
val layoutList = view.findViewById<ImageView>(R.id.downloadedList) val layoutList = view.findViewById<ImageView>(R.id.downloadedList)
val layoutcompact = view.findViewById<ImageView>(R.id.downloadedGrid) val layoutcompact = view.findViewById<ImageView>(R.id.downloadedGrid)
var selected = when (style) { var selected = when (style) {
@ -135,7 +130,7 @@ class OfflineAnimeFragment : Fragment(), OfflineAnimeSearchListener {
layoutList.setOnClickListener { layoutList.setOnClickListener {
selected(it as ImageView) selected(it as ImageView)
style = 0 style = 0
PrefWrapper.setVal(PrefName.OfflineView, style) PrefManager.setVal(PrefName.OfflineView, style)
gridView.visibility = View.GONE gridView.visibility = View.GONE
gridView = view.findViewById(R.id.gridView) gridView = view.findViewById(R.id.gridView)
adapter.notifyNewGrid() adapter.notifyNewGrid()
@ -145,7 +140,7 @@ class OfflineAnimeFragment : Fragment(), OfflineAnimeSearchListener {
layoutcompact.setOnClickListener { layoutcompact.setOnClickListener {
selected(it as ImageView) selected(it as ImageView)
style = 1 style = 1
PrefWrapper.setVal(PrefName.OfflineView, style) PrefManager.setVal(PrefName.OfflineView, style)
gridView.visibility = View.GONE gridView.visibility = View.GONE
gridView = view.findViewById(R.id.gridView1) gridView = view.findViewById(R.id.gridView1)
adapter.notifyNewGrid() adapter.notifyNewGrid()
@ -212,7 +207,7 @@ class OfflineAnimeFragment : Fragment(), OfflineAnimeSearchListener {
builder.setMessage("Are you sure you want to delete ${item.title}?") builder.setMessage("Are you sure you want to delete ${item.title}?")
builder.setPositiveButton("Yes") { _, _ -> builder.setPositiveButton("Yes") { _, _ ->
downloadManager.removeMedia(item.title, type) downloadManager.removeMedia(item.title, type)
val mediaIds = PrefWrapper.getAnimeDownloadPreferences().all?.filter { it.key.contains(item.title) }?.values ?: emptySet() val mediaIds = PrefManager.getAnimeDownloadPreferences().all?.filter { it.key.contains(item.title) }?.values ?: emptySet()
if (mediaIds.isEmpty()) { if (mediaIds.isEmpty()) {
snackString("No media found") // if this happens, terrible things have happened snackString("No media found") // if this happens, terrible things have happened
} }

View file

@ -12,7 +12,7 @@ import android.widget.TextView
import androidx.cardview.widget.CardView import androidx.cardview.widget.CardView
import ani.dantotsu.R import ani.dantotsu.R
import ani.dantotsu.settings.saving.PrefName import ani.dantotsu.settings.saving.PrefName
import ani.dantotsu.settings.saving.PrefWrapper import ani.dantotsu.settings.saving.PrefManager
class OfflineMangaAdapter( class OfflineMangaAdapter(
@ -23,7 +23,7 @@ class OfflineMangaAdapter(
private val inflater: LayoutInflater = private val inflater: LayoutInflater =
context.getSystemService(Context.LAYOUT_INFLATER_SERVICE) as LayoutInflater context.getSystemService(Context.LAYOUT_INFLATER_SERVICE) as LayoutInflater
private var originalItems: List<OfflineMangaModel> = items private var originalItems: List<OfflineMangaModel> = items
private var style = PrefWrapper.getVal(PrefName.OfflineView, 0) private var style: Int = PrefManager.getVal(PrefName.OfflineView)
override fun getCount(): Int { override fun getCount(): Int {
return items.size return items.size
@ -105,7 +105,7 @@ class OfflineMangaAdapter(
} }
fun notifyNewGrid() { fun notifyNewGrid() {
style = PrefWrapper.getVal(PrefName.OfflineView, 0) style = PrefManager.getVal(PrefName.OfflineView)
notifyDataSetChanged() notifyDataSetChanged()
} }
} }

View file

@ -1,6 +1,5 @@
package ani.dantotsu.download.manga package ani.dantotsu.download.manga
import android.content.Context
import android.content.Intent import android.content.Intent
import android.net.Uri import android.net.Uri
import android.os.Bundle import android.os.Bundle
@ -33,16 +32,14 @@ import ani.dantotsu.currContext
import ani.dantotsu.download.DownloadedType import ani.dantotsu.download.DownloadedType
import ani.dantotsu.download.DownloadsManager import ani.dantotsu.download.DownloadsManager
import ani.dantotsu.initActivity import ani.dantotsu.initActivity
import ani.dantotsu.loadData
import ani.dantotsu.logger import ani.dantotsu.logger
import ani.dantotsu.media.Media import ani.dantotsu.media.Media
import ani.dantotsu.media.MediaDetailsActivity import ani.dantotsu.media.MediaDetailsActivity
import ani.dantotsu.navBarHeight import ani.dantotsu.navBarHeight
import ani.dantotsu.setSafeOnClickListener import ani.dantotsu.setSafeOnClickListener
import ani.dantotsu.settings.SettingsDialogFragment import ani.dantotsu.settings.SettingsDialogFragment
import ani.dantotsu.settings.UserInterfaceSettings
import ani.dantotsu.settings.saving.PrefName import ani.dantotsu.settings.saving.PrefName
import ani.dantotsu.settings.saving.PrefWrapper import ani.dantotsu.settings.saving.PrefManager
import ani.dantotsu.snackString import ani.dantotsu.snackString
import com.google.android.material.card.MaterialCardView import com.google.android.material.card.MaterialCardView
import com.google.android.material.imageview.ShapeableImageView import com.google.android.material.imageview.ShapeableImageView
@ -63,8 +60,6 @@ class OfflineMangaFragment : Fragment(), OfflineMangaSearchListener {
private lateinit var gridView: GridView private lateinit var gridView: GridView
private lateinit var adapter: OfflineMangaAdapter private lateinit var adapter: OfflineMangaAdapter
private lateinit var total: TextView private lateinit var total: TextView
private var uiSettings: UserInterfaceSettings =
loadData("ui_settings") ?: UserInterfaceSettings()
override fun onCreateView( override fun onCreateView(
inflater: LayoutInflater, inflater: LayoutInflater,
@ -90,7 +85,7 @@ class OfflineMangaFragment : Fragment(), OfflineMangaSearchListener {
SettingsDialogFragment.newInstance(SettingsDialogFragment.Companion.PageType.OfflineMANGA) SettingsDialogFragment.newInstance(SettingsDialogFragment.Companion.PageType.OfflineMANGA)
dialogFragment.show((it.context as AppCompatActivity).supportFragmentManager, "dialog") dialogFragment.show((it.context as AppCompatActivity).supportFragmentManager, "dialog")
} }
if (!uiSettings.immersiveMode) { if (!(PrefManager.getVal(PrefName.ImmersiveMode) as Boolean)) {
view.rootView.fitsSystemWindows = true view.rootView.fitsSystemWindows = true
} }
@ -109,7 +104,7 @@ class OfflineMangaFragment : Fragment(), OfflineMangaSearchListener {
onSearchQuery(s.toString()) onSearchQuery(s.toString())
} }
}) })
var style = PrefWrapper.getVal(PrefName.OfflineView, 0) var style: Int = PrefManager.getVal(PrefName.OfflineView)
val layoutList = view.findViewById<ImageView>(R.id.downloadedList) val layoutList = view.findViewById<ImageView>(R.id.downloadedList)
val layoutcompact = view.findViewById<ImageView>(R.id.downloadedGrid) val layoutcompact = view.findViewById<ImageView>(R.id.downloadedGrid)
var selected = when (style) { var selected = when (style) {
@ -128,7 +123,7 @@ class OfflineMangaFragment : Fragment(), OfflineMangaSearchListener {
layoutList.setOnClickListener { layoutList.setOnClickListener {
selected(it as ImageView) selected(it as ImageView)
style = 0 style = 0
PrefWrapper.setVal(PrefName.OfflineView, style) PrefManager.setVal(PrefName.OfflineView, style)
gridView.visibility = View.GONE gridView.visibility = View.GONE
gridView = view.findViewById(R.id.gridView) gridView = view.findViewById(R.id.gridView)
adapter.notifyNewGrid() adapter.notifyNewGrid()
@ -139,7 +134,7 @@ class OfflineMangaFragment : Fragment(), OfflineMangaSearchListener {
layoutcompact.setOnClickListener { layoutcompact.setOnClickListener {
selected(it as ImageView) selected(it as ImageView)
style = 1 style = 1
PrefWrapper.setVal(PrefName.OfflineView, style) PrefManager.setVal(PrefName.OfflineView, style)
gridView.visibility = View.GONE gridView.visibility = View.GONE
gridView = view.findViewById(R.id.gridView1) gridView = view.findViewById(R.id.gridView1)
adapter.notifyNewGrid() adapter.notifyNewGrid()

View file

@ -13,7 +13,6 @@ import android.util.Log
import androidx.annotation.OptIn import androidx.annotation.OptIn
import androidx.core.app.ActivityCompat import androidx.core.app.ActivityCompat
import androidx.core.content.ContextCompat import androidx.core.content.ContextCompat
import androidx.core.content.ContextCompat.getString
import androidx.media3.common.C import androidx.media3.common.C
import androidx.media3.common.MediaItem import androidx.media3.common.MediaItem
import androidx.media3.common.MimeTypes import androidx.media3.common.MimeTypes
@ -43,7 +42,7 @@ import ani.dantotsu.parsers.Subtitle
import ani.dantotsu.parsers.SubtitleType import ani.dantotsu.parsers.SubtitleType
import ani.dantotsu.parsers.Video import ani.dantotsu.parsers.Video
import ani.dantotsu.parsers.VideoType import ani.dantotsu.parsers.VideoType
import ani.dantotsu.settings.saving.PrefWrapper import ani.dantotsu.settings.saving.PrefManager
import eu.kanade.tachiyomi.network.NetworkHelper import eu.kanade.tachiyomi.network.NetworkHelper
import uy.kohesive.injekt.Injekt import uy.kohesive.injekt.Injekt
import uy.kohesive.injekt.api.get import uy.kohesive.injekt.api.get
@ -230,13 +229,13 @@ object Helper {
DownloadService.sendRemoveDownload( DownloadService.sendRemoveDownload(
context, context,
ExoplayerDownloadService::class.java, ExoplayerDownloadService::class.java,
PrefWrapper.getAnimeDownloadPreferences().getString( PrefManager.getAnimeDownloadPreferences().getString(
animeDownloadTask.getTaskName(), animeDownloadTask.getTaskName(),
"" ""
) ?: "", ) ?: "",
false false
) )
PrefWrapper.getAnimeDownloadPreferences().edit() PrefManager.getAnimeDownloadPreferences().edit()
.remove(animeDownloadTask.getTaskName()) .remove(animeDownloadTask.getTaskName())
.apply() .apply()
downloadsManger.removeDownload( downloadsManger.removeDownload(

View file

@ -27,23 +27,19 @@ import ani.dantotsu.connections.anilist.AnilistAnimeViewModel
import ani.dantotsu.connections.anilist.SearchResults import ani.dantotsu.connections.anilist.SearchResults
import ani.dantotsu.connections.anilist.getUserId import ani.dantotsu.connections.anilist.getUserId
import ani.dantotsu.databinding.FragmentAnimeBinding import ani.dantotsu.databinding.FragmentAnimeBinding
import ani.dantotsu.loadData
import ani.dantotsu.media.MediaAdaptor import ani.dantotsu.media.MediaAdaptor
import ani.dantotsu.media.ProgressAdapter import ani.dantotsu.media.ProgressAdapter
import ani.dantotsu.media.SearchActivity import ani.dantotsu.media.SearchActivity
import ani.dantotsu.navBarHeight import ani.dantotsu.navBarHeight
import ani.dantotsu.px import ani.dantotsu.px
import ani.dantotsu.settings.UserInterfaceSettings
import ani.dantotsu.settings.saving.PrefName import ani.dantotsu.settings.saving.PrefName
import ani.dantotsu.settings.saving.PrefWrapper import ani.dantotsu.settings.saving.PrefManager
import ani.dantotsu.snackString import ani.dantotsu.snackString
import ani.dantotsu.statusBarHeight import ani.dantotsu.statusBarHeight
import kotlinx.coroutines.Dispatchers import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.delay import kotlinx.coroutines.delay
import kotlinx.coroutines.launch import kotlinx.coroutines.launch
import kotlinx.coroutines.withContext import kotlinx.coroutines.withContext
import uy.kohesive.injekt.Injekt
import uy.kohesive.injekt.api.get
import kotlin.math.max import kotlin.math.max
import kotlin.math.min import kotlin.math.min
@ -53,9 +49,6 @@ class AnimeFragment : Fragment() {
private val binding get() = _binding!! private val binding get() = _binding!!
private lateinit var animePageAdapter: AnimePageAdapter private lateinit var animePageAdapter: AnimePageAdapter
private var uiSettings: UserInterfaceSettings =
loadData("ui_settings") ?: UserInterfaceSettings()
val model: AnilistAnimeViewModel by activityViewModels() val model: AnilistAnimeViewModel by activityViewModels()
override fun onCreateView( override fun onCreateView(
@ -220,7 +213,7 @@ class AnimeFragment : Fragment() {
if (it != null) { if (it != null) {
animePageAdapter.updateTrending( animePageAdapter.updateTrending(
MediaAdaptor( MediaAdaptor(
if (uiSettings.smallView) 3 else 2, if (PrefManager.getVal(PrefName.SmallView)) 3 else 2,
it, it,
requireActivity(), requireActivity(),
viewPager = animePageAdapter.trendingViewPager viewPager = animePageAdapter.trendingViewPager
@ -271,8 +264,8 @@ class AnimeFragment : Fragment() {
model.loaded = true model.loaded = true
model.loadTrending(1) model.loadTrending(1)
model.loadUpdated() model.loadUpdated()
model.loadPopular("ANIME", sort = Anilist.sortBy[1], onList = PrefWrapper.getVal( model.loadPopular("ANIME", sort = Anilist.sortBy[1], onList = PrefManager.getVal(
PrefName.PopularAnimeList, true)) PrefName.PopularAnimeList))
} }
live.postValue(false) live.postValue(false)
_binding?.animeRefresh?.isRefreshing = false _binding?.animeRefresh?.isRefreshing = false

View file

@ -1,6 +1,5 @@
package ani.dantotsu.home package ani.dantotsu.home
import android.content.Context
import android.content.Intent import android.content.Intent
import android.os.Handler import android.os.Handler
import android.os.Looper import android.os.Looper
@ -22,7 +21,6 @@ import ani.dantotsu.R
import ani.dantotsu.connections.anilist.Anilist import ani.dantotsu.connections.anilist.Anilist
import ani.dantotsu.currContext import ani.dantotsu.currContext
import ani.dantotsu.databinding.ItemAnimePageBinding import ani.dantotsu.databinding.ItemAnimePageBinding
import ani.dantotsu.loadData
import ani.dantotsu.loadImage import ani.dantotsu.loadImage
import ani.dantotsu.media.CalendarActivity import ani.dantotsu.media.CalendarActivity
import ani.dantotsu.media.GenreActivity import ani.dantotsu.media.GenreActivity
@ -33,9 +31,8 @@ import ani.dantotsu.setSafeOnClickListener
import ani.dantotsu.setSlideIn import ani.dantotsu.setSlideIn
import ani.dantotsu.setSlideUp import ani.dantotsu.setSlideUp
import ani.dantotsu.settings.SettingsDialogFragment import ani.dantotsu.settings.SettingsDialogFragment
import ani.dantotsu.settings.UserInterfaceSettings
import ani.dantotsu.settings.saving.PrefName import ani.dantotsu.settings.saving.PrefName
import ani.dantotsu.settings.saving.PrefWrapper import ani.dantotsu.settings.saving.PrefManager
import ani.dantotsu.statusBarHeight import ani.dantotsu.statusBarHeight
import com.google.android.material.card.MaterialCardView import com.google.android.material.card.MaterialCardView
import com.google.android.material.textfield.TextInputLayout import com.google.android.material.textfield.TextInputLayout
@ -46,8 +43,6 @@ class AnimePageAdapter : RecyclerView.Adapter<AnimePageAdapter.AnimePageViewHold
private var trendHandler: Handler? = null private var trendHandler: Handler? = null
private lateinit var trendRun: Runnable private lateinit var trendRun: Runnable
var trendingViewPager: ViewPager2? = null var trendingViewPager: ViewPager2? = null
private var uiSettings: UserInterfaceSettings =
loadData("ui_settings") ?: UserInterfaceSettings()
override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): AnimePageViewHolder { override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): AnimePageViewHolder {
val binding = val binding =
@ -75,7 +70,7 @@ class AnimePageAdapter : RecyclerView.Adapter<AnimePageAdapter.AnimePageViewHold
binding.animeTitleContainer.updatePadding(top = statusBarHeight) binding.animeTitleContainer.updatePadding(top = statusBarHeight)
if (uiSettings.smallView) binding.animeTrendingContainer.updateLayoutParams<ViewGroup.MarginLayoutParams> { if (PrefManager.getVal(PrefName.SmallView)) binding.animeTrendingContainer.updateLayoutParams<ViewGroup.MarginLayoutParams> {
bottomMargin = (-108f).px bottomMargin = (-108f).px
} }
@ -130,12 +125,12 @@ class AnimePageAdapter : RecyclerView.Adapter<AnimePageAdapter.AnimePageViewHold
binding.animeIncludeList.visibility = binding.animeIncludeList.visibility =
if (Anilist.userid != null) View.VISIBLE else View.GONE if (Anilist.userid != null) View.VISIBLE else View.GONE
binding.animeIncludeList.isChecked = PrefWrapper.getVal(PrefName.PopularAnimeList, true) binding.animeIncludeList.isChecked = PrefManager.getVal(PrefName.PopularAnimeList)
binding.animeIncludeList.setOnCheckedChangeListener { _, isChecked -> binding.animeIncludeList.setOnCheckedChangeListener { _, isChecked ->
onIncludeListClick.invoke(isChecked) onIncludeListClick.invoke(isChecked)
PrefWrapper.setVal(PrefName.PopularAnimeList, isChecked) PrefManager.setVal(PrefName.PopularAnimeList, isChecked)
} }
if (ready.value == false) if (ready.value == false)
ready.postValue(true) ready.postValue(true)
@ -174,12 +169,12 @@ class AnimePageAdapter : RecyclerView.Adapter<AnimePageAdapter.AnimePageViewHold
) )
binding.animeTrendingViewPager.layoutAnimation = binding.animeTrendingViewPager.layoutAnimation =
LayoutAnimationController(setSlideIn(uiSettings), 0.25f) LayoutAnimationController(setSlideIn(), 0.25f)
binding.animeTitleContainer.startAnimation(setSlideUp(uiSettings)) binding.animeTitleContainer.startAnimation(setSlideUp())
binding.animeListContainer.layoutAnimation = binding.animeListContainer.layoutAnimation =
LayoutAnimationController(setSlideIn(uiSettings), 0.25f) LayoutAnimationController(setSlideIn(), 0.25f)
binding.animeSeasonsCont.layoutAnimation = binding.animeSeasonsCont.layoutAnimation =
LayoutAnimationController(setSlideIn(uiSettings), 0.25f) LayoutAnimationController(setSlideIn(), 0.25f)
} }
fun updateRecent(adaptor: MediaAdaptor) { fun updateRecent(adaptor: MediaAdaptor) {
@ -194,11 +189,11 @@ class AnimePageAdapter : RecyclerView.Adapter<AnimePageAdapter.AnimePageViewHold
binding.animeUpdatedRecyclerView.visibility = View.VISIBLE binding.animeUpdatedRecyclerView.visibility = View.VISIBLE
binding.animeRecently.visibility = View.VISIBLE binding.animeRecently.visibility = View.VISIBLE
binding.animeRecently.startAnimation(setSlideUp(uiSettings)) binding.animeRecently.startAnimation(setSlideUp())
binding.animeUpdatedRecyclerView.layoutAnimation = binding.animeUpdatedRecyclerView.layoutAnimation =
LayoutAnimationController(setSlideIn(uiSettings), 0.25f) LayoutAnimationController(setSlideIn(), 0.25f)
binding.animePopular.visibility = View.VISIBLE binding.animePopular.visibility = View.VISIBLE
binding.animePopular.startAnimation(setSlideUp(uiSettings)) binding.animePopular.startAnimation(setSlideUp())
} }
fun updateAvatar() { fun updateAvatar() {

View file

@ -27,7 +27,6 @@ import ani.dantotsu.connections.anilist.AnilistHomeViewModel
import ani.dantotsu.connections.anilist.getUserId import ani.dantotsu.connections.anilist.getUserId
import ani.dantotsu.currContext import ani.dantotsu.currContext
import ani.dantotsu.databinding.FragmentHomeBinding import ani.dantotsu.databinding.FragmentHomeBinding
import ani.dantotsu.loadData
import ani.dantotsu.loadImage import ani.dantotsu.loadImage
import ani.dantotsu.media.Media import ani.dantotsu.media.Media
import ani.dantotsu.media.MediaAdaptor import ani.dantotsu.media.MediaAdaptor
@ -37,7 +36,8 @@ import ani.dantotsu.setSafeOnClickListener
import ani.dantotsu.setSlideIn import ani.dantotsu.setSlideIn
import ani.dantotsu.setSlideUp import ani.dantotsu.setSlideUp
import ani.dantotsu.settings.SettingsDialogFragment import ani.dantotsu.settings.SettingsDialogFragment
import ani.dantotsu.settings.UserInterfaceSettings import ani.dantotsu.settings.saving.PrefName
import ani.dantotsu.settings.saving.PrefManager
import ani.dantotsu.snackString import ani.dantotsu.snackString
import ani.dantotsu.statusBarHeight import ani.dantotsu.statusBarHeight
import kotlinx.coroutines.Dispatchers import kotlinx.coroutines.Dispatchers
@ -70,14 +70,13 @@ class HomeFragment : Fragment() {
override fun onViewCreated(view: View, savedInstanceState: Bundle?) { override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
val scope = lifecycleScope val scope = lifecycleScope
var uiSettings = loadData<UserInterfaceSettings>("ui_settings") ?: UserInterfaceSettings()
fun load() { fun load() {
if (activity != null && _binding != null) lifecycleScope.launch(Dispatchers.Main) { if (activity != null && _binding != null) lifecycleScope.launch(Dispatchers.Main) {
binding.homeUserName.text = Anilist.username binding.homeUserName.text = Anilist.username
binding.homeUserEpisodesWatched.text = Anilist.episodesWatched.toString() binding.homeUserEpisodesWatched.text = Anilist.episodesWatched.toString()
binding.homeUserChaptersRead.text = Anilist.chapterRead.toString() binding.homeUserChaptersRead.text = Anilist.chapterRead.toString()
binding.homeUserAvatar.loadImage(Anilist.avatar) binding.homeUserAvatar.loadImage(Anilist.avatar)
if (!uiSettings.bannerAnimations) binding.homeUserBg.pause() if (!(PrefManager.getVal(PrefName.BannerAnimations) as Boolean)) binding.homeUserBg.pause()
binding.homeUserBg.loadImage(Anilist.bg) binding.homeUserBg.loadImage(Anilist.bg)
binding.homeUserDataProgressBar.visibility = View.GONE binding.homeUserDataProgressBar.visibility = View.GONE
@ -98,14 +97,14 @@ class HomeFragment : Fragment() {
) )
} }
binding.homeUserAvatarContainer.startAnimation(setSlideUp(uiSettings)) binding.homeUserAvatarContainer.startAnimation(setSlideUp())
binding.homeUserDataContainer.visibility = View.VISIBLE binding.homeUserDataContainer.visibility = View.VISIBLE
binding.homeUserDataContainer.layoutAnimation = binding.homeUserDataContainer.layoutAnimation =
LayoutAnimationController(setSlideUp(uiSettings), 0.25f) LayoutAnimationController(setSlideUp(), 0.25f)
binding.homeAnimeList.visibility = View.VISIBLE binding.homeAnimeList.visibility = View.VISIBLE
binding.homeMangaList.visibility = View.VISIBLE binding.homeMangaList.visibility = View.VISIBLE
binding.homeListContainer.layoutAnimation = binding.homeListContainer.layoutAnimation =
LayoutAnimationController(setSlideIn(uiSettings), 0.25f) LayoutAnimationController(setSlideIn(), 0.25f)
} }
else { else {
snackString(currContext()?.getString(R.string.please_reload)) snackString(currContext()?.getString(R.string.please_reload))
@ -127,7 +126,7 @@ class HomeFragment : Fragment() {
binding.homeTopContainer.updatePadding(top = statusBarHeight) binding.homeTopContainer.updatePadding(top = statusBarHeight)
var reached = false var reached = false
val duration = (uiSettings.animationSpeed * 200).toLong() val duration = ((PrefManager.getVal(PrefName.AnimationSpeed) as Float) * 200).toLong()
binding.homeScroll.setOnScrollChangeListener { _, _, _, _, _ -> binding.homeScroll.setOnScrollChangeListener { _, _, _, _, _ ->
if (!binding.homeScroll.canScrollVertically(1)) { if (!binding.homeScroll.canScrollVertically(1)) {
reached = true reached = true
@ -206,13 +205,13 @@ class HomeFragment : Fragment() {
) )
recyclerView.visibility = View.VISIBLE recyclerView.visibility = View.VISIBLE
recyclerView.layoutAnimation = recyclerView.layoutAnimation =
LayoutAnimationController(setSlideIn(uiSettings), 0.25f) LayoutAnimationController(setSlideIn(), 0.25f)
} else { } else {
empty.visibility = View.VISIBLE empty.visibility = View.VISIBLE
} }
title.visibility = View.VISIBLE title.visibility = View.VISIBLE
title.startAnimation(setSlideUp(uiSettings)) title.startAnimation(setSlideUp())
progress.visibility = View.GONE progress.visibility = View.GONE
} }
} }
@ -295,12 +294,12 @@ class HomeFragment : Fragment() {
binding.homeRecommended binding.homeRecommended
) )
binding.homeUserAvatarContainer.startAnimation(setSlideUp(uiSettings)) binding.homeUserAvatarContainer.startAnimation(setSlideUp())
model.empty.observe(viewLifecycleOwner) { model.empty.observe(viewLifecycleOwner) {
binding.homeDantotsuContainer.visibility = if (it == true) View.VISIBLE else View.GONE binding.homeDantotsuContainer.visibility = if (it == true) View.VISIBLE else View.GONE
(binding.homeDantotsuIcon.drawable as Animatable).start() (binding.homeDantotsuIcon.drawable as Animatable).start()
binding.homeDantotsuContainer.startAnimation(setSlideUp(uiSettings)) binding.homeDantotsuContainer.startAnimation(setSlideUp())
binding.homeDantotsuIcon.setSafeOnClickListener { binding.homeDantotsuIcon.setSafeOnClickListener {
(binding.homeDantotsuIcon.drawable as Animatable).start() (binding.homeDantotsuIcon.drawable as Animatable).start()
} }
@ -330,8 +329,6 @@ class HomeFragment : Fragment() {
live.observe(viewLifecycleOwner) { live.observe(viewLifecycleOwner) {
if (it) { if (it) {
scope.launch { scope.launch {
uiSettings =
loadData<UserInterfaceSettings>("ui_settings") ?: UserInterfaceSettings()
withContext(Dispatchers.IO) { withContext(Dispatchers.IO) {
//Get userData First //Get userData First
getUserId(requireContext()) { getUserId(requireContext()) {
@ -340,8 +337,9 @@ class HomeFragment : Fragment() {
model.loaded = true model.loaded = true
model.setListImages() model.setListImages()
var empty = true var empty = true
val homeLayoutShow: List<Boolean> = PrefManager.getVal(PrefName.HomeLayoutShow)
(array.indices).forEach { i -> (array.indices).forEach { i ->
if (uiSettings.homeLayoutShow[i]) { if (homeLayoutShow.elementAt(i)) {
array[i].run() array[i].run()
empty = false empty = false
} else withContext(Dispatchers.Main) { } else withContext(Dispatchers.Main) {

View file

@ -25,22 +25,18 @@ import ani.dantotsu.connections.anilist.AnilistMangaViewModel
import ani.dantotsu.connections.anilist.SearchResults import ani.dantotsu.connections.anilist.SearchResults
import ani.dantotsu.connections.anilist.getUserId import ani.dantotsu.connections.anilist.getUserId
import ani.dantotsu.databinding.FragmentMangaBinding import ani.dantotsu.databinding.FragmentMangaBinding
import ani.dantotsu.loadData
import ani.dantotsu.media.MediaAdaptor import ani.dantotsu.media.MediaAdaptor
import ani.dantotsu.media.ProgressAdapter import ani.dantotsu.media.ProgressAdapter
import ani.dantotsu.navBarHeight import ani.dantotsu.navBarHeight
import ani.dantotsu.px import ani.dantotsu.px
import ani.dantotsu.settings.UserInterfaceSettings
import ani.dantotsu.settings.saving.PrefName import ani.dantotsu.settings.saving.PrefName
import ani.dantotsu.settings.saving.PrefWrapper import ani.dantotsu.settings.saving.PrefManager
import ani.dantotsu.snackString import ani.dantotsu.snackString
import ani.dantotsu.statusBarHeight import ani.dantotsu.statusBarHeight
import kotlinx.coroutines.Dispatchers import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.delay import kotlinx.coroutines.delay
import kotlinx.coroutines.launch import kotlinx.coroutines.launch
import kotlinx.coroutines.withContext import kotlinx.coroutines.withContext
import uy.kohesive.injekt.Injekt
import uy.kohesive.injekt.api.get
import kotlin.math.max import kotlin.math.max
import kotlin.math.min import kotlin.math.min
@ -49,9 +45,6 @@ class MangaFragment : Fragment() {
private val binding get() = _binding!! private val binding get() = _binding!!
private lateinit var mangaPageAdapter: MangaPageAdapter private lateinit var mangaPageAdapter: MangaPageAdapter
private var uiSettings: UserInterfaceSettings =
loadData("ui_settings") ?: UserInterfaceSettings()
val model: AnilistMangaViewModel by activityViewModels() val model: AnilistMangaViewModel by activityViewModels()
override fun onCreateView( override fun onCreateView(
@ -178,7 +171,7 @@ class MangaFragment : Fragment() {
if (it != null) { if (it != null) {
mangaPageAdapter.updateTrending( mangaPageAdapter.updateTrending(
MediaAdaptor( MediaAdaptor(
if (uiSettings.smallView) 3 else 2, if (PrefManager.getVal(PrefName.SmallView)) 3 else 2,
it, it,
requireActivity(), requireActivity(),
viewPager = mangaPageAdapter.trendingViewPager viewPager = mangaPageAdapter.trendingViewPager
@ -245,8 +238,8 @@ class MangaFragment : Fragment() {
model.loaded = true model.loaded = true
model.loadTrending() model.loadTrending()
model.loadTrendingNovel() model.loadTrendingNovel()
model.loadPopular("MANGA", sort = Anilist.sortBy[1], onList = PrefWrapper.getVal( model.loadPopular("MANGA", sort = Anilist.sortBy[1], onList = PrefManager.getVal(
PrefName.PopularMangaList, true)) PrefName.PopularMangaList))
} }
live.postValue(false) live.postValue(false)
_binding?.mangaRefresh?.isRefreshing = false _binding?.mangaRefresh?.isRefreshing = false

View file

@ -1,6 +1,5 @@
package ani.dantotsu.home package ani.dantotsu.home
import android.content.Context
import android.content.Intent import android.content.Intent
import android.os.Handler import android.os.Handler
import android.os.Looper import android.os.Looper
@ -22,7 +21,6 @@ import ani.dantotsu.R
import ani.dantotsu.connections.anilist.Anilist import ani.dantotsu.connections.anilist.Anilist
import ani.dantotsu.currContext import ani.dantotsu.currContext
import ani.dantotsu.databinding.ItemMangaPageBinding import ani.dantotsu.databinding.ItemMangaPageBinding
import ani.dantotsu.loadData
import ani.dantotsu.loadImage import ani.dantotsu.loadImage
import ani.dantotsu.media.GenreActivity import ani.dantotsu.media.GenreActivity
import ani.dantotsu.media.MediaAdaptor import ani.dantotsu.media.MediaAdaptor
@ -32,9 +30,8 @@ import ani.dantotsu.setSafeOnClickListener
import ani.dantotsu.setSlideIn import ani.dantotsu.setSlideIn
import ani.dantotsu.setSlideUp import ani.dantotsu.setSlideUp
import ani.dantotsu.settings.SettingsDialogFragment import ani.dantotsu.settings.SettingsDialogFragment
import ani.dantotsu.settings.UserInterfaceSettings
import ani.dantotsu.settings.saving.PrefName import ani.dantotsu.settings.saving.PrefName
import ani.dantotsu.settings.saving.PrefWrapper import ani.dantotsu.settings.saving.PrefManager
import ani.dantotsu.statusBarHeight import ani.dantotsu.statusBarHeight
import com.google.android.material.card.MaterialCardView import com.google.android.material.card.MaterialCardView
import com.google.android.material.textfield.TextInputLayout import com.google.android.material.textfield.TextInputLayout
@ -45,8 +42,6 @@ class MangaPageAdapter : RecyclerView.Adapter<MangaPageAdapter.MangaPageViewHold
private var trendHandler: Handler? = null private var trendHandler: Handler? = null
private lateinit var trendRun: Runnable private lateinit var trendRun: Runnable
var trendingViewPager: ViewPager2? = null var trendingViewPager: ViewPager2? = null
private var uiSettings: UserInterfaceSettings =
loadData("ui_settings") ?: UserInterfaceSettings()
override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): MangaPageViewHolder { override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): MangaPageViewHolder {
val binding = val binding =
@ -74,7 +69,7 @@ class MangaPageAdapter : RecyclerView.Adapter<MangaPageAdapter.MangaPageViewHold
binding.mangaTitleContainer.updatePadding(top = statusBarHeight) binding.mangaTitleContainer.updatePadding(top = statusBarHeight)
if (uiSettings.smallView) binding.mangaTrendingContainer.updateLayoutParams<ViewGroup.MarginLayoutParams> { if (PrefManager.getVal(PrefName.SmallView)) binding.mangaTrendingContainer.updateLayoutParams<ViewGroup.MarginLayoutParams> {
bottomMargin = (-108f).px bottomMargin = (-108f).px
} }
@ -123,12 +118,12 @@ class MangaPageAdapter : RecyclerView.Adapter<MangaPageAdapter.MangaPageViewHold
binding.mangaIncludeList.visibility = binding.mangaIncludeList.visibility =
if (Anilist.userid != null) View.VISIBLE else View.GONE if (Anilist.userid != null) View.VISIBLE else View.GONE
binding.mangaIncludeList.isChecked = PrefWrapper.getVal(PrefName.PopularMangaList, true) binding.mangaIncludeList.isChecked = PrefManager.getVal(PrefName.PopularMangaList)
binding.mangaIncludeList.setOnCheckedChangeListener { _, isChecked -> binding.mangaIncludeList.setOnCheckedChangeListener { _, isChecked ->
onIncludeListClick.invoke(isChecked) onIncludeListClick.invoke(isChecked)
PrefWrapper.setVal(PrefName.PopularMangaList, isChecked) PrefManager.setVal(PrefName.PopularMangaList, isChecked)
} }
if (ready.value == false) if (ready.value == false)
ready.postValue(true) ready.postValue(true)
@ -164,10 +159,10 @@ class MangaPageAdapter : RecyclerView.Adapter<MangaPageAdapter.MangaPageViewHold
) )
binding.mangaTrendingViewPager.layoutAnimation = binding.mangaTrendingViewPager.layoutAnimation =
LayoutAnimationController(setSlideIn(uiSettings), 0.25f) LayoutAnimationController(setSlideIn(), 0.25f)
binding.mangaTitleContainer.startAnimation(setSlideUp(uiSettings)) binding.mangaTitleContainer.startAnimation(setSlideUp())
binding.mangaListContainer.layoutAnimation = binding.mangaListContainer.layoutAnimation =
LayoutAnimationController(setSlideIn(uiSettings), 0.25f) LayoutAnimationController(setSlideIn(), 0.25f)
} }
fun updateNovel(adaptor: MediaAdaptor) { fun updateNovel(adaptor: MediaAdaptor) {
@ -182,11 +177,11 @@ class MangaPageAdapter : RecyclerView.Adapter<MangaPageAdapter.MangaPageViewHold
binding.mangaNovelRecyclerView.visibility = View.VISIBLE binding.mangaNovelRecyclerView.visibility = View.VISIBLE
binding.mangaNovel.visibility = View.VISIBLE binding.mangaNovel.visibility = View.VISIBLE
binding.mangaNovel.startAnimation(setSlideUp(uiSettings)) binding.mangaNovel.startAnimation(setSlideUp())
binding.mangaNovelRecyclerView.layoutAnimation = binding.mangaNovelRecyclerView.layoutAnimation =
LayoutAnimationController(setSlideIn(uiSettings), 0.25f) LayoutAnimationController(setSlideIn(), 0.25f)
binding.mangaPopular.visibility = View.VISIBLE binding.mangaPopular.visibility = View.VISIBLE
binding.mangaPopular.startAnimation(setSlideUp(uiSettings)) binding.mangaPopular.startAnimation(setSlideUp())
} }
fun updateAvatar() { fun updateAvatar() {

View file

@ -22,18 +22,17 @@ import ani.dantotsu.databinding.ActivityNoInternetBinding
import ani.dantotsu.download.anime.OfflineAnimeFragment import ani.dantotsu.download.anime.OfflineAnimeFragment
import ani.dantotsu.download.manga.OfflineMangaFragment import ani.dantotsu.download.manga.OfflineMangaFragment
import ani.dantotsu.initActivity import ani.dantotsu.initActivity
import ani.dantotsu.loadData
import ani.dantotsu.navBarHeight import ani.dantotsu.navBarHeight
import ani.dantotsu.offline.OfflineFragment import ani.dantotsu.offline.OfflineFragment
import ani.dantotsu.selectedOption import ani.dantotsu.selectedOption
import ani.dantotsu.settings.UserInterfaceSettings import ani.dantotsu.settings.saving.PrefName
import ani.dantotsu.settings.saving.PrefManager
import ani.dantotsu.snackString import ani.dantotsu.snackString
import ani.dantotsu.themes.ThemeManager import ani.dantotsu.themes.ThemeManager
import nl.joery.animatedbottombar.AnimatedBottomBar import nl.joery.animatedbottombar.AnimatedBottomBar
class NoInternet : AppCompatActivity() { class NoInternet : AppCompatActivity() {
private lateinit var binding: ActivityNoInternetBinding private lateinit var binding: ActivityNoInternetBinding
private var uiSettings = UserInterfaceSettings()
override fun onCreate(savedInstanceState: Bundle?) { override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState) super.onCreate(savedInstanceState)
@ -69,8 +68,7 @@ class NoInternet : AppCompatActivity() {
binding.root.doOnAttach { binding.root.doOnAttach {
initActivity(this) initActivity(this)
uiSettings = loadData("ui_settings") ?: uiSettings selectedOption = PrefManager.getVal(PrefName.DefaultStartUpTab)
selectedOption = uiSettings.defaultStartUpTab
binding.includedNavbar.navbarContainer.updateLayoutParams<ViewGroup.MarginLayoutParams> { binding.includedNavbar.navbarContainer.updateLayoutParams<ViewGroup.MarginLayoutParams> {
bottomMargin = navBarHeight bottomMargin = navBarHeight
@ -82,7 +80,7 @@ class NoInternet : AppCompatActivity() {
val mainViewPager = binding.viewpager val mainViewPager = binding.viewpager
mainViewPager.isUserInputEnabled = false mainViewPager.isUserInputEnabled = false
mainViewPager.adapter = ViewPagerAdapter(supportFragmentManager, lifecycle) mainViewPager.adapter = ViewPagerAdapter(supportFragmentManager, lifecycle)
mainViewPager.setPageTransformer(ZoomOutPageTransformer(uiSettings)) mainViewPager.setPageTransformer(ZoomOutPageTransformer())
navbar.setOnTabSelectListener(object : navbar.setOnTabSelectListener(object :
AnimatedBottomBar.OnTabSelectListener { AnimatedBottomBar.OnTabSelectListener {
override fun onTabSelected( override fun onTabSelected(

View file

@ -16,10 +16,10 @@ import androidx.lifecycle.lifecycleScope
import ani.dantotsu.R import ani.dantotsu.R
import ani.dantotsu.Refresh import ani.dantotsu.Refresh
import ani.dantotsu.databinding.ActivityListBinding import ani.dantotsu.databinding.ActivityListBinding
import ani.dantotsu.loadData
import ani.dantotsu.media.user.ListViewPagerAdapter import ani.dantotsu.media.user.ListViewPagerAdapter
import ani.dantotsu.navBarHeight import ani.dantotsu.navBarHeight
import ani.dantotsu.settings.UserInterfaceSettings import ani.dantotsu.settings.saving.PrefName
import ani.dantotsu.settings.saving.PrefManager
import ani.dantotsu.statusBarHeight import ani.dantotsu.statusBarHeight
import ani.dantotsu.themes.ThemeManager import ani.dantotsu.themes.ThemeManager
import com.google.android.material.tabs.TabLayout import com.google.android.material.tabs.TabLayout
@ -66,8 +66,7 @@ class CalendarActivity : AppCompatActivity() {
binding.listTitle.setTextColor(primaryTextColor) binding.listTitle.setTextColor(primaryTextColor)
binding.listTabLayout.setTabTextColors(secondaryTextColor, primaryTextColor) binding.listTabLayout.setTabTextColors(secondaryTextColor, primaryTextColor)
binding.listTabLayout.setSelectedTabIndicatorColor(primaryTextColor) binding.listTabLayout.setSelectedTabIndicatorColor(primaryTextColor)
val uiSettings = loadData<UserInterfaceSettings>("ui_settings") ?: UserInterfaceSettings() if (!(PrefManager.getVal(PrefName.ImmersiveMode) as Boolean)) {
if (!uiSettings.immersiveMode) {
this.window.statusBarColor = this.window.statusBarColor =
ContextCompat.getColor(this, R.color.nav_bg_inv) ContextCompat.getColor(this, R.color.nav_bg_inv)
binding.root.fitsSystemWindows = true binding.root.fitsSystemWindows = true

View file

@ -11,10 +11,8 @@ import androidx.core.util.Pair
import androidx.core.view.ViewCompat import androidx.core.view.ViewCompat
import androidx.recyclerview.widget.RecyclerView import androidx.recyclerview.widget.RecyclerView
import ani.dantotsu.databinding.ItemCharacterBinding import ani.dantotsu.databinding.ItemCharacterBinding
import ani.dantotsu.loadData
import ani.dantotsu.loadImage import ani.dantotsu.loadImage
import ani.dantotsu.setAnimation import ani.dantotsu.setAnimation
import ani.dantotsu.settings.UserInterfaceSettings
import java.io.Serializable import java.io.Serializable
class CharacterAdapter( class CharacterAdapter(
@ -26,13 +24,10 @@ class CharacterAdapter(
return CharacterViewHolder(binding) return CharacterViewHolder(binding)
} }
private val uiSettings =
loadData<UserInterfaceSettings>("ui_settings") ?: UserInterfaceSettings()
@SuppressLint("SetTextI18n") @SuppressLint("SetTextI18n")
override fun onBindViewHolder(holder: CharacterViewHolder, position: Int) { override fun onBindViewHolder(holder: CharacterViewHolder, position: Int) {
val binding = holder.binding val binding = holder.binding
setAnimation(binding.root.context, holder.binding.root, uiSettings) setAnimation(binding.root.context, holder.binding.root)
val character = characterList[position] val character = characterList[position]
binding.itemCompactRelation.text = character.role + " " binding.itemCompactRelation.text = character.role + " "
binding.itemCompactImage.loadImage(character.image) binding.itemCompactImage.loadImage(character.image)

View file

@ -17,13 +17,13 @@ import ani.dantotsu.R
import ani.dantotsu.Refresh import ani.dantotsu.Refresh
import ani.dantotsu.databinding.ActivityCharacterBinding import ani.dantotsu.databinding.ActivityCharacterBinding
import ani.dantotsu.initActivity import ani.dantotsu.initActivity
import ani.dantotsu.loadData
import ani.dantotsu.loadImage import ani.dantotsu.loadImage
import ani.dantotsu.navBarHeight import ani.dantotsu.navBarHeight
import ani.dantotsu.others.ImageViewDialog import ani.dantotsu.others.ImageViewDialog
import ani.dantotsu.others.getSerialized import ani.dantotsu.others.getSerialized
import ani.dantotsu.px import ani.dantotsu.px
import ani.dantotsu.settings.UserInterfaceSettings import ani.dantotsu.settings.saving.PrefName
import ani.dantotsu.settings.saving.PrefManager
import ani.dantotsu.statusBarHeight import ani.dantotsu.statusBarHeight
import ani.dantotsu.themes.ThemeManager import ani.dantotsu.themes.ThemeManager
import com.google.android.material.appbar.AppBarLayout import com.google.android.material.appbar.AppBarLayout
@ -37,7 +37,6 @@ class CharacterDetailsActivity : AppCompatActivity(), AppBarLayout.OnOffsetChang
private val model: OtherDetailsViewModel by viewModels() private val model: OtherDetailsViewModel by viewModels()
private lateinit var character: Character private lateinit var character: Character
private var loaded = false private var loaded = false
val uiSettings = loadData<UserInterfaceSettings>("ui_settings") ?: UserInterfaceSettings()
override fun onCreate(savedInstanceState: Bundle?) { override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState) super.onCreate(savedInstanceState)
@ -48,11 +47,11 @@ class CharacterDetailsActivity : AppCompatActivity(), AppBarLayout.OnOffsetChang
initActivity(this) initActivity(this)
screenWidth = resources.displayMetrics.run { widthPixels / density } screenWidth = resources.displayMetrics.run { widthPixels / density }
if (uiSettings.immersiveMode) this.window.statusBarColor = if (PrefManager.getVal(PrefName.ImmersiveMode)) this.window.statusBarColor =
ContextCompat.getColor(this, R.color.status) ContextCompat.getColor(this, R.color.status)
val banner = val banner =
if (uiSettings.bannerAnimations) binding.characterBanner else binding.characterBannerNoKen if (PrefManager.getVal(PrefName.BannerAnimations)) binding.characterBanner else binding.characterBannerNoKen
banner.updateLayoutParams { height += statusBarHeight } banner.updateLayoutParams { height += statusBarHeight }
binding.characterClose.updateLayoutParams<ViewGroup.MarginLayoutParams> { topMargin += statusBarHeight } binding.characterClose.updateLayoutParams<ViewGroup.MarginLayoutParams> { topMargin += statusBarHeight }
@ -135,16 +134,16 @@ class CharacterDetailsActivity : AppCompatActivity(), AppBarLayout.OnOffsetChang
binding.characterCover.visibility = binding.characterCover.visibility =
if (binding.characterCover.scaleX == 0f) View.GONE else View.VISIBLE if (binding.characterCover.scaleX == 0f) View.GONE else View.VISIBLE
val immersiveMode: Boolean = PrefManager.getVal(PrefName.ImmersiveMode)
if (percentage >= percent && !isCollapsed) { if (percentage >= percent && !isCollapsed) {
isCollapsed = true isCollapsed = true
if (uiSettings.immersiveMode) this.window.statusBarColor = if (immersiveMode) this.window.statusBarColor =
ContextCompat.getColor(this, R.color.nav_bg) ContextCompat.getColor(this, R.color.nav_bg)
binding.characterAppBar.setBackgroundResource(R.color.nav_bg) binding.characterAppBar.setBackgroundResource(R.color.nav_bg)
} }
if (percentage <= percent && isCollapsed) { if (percentage <= percent && isCollapsed) {
isCollapsed = false isCollapsed = false
if (uiSettings.immersiveMode) this.window.statusBarColor = if (immersiveMode) this.window.statusBarColor =
ContextCompat.getColor(this, R.color.status) ContextCompat.getColor(this, R.color.status)
binding.characterAppBar.setBackgroundResource(R.color.bg) binding.characterAppBar.setBackgroundResource(R.color.bg)
} }

View file

@ -12,8 +12,9 @@ import ani.dantotsu.connections.anilist.Anilist
import ani.dantotsu.connections.anilist.GenresViewModel import ani.dantotsu.connections.anilist.GenresViewModel
import ani.dantotsu.databinding.ActivityGenreBinding import ani.dantotsu.databinding.ActivityGenreBinding
import ani.dantotsu.initActivity import ani.dantotsu.initActivity
import ani.dantotsu.loadData
import ani.dantotsu.navBarHeight import ani.dantotsu.navBarHeight
import ani.dantotsu.settings.saving.PrefName
import ani.dantotsu.settings.saving.PrefManager
import ani.dantotsu.statusBarHeight import ani.dantotsu.statusBarHeight
import ani.dantotsu.themes.ThemeManager import ani.dantotsu.themes.ThemeManager
import kotlinx.coroutines.Dispatchers import kotlinx.coroutines.Dispatchers
@ -53,7 +54,8 @@ class GenreActivity : AppCompatActivity() {
GridLayoutManager(this, (screenWidth / 156f).toInt()) GridLayoutManager(this, (screenWidth / 156f).toInt())
lifecycleScope.launch(Dispatchers.IO) { lifecycleScope.launch(Dispatchers.IO) {
model.loadGenres(Anilist.genres ?: loadData("genres_list") ?: arrayListOf()) { model.loadGenres(Anilist.genres ?:
loadLocalGenres() ?: arrayListOf()) {
MainScope().launch { MainScope().launch {
adapter.addGenre(it) adapter.addGenre(it)
} }
@ -61,4 +63,13 @@ class GenreActivity : AppCompatActivity() {
} }
} }
} }
private fun loadLocalGenres(): ArrayList<String>? {
val genres = PrefManager.getVal<Set<String>>(PrefName.GenresList).toMutableList() as ArrayList<String>?
return if (genres.isNullOrEmpty()) {
null
} else {
genres
}
}
} }

View file

@ -26,7 +26,8 @@ import ani.dantotsu.databinding.ItemMediaCompactBinding
import ani.dantotsu.databinding.ItemMediaLargeBinding import ani.dantotsu.databinding.ItemMediaLargeBinding
import ani.dantotsu.databinding.ItemMediaPageBinding import ani.dantotsu.databinding.ItemMediaPageBinding
import ani.dantotsu.databinding.ItemMediaPageSmallBinding import ani.dantotsu.databinding.ItemMediaPageSmallBinding
import ani.dantotsu.settings.UserInterfaceSettings import ani.dantotsu.settings.saving.PrefName
import ani.dantotsu.settings.saving.PrefManager
import com.bumptech.glide.Glide import com.bumptech.glide.Glide
import com.bumptech.glide.load.engine.DiskCacheStrategy import com.bumptech.glide.load.engine.DiskCacheStrategy
import com.bumptech.glide.load.model.GlideUrl import com.bumptech.glide.load.model.GlideUrl
@ -44,9 +45,6 @@ class MediaAdaptor(
private val viewPager: ViewPager2? = null, private val viewPager: ViewPager2? = null,
) : RecyclerView.Adapter<RecyclerView.ViewHolder>() { ) : RecyclerView.Adapter<RecyclerView.ViewHolder>() {
private val uiSettings =
loadData<UserInterfaceSettings>("ui_settings") ?: UserInterfaceSettings()
override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): RecyclerView.ViewHolder { override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): RecyclerView.ViewHolder {
return when (type) { return when (type) {
0 -> MediaViewHolder( 0 -> MediaViewHolder(
@ -91,7 +89,7 @@ class MediaAdaptor(
when (type) { when (type) {
0 -> { 0 -> {
val b = (holder as MediaViewHolder).binding val b = (holder as MediaViewHolder).binding
setAnimation(activity, b.root, uiSettings) setAnimation(activity, b.root)
val media = mediaList?.getOrNull(position) val media = mediaList?.getOrNull(position)
if (media != null) { if (media != null) {
b.itemCompactImage.loadImage(media.cover) b.itemCompactImage.loadImage(media.cover)
@ -135,7 +133,7 @@ class MediaAdaptor(
1 -> { 1 -> {
val b = (holder as MediaLargeViewHolder).binding val b = (holder as MediaLargeViewHolder).binding
setAnimation(activity, b.root, uiSettings) setAnimation(activity, b.root)
val media = mediaList?.get(position) val media = mediaList?.get(position)
if (media != null) { if (media != null) {
b.itemCompactImage.loadImage(media.cover) b.itemCompactImage.loadImage(media.cover)
@ -178,16 +176,17 @@ class MediaAdaptor(
val b = (holder as MediaPageViewHolder).binding val b = (holder as MediaPageViewHolder).binding
val media = mediaList?.get(position) val media = mediaList?.get(position)
if (media != null) { if (media != null) {
val bannerAnimations: Boolean = PrefManager.getVal(PrefName.BannerAnimations)
b.itemCompactImage.loadImage(media.cover) b.itemCompactImage.loadImage(media.cover)
if (uiSettings.bannerAnimations) if (bannerAnimations)
b.itemCompactBanner.setTransitionGenerator( b.itemCompactBanner.setTransitionGenerator(
RandomTransitionGenerator( RandomTransitionGenerator(
(10000 + 15000 * (uiSettings.animationSpeed)).toLong(), (10000 + 15000 * ((PrefManager.getVal(PrefName.AnimationSpeed)) as Float)).toLong(),
AccelerateDecelerateInterpolator() AccelerateDecelerateInterpolator()
) )
) )
val banner = val banner =
if (uiSettings.bannerAnimations) b.itemCompactBanner else b.itemCompactBannerNoKen if (bannerAnimations) b.itemCompactBanner else b.itemCompactBannerNoKen
val context = b.itemCompactBanner.context val context = b.itemCompactBanner.context
if (!(context as Activity).isDestroyed) if (!(context as Activity).isDestroyed)
Glide.with(context as Context) Glide.with(context as Context)
@ -234,16 +233,17 @@ class MediaAdaptor(
val b = (holder as MediaPageSmallViewHolder).binding val b = (holder as MediaPageSmallViewHolder).binding
val media = mediaList?.get(position) val media = mediaList?.get(position)
if (media != null) { if (media != null) {
val bannerAnimations: Boolean = PrefManager.getVal(PrefName.BannerAnimations)
b.itemCompactImage.loadImage(media.cover) b.itemCompactImage.loadImage(media.cover)
if (uiSettings.bannerAnimations) if (bannerAnimations)
b.itemCompactBanner.setTransitionGenerator( b.itemCompactBanner.setTransitionGenerator(
RandomTransitionGenerator( RandomTransitionGenerator(
(10000 + 15000 * (uiSettings.animationSpeed)).toLong(), (10000 + 15000 * ((PrefManager.getVal(PrefName.AnimationSpeed) as Float))).toLong(),
AccelerateDecelerateInterpolator() AccelerateDecelerateInterpolator()
) )
) )
val banner = val banner =
if (uiSettings.bannerAnimations) b.itemCompactBanner else b.itemCompactBannerNoKen if (bannerAnimations) b.itemCompactBanner else b.itemCompactBannerNoKen
val context = b.itemCompactBanner.context val context = b.itemCompactBanner.context
if (!(context as Activity).isDestroyed) if (!(context as Activity).isDestroyed)
Glide.with(context as Context) Glide.with(context as Context)

View file

@ -2,7 +2,6 @@ package ani.dantotsu.media
import android.animation.ObjectAnimator import android.animation.ObjectAnimator
import android.annotation.SuppressLint import android.annotation.SuppressLint
import android.content.Context
import android.content.Intent import android.content.Intent
import android.os.Bundle import android.os.Bundle
import android.text.SpannableStringBuilder import android.text.SpannableStringBuilder
@ -35,7 +34,6 @@ import ani.dantotsu.connections.anilist.Anilist
import ani.dantotsu.copyToClipboard import ani.dantotsu.copyToClipboard
import ani.dantotsu.databinding.ActivityMediaBinding import ani.dantotsu.databinding.ActivityMediaBinding
import ani.dantotsu.initActivity import ani.dantotsu.initActivity
import ani.dantotsu.loadData
import ani.dantotsu.loadImage import ani.dantotsu.loadImage
import ani.dantotsu.media.anime.AnimeWatchFragment import ani.dantotsu.media.anime.AnimeWatchFragment
import ani.dantotsu.media.manga.MangaReadFragment import ani.dantotsu.media.manga.MangaReadFragment
@ -44,10 +42,8 @@ import ani.dantotsu.navBarHeight
import ani.dantotsu.openLinkInBrowser import ani.dantotsu.openLinkInBrowser
import ani.dantotsu.others.ImageViewDialog import ani.dantotsu.others.ImageViewDialog
import ani.dantotsu.others.getSerialized import ani.dantotsu.others.getSerialized
import ani.dantotsu.saveData
import ani.dantotsu.settings.UserInterfaceSettings
import ani.dantotsu.settings.saving.PrefName import ani.dantotsu.settings.saving.PrefName
import ani.dantotsu.settings.saving.PrefWrapper import ani.dantotsu.settings.saving.PrefManager
import ani.dantotsu.snackString import ani.dantotsu.snackString
import ani.dantotsu.statusBarHeight import ani.dantotsu.statusBarHeight
import ani.dantotsu.themes.ThemeManager import ani.dantotsu.themes.ThemeManager
@ -67,7 +63,6 @@ class MediaDetailsActivity : AppCompatActivity(), AppBarLayout.OnOffsetChangedLi
private val scope = lifecycleScope private val scope = lifecycleScope
private val model: MediaDetailsViewModel by viewModels() private val model: MediaDetailsViewModel by viewModels()
private lateinit var tabLayout: NavigationBarView private lateinit var tabLayout: NavigationBarView
private lateinit var uiSettings: UserInterfaceSettings
var selected = 0 var selected = 0
var anime = true var anime = true
private var adult = false private var adult = false
@ -92,7 +87,6 @@ class MediaDetailsActivity : AppCompatActivity(), AppBarLayout.OnOffsetChangedLi
//Ui init //Ui init
initActivity(this) initActivity(this)
uiSettings = loadData<UserInterfaceSettings>("ui_settings") ?: UserInterfaceSettings()
binding.mediaBanner.updateLayoutParams { height += statusBarHeight } binding.mediaBanner.updateLayoutParams { height += statusBarHeight }
binding.mediaBannerNoKen.updateLayoutParams { height += statusBarHeight } binding.mediaBannerNoKen.updateLayoutParams { height += statusBarHeight }
@ -113,20 +107,21 @@ class MediaDetailsActivity : AppCompatActivity(), AppBarLayout.OnOffsetChangedLi
onBackPressedDispatcher.onBackPressed() onBackPressedDispatcher.onBackPressed()
} }
if (uiSettings.bannerAnimations) { val bannerAnimations: Boolean = PrefManager.getVal(PrefName.BannerAnimations)
if (bannerAnimations) {
val adi = AccelerateDecelerateInterpolator() val adi = AccelerateDecelerateInterpolator()
val generator = RandomTransitionGenerator( val generator = RandomTransitionGenerator(
(10000 + 15000 * (uiSettings.animationSpeed)).toLong(), (10000 + 15000 * ((PrefManager.getVal(PrefName.AnimationSpeed) as Float))).toLong(),
adi adi
) )
binding.mediaBanner.setTransitionGenerator(generator) binding.mediaBanner.setTransitionGenerator(generator)
} }
val banner = val banner =
if (uiSettings.bannerAnimations) binding.mediaBanner else binding.mediaBannerNoKen if (bannerAnimations) binding.mediaBanner else binding.mediaBannerNoKen
val viewPager = binding.mediaViewPager val viewPager = binding.mediaViewPager
tabLayout = binding.mediaTab as NavigationBarView tabLayout = binding.mediaTab as NavigationBarView
viewPager.isUserInputEnabled = false viewPager.isUserInputEnabled = false
viewPager.setPageTransformer(ZoomOutPageTransformer(uiSettings)) viewPager.setPageTransformer(ZoomOutPageTransformer())
val isDownload = intent.getBooleanExtra("download", false) val isDownload = intent.getBooleanExtra("download", false)
@ -143,7 +138,7 @@ class MediaDetailsActivity : AppCompatActivity(), AppBarLayout.OnOffsetChangedLi
banner.loadImage(media.banner ?: media.cover, 400) banner.loadImage(media.banner ?: media.cover, 400)
val gestureDetector = GestureDetector(this, object : GesturesListener() { val gestureDetector = GestureDetector(this, object : GesturesListener() {
override fun onDoubleClick(event: MotionEvent) { override fun onDoubleClick(event: MotionEvent) {
if (!uiSettings.bannerAnimations) if (!(PrefManager.getVal(PrefName.BannerAnimations) as Boolean))
snackString(getString(R.string.enable_banner_animations)) snackString(getString(R.string.enable_banner_animations))
else { else {
binding.mediaBanner.restart() binding.mediaBanner.restart()
@ -161,7 +156,7 @@ class MediaDetailsActivity : AppCompatActivity(), AppBarLayout.OnOffsetChangedLi
} }
}) })
banner.setOnTouchListener { _, motionEvent -> gestureDetector.onTouchEvent(motionEvent);true } banner.setOnTouchListener { _, motionEvent -> gestureDetector.onTouchEvent(motionEvent);true }
if (PrefWrapper.getVal(PrefName.Incognito, false)) { if (PrefManager.getVal(PrefName.Incognito)) {
binding.mediaTitle.text = " ${media.userPreferredName}" binding.mediaTitle.text = " ${media.userPreferredName}"
binding.incognito.visibility = View.VISIBLE binding.incognito.visibility = View.VISIBLE
} else { } else {
@ -285,7 +280,10 @@ class MediaDetailsActivity : AppCompatActivity(), AppBarLayout.OnOffsetChangedLi
} else snackString(getString(R.string.please_login_anilist)) } else snackString(getString(R.string.please_login_anilist))
} }
binding.mediaAddToList.setOnLongClickListener { binding.mediaAddToList.setOnLongClickListener {
saveData("${media.id}_progressDialog", true) PrefManager.setCustomVal(
"${media.id}_progressDialog",
true,
)
snackString(getString(R.string.auto_update_reset)) snackString(getString(R.string.auto_update_reset))
true true
} }
@ -346,7 +344,7 @@ class MediaDetailsActivity : AppCompatActivity(), AppBarLayout.OnOffsetChangedLi
viewPager.setCurrentItem(selected, false) viewPager.setCurrentItem(selected, false)
val sel = model.loadSelected(media, isDownload) val sel = model.loadSelected(media, isDownload)
sel.window = selected sel.window = selected
model.saveSelected(media.id, sel, this) model.saveSelected(media.id, sel)
true true
} }
@ -355,7 +353,7 @@ class MediaDetailsActivity : AppCompatActivity(), AppBarLayout.OnOffsetChangedLi
viewPager.setCurrentItem(selected, false) viewPager.setCurrentItem(selected, false)
if (model.continueMedia == null && media.cameFromContinue) { if (model.continueMedia == null && media.cameFromContinue) {
model.continueMedia = PrefWrapper.getVal(PrefName.ContinueMedia, true) model.continueMedia = PrefManager.getVal(PrefName.ContinueMedia)
selected = 1 selected = 1
} }
@ -440,7 +438,7 @@ class MediaDetailsActivity : AppCompatActivity(), AppBarLayout.OnOffsetChangedLi
binding.mediaCover.visibility = binding.mediaCover.visibility =
if (binding.mediaCover.scaleX == 0f) View.GONE else View.VISIBLE if (binding.mediaCover.scaleX == 0f) View.GONE else View.VISIBLE
val duration = (200 * uiSettings.animationSpeed).toLong() val duration = (200 * (PrefManager.getVal(PrefName.AnimationSpeed) as Float)).toLong()
val typedValue = TypedValue() val typedValue = TypedValue()
this@MediaDetailsActivity.theme.resolveAttribute( this@MediaDetailsActivity.theme.resolveAttribute(
com.google.android.material.R.attr.colorSecondary, com.google.android.material.R.attr.colorSecondary,
@ -470,7 +468,7 @@ class MediaDetailsActivity : AppCompatActivity(), AppBarLayout.OnOffsetChangedLi
.start() .start()
ObjectAnimator.ofFloat(binding.mediaCollapseContainer, "translationX", 0f) ObjectAnimator.ofFloat(binding.mediaCollapseContainer, "translationX", 0f)
.setDuration(duration).start() .setDuration(duration).start()
if (uiSettings.bannerAnimations) binding.mediaBanner.resume() if (PrefManager.getVal(PrefName.BannerAnimations)) binding.mediaBanner.resume()
} }
if (percentage == 1 && model.scrolledToTop.value != false) model.scrolledToTop.postValue( if (percentage == 1 && model.scrolledToTop.value != false) model.scrolledToTop.postValue(
false false

View file

@ -1,6 +1,5 @@
package ani.dantotsu.media package ani.dantotsu.media
import android.app.Activity
import android.os.Handler import android.os.Handler
import android.os.Looper import android.os.Looper
import androidx.fragment.app.FragmentManager import androidx.fragment.app.FragmentManager
@ -10,7 +9,6 @@ import androidx.lifecycle.ViewModel
import ani.dantotsu.R import ani.dantotsu.R
import ani.dantotsu.connections.anilist.Anilist import ani.dantotsu.connections.anilist.Anilist
import ani.dantotsu.currContext import ani.dantotsu.currContext
import ani.dantotsu.loadData
import ani.dantotsu.logger import ani.dantotsu.logger
import ani.dantotsu.media.anime.Episode import ani.dantotsu.media.anime.Episode
import ani.dantotsu.media.anime.SelectorDialogFragment import ani.dantotsu.media.anime.SelectorDialogFragment
@ -27,30 +25,28 @@ import ani.dantotsu.parsers.NovelSources
import ani.dantotsu.parsers.ShowResponse import ani.dantotsu.parsers.ShowResponse
import ani.dantotsu.parsers.VideoExtractor import ani.dantotsu.parsers.VideoExtractor
import ani.dantotsu.parsers.WatchSources import ani.dantotsu.parsers.WatchSources
import ani.dantotsu.saveData
import ani.dantotsu.settings.saving.PrefName import ani.dantotsu.settings.saving.PrefName
import ani.dantotsu.settings.saving.PrefWrapper import ani.dantotsu.settings.saving.PrefManager
import ani.dantotsu.snackString import ani.dantotsu.snackString
import ani.dantotsu.tryWithSuspend import ani.dantotsu.tryWithSuspend
import com.bumptech.glide.load.resource.bitmap.BitmapTransformation import com.bumptech.glide.load.resource.bitmap.BitmapTransformation
import kotlinx.coroutines.Dispatchers import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.MainScope import kotlinx.coroutines.MainScope
import kotlinx.coroutines.launch import kotlinx.coroutines.launch
import uy.kohesive.injekt.Injekt
import uy.kohesive.injekt.api.get
class MediaDetailsViewModel : ViewModel() { class MediaDetailsViewModel : ViewModel() {
val scrolledToTop = MutableLiveData(true) val scrolledToTop = MutableLiveData(true)
fun saveSelected(id: Int, data: Selected, activity: Activity? = null) { fun saveSelected(id: Int, data: Selected) {
saveData("$id-select", data, activity) PrefManager.setCustomVal("Selected-$id", data)
} }
fun loadSelected(media: Media, isDownload: Boolean = false): Selected { fun loadSelected(media: Media, isDownload: Boolean = false): Selected {
val data = loadData<Selected>("${media.id}-select") ?: Selected().let { val data = PrefManager.getNullableCustomVal<Selected?>("Selected-${media.id}", null)
?: Selected().let {
it.sourceIndex = 0 it.sourceIndex = 0
it.preferDub = PrefWrapper.getVal(PrefName.SettingsPreferDub, false) it.preferDub = PrefManager.getVal(PrefName.SettingsPreferDub)
saveSelected(media.id, it) saveSelected(media.id, it)
it it
} }

View file

@ -2,7 +2,6 @@ package ani.dantotsu.media
import android.animation.ObjectAnimator import android.animation.ObjectAnimator
import android.annotation.SuppressLint import android.annotation.SuppressLint
import android.content.Context
import android.content.Intent import android.content.Intent
import android.os.Build import android.os.Build
import android.os.Bundle import android.os.Bundle
@ -27,7 +26,7 @@ import ani.dantotsu.connections.anilist.Anilist
import ani.dantotsu.connections.anilist.GenresViewModel import ani.dantotsu.connections.anilist.GenresViewModel
import ani.dantotsu.databinding.* import ani.dantotsu.databinding.*
import ani.dantotsu.settings.saving.PrefName import ani.dantotsu.settings.saving.PrefName
import ani.dantotsu.settings.saving.PrefWrapper import ani.dantotsu.settings.saving.PrefManager
import io.noties.markwon.Markwon import io.noties.markwon.Markwon
import io.noties.markwon.SoftBreakAddsNewLinePlugin import io.noties.markwon.SoftBreakAddsNewLinePlugin
import kotlinx.coroutines.Dispatchers import kotlinx.coroutines.Dispatchers
@ -62,7 +61,7 @@ class MediaInfoFragment : Fragment() {
@SuppressLint("SetJavaScriptEnabled") @SuppressLint("SetJavaScriptEnabled")
override fun onViewCreated(view: View, savedInstanceState: Bundle?) { override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
val model: MediaDetailsViewModel by activityViewModels() val model: MediaDetailsViewModel by activityViewModels()
val offline = PrefWrapper.getVal(PrefName.OfflineMode, false) val offline: Boolean = PrefManager.getVal(PrefName.OfflineMode)
binding.mediaInfoProgressBar.visibility = if (!loaded) View.VISIBLE else View.GONE binding.mediaInfoProgressBar.visibility = if (!loaded) View.VISIBLE else View.GONE
binding.mediaInfoContainer.visibility = if (loaded) View.VISIBLE else View.GONE binding.mediaInfoContainer.visibility = if (loaded) View.VISIBLE else View.GONE
binding.mediaInfoContainer.updateLayoutParams<ViewGroup.MarginLayoutParams> { bottomMargin += 128f.px + navBarHeight } binding.mediaInfoContainer.updateLayoutParams<ViewGroup.MarginLayoutParams> { bottomMargin += 128f.px + navBarHeight }

View file

@ -17,7 +17,7 @@ import ani.dantotsu.connections.anilist.AnilistSearch
import ani.dantotsu.connections.anilist.SearchResults import ani.dantotsu.connections.anilist.SearchResults
import ani.dantotsu.databinding.ActivitySearchBinding import ani.dantotsu.databinding.ActivitySearchBinding
import ani.dantotsu.settings.saving.PrefName import ani.dantotsu.settings.saving.PrefName
import ani.dantotsu.settings.saving.PrefWrapper import ani.dantotsu.settings.saving.PrefManager
import ani.dantotsu.themes.ThemeManager import ani.dantotsu.themes.ThemeManager
import kotlinx.coroutines.Dispatchers import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.launch import kotlinx.coroutines.launch
@ -53,7 +53,7 @@ class SearchActivity : AppCompatActivity() {
bottom = navBarHeight + 80f.px bottom = navBarHeight + 80f.px
) )
style = PrefWrapper.getVal(PrefName.SearchStyle,0) style = PrefManager.getVal(PrefName.SearchStyle)
var listOnly: Boolean? = intent.getBooleanExtra("listOnly", false) var listOnly: Boolean? = intent.getBooleanExtra("listOnly", false)
if (!listOnly!!) listOnly = null if (!listOnly!!) listOnly = null

View file

@ -23,7 +23,7 @@ import ani.dantotsu.connections.anilist.Anilist
import ani.dantotsu.databinding.ItemChipBinding import ani.dantotsu.databinding.ItemChipBinding
import ani.dantotsu.databinding.ItemSearchHeaderBinding import ani.dantotsu.databinding.ItemSearchHeaderBinding
import ani.dantotsu.settings.saving.PrefName import ani.dantotsu.settings.saving.PrefName
import ani.dantotsu.settings.saving.PrefWrapper import ani.dantotsu.settings.saving.PrefManager
import com.google.android.material.checkbox.MaterialCheckBox.* import com.google.android.material.checkbox.MaterialCheckBox.*
import kotlinx.coroutines.CoroutineScope import kotlinx.coroutines.CoroutineScope
import kotlinx.coroutines.Dispatchers import kotlinx.coroutines.Dispatchers
@ -72,7 +72,7 @@ class SearchAdapter(private val activity: SearchActivity, private val type: Stri
} }
binding.searchBar.hint = activity.result.type binding.searchBar.hint = activity.result.type
if (PrefWrapper.getVal(PrefName.Incognito, false)) { if (PrefManager.getVal(PrefName.Incognito)) {
val startIconDrawableRes = R.drawable.ic_incognito_24 val startIconDrawableRes = R.drawable.ic_incognito_24
val startIconDrawable: Drawable? = val startIconDrawable: Drawable? =
context?.let { AppCompatResources.getDrawable(it, startIconDrawableRes) } context?.let { AppCompatResources.getDrawable(it, startIconDrawableRes) }
@ -148,14 +148,14 @@ class SearchAdapter(private val activity: SearchActivity, private val type: Stri
it.alpha = 1f it.alpha = 1f
binding.searchResultList.alpha = 0.33f binding.searchResultList.alpha = 0.33f
activity.style = 0 activity.style = 0
PrefWrapper.setVal(PrefName.SearchStyle, 0) PrefManager.setVal(PrefName.SearchStyle, 0)
activity.recycler() activity.recycler()
} }
binding.searchResultList.setOnClickListener { binding.searchResultList.setOnClickListener {
it.alpha = 1f it.alpha = 1f
binding.searchResultGrid.alpha = 0.33f binding.searchResultGrid.alpha = 0.33f
activity.style = 1 activity.style = 1
PrefWrapper.setVal(PrefName.SearchStyle, 1) PrefManager.setVal(PrefName.SearchStyle, 1)
activity.recycler() activity.recycler()
} }

View file

@ -9,8 +9,8 @@ import androidx.recyclerview.widget.RecyclerView
import ani.dantotsu.R import ani.dantotsu.R
import ani.dantotsu.databinding.ItemSearchHistoryBinding import ani.dantotsu.databinding.ItemSearchHistoryBinding
import ani.dantotsu.settings.saving.PrefName import ani.dantotsu.settings.saving.PrefName
import ani.dantotsu.settings.saving.PrefWrapper import ani.dantotsu.settings.saving.PrefManager
import ani.dantotsu.settings.saving.PrefWrapper.asLiveStringSet import ani.dantotsu.settings.saving.PrefManager.asLiveStringSet
import ani.dantotsu.settings.saving.SharedPreferenceStringSetLiveData import ani.dantotsu.settings.saving.SharedPreferenceStringSetLiveData
import java.util.Locale import java.util.Locale
@ -26,7 +26,7 @@ class SearchHistoryAdapter(private val type: String, private val searchClicked:
} }
init { init {
searchHistoryLiveData = PrefWrapper.getLiveVal(historyType, mutableSetOf<String>()).asLiveStringSet() searchHistoryLiveData = PrefManager.getLiveVal(historyType, mutableSetOf<String>()).asLiveStringSet()
searchHistoryLiveData?.observeForever { searchHistoryLiveData?.observeForever {
searchHistory = it.toMutableSet() searchHistory = it.toMutableSet()
submitList(searchHistory?.reversed()) submitList(searchHistory?.reversed())
@ -35,14 +35,14 @@ class SearchHistoryAdapter(private val type: String, private val searchClicked:
fun remove(item: String) { fun remove(item: String) {
searchHistory?.remove(item) searchHistory?.remove(item)
PrefWrapper.setVal(historyType, searchHistory) PrefManager.setVal(historyType, searchHistory)
} }
fun add(item: String) { fun add(item: String) {
if (searchHistory?.contains(item) == true || item.isBlank()) return if (searchHistory?.contains(item) == true || item.isBlank()) return
if (PrefWrapper.getVal(PrefName.Incognito, false)) return if (PrefManager.getVal(PrefName.Incognito)) return
searchHistory?.add(item) searchHistory?.add(item)
PrefWrapper.setVal(historyType, searchHistory) PrefManager.setVal(historyType, searchHistory)
} }
override fun onCreateViewHolder( override fun onCreateViewHolder(

View file

@ -1,7 +1,6 @@
package ani.dantotsu.media.anime package ani.dantotsu.media.anime
import android.annotation.SuppressLint import android.annotation.SuppressLint
import android.content.Context
import android.content.Intent import android.content.Intent
import android.net.Uri import android.net.Uri
import android.view.LayoutInflater import android.view.LayoutInflater
@ -28,7 +27,7 @@ import ani.dantotsu.parsers.AnimeSources
import ani.dantotsu.parsers.DynamicAnimeParser import ani.dantotsu.parsers.DynamicAnimeParser
import ani.dantotsu.parsers.WatchSources import ani.dantotsu.parsers.WatchSources
import ani.dantotsu.settings.saving.PrefName import ani.dantotsu.settings.saving.PrefName
import ani.dantotsu.settings.saving.PrefWrapper import ani.dantotsu.settings.saving.PrefManager
import ani.dantotsu.subcriptions.Notifications.Companion.openSettings import ani.dantotsu.subcriptions.Notifications.Companion.openSettings
import ani.dantotsu.subcriptions.Subscription.Companion.getChannelId import ani.dantotsu.subcriptions.Subscription.Companion.getChannelId
import com.google.android.material.chip.Chip import com.google.android.material.chip.Chip
@ -61,7 +60,7 @@ class AnimeWatchAdapter(
_binding = binding _binding = binding
//Youtube //Youtube
if (media.anime!!.youtube != null && fragment.uiSettings.showYtButton) { if (media.anime!!.youtube != null && PrefManager.getVal(PrefName.ShowYtButton)) {
binding.animeSourceYT.visibility = View.VISIBLE binding.animeSourceYT.visibility = View.VISIBLE
binding.animeSourceYT.setOnClickListener { binding.animeSourceYT.setOnClickListener {
val intent = Intent(Intent.ACTION_VIEW, Uri.parse(media.anime.youtube)) val intent = Intent(Intent.ACTION_VIEW, Uri.parse(media.anime.youtube))
@ -92,9 +91,8 @@ class AnimeWatchAdapter(
null null
) )
} }
val offline = if (!isOnline(binding.root.context) || PrefWrapper.getVal( val offline = if (!isOnline(binding.root.context) || PrefManager.getVal(
PrefName.OfflineMode, PrefName.OfflineMode
false
) )
) View.GONE else View.VISIBLE ) View.GONE else View.VISIBLE
@ -200,7 +198,7 @@ class AnimeWatchAdapter(
var refresh = false var refresh = false
var run = false var run = false
var reversed = media.selected!!.recyclerReversed var reversed = media.selected!!.recyclerReversed
var style = media.selected!!.recyclerStyle ?: fragment.uiSettings.animeDefaultView var style = media.selected!!.recyclerStyle ?: PrefManager.getVal(PrefName.AnimeDefaultView)
dialogBinding.animeSourceTop.rotation = if (reversed) -90f else 90f dialogBinding.animeSourceTop.rotation = if (reversed) -90f else 90f
dialogBinding.sortText.text = if (reversed) "Down to Up" else "Up to Down" dialogBinding.sortText.text = if (reversed) "Down to Up" else "Up to Down"
dialogBinding.animeSourceTop.setOnClickListener { dialogBinding.animeSourceTop.setOnClickListener {
@ -358,7 +356,7 @@ class AnimeWatchAdapter(
val episodes = media.anime.episodes!!.keys.toTypedArray() val episodes = media.anime.episodes!!.keys.toTypedArray()
val anilistEp = (media.userProgress ?: 0).plus(1) val anilistEp = (media.userProgress ?: 0).plus(1)
val appEp = loadData<String>("${media.id}_current_ep")?.toIntOrNull() ?: 1 val appEp = PrefManager.getNullableCustomVal<String?>("${media.id}_current_ep", null)?.toIntOrNull() ?: 1
var continueEp = (if (anilistEp > appEp) anilistEp else appEp).toString() var continueEp = (if (anilistEp > appEp) anilistEp else appEp).toString()
if (episodes.contains(continueEp)) { if (episodes.contains(continueEp)) {
@ -370,7 +368,7 @@ class AnimeWatchAdapter(
media.id, media.id,
continueEp continueEp
) )
if ((binding.itemEpisodeProgress.layoutParams as LinearLayout.LayoutParams).weight > fragment.playerSettings.watchPercentage) { if ((binding.itemEpisodeProgress.layoutParams as LinearLayout.LayoutParams).weight > PrefManager.getVal<Float>(PrefName.WatchPercentage)) {
val e = episodes.indexOf(continueEp) val e = episodes.indexOf(continueEp)
if (e != -1 && e + 1 < episodes.size) { if (e != -1 && e + 1 < episodes.size) {
continueEp = episodes[e + 1] continueEp = episodes[e + 1]
@ -397,7 +395,7 @@ class AnimeWatchAdapter(
fragment.onEpisodeClick(continueEp) fragment.onEpisodeClick(continueEp)
} }
if (fragment.continueEp) { if (fragment.continueEp) {
if ((binding.itemEpisodeProgress.layoutParams as LinearLayout.LayoutParams).weight < fragment.playerSettings.watchPercentage) { if ((binding.itemEpisodeProgress.layoutParams as LinearLayout.LayoutParams).weight < PrefManager.getVal<Float>(PrefName.WatchPercentage)) {
binding.animeSourceContinue.performClick() binding.animeSourceContinue.performClick()
fragment.continueEp = false fragment.continueEp = false
} }

View file

@ -40,10 +40,9 @@ import ani.dantotsu.others.LanguageMapper
import ani.dantotsu.parsers.AnimeParser import ani.dantotsu.parsers.AnimeParser
import ani.dantotsu.parsers.AnimeSources import ani.dantotsu.parsers.AnimeSources
import ani.dantotsu.parsers.HAnimeSources import ani.dantotsu.parsers.HAnimeSources
import ani.dantotsu.settings.PlayerSettings
import ani.dantotsu.settings.UserInterfaceSettings
import ani.dantotsu.settings.extensionprefs.AnimeSourcePreferencesFragment import ani.dantotsu.settings.extensionprefs.AnimeSourcePreferencesFragment
import ani.dantotsu.settings.saving.PrefWrapper import ani.dantotsu.settings.saving.PrefName
import ani.dantotsu.settings.saving.PrefManager
import ani.dantotsu.subcriptions.Notifications import ani.dantotsu.subcriptions.Notifications
import ani.dantotsu.subcriptions.Notifications.Group.ANIME_GROUP import ani.dantotsu.subcriptions.Notifications.Group.ANIME_GROUP
import ani.dantotsu.subcriptions.Subscription.Companion.getChannelId import ani.dantotsu.subcriptions.Subscription.Companion.getChannelId
@ -86,8 +85,6 @@ class AnimeWatchFragment : Fragment() {
var continueEp: Boolean = false var continueEp: Boolean = false
var loaded = false var loaded = false
lateinit var playerSettings: PlayerSettings
lateinit var uiSettings: UserInterfaceSettings
override fun onCreateView( override fun onCreateView(
inflater: LayoutInflater, inflater: LayoutInflater,
container: ViewGroup?, container: ViewGroup?,
@ -120,12 +117,6 @@ class AnimeWatchFragment : Fragment() {
var maxGridSize = (screenWidth / 100f).roundToInt() var maxGridSize = (screenWidth / 100f).roundToInt()
maxGridSize = max(4, maxGridSize - (maxGridSize % 2)) maxGridSize = max(4, maxGridSize - (maxGridSize % 2))
playerSettings =
loadData("player_settings", toast = false)
?: PlayerSettings().apply { saveData("player_settings", this) }
uiSettings = loadData("ui_settings", toast = false)
?: UserInterfaceSettings().apply { saveData("ui_settings", this) }
val gridLayoutManager = GridLayoutManager(requireContext(), maxGridSize) val gridLayoutManager = GridLayoutManager(requireContext(), maxGridSize)
gridLayoutManager.spanSizeLookup = object : GridLayoutManager.SpanSizeLookup() { gridLayoutManager.spanSizeLookup = object : GridLayoutManager.SpanSizeLookup() {
@ -174,7 +165,7 @@ class AnimeWatchFragment : Fragment() {
media.selected = model.loadSelected(media) media.selected = model.loadSelected(media)
subscribed = subscribed =
SubscriptionHelper.getSubscriptions(requireContext()).containsKey(media.id) SubscriptionHelper.getSubscriptions().containsKey(media.id)
style = media.selected!!.recyclerStyle style = media.selected!!.recyclerStyle
reverse = media.selected!!.recyclerReversed reverse = media.selected!!.recyclerReversed
@ -191,7 +182,7 @@ class AnimeWatchFragment : Fragment() {
headerAdapter = AnimeWatchAdapter(it, this, model.watchSources!!) headerAdapter = AnimeWatchAdapter(it, this, model.watchSources!!)
episodeAdapter = episodeAdapter =
EpisodeAdapter( EpisodeAdapter(
style ?: uiSettings.animeDefaultView, style ?: PrefManager.getVal(PrefName.AnimeDefaultView),
media, media,
this, this,
offlineMode = offlineMode offlineMode = offlineMode
@ -292,7 +283,7 @@ class AnimeWatchFragment : Fragment() {
model.watchSources?.get(selected.sourceIndex)?.showUserTextListener = null model.watchSources?.get(selected.sourceIndex)?.showUserTextListener = null
selected.sourceIndex = i selected.sourceIndex = i
selected.server = null selected.server = null
model.saveSelected(media.id, selected, requireActivity()) model.saveSelected(media.id, selected)
media.selected = selected media.selected = selected
return model.watchSources?.get(i)!! return model.watchSources?.get(i)!!
} }
@ -300,7 +291,7 @@ class AnimeWatchFragment : Fragment() {
fun onLangChange(i: Int) { fun onLangChange(i: Int) {
val selected = model.loadSelected(media) val selected = model.loadSelected(media)
selected.langIndex = i selected.langIndex = i
model.saveSelected(media.id, selected, requireActivity()) model.saveSelected(media.id, selected)
media.selected = selected media.selected = selected
} }
@ -308,7 +299,7 @@ class AnimeWatchFragment : Fragment() {
val selected = model.loadSelected(media) val selected = model.loadSelected(media)
model.watchSources?.get(selected.sourceIndex)?.selectDub = checked model.watchSources?.get(selected.sourceIndex)?.selectDub = checked
selected.preferDub = checked selected.preferDub = checked
model.saveSelected(media.id, selected, requireActivity()) model.saveSelected(media.id, selected)
media.selected = selected media.selected = selected
lifecycleScope.launch(Dispatchers.IO) { lifecycleScope.launch(Dispatchers.IO) {
model.forceLoadEpisode( model.forceLoadEpisode(
@ -327,7 +318,7 @@ class AnimeWatchFragment : Fragment() {
reverse = rev reverse = rev
media.selected!!.recyclerStyle = style media.selected!!.recyclerStyle = style
media.selected!!.recyclerReversed = reverse media.selected!!.recyclerReversed = reverse
model.saveSelected(media.id, media.selected!!, requireActivity()) model.saveSelected(media.id, media.selected!!)
reload() reload()
} }
@ -335,7 +326,7 @@ class AnimeWatchFragment : Fragment() {
media.selected!!.chip = i media.selected!!.chip = i
start = s start = s
end = e end = e
model.saveSelected(media.id, media.selected!!, requireActivity()) model.saveSelected(media.id, media.selected!!)
reload() reload()
} }
@ -436,7 +427,7 @@ class AnimeWatchFragment : Fragment() {
fun onEpisodeClick(i: String) { fun onEpisodeClick(i: String) {
model.continueMedia = false model.continueMedia = false
model.saveSelected(media.id, media.selected!!, requireActivity()) model.saveSelected(media.id, media.selected!!)
model.onEpisodeClick(media, i, requireActivity().supportFragmentManager) model.onEpisodeClick(media, i, requireActivity().supportFragmentManager)
} }
@ -475,11 +466,11 @@ class AnimeWatchFragment : Fragment() {
) )
) )
val taskName = AnimeDownloaderService.AnimeDownloadTask.getTaskName(media.mainName(), i) val taskName = AnimeDownloaderService.AnimeDownloadTask.getTaskName(media.mainName(), i)
val id = PrefWrapper.getAnimeDownloadPreferences().getString( val id = PrefManager.getAnimeDownloadPreferences().getString(
taskName, taskName,
"" ""
) ?: "" ) ?: ""
PrefWrapper.getAnimeDownloadPreferences().edit().remove(taskName).apply() PrefManager.getAnimeDownloadPreferences().edit().remove(taskName).apply()
DownloadService.sendRemoveDownload( DownloadService.sendRemoveDownload(
requireContext(), requireContext(),
ExoplayerDownloadService::class.java, ExoplayerDownloadService::class.java,
@ -531,7 +522,7 @@ class AnimeWatchFragment : Fragment() {
selected.latest = selected.latest =
media.userProgress?.toFloat()?.takeIf { selected.latest < it } ?: selected.latest media.userProgress?.toFloat()?.takeIf { selected.latest < it } ?: selected.latest
model.saveSelected(media.id, selected, requireActivity()) model.saveSelected(media.id, selected)
headerAdapter.handleEpisodes() headerAdapter.handleEpisodes()
val isDownloaded = model.watchSources!!.isDownloadedSource(media.selected!!.sourceIndex) val isDownloaded = model.watchSources!!.isDownloadedSource(media.selected!!.sourceIndex)
episodeAdapter.offlineMode = isDownloaded episodeAdapter.offlineMode = isDownloaded
@ -547,7 +538,7 @@ class AnimeWatchFragment : Fragment() {
arr = (arr.reversed() as? ArrayList<Episode>) ?: arr arr = (arr.reversed() as? ArrayList<Episode>) ?: arr
} }
episodeAdapter.arr = arr episodeAdapter.arr = arr
episodeAdapter.updateType(style ?: uiSettings.animeDefaultView) episodeAdapter.updateType(style ?: PrefManager.getVal(PrefName.AnimeDefaultView))
episodeAdapter.notifyItemRangeInserted(0, arr.size) episodeAdapter.notifyItemRangeInserted(0, arr.size)
for (download in downloadManager.animeDownloadedTypes) { for (download in downloadManager.animeDownloadedTypes) {
if (download.title == media.mainName()) { if (download.title == media.mainName()) {

View file

@ -20,7 +20,7 @@ import ani.dantotsu.databinding.ItemEpisodeListBinding
import ani.dantotsu.download.anime.AnimeDownloaderService import ani.dantotsu.download.anime.AnimeDownloaderService
import ani.dantotsu.download.video.Helper import ani.dantotsu.download.video.Helper
import ani.dantotsu.media.Media import ani.dantotsu.media.Media
import ani.dantotsu.settings.saving.PrefWrapper import ani.dantotsu.settings.saving.PrefManager
import com.bumptech.glide.Glide import com.bumptech.glide.Glide
import com.bumptech.glide.load.model.GlideUrl import com.bumptech.glide.load.model.GlideUrl
import kotlinx.coroutines.delay import kotlinx.coroutines.delay
@ -29,8 +29,8 @@ import kotlin.math.ln
import kotlin.math.pow import kotlin.math.pow
fun handleProgress(cont: LinearLayout, bar: View, empty: View, mediaId: Int, ep: String) { fun handleProgress(cont: LinearLayout, bar: View, empty: View, mediaId: Int, ep: String) {
val curr = loadData<Long>("${mediaId}_${ep}") val curr = PrefManager.getNullableCustomVal("${mediaId}_${ep}", null as Long?)
val max = loadData<Long>("${mediaId}_${ep}_max") val max = PrefManager.getNullableCustomVal("${mediaId}_${ep}_max", null as Long?)
if (curr != null && max != null) { if (curr != null && max != null) {
cont.visibility = View.VISIBLE cont.visibility = View.VISIBLE
val div = curr.toFloat() / max.toFloat() val div = curr.toFloat() / max.toFloat()
@ -109,7 +109,7 @@ class EpisodeAdapter(
when (holder) { when (holder) {
is EpisodeListViewHolder -> { is EpisodeListViewHolder -> {
val binding = holder.binding val binding = holder.binding
setAnimation(fragment.requireContext(), holder.binding.root, fragment.uiSettings) setAnimation(fragment.requireContext(), holder.binding.root)
val thumb = val thumb =
ep.thumb?.let { if (it.url.isNotEmpty()) GlideUrl(it.url) { it.headers } else null } ep.thumb?.let { if (it.url.isNotEmpty()) GlideUrl(it.url) { it.headers } else null }
@ -158,7 +158,7 @@ class EpisodeAdapter(
is EpisodeGridViewHolder -> { is EpisodeGridViewHolder -> {
val binding = holder.binding val binding = holder.binding
setAnimation(fragment.requireContext(), holder.binding.root, fragment.uiSettings) setAnimation(fragment.requireContext(), holder.binding.root)
val thumb = val thumb =
ep.thumb?.let { if (it.url.isNotEmpty()) GlideUrl(it.url) { it.headers } else null } ep.thumb?.let { if (it.url.isNotEmpty()) GlideUrl(it.url) { it.headers } else null }
@ -201,7 +201,7 @@ class EpisodeAdapter(
is EpisodeCompactViewHolder -> { is EpisodeCompactViewHolder -> {
val binding = holder.binding val binding = holder.binding
setAnimation(fragment.requireContext(), holder.binding.root, fragment.uiSettings) setAnimation(fragment.requireContext(), holder.binding.root)
binding.itemEpisodeNumber.text = ep.number binding.itemEpisodeNumber.text = ep.number
binding.itemEpisodeFillerView.visibility = binding.itemEpisodeFillerView.visibility =
if (ep.filler) View.VISIBLE else View.GONE if (ep.filler) View.VISIBLE else View.GONE
@ -252,7 +252,7 @@ class EpisodeAdapter(
media.mainName(), media.mainName(),
episodeNumber episodeNumber
) )
val id = PrefWrapper.getAnimeDownloadPreferences().getString( val id = PrefManager.getAnimeDownloadPreferences().getString(
taskName, taskName,
"" ""
) ?: "" ) ?: ""

View file

@ -80,11 +80,9 @@ import ani.dantotsu.others.AniSkip.getType
import ani.dantotsu.others.ResettableTimer import ani.dantotsu.others.ResettableTimer
import ani.dantotsu.others.getSerialized import ani.dantotsu.others.getSerialized
import ani.dantotsu.parsers.* import ani.dantotsu.parsers.*
import ani.dantotsu.settings.PlayerSettings
import ani.dantotsu.settings.PlayerSettingsActivity import ani.dantotsu.settings.PlayerSettingsActivity
import ani.dantotsu.settings.UserInterfaceSettings
import ani.dantotsu.settings.saving.PrefName import ani.dantotsu.settings.saving.PrefName
import ani.dantotsu.settings.saving.PrefWrapper import ani.dantotsu.settings.saving.PrefManager
import ani.dantotsu.themes.ThemeManager import ani.dantotsu.themes.ThemeManager
import com.bumptech.glide.Glide import com.bumptech.glide.Glide
import com.google.android.gms.cast.framework.CastButtonFactory import com.google.android.gms.cast.framework.CastButtonFactory
@ -185,9 +183,6 @@ class ExoplayerView : AppCompatActivity(), Player.Listener, SessionAvailabilityL
private var pipEnabled = false private var pipEnabled = false
private var aspectRatio = Rational(16, 9) private var aspectRatio = Rational(16, 9)
var settings = PlayerSettings()
private var uiSettings = UserInterfaceSettings()
private val handler = Handler(Looper.getMainLooper()) private val handler = Handler(Looper.getMainLooper())
val model: MediaDetailsViewModel by viewModels() val model: MediaDetailsViewModel by viewModels()
@ -241,8 +236,8 @@ class ExoplayerView : AppCompatActivity(), Player.Listener, SessionAvailabilityL
} }
} }
private fun setupSubFormatting(playerView: PlayerView, settings: PlayerSettings) { private fun setupSubFormatting(playerView: PlayerView) {
val primaryColor = when (settings.primaryColor) { val primaryColor = when (PrefManager.getVal<Int>(PrefName.PrimaryColor)) {
0 -> Color.BLACK 0 -> Color.BLACK
1 -> Color.DKGRAY 1 -> Color.DKGRAY
2 -> Color.GRAY 2 -> Color.GRAY
@ -257,7 +252,7 @@ class ExoplayerView : AppCompatActivity(), Player.Listener, SessionAvailabilityL
11 -> Color.TRANSPARENT 11 -> Color.TRANSPARENT
else -> Color.WHITE else -> Color.WHITE
} }
val secondaryColor = when (settings.secondaryColor) { val secondaryColor = when (PrefManager.getVal<Int>(PrefName.SecondaryColor)) {
0 -> Color.BLACK 0 -> Color.BLACK
1 -> Color.DKGRAY 1 -> Color.DKGRAY
2 -> Color.GRAY 2 -> Color.GRAY
@ -272,14 +267,14 @@ class ExoplayerView : AppCompatActivity(), Player.Listener, SessionAvailabilityL
11 -> Color.TRANSPARENT 11 -> Color.TRANSPARENT
else -> Color.BLACK else -> Color.BLACK
} }
val outline = when (settings.outline) { val outline = when (PrefManager.getVal<Int>(PrefName.Outline)) {
0 -> EDGE_TYPE_OUTLINE // Normal 0 -> EDGE_TYPE_OUTLINE // Normal
1 -> EDGE_TYPE_DEPRESSED // Shine 1 -> EDGE_TYPE_DEPRESSED // Shine
2 -> EDGE_TYPE_DROP_SHADOW // Drop shadow 2 -> EDGE_TYPE_DROP_SHADOW // Drop shadow
3 -> EDGE_TYPE_NONE // No outline 3 -> EDGE_TYPE_NONE // No outline
else -> EDGE_TYPE_OUTLINE // Normal else -> EDGE_TYPE_OUTLINE // Normal
} }
val subBackground = when (settings.subBackground) { val subBackground = when (PrefManager.getVal<Int>(PrefName.SubBackground)) {
0 -> Color.TRANSPARENT 0 -> Color.TRANSPARENT
1 -> Color.BLACK 1 -> Color.BLACK
2 -> Color.DKGRAY 2 -> Color.DKGRAY
@ -294,7 +289,7 @@ class ExoplayerView : AppCompatActivity(), Player.Listener, SessionAvailabilityL
11 -> Color.MAGENTA 11 -> Color.MAGENTA
else -> Color.TRANSPARENT else -> Color.TRANSPARENT
} }
val subWindow = when (settings.subWindow) { val subWindow = when (PrefManager.getVal<Int>(PrefName.SubWindow)) {
0 -> Color.TRANSPARENT 0 -> Color.TRANSPARENT
1 -> Color.BLACK 1 -> Color.BLACK
2 -> Color.DKGRAY 2 -> Color.DKGRAY
@ -309,7 +304,7 @@ class ExoplayerView : AppCompatActivity(), Player.Listener, SessionAvailabilityL
11 -> Color.MAGENTA 11 -> Color.MAGENTA
else -> Color.TRANSPARENT else -> Color.TRANSPARENT
} }
val font = when (settings.font) { val font = when (PrefManager.getVal<Int>(PrefName.Font)) {
0 -> ResourcesCompat.getFont(this, R.font.poppins_semi_bold) 0 -> ResourcesCompat.getFont(this, R.font.poppins_semi_bold)
1 -> ResourcesCompat.getFont(this, R.font.poppins_bold) 1 -> ResourcesCompat.getFont(this, R.font.poppins_bold)
2 -> ResourcesCompat.getFont(this, R.font.poppins) 2 -> ResourcesCompat.getFont(this, R.font.poppins)
@ -332,7 +327,7 @@ class ExoplayerView : AppCompatActivity(), Player.Listener, SessionAvailabilityL
override fun onCreate(savedInstanceState: Bundle?) { override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState) super.onCreate(savedInstanceState)
ThemeManager(this).applyTheme() ThemeManager(this).applyTheme()
binding = ActivityExoplayerBinding.inflate(layoutInflater) binding = ActivityExoplayerBinding.inflate(layoutInflater)
setContentView(binding.root) setContentView(binding.root)
@ -355,19 +350,6 @@ class ExoplayerView : AppCompatActivity(), Player.Listener, SessionAvailabilityL
finishAndRemoveTask() finishAndRemoveTask()
} }
settings = loadData("player_settings") ?: PlayerSettings().apply {
saveData(
"player_settings",
this
)
}
uiSettings = loadData("ui_settings") ?: UserInterfaceSettings().apply {
saveData(
"ui_settings",
this
)
}
playerView = findViewById(R.id.player_view) playerView = findViewById(R.id.player_view)
exoPlay = playerView.findViewById(androidx.media3.ui.R.id.exo_play) exoPlay = playerView.findViewById(androidx.media3.ui.R.id.exo_play)
exoSource = playerView.findViewById(R.id.exo_source) exoSource = playerView.findViewById(R.id.exo_source)
@ -426,14 +408,14 @@ class ExoplayerView : AppCompatActivity(), Player.Listener, SessionAvailabilityL
} }
} }
setupSubFormatting(playerView, settings) setupSubFormatting(playerView)
playerView.subtitleView?.alpha = when (settings.subtitles) { playerView.subtitleView?.alpha = when (PrefManager.getVal<Boolean>(PrefName.Subtitles)) {
true -> 1f true -> 1f
false -> 0f false -> 0f
} }
val fontSize = settings.fontSize.toFloat() val fontSize = PrefManager.getVal<Int>(PrefName.FontSize).toFloat()
playerView.subtitleView?.setFixedTextSize(TypedValue.COMPLEX_UNIT_SP, fontSize) playerView.subtitleView?.setFixedTextSize(TypedValue.COMPLEX_UNIT_SP, fontSize)
if (savedInstanceState != null) { if (savedInstanceState != null) {
@ -466,17 +448,16 @@ class ExoplayerView : AppCompatActivity(), Player.Listener, SessionAvailabilityL
} else View.GONE } else View.GONE
} }
exoSkipOpEd.alpha = if (settings.autoSkipOPED) 1f else 0.3f exoSkipOpEd.alpha = if (PrefManager.getVal(PrefName.AutoSkipOPED)) 1f else 0.3f
exoSkipOpEd.setOnClickListener { exoSkipOpEd.setOnClickListener {
settings.autoSkipOPED = if (settings.autoSkipOPED) { if (PrefManager.getVal(PrefName.AutoSkipOPED)) {
snackString(getString(R.string.disabled_auto_skip)) snackString(getString(R.string.disabled_auto_skip))
false PrefManager.setVal(PrefName.AutoSkipOPED, false)
} else { } else {
snackString(getString(R.string.auto_skip)) snackString(getString(R.string.auto_skip))
true PrefManager.setVal(PrefName.AutoSkipOPED, true)
} }
saveData("player_settings", settings) exoSkipOpEd.alpha = if (PrefManager.getVal(PrefName.AutoSkipOPED)) 1f else 0.3f
exoSkipOpEd.alpha = if (settings.autoSkipOPED) 1f else 0.3f
} }
//Play Pause //Play Pause
@ -503,7 +484,9 @@ class ExoplayerView : AppCompatActivity(), Player.Listener, SessionAvailabilityL
// Picture-in-picture // Picture-in-picture
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.N) { if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.N) {
pipEnabled = pipEnabled =
packageManager.hasSystemFeature(PackageManager.FEATURE_PICTURE_IN_PICTURE) && settings.pip packageManager.hasSystemFeature(PackageManager.FEATURE_PICTURE_IN_PICTURE) && PrefManager.getVal(
PrefName.Pip
)
if (pipEnabled) { if (pipEnabled) {
exoPip.visibility = View.VISIBLE exoPip.visibility = View.VISIBLE
exoPip.setOnClickListener { exoPip.setOnClickListener {
@ -536,11 +519,12 @@ class ExoplayerView : AppCompatActivity(), Player.Listener, SessionAvailabilityL
} }
//Skip Time Button //Skip Time Button
if (settings.skipTime > 0) { var skipTime = PrefManager.getVal<Int>(PrefName.SkipTime)
exoSkip.findViewById<TextView>(R.id.exo_skip_time).text = settings.skipTime.toString() if (skipTime > 0) {
exoSkip.findViewById<TextView>(R.id.exo_skip_time).text = skipTime.toString()
exoSkip.setOnClickListener { exoSkip.setOnClickListener {
if (isInitialized) if (isInitialized)
exoPlayer.seekTo(exoPlayer.currentPosition + settings.skipTime * 1000) exoPlayer.seekTo(exoPlayer.currentPosition + skipTime * 1000)
} }
exoSkip.setOnLongClickListener { exoSkip.setOnLongClickListener {
val dialog = Dialog(this, R.style.MyPopup) val dialog = Dialog(this, R.style.MyPopup)
@ -551,18 +535,19 @@ class ExoplayerView : AppCompatActivity(), Player.Listener, SessionAvailabilityL
ViewGroup.LayoutParams.WRAP_CONTENT, ViewGroup.LayoutParams.WRAP_CONTENT,
ViewGroup.LayoutParams.WRAP_CONTENT ViewGroup.LayoutParams.WRAP_CONTENT
) )
if (settings.skipTime <= 120) { if (skipTime <= 120) {
dialog.findViewById<Slider>(R.id.seekbar).value = settings.skipTime.toFloat() dialog.findViewById<Slider>(R.id.seekbar).value = skipTime.toFloat()
} else { } else {
dialog.findViewById<Slider>(R.id.seekbar).value = 120f dialog.findViewById<Slider>(R.id.seekbar).value = 120f
} }
dialog.findViewById<Slider>(R.id.seekbar).addOnChangeListener { _, value, _ -> dialog.findViewById<Slider>(R.id.seekbar).addOnChangeListener { _, value, _ ->
settings.skipTime = value.toInt() skipTime = value.toInt()
saveData(player, settings) //saveData(player, settings)
PrefManager.setVal(PrefName.SkipTime, skipTime)
playerView.findViewById<TextView>(R.id.exo_skip_time).text = playerView.findViewById<TextView>(R.id.exo_skip_time).text =
settings.skipTime.toString() skipTime.toString()
dialog.findViewById<TextView>(R.id.seekbar_value).text = dialog.findViewById<TextView>(R.id.seekbar_value).text =
settings.skipTime.toString() skipTime.toString()
} }
dialog.findViewById<Slider>(R.id.seekbar) dialog.findViewById<Slider>(R.id.seekbar)
.addOnSliderTouchListener(object : Slider.OnSliderTouchListener { .addOnSliderTouchListener(object : Slider.OnSliderTouchListener {
@ -574,7 +559,7 @@ class ExoplayerView : AppCompatActivity(), Player.Listener, SessionAvailabilityL
dialog.findViewById<TextView>(R.id.seekbar_title).text = dialog.findViewById<TextView>(R.id.seekbar_title).text =
getString(R.string.skip_time) getString(R.string.skip_time)
dialog.findViewById<TextView>(R.id.seekbar_value).text = dialog.findViewById<TextView>(R.id.seekbar_value).text =
settings.skipTime.toString() skipTime.toString()
@Suppress("DEPRECATION") @Suppress("DEPRECATION")
dialog.window?.decorView?.systemUiVisibility = View.SYSTEM_UI_FLAG_HIDE_NAVIGATION dialog.window?.decorView?.systemUiVisibility = View.SYSTEM_UI_FLAG_HIDE_NAVIGATION
dialog.show() dialog.show()
@ -584,7 +569,7 @@ class ExoplayerView : AppCompatActivity(), Player.Listener, SessionAvailabilityL
exoSkip.visibility = View.GONE exoSkip.visibility = View.GONE
} }
val gestureSpeed = (300 * uiSettings.animationSpeed).toLong() val gestureSpeed = (300 * PrefManager.getVal<Float>(PrefName.AnimationSpeed)).toLong()
//Player UI Visibility Handler //Player UI Visibility Handler
val brightnessRunnable = Runnable { val brightnessRunnable = Runnable {
if (exoBrightnessCont.alpha == 1f) if (exoBrightnessCont.alpha == 1f)
@ -614,7 +599,7 @@ class ExoplayerView : AppCompatActivity(), Player.Listener, SessionAvailabilityL
} }
}) })
val overshoot = AnimationUtils.loadInterpolator(this, R.anim.over_shoot) val overshoot = AnimationUtils.loadInterpolator(this, R.anim.over_shoot)
val controllerDuration = (uiSettings.animationSpeed * 200).toLong() val controllerDuration = (300 * PrefManager.getVal<Float>(PrefName.AnimationSpeed)).toLong()
fun handleController() { fun handleController() {
if (if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.N) !isInPictureInPictureMode else true) { if (if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.N) !isInPictureInPictureMode else true) {
if (playerView.isControllerFullyVisible) { if (playerView.isControllerFullyVisible) {
@ -699,13 +684,14 @@ class ExoplayerView : AppCompatActivity(), Player.Listener, SessionAvailabilityL
var seekTimesR = 0 var seekTimesR = 0
fun seek(forward: Boolean, event: MotionEvent? = null) { fun seek(forward: Boolean, event: MotionEvent? = null) {
val seekTime = PrefManager.getVal<Int>(PrefName.SeekTime)
val (card, text) = if (forward) { val (card, text) = if (forward) {
forwardText.text = "+${settings.seekTime * ++seekTimesF}" forwardText.text = "+${seekTime * ++seekTimesF}"
handler.post { exoPlayer.seekTo(exoPlayer.currentPosition + settings.seekTime * 1000) } handler.post { exoPlayer.seekTo(exoPlayer.currentPosition + seekTime * 1000) }
fastForwardCard to forwardText fastForwardCard to forwardText
} else { } else {
rewindText.text = "-${settings.seekTime * ++seekTimesR}" rewindText.text = "-${seekTime * ++seekTimesR}"
handler.post { exoPlayer.seekTo(exoPlayer.currentPosition - settings.seekTime * 1000) } handler.post { exoPlayer.seekTo(exoPlayer.currentPosition - seekTime * 1000) }
fastRewindCard to rewindText fastRewindCard to rewindText
} }
@ -760,7 +746,7 @@ class ExoplayerView : AppCompatActivity(), Player.Listener, SessionAvailabilityL
} }
} }
if (!settings.doubleTap) { if (!PrefManager.getVal<Boolean>(PrefName.DoubleTap)) {
playerView.findViewById<View>(R.id.exo_fast_forward_button_cont).visibility = playerView.findViewById<View>(R.id.exo_fast_forward_button_cont).visibility =
View.VISIBLE View.VISIBLE
playerView.findViewById<View>(R.id.exo_fast_rewind_button_cont).visibility = playerView.findViewById<View>(R.id.exo_fast_rewind_button_cont).visibility =
@ -781,10 +767,10 @@ class ExoplayerView : AppCompatActivity(), Player.Listener, SessionAvailabilityL
keyMap[KEYCODE_DPAD_LEFT] = { seek(false) } keyMap[KEYCODE_DPAD_LEFT] = { seek(false) }
//Screen Gestures //Screen Gestures
if (settings.gestures || settings.doubleTap) { if (PrefManager.getVal<Boolean>(PrefName.Gestures) || PrefManager.getVal<Boolean>(PrefName.DoubleTap)) {
fun doubleTap(forward: Boolean, event: MotionEvent) { fun doubleTap(forward: Boolean, event: MotionEvent) {
if (!locked && isInitialized && settings.doubleTap) { if (!locked && isInitialized && PrefManager.getVal<Boolean>(PrefName.DoubleTap)) {
seek(forward, event) seek(forward, event)
} }
} }
@ -855,7 +841,7 @@ class ExoplayerView : AppCompatActivity(), Player.Listener, SessionAvailabilityL
//FastRewind (Left Panel) //FastRewind (Left Panel)
val fastRewindDetector = GestureDetector(this, object : GesturesListener() { val fastRewindDetector = GestureDetector(this, object : GesturesListener() {
override fun onLongClick(event: MotionEvent) { override fun onLongClick(event: MotionEvent) {
if (settings.fastforward) fastForward() if (PrefManager.getVal(PrefName.FastForward)) fastForward()
} }
override fun onDoubleClick(event: MotionEvent) { override fun onDoubleClick(event: MotionEvent) {
@ -863,7 +849,7 @@ class ExoplayerView : AppCompatActivity(), Player.Listener, SessionAvailabilityL
} }
override fun onScrollYClick(y: Float) { override fun onScrollYClick(y: Float) {
if (!locked && settings.gestures) { if (!locked && PrefManager.getVal(PrefName.Gestures)) {
exoBrightness.value = clamp(exoBrightness.value + y / 100, 0f, 10f) exoBrightness.value = clamp(exoBrightness.value + y / 100, 0f, 10f)
if (exoBrightnessCont.visibility != View.VISIBLE) { if (exoBrightnessCont.visibility != View.VISIBLE) {
exoBrightnessCont.visibility = View.VISIBLE exoBrightnessCont.visibility = View.VISIBLE
@ -887,7 +873,7 @@ class ExoplayerView : AppCompatActivity(), Player.Listener, SessionAvailabilityL
//FastForward (Right Panel) //FastForward (Right Panel)
val fastForwardDetector = GestureDetector(this, object : GesturesListener() { val fastForwardDetector = GestureDetector(this, object : GesturesListener() {
override fun onLongClick(event: MotionEvent) { override fun onLongClick(event: MotionEvent) {
if (settings.fastforward) fastForward() if (PrefManager.getVal(PrefName.FastForward)) fastForward()
} }
override fun onDoubleClick(event: MotionEvent) { override fun onDoubleClick(event: MotionEvent) {
@ -895,7 +881,7 @@ class ExoplayerView : AppCompatActivity(), Player.Listener, SessionAvailabilityL
} }
override fun onScrollYClick(y: Float) { override fun onScrollYClick(y: Float) {
if (!locked && settings.gestures) { if (!locked && PrefManager.getVal(PrefName.Gestures)) {
exoVolume.value = clamp(exoVolume.value + y / 100, 0f, 10f) exoVolume.value = clamp(exoVolume.value + y / 100, 0f, 10f)
if (exoVolumeCont.visibility != View.VISIBLE) { if (exoVolumeCont.visibility != View.VISIBLE) {
exoVolumeCont.visibility = View.VISIBLE exoVolumeCont.visibility = View.VISIBLE
@ -949,10 +935,9 @@ class ExoplayerView : AppCompatActivity(), Player.Listener, SessionAvailabilityL
fun change(index: Int) { fun change(index: Int) {
if (isInitialized) { if (isInitialized) {
changingServer = false changingServer = false
saveData( PrefManager.setCustomVal(
"${media.id}_${episodeArr[currentEpisodeIndex]}", "${media.id}_${episodeArr[currentEpisodeIndex]}",
exoPlayer.currentPosition, exoPlayer.currentPosition
this
) )
exoPlayer.seekTo(0) exoPlayer.seekTo(0)
val prev = episodeArr[currentEpisodeIndex] val prev = episodeArr[currentEpisodeIndex]
@ -1009,12 +994,15 @@ class ExoplayerView : AppCompatActivity(), Player.Listener, SessionAvailabilityL
currentEpisodeIndex = episodeArr.indexOf(ep.number) currentEpisodeIndex = episodeArr.indexOf(ep.number)
episodeTitle.setSelection(currentEpisodeIndex) episodeTitle.setSelection(currentEpisodeIndex)
if (isInitialized) releasePlayer() if (isInitialized) releasePlayer()
playbackPosition = loadData("${media.id}_${ep.number}", this) ?: 0 playbackPosition = PrefManager.getCustomVal(
"${media.id}_${ep.number}",
0
)
initPlayer() initPlayer()
preloading = false preloading = false
val context = this val context = this
val offline = PrefWrapper.getVal(PrefName.OfflineMode, false) val offline: Boolean = PrefManager.getVal(PrefName.OfflineMode)
val incognito = PrefWrapper.getVal(PrefName.Incognito, false) val incognito: Boolean = PrefManager.getVal(PrefName.Incognito)
if ((isOnline(context) && !offline) && Discord.token != null && !incognito) { if ((isOnline(context) && !offline) && Discord.token != null && !incognito) {
lifecycleScope.launch { lifecycleScope.launch {
val presence = RPC.createPresence(RPC.Companion.RPCData( val presence = RPC.createPresence(RPC.Companion.RPCData(
@ -1059,7 +1047,7 @@ class ExoplayerView : AppCompatActivity(), Player.Listener, SessionAvailabilityL
} }
//FullScreen //FullScreen
isFullscreen = loadData("${media.id}_fullscreenInt", this) ?: isFullscreen isFullscreen = PrefManager.getCustomVal("${media.id}_fullscreenInt", isFullscreen)
playerView.resizeMode = when (isFullscreen) { playerView.resizeMode = when (isFullscreen) {
0 -> AspectRatioFrameLayout.RESIZE_MODE_FIT 0 -> AspectRatioFrameLayout.RESIZE_MODE_FIT
1 -> AspectRatioFrameLayout.RESIZE_MODE_ZOOM 1 -> AspectRatioFrameLayout.RESIZE_MODE_ZOOM
@ -1083,11 +1071,11 @@ class ExoplayerView : AppCompatActivity(), Player.Listener, SessionAvailabilityL
else -> "Original" else -> "Original"
} }
) )
saveData("${media.id}_fullscreenInt", isFullscreen, this) PrefManager.setCustomVal("${media.id}_fullscreenInt", isFullscreen)
} }
//Cast //Cast
if (settings.cast) { if (PrefManager.getVal(PrefName.Cast)) {
playerView.findViewById<MediaRouteButton>(R.id.exo_cast).apply { playerView.findViewById<MediaRouteButton>(R.id.exo_cast).apply {
visibility = View.VISIBLE visibility = View.VISIBLE
try { try {
@ -1105,10 +1093,9 @@ class ExoplayerView : AppCompatActivity(), Player.Listener, SessionAvailabilityL
//Settings //Settings
exoSettings.setOnClickListener { exoSettings.setOnClickListener {
saveData( PrefManager.setCustomVal(
"${media.id}_${media.anime!!.selectedEpisode}", "${media.id}_${media.anime!!.selectedEpisode}",
exoPlayer.currentPosition, exoPlayer.currentPosition
this
) )
val intent = Intent(this, PlayerSettingsActivity::class.java).apply { val intent = Intent(this, PlayerSettingsActivity::class.java).apply {
putExtra("subtitle", subtitle) putExtra("subtitle", subtitle)
@ -1119,7 +1106,7 @@ class ExoplayerView : AppCompatActivity(), Player.Listener, SessionAvailabilityL
//Speed //Speed
val speeds = val speeds =
if (settings.cursedSpeeds) if (PrefManager.getVal(PrefName.CursedSpeeds))
arrayOf(1f, 1.25f, 1.5f, 1.75f, 2f, 2.5f, 3f, 4f, 5f, 10f, 25f, 50f) arrayOf(1f, 1.25f, 1.5f, 1.75f, 2f, 2.5f, 3f, 4f, 5f, 10f, 25f, 50f)
else else
arrayOf( arrayOf(
@ -1139,7 +1126,11 @@ class ExoplayerView : AppCompatActivity(), Player.Listener, SessionAvailabilityL
) )
val speedsName = speeds.map { "${it}x" }.toTypedArray() val speedsName = speeds.map { "${it}x" }.toTypedArray()
var curSpeed = loadData("${media.id}_speed", this) ?: settings.defaultSpeed //var curSpeed = loadData("${media.id}_speed", this) ?: settings.defaultSpeed
var curSpeed = PrefManager.getCustomVal(
"${media.id}_speed",
PrefManager.getVal<Int>(PrefName.DefaultSpeed)
)
playbackParameters = PlaybackParameters(speeds[curSpeed]) playbackParameters = PlaybackParameters(speeds[curSpeed])
var speed: Float var speed: Float
@ -1148,7 +1139,7 @@ class ExoplayerView : AppCompatActivity(), Player.Listener, SessionAvailabilityL
exoSpeed.setOnClickListener { exoSpeed.setOnClickListener {
val dialog = speedDialog.setSingleChoiceItems(speedsName, curSpeed) { dialog, i -> val dialog = speedDialog.setSingleChoiceItems(speedsName, curSpeed) { dialog, i ->
if (isInitialized) { if (isInitialized) {
saveData("${media.id}_speed", i, this) PrefManager.setCustomVal("${media.id}_speed", i)
speed = speeds[i] speed = speeds[i]
curSpeed = i curSpeed = i
playbackParameters = PlaybackParameters(speed) playbackParameters = PlaybackParameters(speed)
@ -1161,7 +1152,7 @@ class ExoplayerView : AppCompatActivity(), Player.Listener, SessionAvailabilityL
} }
speedDialog.setOnCancelListener { hideSystemBars() } speedDialog.setOnCancelListener { hideSystemBars() }
if (settings.autoPlay) { if (PrefManager.getVal(PrefName.AutoPlay)) {
var touchTimer = Timer() var touchTimer = Timer()
fun touched() { fun touched() {
interacted = true interacted = true
@ -1182,8 +1173,8 @@ class ExoplayerView : AppCompatActivity(), Player.Listener, SessionAvailabilityL
} }
} }
isFullscreen = settings.resize isFullscreen = PrefManager.getVal(PrefName.Resize)
playerView.resizeMode = when (settings.resize) { playerView.resizeMode = when (isFullscreen) {
0 -> AspectRatioFrameLayout.RESIZE_MODE_FIT 0 -> AspectRatioFrameLayout.RESIZE_MODE_FIT
1 -> AspectRatioFrameLayout.RESIZE_MODE_ZOOM 1 -> AspectRatioFrameLayout.RESIZE_MODE_ZOOM
2 -> AspectRatioFrameLayout.RESIZE_MODE_FILL 2 -> AspectRatioFrameLayout.RESIZE_MODE_FILL
@ -1191,25 +1182,42 @@ class ExoplayerView : AppCompatActivity(), Player.Listener, SessionAvailabilityL
} }
preloading = false preloading = false
val incognito = PrefWrapper.getVal(PrefName.Incognito, false) val incognito: Boolean = PrefManager.getVal(PrefName.Incognito)
val showProgressDialog = val showProgressDialog =
if (settings.askIndividual) loadData<Boolean>("${media.id}_progressDialog") if (PrefManager.getVal(PrefName.AskIndividualPlayer)) PrefManager.getCustomVal(
?: true else false "${media.id}_progressDialog",
if (!incognito && showProgressDialog && Anilist.userid != null && if (media.isAdult) settings.updateForH else true) true
) else false
if (!incognito && showProgressDialog && Anilist.userid != null && if (media.isAdult) PrefManager.getVal<Boolean>(
PrefName.UpdateForHPlayer
) else true
)
AlertDialog.Builder(this, R.style.MyPopup) AlertDialog.Builder(this, R.style.MyPopup)
.setTitle(getString(R.string.auto_update, media.userPreferredName)) .setTitle(getString(R.string.auto_update, media.userPreferredName))
.apply { .apply {
setOnCancelListener { hideSystemBars() } setOnCancelListener { hideSystemBars() }
setCancelable(false) setCancelable(false)
setPositiveButton(getString(R.string.yes)) { dialog, _ -> setPositiveButton(getString(R.string.yes)) { dialog, _ ->
saveData("${media.id}_progressDialog", false) PrefManager.setCustomVal(
saveData("${media.id}_save_progress", true) "${media.id}_ProgressDialog",
false
)
PrefManager.setCustomVal(
"${media.id}_save_progress",
true
)
dialog.dismiss() dialog.dismiss()
model.setEpisode(episodes[media.anime!!.selectedEpisode!!]!!, "invoke") model.setEpisode(episodes[media.anime!!.selectedEpisode!!]!!, "invoke")
} }
setNegativeButton(getString(R.string.no)) { dialog, _ -> setNegativeButton(getString(R.string.no)) { dialog, _ ->
saveData("${media.id}_progressDialog", false) PrefManager.setCustomVal(
saveData("${media.id}_save_progress", false) "${media.id}_ProgressDialog",
false
)
PrefManager.setCustomVal(
"${media.id}_save_progress",
false
)
toast(getString(R.string.reset_auto_update)) toast(getString(R.string.reset_auto_update))
dialog.dismiss() dialog.dismiss()
model.setEpisode(episodes[media.anime!!.selectedEpisode!!]!!, "invoke") model.setEpisode(episodes[media.anime!!.selectedEpisode!!]!!, "invoke")
@ -1219,7 +1227,7 @@ class ExoplayerView : AppCompatActivity(), Player.Listener, SessionAvailabilityL
else model.setEpisode(episodes[media.anime!!.selectedEpisode!!]!!, "invoke") else model.setEpisode(episodes[media.anime!!.selectedEpisode!!]!!, "invoke")
//Start the recursive Fun //Start the recursive Fun
if (settings.timeStampsEnabled) if (PrefManager.getVal(PrefName.TimeStampsEnabled))
updateTimeStamp() updateTimeStamp()
} }
@ -1227,12 +1235,15 @@ class ExoplayerView : AppCompatActivity(), Player.Listener, SessionAvailabilityL
private fun initPlayer() { private fun initPlayer() {
checkNotch() checkNotch()
saveData("${media.id}_current_ep", media.anime!!.selectedEpisode!!, this) PrefManager.setCustomVal(
"${media.id}_current_ep",
media.anime!!.selectedEpisode!!
)
val set = loadData<MutableSet<Int>>("continue_ANIME", this) ?: mutableSetOf() val set = PrefManager.getVal<Set<Int>>(PrefName.ContinueAnime).toMutableSet()
if (set.contains(media.id)) set.remove(media.id) if (set.contains(media.id)) set.remove(media.id)
set.add(media.id) set.add(media.id)
saveData("continue_ANIME", set, this) PrefManager.setVal(PrefName.ContinueAnime, set.toSet())
lifecycleScope.launch(Dispatchers.IO) { lifecycleScope.launch(Dispatchers.IO) {
extractor?.onVideoStopped(video) extractor?.onVideoStopped(video)
@ -1243,7 +1254,8 @@ class ExoplayerView : AppCompatActivity(), Player.Listener, SessionAvailabilityL
video = ext.videos.getOrNull(episode.selectedVideo) ?: return video = ext.videos.getOrNull(episode.selectedVideo) ?: return
subtitle = intent.getSerialized("subtitle") subtitle = intent.getSerialized("subtitle")
?: when (val subLang: String? = loadData("subLang_${media.id}", this)) { ?: when (val subLang: String? =
PrefManager.getCustomVal("subLang_${media.id}", null as String?)) {
null -> { null -> {
when (episode.selectedSubtitle) { when (episode.selectedSubtitle) {
null -> null null -> null
@ -1342,7 +1354,7 @@ class ExoplayerView : AppCompatActivity(), Player.Listener, SessionAvailabilityL
val downloadedMediaItem = if (ext.server.offline) { val downloadedMediaItem = if (ext.server.offline) {
val key = ext.server.name val key = ext.server.name
downloadId = PrefWrapper.getAnimeDownloadPreferences() downloadId = PrefManager.getAnimeDownloadPreferences()
.getString(key, null) .getString(key, null)
if (downloadId != null) { if (downloadId != null) {
Helper.downloadManager(this) Helper.downloadManager(this)
@ -1399,7 +1411,7 @@ class ExoplayerView : AppCompatActivity(), Player.Listener, SessionAvailabilityL
// TrackSelectionOverride(trackSelector, 2)) // TrackSelectionOverride(trackSelector, 2))
) )
if (playbackPosition != 0L && !changingServer && !settings.alwaysContinue) { if (playbackPosition != 0L && !changingServer && !PrefManager.getVal<Boolean>(PrefName.AlwaysContinue)) {
val time = String.format( val time = String.format(
"%02d:%02d:%02d", TimeUnit.MILLISECONDS.toHours(playbackPosition), "%02d:%02d:%02d", TimeUnit.MILLISECONDS.toHours(playbackPosition),
TimeUnit.MILLISECONDS.toMinutes(playbackPosition) - TimeUnit.HOURS.toMinutes( TimeUnit.MILLISECONDS.toMinutes(playbackPosition) - TimeUnit.HOURS.toMinutes(
@ -1441,9 +1453,12 @@ class ExoplayerView : AppCompatActivity(), Player.Listener, SessionAvailabilityL
this.playbackParameters = this@ExoplayerView.playbackParameters this.playbackParameters = this@ExoplayerView.playbackParameters
setMediaItem(mediaItem) setMediaItem(mediaItem)
prepare() prepare()
loadData<Long>("${media.id}_${media.anime!!.selectedEpisode}_max")?.apply { PrefManager.getCustomVal(
if (this <= playbackPosition) playbackPosition = max(0, this - 5) "${media.id}_${media.anime!!.selectedEpisode}_max",
} Long.MAX_VALUE
)
.takeIf { it != Long.MAX_VALUE }
?.let { if (it <= playbackPosition) playbackPosition = max(0, it - 5) }
seekTo(playbackPosition) seekTo(playbackPosition)
} }
playerView.player = exoPlayer playerView.player = exoPlayer
@ -1516,8 +1531,10 @@ class ExoplayerView : AppCompatActivity(), Player.Listener, SessionAvailabilityL
changingServer = true changingServer = true
media.selected!!.server = null media.selected!!.server = null
saveData("${media.id}_${media.anime!!.selectedEpisode}", exoPlayer.currentPosition, this) PrefManager.setCustomVal(
model.saveSelected(media.id, media.selected!!, this) "${media.id}_${media.anime!!.selectedEpisode}", exoPlayer.currentPosition
)
model.saveSelected(media.id, media.selected!!)
model.onEpisodeClick( model.onEpisodeClick(
media, episode.number, this.supportFragmentManager, media, episode.number, this.supportFragmentManager,
launch = false launch = false
@ -1525,8 +1542,10 @@ class ExoplayerView : AppCompatActivity(), Player.Listener, SessionAvailabilityL
} }
private fun subClick() { private fun subClick() {
saveData("${media.id}_${media.anime!!.selectedEpisode}", exoPlayer.currentPosition, this) PrefManager.setCustomVal(
model.saveSelected(media.id, media.selected!!, this) "${media.id}_${media.anime!!.selectedEpisode}", exoPlayer.currentPosition
)
model.saveSelected(media.id, media.selected!!)
SubtitleDialogFragment().show(supportFragmentManager, "dialog") SubtitleDialogFragment().show(supportFragmentManager, "dialog")
} }
@ -1538,10 +1557,9 @@ class ExoplayerView : AppCompatActivity(), Player.Listener, SessionAvailabilityL
playerView.player?.pause() playerView.player?.pause()
} }
if (exoPlayer.currentPosition > 5000) { if (exoPlayer.currentPosition > 5000) {
saveData( PrefManager.setCustomVal(
"${media.id}_${media.anime!!.selectedEpisode}", "${media.id}_${media.anime!!.selectedEpisode}",
exoPlayer.currentPosition, exoPlayer.currentPosition
this
) )
} }
} }
@ -1566,7 +1584,7 @@ class ExoplayerView : AppCompatActivity(), Player.Listener, SessionAvailabilityL
private var wasPlaying = false private var wasPlaying = false
override fun onWindowFocusChanged(hasFocus: Boolean) { override fun onWindowFocusChanged(hasFocus: Boolean) {
if (settings.focusPause && !epChanging) { if (PrefManager.getVal(PrefName.FocusPause) && !epChanging) {
if (isInitialized && !hasFocus) wasPlaying = exoPlayer.isPlaying if (isInitialized && !hasFocus) wasPlaying = exoPlayer.isPlaying
if (hasFocus) { if (hasFocus) {
if (isInitialized && wasPlaying) exoPlayer.play() if (isInitialized && wasPlaying) exoPlayer.play()
@ -1590,7 +1608,10 @@ class ExoplayerView : AppCompatActivity(), Player.Listener, SessionAvailabilityL
override fun onRenderedFirstFrame() { override fun onRenderedFirstFrame() {
super.onRenderedFirstFrame() super.onRenderedFirstFrame()
saveData("${media.id}_${media.anime!!.selectedEpisode}_max", exoPlayer.duration, this) PrefManager.setCustomVal(
"${media.id}_${media.anime!!.selectedEpisode}_max",
exoPlayer.duration
)
val height = (exoPlayer.videoFormat ?: return).height val height = (exoPlayer.videoFormat ?: return).height
val width = (exoPlayer.videoFormat ?: return).width val width = (exoPlayer.videoFormat ?: return).width
@ -1607,14 +1628,14 @@ class ExoplayerView : AppCompatActivity(), Player.Listener, SessionAvailabilityL
exoPlayer.seekTo(0) exoPlayer.seekTo(0)
} }
if (!isTimeStampsLoaded && settings.timeStampsEnabled) { if (!isTimeStampsLoaded && PrefManager.getVal(PrefName.TimeStampsEnabled)) {
val dur = exoPlayer.duration val dur = exoPlayer.duration
lifecycleScope.launch(Dispatchers.IO) { lifecycleScope.launch(Dispatchers.IO) {
model.loadTimeStamps( model.loadTimeStamps(
media.idMAL, media.idMAL,
media.anime?.selectedEpisode?.trim()?.toIntOrNull(), media.anime?.selectedEpisode?.trim()?.toIntOrNull(),
dur / 1000, dur / 1000,
settings.useProxyForTimeStamps PrefManager.getVal(PrefName.UseProxyForTimeStamps)
) )
} }
} }
@ -1624,7 +1645,10 @@ class ExoplayerView : AppCompatActivity(), Player.Listener, SessionAvailabilityL
private var preloading = false private var preloading = false
private fun updateProgress() { private fun updateProgress() {
if (isInitialized) { if (isInitialized) {
if (exoPlayer.currentPosition.toFloat() / exoPlayer.duration > settings.watchPercentage) { if (exoPlayer.currentPosition.toFloat() / exoPlayer.duration > PrefManager.getVal<Float>(
PrefName.WatchPercentage
)
) {
preloading = true preloading = true
nextEpisode(false) { i -> nextEpisode(false) { i ->
val ep = episodes[episodeArr[currentEpisodeIndex + i]] ?: return@nextEpisode val ep = episodes[episodeArr[currentEpisodeIndex + i]] ?: return@nextEpisode
@ -1655,7 +1679,7 @@ class ExoplayerView : AppCompatActivity(), Player.Listener, SessionAvailabilityL
val new = currentTimeStamp val new = currentTimeStamp
timeStampText.text = if (new != null) { timeStampText.text = if (new != null) {
if (settings.showTimeStampButton) { if (PrefManager.getVal(PrefName.ShowTimeStampButton)) {
skipTimeButton.visibility = View.VISIBLE skipTimeButton.visibility = View.VISIBLE
exoSkip.visibility = View.GONE exoSkip.visibility = View.GONE
skipTimeText.text = new.skipType.getType() skipTimeText.text = new.skipType.getType()
@ -1663,7 +1687,7 @@ class ExoplayerView : AppCompatActivity(), Player.Listener, SessionAvailabilityL
exoPlayer.seekTo((new.interval.endTime * 1000).toLong()) exoPlayer.seekTo((new.interval.endTime * 1000).toLong())
} }
} }
if (settings.autoSkipOPED && (new.skipType == "op" || new.skipType == "ed") && !skippedTimeStamps.contains( if (PrefManager.getVal(PrefName.AutoSkipOPED) && (new.skipType == "op" || new.skipType == "ed") && !skippedTimeStamps.contains(
new new
) )
) { ) {
@ -1673,7 +1697,8 @@ class ExoplayerView : AppCompatActivity(), Player.Listener, SessionAvailabilityL
new.skipType.getType() new.skipType.getType()
} else { } else {
skipTimeButton.visibility = View.GONE skipTimeButton.visibility = View.GONE
if (settings.skipTime > 0) exoSkip.visibility = View.VISIBLE if (PrefManager.getVal<Int>(PrefName.SkipTime) > 0) exoSkip.visibility =
View.VISIBLE
"" ""
} }
} }
@ -1735,7 +1760,7 @@ class ExoplayerView : AppCompatActivity(), Player.Listener, SessionAvailabilityL
} }
} }
isBuffering = playbackState == Player.STATE_BUFFERING isBuffering = playbackState == Player.STATE_BUFFERING
if (playbackState == Player.STATE_ENDED && settings.autoPlay) { if (playbackState == Player.STATE_ENDED && PrefManager.getVal(PrefName.AutoPlay)) {
if (interacted) exoNext.performClick() if (interacted) exoNext.performClick()
else toast(getString(R.string.autoplay_cancelled)) else toast(getString(R.string.autoplay_cancelled))
} }
@ -1743,9 +1768,16 @@ class ExoplayerView : AppCompatActivity(), Player.Listener, SessionAvailabilityL
} }
private fun updateAniProgress() { private fun updateAniProgress() {
val incognito = PrefWrapper.getVal(PrefName.Incognito, false) val incognito: Boolean = PrefManager.getVal(PrefName.Incognito)
if (!incognito && exoPlayer.currentPosition / episodeLength > settings.watchPercentage && Anilist.userid != null) if (!incognito && exoPlayer.currentPosition / episodeLength > PrefManager.getVal<Float>(
if (loadData<Boolean>("${media.id}_save_progress") != false && if (media.isAdult) settings.updateForH else true) { PrefName.WatchPercentage
) && Anilist.userid != null
)
if (PrefManager.getCustomVal(
"${media.id}_save_progress",
true
) && (if (media.isAdult) PrefManager.getVal(PrefName.UpdateForHPlayer) else true)
) {
media.anime!!.selectedEpisode?.apply { media.anime!!.selectedEpisode?.apply {
updateProgress(media, this) updateProgress(media, this)
} }
@ -1758,7 +1790,7 @@ class ExoplayerView : AppCompatActivity(), Player.Listener, SessionAvailabilityL
while (isFiller) { while (isFiller) {
if (episodeArr.size > currentEpisodeIndex + i) { if (episodeArr.size > currentEpisodeIndex + i) {
isFiller = isFiller =
if (settings.autoSkipFiller) episodes[episodeArr[currentEpisodeIndex + i]]?.filler if (PrefManager.getVal(PrefName.AutoSkipFiller)) episodes[episodeArr[currentEpisodeIndex + i]]?.filler
?: false else false ?: false else false
if (!isFiller) runnable.invoke(i) if (!isFiller) runnable.invoke(i)
i++ i++
@ -1855,7 +1887,10 @@ class ExoplayerView : AppCompatActivity(), Player.Listener, SessionAvailabilityL
orientationListener?.enable() orientationListener?.enable()
} }
if (isInitialized) { if (isInitialized) {
saveData("${media.id}_${episode.number}", exoPlayer.currentPosition, this) PrefManager.setCustomVal(
"${media.id}_${episode.number}",
exoPlayer.currentPosition
)
if (wasPlaying) exoPlayer.play() if (wasPlaying) exoPlayer.play()
} }
} }

View file

@ -28,7 +28,7 @@ import ani.dantotsu.parsers.Subtitle
import ani.dantotsu.parsers.VideoExtractor import ani.dantotsu.parsers.VideoExtractor
import ani.dantotsu.parsers.VideoType import ani.dantotsu.parsers.VideoType
import ani.dantotsu.settings.saving.PrefName import ani.dantotsu.settings.saving.PrefName
import ani.dantotsu.settings.saving.PrefWrapper import ani.dantotsu.settings.saving.PrefManager
import com.google.firebase.crashlytics.FirebaseCrashlytics import com.google.firebase.crashlytics.FirebaseCrashlytics
import kotlinx.coroutines.CoroutineScope import kotlinx.coroutines.CoroutineScope
import kotlinx.coroutines.Dispatchers import kotlinx.coroutines.Dispatchers
@ -94,7 +94,7 @@ class SelectorDialogFragment : BottomSheetDialogFragment() {
binding.selectorAutoText.text = selected binding.selectorAutoText.text = selected
binding.selectorCancel.setOnClickListener { binding.selectorCancel.setOnClickListener {
media!!.selected!!.server = null media!!.selected!!.server = null
model.saveSelected(media!!.id, media!!.selected!!, requireActivity()) model.saveSelected(media!!.id, media!!.selected!!)
tryWith { tryWith {
dismiss() dismiss()
} }
@ -143,11 +143,11 @@ class SelectorDialogFragment : BottomSheetDialogFragment() {
} }
binding.selectorRecyclerView.adapter = null binding.selectorRecyclerView.adapter = null
binding.selectorProgressBar.visibility = View.VISIBLE binding.selectorProgressBar.visibility = View.VISIBLE
makeDefault = loadData("make_default") ?: true makeDefault = PrefManager.getVal(PrefName.MakeDefault)
binding.selectorMakeDefault.isChecked = makeDefault binding.selectorMakeDefault.isChecked = makeDefault
binding.selectorMakeDefault.setOnClickListener { binding.selectorMakeDefault.setOnClickListener {
makeDefault = binding.selectorMakeDefault.isChecked makeDefault = binding.selectorMakeDefault.isChecked
saveData("make_default", makeDefault) PrefManager.setVal(PrefName.MakeDefault, makeDefault)
} }
binding.selectorRecyclerView.layoutManager = binding.selectorRecyclerView.layoutManager =
LinearLayoutManager( LinearLayoutManager(
@ -301,7 +301,7 @@ class SelectorDialogFragment : BottomSheetDialogFragment() {
extractor.server.name extractor.server.name
media!!.anime!!.episodes!![media!!.anime!!.selectedEpisode!!]!!.selectedVideo = media!!.anime!!.episodes!![media!!.anime!!.selectedEpisode!!]!!.selectedVideo =
position position
if (PrefWrapper.getVal(PrefName.DownloadManager, 0) != 0) { if ((PrefManager.getVal(PrefName.DownloadManager) as Int) != 0) {
download( download(
requireActivity(), requireActivity(),
media!!.anime!!.episodes!![media!!.anime!!.selectedEpisode!!]!!, media!!.anime!!.episodes!![media!!.anime!!.selectedEpisode!!]!!,
@ -412,7 +412,7 @@ class SelectorDialogFragment : BottomSheetDialogFragment() {
if (makeDefault) { if (makeDefault) {
media!!.selected!!.server = extractor.server.name media!!.selected!!.server = extractor.server.name
media!!.selected!!.video = bindingAdapterPosition media!!.selected!!.video = bindingAdapterPosition
model.saveSelected(media!!.id, media!!.selected!!, requireActivity()) model.saveSelected(media!!.id, media!!.selected!!)
} }
startExoplayer(media!!) startExoplayer(media!!)
} }

View file

@ -15,10 +15,9 @@ import ani.dantotsu.BottomSheetDialogFragment
import ani.dantotsu.R import ani.dantotsu.R
import ani.dantotsu.databinding.BottomSheetSubtitlesBinding import ani.dantotsu.databinding.BottomSheetSubtitlesBinding
import ani.dantotsu.databinding.ItemSubtitleTextBinding import ani.dantotsu.databinding.ItemSubtitleTextBinding
import ani.dantotsu.loadData
import ani.dantotsu.media.MediaDetailsViewModel import ani.dantotsu.media.MediaDetailsViewModel
import ani.dantotsu.parsers.Subtitle import ani.dantotsu.parsers.Subtitle
import ani.dantotsu.saveData import ani.dantotsu.settings.saving.PrefManager
class SubtitleDialogFragment : BottomSheetDialogFragment() { class SubtitleDialogFragment : BottomSheetDialogFragment() {
private var _binding: BottomSheetSubtitlesBinding? = null private var _binding: BottomSheetSubtitlesBinding? = null
@ -69,7 +68,7 @@ class SubtitleDialogFragment : BottomSheetDialogFragment() {
binding.subtitleTitle.setText(R.string.none) binding.subtitleTitle.setText(R.string.none)
model.getMedia().observe(viewLifecycleOwner) { media -> model.getMedia().observe(viewLifecycleOwner) { media ->
val mediaID: Int = media.id val mediaID: Int = media.id
val selSubs: String? = loadData("subLang_${mediaID}", activity) val selSubs = PrefManager.getCustomVal<String?>("subLang_${mediaID}", null)
if (episode.selectedSubtitle != null && selSubs != "None") { if (episode.selectedSubtitle != null && selSubs != "None") {
binding.root.setCardBackgroundColor(TRANSPARENT) binding.root.setCardBackgroundColor(TRANSPARENT)
} }
@ -79,7 +78,7 @@ class SubtitleDialogFragment : BottomSheetDialogFragment() {
model.setEpisode(episode, "Subtitle") model.setEpisode(episode, "Subtitle")
model.getMedia().observe(viewLifecycleOwner) { media -> model.getMedia().observe(viewLifecycleOwner) { media ->
val mediaID: Int = media.id val mediaID: Int = media.id
saveData("subLang_${mediaID}", "None", activity) PrefManager.setCustomVal("subLang_${mediaID}", "None")
} }
dismiss() dismiss()
} }
@ -108,7 +107,7 @@ class SubtitleDialogFragment : BottomSheetDialogFragment() {
} }
model.getMedia().observe(viewLifecycleOwner) { media -> model.getMedia().observe(viewLifecycleOwner) { media ->
val mediaID: Int = media.id val mediaID: Int = media.id
val selSubs: String? = loadData("subLang_${mediaID}", activity) val selSubs: String? = PrefManager.getCustomVal<String?>("subLang_${mediaID}", null)
if (episode.selectedSubtitle != position - 1 && selSubs != subtitles[position - 1].language) { if (episode.selectedSubtitle != position - 1 && selSubs != subtitles[position - 1].language) {
binding.root.setCardBackgroundColor(TRANSPARENT) binding.root.setCardBackgroundColor(TRANSPARENT)
} }
@ -119,7 +118,7 @@ class SubtitleDialogFragment : BottomSheetDialogFragment() {
model.setEpisode(episode, "Subtitle") model.setEpisode(episode, "Subtitle")
model.getMedia().observe(viewLifecycleOwner) { media -> model.getMedia().observe(viewLifecycleOwner) { media ->
val mediaID: Int = media.id val mediaID: Int = media.id
saveData("subLang_${mediaID}", subtitles[position - 1].language, activity) PrefManager.setCustomVal("subLang_${mediaID}", subtitles[position - 1].language)
} }
dismiss() dismiss()
} }

View file

@ -261,7 +261,7 @@ class MangaChapterAdapter(
when (holder) { when (holder) {
is ChapterCompactViewHolder -> { is ChapterCompactViewHolder -> {
val binding = holder.binding val binding = holder.binding
setAnimation(fragment.requireContext(), holder.binding.root, fragment.uiSettings) setAnimation(fragment.requireContext(), holder.binding.root)
val ep = arr[position] val ep = arr[position]
val parsedNumber = MangaNameAdapter.findChapterNumber(ep.number)?.toInt() val parsedNumber = MangaNameAdapter.findChapterNumber(ep.number)?.toInt()
binding.itemEpisodeNumber.text = parsedNumber?.toString() ?: ep.number binding.itemEpisodeNumber.text = parsedNumber?.toString() ?: ep.number
@ -287,7 +287,7 @@ class MangaChapterAdapter(
val binding = holder.binding val binding = holder.binding
val ep = arr[position] val ep = arr[position]
holder.bind(ep.number, ep.progress) holder.bind(ep.number, ep.progress)
setAnimation(fragment.requireContext(), holder.binding.root, fragment.uiSettings) setAnimation(fragment.requireContext(), holder.binding.root)
binding.itemChapterNumber.text = ep.number binding.itemChapterNumber.text = ep.number
if (ep.progress.isNullOrEmpty()) { if (ep.progress.isNullOrEmpty()) {
binding.itemChapterTitle.visibility = View.GONE binding.itemChapterTitle.visibility = View.GONE

View file

@ -2,7 +2,6 @@ package ani.dantotsu.media.manga
import android.annotation.SuppressLint import android.annotation.SuppressLint
import android.app.AlertDialog import android.app.AlertDialog
import android.content.Context
import android.content.Intent import android.content.Intent
import android.view.LayoutInflater import android.view.LayoutInflater
import android.view.View import android.view.View
@ -29,7 +28,7 @@ import ani.dantotsu.parsers.DynamicMangaParser
import ani.dantotsu.parsers.MangaReadSources import ani.dantotsu.parsers.MangaReadSources
import ani.dantotsu.parsers.MangaSources import ani.dantotsu.parsers.MangaSources
import ani.dantotsu.settings.saving.PrefName import ani.dantotsu.settings.saving.PrefName
import ani.dantotsu.settings.saving.PrefWrapper import ani.dantotsu.settings.saving.PrefManager
import ani.dantotsu.subcriptions.Notifications.Companion.openSettings import ani.dantotsu.subcriptions.Notifications.Companion.openSettings
import ani.dantotsu.subcriptions.Subscription.Companion.getChannelId import ani.dantotsu.subcriptions.Subscription.Companion.getChannelId
import com.google.android.material.chip.Chip import com.google.android.material.chip.Chip
@ -71,7 +70,7 @@ class MangaReadAdapter(
null null
) )
} }
val offline = if (!isOnline(binding.root.context) || PrefWrapper.getVal(PrefName.OfflineMode, false) val offline = if (!isOnline(binding.root.context) || PrefManager.getVal(PrefName.OfflineMode)
) View.GONE else View.VISIBLE ) View.GONE else View.VISIBLE
binding.animeSourceNameContainer.visibility = offline binding.animeSourceNameContainer.visibility = offline
@ -161,7 +160,7 @@ class MangaReadAdapter(
var refresh = false var refresh = false
var run = false var run = false
var reversed = media.selected!!.recyclerReversed var reversed = media.selected!!.recyclerReversed
var style = media.selected!!.recyclerStyle ?: fragment.uiSettings.mangaDefaultView var style = media.selected!!.recyclerStyle ?: PrefManager.getVal(PrefName.MangaDefaultView)
dialogBinding.animeSourceTop.rotation = if (reversed) -90f else 90f dialogBinding.animeSourceTop.rotation = if (reversed) -90f else 90f
dialogBinding.sortText.text = if (reversed) "Down to Up" else "Up to Down" dialogBinding.sortText.text = if (reversed) "Down to Up" else "Up to Down"
dialogBinding.animeSourceTop.setOnClickListener { dialogBinding.animeSourceTop.setOnClickListener {
@ -390,7 +389,7 @@ class MangaReadAdapter(
if (media.manga?.chapters != null) { if (media.manga?.chapters != null) {
val chapters = media.manga.chapters!!.keys.toTypedArray() val chapters = media.manga.chapters!!.keys.toTypedArray()
val anilistEp = (media.userProgress ?: 0).plus(1) val anilistEp = (media.userProgress ?: 0).plus(1)
val appEp = loadData<String>("${media.id}_current_chp")?.toIntOrNull() ?: 1 val appEp = PrefManager.getNullableCustomVal<String?>("${media.id}_current_chp", null)?.toIntOrNull() ?: 1
var continueEp = (if (anilistEp > appEp) anilistEp else appEp).toString() var continueEp = (if (anilistEp > appEp) anilistEp else appEp).toString()
val filteredChapters = chapters.filter { chapterKey -> val filteredChapters = chapters.filter { chapterKey ->
val chapter = media.manga.chapters!![chapterKey]!! val chapter = media.manga.chapters!![chapterKey]!!

View file

@ -43,8 +43,9 @@ import ani.dantotsu.parsers.DynamicMangaParser
import ani.dantotsu.parsers.HMangaSources import ani.dantotsu.parsers.HMangaSources
import ani.dantotsu.parsers.MangaParser import ani.dantotsu.parsers.MangaParser
import ani.dantotsu.parsers.MangaSources import ani.dantotsu.parsers.MangaSources
import ani.dantotsu.settings.UserInterfaceSettings
import ani.dantotsu.settings.extensionprefs.MangaSourcePreferencesFragment import ani.dantotsu.settings.extensionprefs.MangaSourcePreferencesFragment
import ani.dantotsu.settings.saving.PrefName
import ani.dantotsu.settings.saving.PrefManager
import ani.dantotsu.subcriptions.Notifications import ani.dantotsu.subcriptions.Notifications
import ani.dantotsu.subcriptions.Notifications.Group.MANGA_GROUP import ani.dantotsu.subcriptions.Notifications.Group.MANGA_GROUP
import ani.dantotsu.subcriptions.Subscription.Companion.getChannelId import ani.dantotsu.subcriptions.Subscription.Companion.getChannelId
@ -87,9 +88,6 @@ open class MangaReadFragment : Fragment(), ScanlatorSelectionListener {
var continueEp: Boolean = false var continueEp: Boolean = false
var loaded = false var loaded = false
val uiSettings = loadData("ui_settings", toast = false)
?: UserInterfaceSettings().apply { saveData("ui_settings", this) }
override fun onCreateView( override fun onCreateView(
inflater: LayoutInflater, inflater: LayoutInflater,
container: ViewGroup?, container: ViewGroup?,
@ -172,7 +170,7 @@ open class MangaReadFragment : Fragment(), ScanlatorSelectionListener {
media.selected = model.loadSelected(media) media.selected = model.loadSelected(media)
subscribed = subscribed =
SubscriptionHelper.getSubscriptions(requireContext()).containsKey(media.id) SubscriptionHelper.getSubscriptions().containsKey(media.id)
style = media.selected!!.recyclerStyle style = media.selected!!.recyclerStyle
reverse = media.selected!!.recyclerReversed reverse = media.selected!!.recyclerReversed
@ -183,7 +181,7 @@ open class MangaReadFragment : Fragment(), ScanlatorSelectionListener {
headerAdapter = MangaReadAdapter(it, this, model.mangaReadSources!!) headerAdapter = MangaReadAdapter(it, this, model.mangaReadSources!!)
headerAdapter.scanlatorSelectionListener = this headerAdapter.scanlatorSelectionListener = this
chapterAdapter = chapterAdapter =
MangaChapterAdapter(style ?: uiSettings.mangaDefaultView, media, this) MangaChapterAdapter(style ?: PrefManager.getVal(PrefName.MangaDefaultView), media, this)
for (download in downloadManager.mangaDownloadedTypes) { for (download in downloadManager.mangaDownloadedTypes) {
chapterAdapter.stopDownload(download.chapter) chapterAdapter.stopDownload(download.chapter)
@ -302,7 +300,7 @@ open class MangaReadFragment : Fragment(), ScanlatorSelectionListener {
model.mangaReadSources?.get(selected.sourceIndex)?.showUserTextListener = null model.mangaReadSources?.get(selected.sourceIndex)?.showUserTextListener = null
selected.sourceIndex = i selected.sourceIndex = i
selected.server = null selected.server = null
model.saveSelected(media.id, selected, requireActivity()) model.saveSelected(media.id, selected)
media.selected = selected media.selected = selected
return model.mangaReadSources?.get(i)!! return model.mangaReadSources?.get(i)!!
} }
@ -310,14 +308,14 @@ open class MangaReadFragment : Fragment(), ScanlatorSelectionListener {
fun onLangChange(i: Int) { fun onLangChange(i: Int) {
val selected = model.loadSelected(media) val selected = model.loadSelected(media)
selected.langIndex = i selected.langIndex = i
model.saveSelected(media.id, selected, requireActivity()) model.saveSelected(media.id, selected)
media.selected = selected media.selected = selected
} }
fun onScanlatorChange(list: List<String>) { fun onScanlatorChange(list: List<String>) {
val selected = model.loadSelected(media) val selected = model.loadSelected(media)
selected.scanlators = list selected.scanlators = list
model.saveSelected(media.id, selected, requireActivity()) model.saveSelected(media.id, selected)
media.selected = selected media.selected = selected
} }
@ -330,7 +328,7 @@ open class MangaReadFragment : Fragment(), ScanlatorSelectionListener {
reverse = rev reverse = rev
media.selected!!.recyclerStyle = style media.selected!!.recyclerStyle = style
media.selected!!.recyclerReversed = reverse media.selected!!.recyclerReversed = reverse
model.saveSelected(media.id, media.selected!!, requireActivity()) model.saveSelected(media.id, media.selected!!)
reload() reload()
} }
@ -338,7 +336,7 @@ open class MangaReadFragment : Fragment(), ScanlatorSelectionListener {
media.selected!!.chip = i media.selected!!.chip = i
start = s start = s
end = e end = e
model.saveSelected(media.id, media.selected!!, requireActivity()) model.saveSelected(media.id, media.selected!!)
reload() reload()
} }
@ -436,7 +434,7 @@ open class MangaReadFragment : Fragment(), ScanlatorSelectionListener {
model.continueMedia = false model.continueMedia = false
media.manga?.chapters?.get(i)?.let { media.manga?.chapters?.get(i)?.let {
media.manga?.selectedChapter = i media.manga?.selectedChapter = i
model.saveSelected(media.id, media.selected!!, requireActivity()) model.saveSelected(media.id, media.selected!!)
ChapterLoaderDialog.newInstance(it, true) ChapterLoaderDialog.newInstance(it, true)
.show(requireActivity().supportFragmentManager, "dialog") .show(requireActivity().supportFragmentManager, "dialog")
} }
@ -574,7 +572,7 @@ open class MangaReadFragment : Fragment(), ScanlatorSelectionListener {
selected.latest = selected.latest =
media.userProgress?.toFloat()?.takeIf { selected.latest < it } ?: selected.latest media.userProgress?.toFloat()?.takeIf { selected.latest < it } ?: selected.latest
model.saveSelected(media.id, selected, requireActivity()) model.saveSelected(media.id, selected)
headerAdapter.handleChapters() headerAdapter.handleChapters()
chapterAdapter.notifyItemRangeRemoved(0, chapterAdapter.arr.size) chapterAdapter.notifyItemRangeRemoved(0, chapterAdapter.arr.size)
var arr: ArrayList<MangaChapter> = arrayListOf() var arr: ArrayList<MangaChapter> = arrayListOf()
@ -588,7 +586,7 @@ open class MangaReadFragment : Fragment(), ScanlatorSelectionListener {
arr = (arr.reversed() as? ArrayList<MangaChapter>) ?: arr arr = (arr.reversed() as? ArrayList<MangaChapter>) ?: arr
} }
chapterAdapter.arr = arr chapterAdapter.arr = arr
chapterAdapter.updateType(style ?: uiSettings.mangaDefaultView) chapterAdapter.updateType(style ?: PrefManager.getVal(PrefName.MangaDefaultView))
chapterAdapter.notifyItemRangeInserted(0, arr.size) chapterAdapter.notifyItemRangeInserted(0, arr.size)
} }

View file

@ -33,8 +33,7 @@ abstract class BaseImageAdapter(
val activity: MangaReaderActivity, val activity: MangaReaderActivity,
chapter: MangaChapter chapter: MangaChapter
) : RecyclerView.Adapter<RecyclerView.ViewHolder>() { ) : RecyclerView.Adapter<RecyclerView.ViewHolder>() {
val settings = activity.settings.default val settings = activity.defaultSettings
val uiSettings = activity.uiSettings
val images = chapter.images() val images = chapter.images()
@SuppressLint("ClickableViewAccessibility") @SuppressLint("ClickableViewAccessibility")

View file

@ -14,6 +14,8 @@ import ani.dantotsu.media.manga.MangaChapter
import ani.dantotsu.settings.CurrentReaderSettings.Directions.LEFT_TO_RIGHT import ani.dantotsu.settings.CurrentReaderSettings.Directions.LEFT_TO_RIGHT
import ani.dantotsu.settings.CurrentReaderSettings.Directions.RIGHT_TO_LEFT import ani.dantotsu.settings.CurrentReaderSettings.Directions.RIGHT_TO_LEFT
import ani.dantotsu.settings.CurrentReaderSettings.Layouts.PAGED import ani.dantotsu.settings.CurrentReaderSettings.Layouts.PAGED
import ani.dantotsu.settings.saving.PrefName
import ani.dantotsu.settings.saving.PrefManager
import com.bumptech.glide.load.resource.bitmap.BitmapTransformation import com.bumptech.glide.load.resource.bitmap.BitmapTransformation
import com.davemorrissey.labs.subscaleview.ImageSource import com.davemorrissey.labs.subscaleview.ImageSource
import com.davemorrissey.labs.subscaleview.SubsamplingScaleImageView import com.davemorrissey.labs.subscaleview.SubsamplingScaleImageView
@ -83,7 +85,7 @@ open class ImageAdapter(
imageView.minScale = scale imageView.minScale = scale
ObjectAnimator.ofFloat(parent, "alpha", 0f, 1f) ObjectAnimator.ofFloat(parent, "alpha", 0f, 1f)
.setDuration((400 * uiSettings.animationSpeed).toLong()) .setDuration((400 * PrefManager.getVal<Float>(PrefName.AnimationSpeed)).toLong())
.start() .start()
progress.visibility = View.GONE progress.visibility = View.GONE

View file

@ -3,6 +3,7 @@ package ani.dantotsu.media.manga.mangareader
import android.animation.ObjectAnimator import android.animation.ObjectAnimator
import android.annotation.SuppressLint import android.annotation.SuppressLint
import android.app.AlertDialog import android.app.AlertDialog
import android.content.Context
import android.content.Intent import android.content.Intent
import android.content.res.Configuration import android.content.res.Configuration
import android.content.res.Resources import android.content.res.Resources
@ -43,18 +44,18 @@ import ani.dantotsu.others.ImageViewDialog
import ani.dantotsu.parsers.HMangaSources import ani.dantotsu.parsers.HMangaSources
import ani.dantotsu.parsers.MangaImage import ani.dantotsu.parsers.MangaImage
import ani.dantotsu.parsers.MangaSources import ani.dantotsu.parsers.MangaSources
import ani.dantotsu.settings.CurrentReaderSettings
import ani.dantotsu.settings.CurrentReaderSettings.Companion.applyWebtoon import ani.dantotsu.settings.CurrentReaderSettings.Companion.applyWebtoon
import ani.dantotsu.settings.CurrentReaderSettings.Directions.* import ani.dantotsu.settings.CurrentReaderSettings.Directions.*
import ani.dantotsu.settings.CurrentReaderSettings.DualPageModes.* import ani.dantotsu.settings.CurrentReaderSettings.DualPageModes.*
import ani.dantotsu.settings.CurrentReaderSettings.Layouts.* import ani.dantotsu.settings.CurrentReaderSettings.Layouts.*
import ani.dantotsu.settings.ReaderSettings
import ani.dantotsu.settings.UserInterfaceSettings
import ani.dantotsu.settings.saving.PrefName import ani.dantotsu.settings.saving.PrefName
import ani.dantotsu.settings.saving.PrefWrapper import ani.dantotsu.settings.saving.PrefManager
import ani.dantotsu.themes.ThemeManager import ani.dantotsu.themes.ThemeManager
import com.alexvasilkov.gestures.views.GestureFrameLayout import com.alexvasilkov.gestures.views.GestureFrameLayout
import com.bumptech.glide.load.resource.bitmap.BitmapTransformation import com.bumptech.glide.load.resource.bitmap.BitmapTransformation
import com.davemorrissey.labs.subscaleview.SubsamplingScaleImageView import com.davemorrissey.labs.subscaleview.SubsamplingScaleImageView
import com.google.firebase.crashlytics.FirebaseCrashlytics
import com.google.firebase.crashlytics.ktx.crashlytics import com.google.firebase.crashlytics.ktx.crashlytics
import com.google.firebase.ktx.Firebase import com.google.firebase.ktx.Firebase
import eu.kanade.tachiyomi.extension.manga.MangaExtensionManager import eu.kanade.tachiyomi.extension.manga.MangaExtensionManager
@ -62,6 +63,10 @@ import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.launch import kotlinx.coroutines.launch
import uy.kohesive.injekt.Injekt import uy.kohesive.injekt.Injekt
import uy.kohesive.injekt.api.get import uy.kohesive.injekt.api.get
import java.io.FileInputStream
import java.io.FileOutputStream
import java.io.ObjectInputStream
import java.io.ObjectOutputStream
import java.util.* import java.util.*
import kotlin.math.min import kotlin.math.min
import kotlin.properties.Delegates import kotlin.properties.Delegates
@ -74,6 +79,8 @@ class MangaReaderActivity : AppCompatActivity() {
private val model: MediaDetailsViewModel by viewModels() private val model: MediaDetailsViewModel by viewModels()
private val scope = lifecycleScope private val scope = lifecycleScope
var defaultSettings = CurrentReaderSettings()
private lateinit var media: Media private lateinit var media: Media
private lateinit var chapter: MangaChapter private lateinit var chapter: MangaChapter
private lateinit var chapters: MutableMap<String, MangaChapter> private lateinit var chapters: MutableMap<String, MangaChapter>
@ -84,13 +91,9 @@ class MangaReaderActivity : AppCompatActivity() {
private var isContVisible = false private var isContVisible = false
private var showProgressDialog = true private var showProgressDialog = true
//private var progressDialog: AlertDialog.Builder? = null
private var maxChapterPage = 0L private var maxChapterPage = 0L
private var currentChapterPage = 0L private var currentChapterPage = 0L
lateinit var settings: ReaderSettings
lateinit var uiSettings: UserInterfaceSettings
private var notchHeight: Int? = null private var notchHeight: Int? = null
private var imageAdapter: BaseImageAdapter? = null private var imageAdapter: BaseImageAdapter? = null
@ -99,7 +102,7 @@ class MangaReaderActivity : AppCompatActivity() {
var isAnimating = false var isAnimating = false
override fun onAttachedToWindow() { override fun onAttachedToWindow() {
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.P && !settings.showSystemBars) { if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.P && !PrefManager.getVal<Boolean>(PrefName.ShowSystemBars)) {
val displayCutout = window.decorView.rootWindowInsets.displayCutout val displayCutout = window.decorView.rootWindowInsets.displayCutout
if (displayCutout != null) { if (displayCutout != null) {
if (displayCutout.boundingRects.size > 0) { if (displayCutout.boundingRects.size > 0) {
@ -121,7 +124,7 @@ class MangaReaderActivity : AppCompatActivity() {
} }
private fun hideBars() { private fun hideBars() {
if (!settings.showSystemBars) hideSystemBars() if (PrefManager.getVal(PrefName.ShowSystemBars)) hideSystemBars()
} }
override fun onDestroy() { override fun onDestroy() {
@ -136,7 +139,6 @@ class MangaReaderActivity : AppCompatActivity() {
override fun onCreate(savedInstanceState: Bundle?) { override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState) super.onCreate(savedInstanceState)
ThemeManager(this).applyTheme() ThemeManager(this).applyTheme()
binding = ActivityMangaReaderBinding.inflate(layoutInflater) binding = ActivityMangaReaderBinding.inflate(layoutInflater)
setContentView(binding.root) setContentView(binding.root)
@ -144,19 +146,13 @@ class MangaReaderActivity : AppCompatActivity() {
onBackPressedDispatcher.onBackPressed() onBackPressedDispatcher.onBackPressed()
} }
defaultSettings = loadReaderSettings("reader_settings") ?: defaultSettings
onBackPressedDispatcher.addCallback(this) { onBackPressedDispatcher.addCallback(this) {
progress { finish() } progress { finish() }
} }
settings = loadData("reader_settings", this) controllerDuration = (PrefManager.getVal<Float>(PrefName.AnimationSpeed) * 200).toLong()
?: ReaderSettings().apply { saveData("reader_settings", this) }
uiSettings = loadData("ui_settings", this) ?: UserInterfaceSettings().apply {
saveData(
"ui_settings",
this
)
}
controllerDuration = (uiSettings.animationSpeed * 200).toLong()
hideBars() hideBars()
@ -179,7 +175,7 @@ class MangaReaderActivity : AppCompatActivity() {
binding.mangaReaderSlider.addOnChangeListener { _, value, fromUser -> binding.mangaReaderSlider.addOnChangeListener { _, value, fromUser ->
if (fromUser) { if (fromUser) {
sliding = true sliding = true
if (settings.default.layout != PAGED) if (defaultSettings.layout != PAGED)
binding.mangaReaderRecycler.scrollToPosition((value.toInt() - 1) / (dualPage { 2 } binding.mangaReaderRecycler.scrollToPosition((value.toInt() - 1) / (dualPage { 2 }
?: 1)) ?: 1))
else else
@ -202,14 +198,16 @@ class MangaReaderActivity : AppCompatActivity() {
else model.getMedia().value ?: return else model.getMedia().value ?: return
model.setMedia(media) model.setMedia(media)
if (settings.autoDetectWebtoon && media.countryOfOrigin != "JP") applyWebtoon(settings.default) if (PrefManager.getVal(PrefName.AutoDetectWebtoon) && media.countryOfOrigin != "JP") applyWebtoon(
settings.default = loadData("${media.id}_current_settings") ?: settings.default defaultSettings
)
defaultSettings = loadReaderSettings("${media.id}_current_settings") ?: defaultSettings
chapters = media.manga?.chapters ?: return chapters = media.manga?.chapters ?: return
chapter = chapters[media.manga!!.selectedChapter] ?: return chapter = chapters[media.manga!!.selectedChapter] ?: return
model.mangaReadSources = if (media.isAdult) HMangaSources else MangaSources model.mangaReadSources = if (media.isAdult) HMangaSources else MangaSources
binding.mangaReaderSource.visibility = if (settings.showSource) View.VISIBLE else View.GONE binding.mangaReaderSource.visibility = if (PrefManager.getVal(PrefName.ShowSource)) View.VISIBLE else View.GONE
if (model.mangaReadSources!!.names.isEmpty()) { if (model.mangaReadSources!!.names.isEmpty()) {
//try to reload sources //try to reload sources
try { try {
@ -254,13 +252,15 @@ class MangaReaderActivity : AppCompatActivity() {
} }
showProgressDialog = showProgressDialog =
if (settings.askIndividual) loadData<Boolean>("${media.id}_progressDialog") if (PrefManager.getVal(PrefName.AskIndividualReader)) PrefManager.getCustomVal(
?: true else false "${media.id}_progressDialog",
true
) else false
//Chapter Change //Chapter Change
fun change(index: Int) { fun change(index: Int) {
mangaCache.clear() mangaCache.clear()
saveData("${media.id}_${chaptersArr[currentChapterIndex]}", currentChapterPage, this) PrefManager.setCustomVal("${media.id}_${chaptersArr[currentChapterIndex]}", currentChapterPage)
ChapterLoaderDialog.newInstance(chapters[chaptersArr[index]]!!) ChapterLoaderDialog.newInstance(chapters[chaptersArr[index]]!!)
.show(supportFragmentManager, "dialog") .show(supportFragmentManager, "dialog")
} }
@ -309,7 +309,7 @@ class MangaReaderActivity : AppCompatActivity() {
chapter = chap chapter = chap
media.manga!!.selectedChapter = chapter.number media.manga!!.selectedChapter = chapter.number
media.selected = model.loadSelected(media) media.selected = model.loadSelected(media)
saveData("${media.id}_current_chp", chap.number, this) PrefManager.setCustomVal("${media.id}_current_chp", chap.number)
currentChapterIndex = chaptersArr.indexOf(chap.number) currentChapterIndex = chaptersArr.indexOf(chap.number)
binding.mangaReaderChapterSelect.setSelection(currentChapterIndex) binding.mangaReaderChapterSelect.setSelection(currentChapterIndex)
binding.mangaReaderNextChap.text = binding.mangaReaderNextChap.text =
@ -318,8 +318,8 @@ class MangaReaderActivity : AppCompatActivity() {
chaptersTitleArr.getOrNull(currentChapterIndex - 1) ?: "" chaptersTitleArr.getOrNull(currentChapterIndex - 1) ?: ""
applySettings() applySettings()
val context = this val context = this
val offline = PrefWrapper.getVal(PrefName.OfflineMode, false) val offline: Boolean = PrefManager.getVal(PrefName.OfflineMode)
val incognito = PrefWrapper.getVal(PrefName.Incognito, false) val incognito: Boolean = PrefManager.getVal(PrefName.Incognito)
if ((isOnline(context) && !offline) && Discord.token != null && !incognito) { if ((isOnline(context) && !offline) && Discord.token != null && !incognito) {
lifecycleScope.launch { lifecycleScope.launch {
val presence = RPC.createPresence( val presence = RPC.createPresence(
@ -368,7 +368,7 @@ class MangaReaderActivity : AppCompatActivity() {
private val snapHelper = PagerSnapHelper() private val snapHelper = PagerSnapHelper()
fun <T> dualPage(callback: () -> T): T? { fun <T> dualPage(callback: () -> T): T? {
return when (settings.default.dualPageMode) { return when (defaultSettings.dualPageMode) {
No -> null No -> null
Automatic -> { Automatic -> {
val orientation = resources.configuration.orientation val orientation = resources.configuration.orientation
@ -383,29 +383,29 @@ class MangaReaderActivity : AppCompatActivity() {
@SuppressLint("ClickableViewAccessibility") @SuppressLint("ClickableViewAccessibility")
fun applySettings() { fun applySettings() {
saveData("${media.id}_current_settings", settings.default) saveReaderSettings("${media.id}_current_settings", defaultSettings)
hideBars() hideBars()
//true colors //true colors
SubsamplingScaleImageView.setPreferredBitmapConfig( SubsamplingScaleImageView.setPreferredBitmapConfig(
if (settings.default.trueColors) Bitmap.Config.ARGB_8888 if (defaultSettings.trueColors) Bitmap.Config.ARGB_8888
else Bitmap.Config.RGB_565 else Bitmap.Config.RGB_565
) )
//keep screen On //keep screen On
if (settings.default.keepScreenOn) window.addFlags(WindowManager.LayoutParams.FLAG_KEEP_SCREEN_ON) if (defaultSettings.keepScreenOn) window.addFlags(WindowManager.LayoutParams.FLAG_KEEP_SCREEN_ON)
else window.clearFlags(WindowManager.LayoutParams.FLAG_KEEP_SCREEN_ON) else window.clearFlags(WindowManager.LayoutParams.FLAG_KEEP_SCREEN_ON)
binding.mangaReaderPager.unregisterOnPageChangeCallback(pageChangeCallback) binding.mangaReaderPager.unregisterOnPageChangeCallback(pageChangeCallback)
currentChapterPage = loadData("${media.id}_${chapter.number}", this) ?: 1 currentChapterPage = PrefManager.getCustomVal("${media.id}_${chapter.number}", 1L)
val chapImages = chapter.images() val chapImages = chapter.images()
maxChapterPage = 0 maxChapterPage = 0
if (chapImages.isNotEmpty()) { if (chapImages.isNotEmpty()) {
maxChapterPage = chapImages.size.toLong() maxChapterPage = chapImages.size.toLong()
saveData("${media.id}_${chapter.number}_max", maxChapterPage) PrefManager.setCustomVal("${media.id}_${chapter.number}_max", maxChapterPage)
imageAdapter = imageAdapter =
dualPage { DualPageAdapter(this, chapter) } ?: ImageAdapter(this, chapter) dualPage { DualPageAdapter(this, chapter) } ?: ImageAdapter(this, chapter)
@ -420,15 +420,15 @@ class MangaReaderActivity : AppCompatActivity() {
binding.mangaReaderSlider.visibility = View.GONE binding.mangaReaderSlider.visibility = View.GONE
} }
binding.mangaReaderPageNumber.text = binding.mangaReaderPageNumber.text =
if (settings.default.hidePageNumbers) "" else "${currentChapterPage}/$maxChapterPage" if (defaultSettings.hidePageNumbers) "" else "${currentChapterPage}/$maxChapterPage"
} }
val currentPage = currentChapterPage.toInt() val currentPage = currentChapterPage.toInt()
if ((settings.default.direction == TOP_TO_BOTTOM || settings.default.direction == BOTTOM_TO_TOP)) { if ((defaultSettings.direction == TOP_TO_BOTTOM || defaultSettings.direction == BOTTOM_TO_TOP)) {
binding.mangaReaderSwipy.vertical = true binding.mangaReaderSwipy.vertical = true
if (settings.default.direction == TOP_TO_BOTTOM) { if (defaultSettings.direction == TOP_TO_BOTTOM) {
binding.BottomSwipeText.text = chaptersTitleArr.getOrNull(currentChapterIndex + 1) binding.BottomSwipeText.text = chaptersTitleArr.getOrNull(currentChapterIndex + 1)
?: getString(R.string.no_chapter) ?: getString(R.string.no_chapter)
binding.TopSwipeText.text = chaptersTitleArr.getOrNull(currentChapterIndex - 1) binding.TopSwipeText.text = chaptersTitleArr.getOrNull(currentChapterIndex - 1)
@ -465,7 +465,7 @@ class MangaReaderActivity : AppCompatActivity() {
} }
} else { } else {
binding.mangaReaderSwipy.vertical = false binding.mangaReaderSwipy.vertical = false
if (settings.default.direction == RIGHT_TO_LEFT) { if (defaultSettings.direction == RIGHT_TO_LEFT) {
binding.LeftSwipeText.text = chaptersTitleArr.getOrNull(currentChapterIndex + 1) binding.LeftSwipeText.text = chaptersTitleArr.getOrNull(currentChapterIndex + 1)
?: getString(R.string.no_chapter) ?: getString(R.string.no_chapter)
binding.RightSwipeText.text = chaptersTitleArr.getOrNull(currentChapterIndex - 1) binding.RightSwipeText.text = chaptersTitleArr.getOrNull(currentChapterIndex - 1)
@ -502,11 +502,11 @@ class MangaReaderActivity : AppCompatActivity() {
} }
} }
if (settings.default.layout != PAGED) { if (defaultSettings.layout != PAGED) {
binding.mangaReaderRecyclerContainer.visibility = View.VISIBLE binding.mangaReaderRecyclerContainer.visibility = View.VISIBLE
binding.mangaReaderRecyclerContainer.controller.settings.isRotationEnabled = binding.mangaReaderRecyclerContainer.controller.settings.isRotationEnabled =
settings.default.rotation defaultSettings.rotation
val detector = GestureDetectorCompat(this, object : GesturesListener() { val detector = GestureDetectorCompat(this, object : GesturesListener() {
override fun onLongPress(e: MotionEvent) { override fun onLongPress(e: MotionEvent) {
@ -529,7 +529,7 @@ class MangaReaderActivity : AppCompatActivity() {
val page = val page =
chapter.dualPages().getOrNull(pos) ?: return@dualPage false chapter.dualPages().getOrNull(pos) ?: return@dualPage false
val nextPage = page.second val nextPage = page.second
if (settings.default.direction != LEFT_TO_RIGHT && nextPage != null) if (defaultSettings.direction != LEFT_TO_RIGHT && nextPage != null)
onImageLongClicked(pos * 2, nextPage, page.first, callback) onImageLongClicked(pos * 2, nextPage, page.first, callback)
else else
onImageLongClicked(pos * 2, page.first, nextPage, callback) onImageLongClicked(pos * 2, page.first, nextPage, callback)
@ -551,11 +551,11 @@ class MangaReaderActivity : AppCompatActivity() {
val manager = PreloadLinearLayoutManager( val manager = PreloadLinearLayoutManager(
this, this,
if (settings.default.direction == TOP_TO_BOTTOM || settings.default.direction == BOTTOM_TO_TOP) if (defaultSettings.direction == TOP_TO_BOTTOM || defaultSettings.direction == BOTTOM_TO_TOP)
RecyclerView.VERTICAL RecyclerView.VERTICAL
else else
RecyclerView.HORIZONTAL, RecyclerView.HORIZONTAL,
!(settings.default.direction == TOP_TO_BOTTOM || settings.default.direction == LEFT_TO_RIGHT) !(defaultSettings.direction == TOP_TO_BOTTOM || defaultSettings.direction == LEFT_TO_RIGHT)
) )
manager.preloadItemCount = 5 manager.preloadItemCount = 5
@ -574,7 +574,7 @@ class MangaReaderActivity : AppCompatActivity() {
addOnScrollListener(object : RecyclerView.OnScrollListener() { addOnScrollListener(object : RecyclerView.OnScrollListener() {
override fun onScrolled(v: RecyclerView, dx: Int, dy: Int) { override fun onScrolled(v: RecyclerView, dx: Int, dy: Int) {
settings.default.apply { defaultSettings.apply {
if ( if (
((direction == TOP_TO_BOTTOM || direction == BOTTOM_TO_TOP) ((direction == TOP_TO_BOTTOM || direction == BOTTOM_TO_TOP)
&& (!v.canScrollVertically(-1) || !v.canScrollVertically(1))) && (!v.canScrollVertically(-1) || !v.canScrollVertically(1)))
@ -593,25 +593,25 @@ class MangaReaderActivity : AppCompatActivity() {
super.onScrolled(v, dx, dy) super.onScrolled(v, dx, dy)
} }
}) })
if ((settings.default.direction == TOP_TO_BOTTOM || settings.default.direction == BOTTOM_TO_TOP)) if ((defaultSettings.direction == TOP_TO_BOTTOM || defaultSettings.direction == BOTTOM_TO_TOP))
updatePadding(0, 128f.px, 0, 128f.px) updatePadding(0, 128f.px, 0, 128f.px)
else else
updatePadding(128f.px, 0, 128f.px, 0) updatePadding(128f.px, 0, 128f.px, 0)
snapHelper.attachToRecyclerView( snapHelper.attachToRecyclerView(
if (settings.default.layout == CONTINUOUS_PAGED) this if (defaultSettings.layout == CONTINUOUS_PAGED) this
else null else null
) )
onVolumeUp = { onVolumeUp = {
if ((settings.default.direction == TOP_TO_BOTTOM || settings.default.direction == BOTTOM_TO_TOP)) if ((defaultSettings.direction == TOP_TO_BOTTOM || defaultSettings.direction == BOTTOM_TO_TOP))
smoothScrollBy(0, -500) smoothScrollBy(0, -500)
else else
smoothScrollBy(-500, 0) smoothScrollBy(-500, 0)
} }
onVolumeDown = { onVolumeDown = {
if ((settings.default.direction == TOP_TO_BOTTOM || settings.default.direction == BOTTOM_TO_TOP)) if ((defaultSettings.direction == TOP_TO_BOTTOM || defaultSettings.direction == BOTTOM_TO_TOP))
smoothScrollBy(0, 500) smoothScrollBy(0, 500)
else else
smoothScrollBy(500, 0) smoothScrollBy(500, 0)
@ -626,11 +626,11 @@ class MangaReaderActivity : AppCompatActivity() {
visibility = View.VISIBLE visibility = View.VISIBLE
adapter = imageAdapter adapter = imageAdapter
layoutDirection = layoutDirection =
if (settings.default.direction == BOTTOM_TO_TOP || settings.default.direction == RIGHT_TO_LEFT) if (defaultSettings.direction == BOTTOM_TO_TOP || defaultSettings.direction == RIGHT_TO_LEFT)
View.LAYOUT_DIRECTION_RTL View.LAYOUT_DIRECTION_RTL
else View.LAYOUT_DIRECTION_LTR else View.LAYOUT_DIRECTION_LTR
orientation = orientation =
if (settings.default.direction == LEFT_TO_RIGHT || settings.default.direction == RIGHT_TO_LEFT) if (defaultSettings.direction == LEFT_TO_RIGHT || defaultSettings.direction == RIGHT_TO_LEFT)
ViewPager2.ORIENTATION_HORIZONTAL ViewPager2.ORIENTATION_HORIZONTAL
else ViewPager2.ORIENTATION_VERTICAL else ViewPager2.ORIENTATION_VERTICAL
registerOnPageChangeCallback(pageChangeCallback) registerOnPageChangeCallback(pageChangeCallback)
@ -653,7 +653,7 @@ class MangaReaderActivity : AppCompatActivity() {
return when (event.keyCode) { return when (event.keyCode) {
KEYCODE_VOLUME_UP, KEYCODE_DPAD_UP, KEYCODE_PAGE_UP -> { KEYCODE_VOLUME_UP, KEYCODE_DPAD_UP, KEYCODE_PAGE_UP -> {
if (event.keyCode == KEYCODE_VOLUME_UP) if (event.keyCode == KEYCODE_VOLUME_UP)
if (!settings.default.volumeButtons) if (!defaultSettings.volumeButtons)
return false return false
if (event.action == ACTION_DOWN) { if (event.action == ACTION_DOWN) {
onVolumeUp?.invoke() onVolumeUp?.invoke()
@ -663,7 +663,7 @@ class MangaReaderActivity : AppCompatActivity() {
KEYCODE_VOLUME_DOWN, KEYCODE_DPAD_DOWN, KEYCODE_PAGE_DOWN -> { KEYCODE_VOLUME_DOWN, KEYCODE_DPAD_DOWN, KEYCODE_PAGE_DOWN -> {
if (event.keyCode == KEYCODE_VOLUME_DOWN) if (event.keyCode == KEYCODE_VOLUME_DOWN)
if (!settings.default.volumeButtons) if (!defaultSettings.volumeButtons)
return false return false
if (event.action == ACTION_DOWN) { if (event.action == ACTION_DOWN) {
onVolumeDown?.invoke() onVolumeDown?.invoke()
@ -710,14 +710,14 @@ class MangaReaderActivity : AppCompatActivity() {
fun handleController(shouldShow: Boolean? = null, event: MotionEvent? = null) { fun handleController(shouldShow: Boolean? = null, event: MotionEvent? = null) {
var pressLocation = pressPos.CENTER var pressLocation = pressPos.CENTER
if (!sliding) { if (!sliding) {
if (event != null && settings.default.layout == PAGED) { if (event != null && defaultSettings.layout == PAGED) {
if (event.action != MotionEvent.ACTION_UP) return if (event.action != MotionEvent.ACTION_UP) return
val x = event.rawX.toInt() val x = event.rawX.toInt()
val y = event.rawY.toInt() val y = event.rawY.toInt()
val screenWidth = Resources.getSystem().displayMetrics.widthPixels val screenWidth = Resources.getSystem().displayMetrics.widthPixels
//if in the 1st 1/5th of the screen width, left and lower than 1/5th of the screen height, left //if in the 1st 1/5th of the screen width, left and lower than 1/5th of the screen height, left
if (screenWidth / 5 in x + 1..<y) { if (screenWidth / 5 in x + 1..<y) {
pressLocation = if (settings.default.direction == RIGHT_TO_LEFT) { pressLocation = if (defaultSettings.direction == RIGHT_TO_LEFT) {
pressPos.RIGHT pressPos.RIGHT
} else { } else {
pressPos.LEFT pressPos.LEFT
@ -725,7 +725,7 @@ class MangaReaderActivity : AppCompatActivity() {
} }
//if in the last 1/5th of the screen width, right and lower than 1/5th of the screen height, right //if in the last 1/5th of the screen width, right and lower than 1/5th of the screen height, right
else if (x > screenWidth - screenWidth / 5 && y > screenWidth / 5) { else if (x > screenWidth - screenWidth / 5 && y > screenWidth / 5) {
pressLocation = if (settings.default.direction == RIGHT_TO_LEFT) { pressLocation = if (defaultSettings.direction == RIGHT_TO_LEFT) {
pressPos.LEFT pressPos.LEFT
} else { } else {
pressPos.RIGHT pressPos.RIGHT
@ -757,12 +757,12 @@ class MangaReaderActivity : AppCompatActivity() {
} }
} }
if (!settings.showSystemBars) { if (!PrefManager.getVal<Boolean>(PrefName.ShowSystemBars)) {
hideBars() hideBars()
checkNotch() checkNotch()
} }
//horizontal scrollbar //horizontal scrollbar
if (settings.default.horizontalScrollBar) { if (defaultSettings.horizontalScrollBar) {
binding.mangaReaderSliderContainer.updateLayoutParams { binding.mangaReaderSliderContainer.updateLayoutParams {
height = ViewGroup.LayoutParams.WRAP_CONTENT height = ViewGroup.LayoutParams.WRAP_CONTENT
width = ViewGroup.LayoutParams.WRAP_CONTENT width = ViewGroup.LayoutParams.WRAP_CONTENT
@ -789,7 +789,7 @@ class MangaReaderActivity : AppCompatActivity() {
} }
} }
binding.mangaReaderSlider.layoutDirection = binding.mangaReaderSlider.layoutDirection =
if (settings.default.direction == RIGHT_TO_LEFT || settings.default.direction == BOTTOM_TO_TOP) if (defaultSettings.direction == RIGHT_TO_LEFT || defaultSettings.direction == BOTTOM_TO_TOP)
View.LAYOUT_DIRECTION_RTL View.LAYOUT_DIRECTION_RTL
else View.LAYOUT_DIRECTION_LTR else View.LAYOUT_DIRECTION_LTR
shouldShow?.apply { isContVisible = !this } shouldShow?.apply { isContVisible = !this }
@ -827,9 +827,9 @@ class MangaReaderActivity : AppCompatActivity() {
fun updatePageNumber(page: Long) { fun updatePageNumber(page: Long) {
if (currentChapterPage != page) { if (currentChapterPage != page) {
currentChapterPage = page currentChapterPage = page
saveData("${media.id}_${chapter.number}", page, this) PrefManager.setCustomVal("${media.id}_${chapter.number}", page)
binding.mangaReaderPageNumber.text = binding.mangaReaderPageNumber.text =
if (settings.default.hidePageNumbers) "" else "${currentChapterPage}/$maxChapterPage" if (defaultSettings.hidePageNumbers) "" else "${currentChapterPage}/$maxChapterPage"
if (!sliding) binding.mangaReaderSlider.apply { if (!sliding) binding.mangaReaderSlider.apply {
value = clamp(currentChapterPage.toFloat(), 1f, valueTo) value = clamp(currentChapterPage.toFloat(), 1f, valueTo)
} }
@ -850,16 +850,16 @@ class MangaReaderActivity : AppCompatActivity() {
private fun progress(runnable: Runnable) { private fun progress(runnable: Runnable) {
if (maxChapterPage - currentChapterPage <= 1 && Anilist.userid != null) { if (maxChapterPage - currentChapterPage <= 1 && Anilist.userid != null) {
showProgressDialog = showProgressDialog =
if (settings.askIndividual) loadData<Boolean>("${media.id}_progressDialog") if (PrefManager.getVal(PrefName.AskIndividualReader)) PrefManager.getCustomVal("${media.id}_progressDialog", true)
?: true else false else false
val incognito = PrefWrapper.getVal(PrefName.Incognito, false) val incognito: Boolean = PrefManager.getVal(PrefName.Incognito)
if (showProgressDialog && !incognito) { if (showProgressDialog && !incognito) {
val dialogView = layoutInflater.inflate(R.layout.item_custom_dialog, null) val dialogView = layoutInflater.inflate(R.layout.item_custom_dialog, null)
val checkbox = dialogView.findViewById<CheckBox>(R.id.dialog_checkbox) val checkbox = dialogView.findViewById<CheckBox>(R.id.dialog_checkbox)
checkbox.text = getString(R.string.dont_ask_again, media.userPreferredName) checkbox.text = getString(R.string.dont_ask_again, media.userPreferredName)
checkbox.setOnCheckedChangeListener { _, isChecked -> checkbox.setOnCheckedChangeListener { _, isChecked ->
saveData("${media.id}_progressDialog", !isChecked) PrefManager.setCustomVal("${media.id}_progressDialog", !isChecked)
showProgressDialog = !isChecked showProgressDialog = !isChecked
} }
AlertDialog.Builder(this, R.style.MyPopup) AlertDialog.Builder(this, R.style.MyPopup)
@ -867,7 +867,7 @@ class MangaReaderActivity : AppCompatActivity() {
.setView(dialogView) .setView(dialogView)
.setCancelable(false) .setCancelable(false)
.setPositiveButton(getString(R.string.yes)) { dialog, _ -> .setPositiveButton(getString(R.string.yes)) { dialog, _ ->
saveData("${media.id}_save_progress", true) PrefManager.setCustomVal("${media.id}_save_progress", true)
updateProgress( updateProgress(
media, media,
MangaNameAdapter.findChapterNumber(media.manga!!.selectedChapter!!) MangaNameAdapter.findChapterNumber(media.manga!!.selectedChapter!!)
@ -877,7 +877,7 @@ class MangaReaderActivity : AppCompatActivity() {
runnable.run() runnable.run()
} }
.setNegativeButton(getString(R.string.no)) { dialog, _ -> .setNegativeButton(getString(R.string.no)) { dialog, _ ->
saveData("${media.id}_save_progress", false) PrefManager.setCustomVal("${media.id}_save_progress", false)
dialog.dismiss() dialog.dismiss()
runnable.run() runnable.run()
} }
@ -885,9 +885,9 @@ class MangaReaderActivity : AppCompatActivity() {
.create() .create()
.show() .show()
} else { } else {
if (!incognito && loadData<Boolean>("${media.id}_save_progress") != false && if (media.isAdult) settings.updateForH else true) if (!incognito && PrefManager.getCustomVal("${media.id}_save_progress", true) && if (media.isAdult) PrefManager.getVal<Boolean>(PrefName.UpdateForHReader) else true)
updateProgress( updateProgress(
media, media,
MangaNameAdapter.findChapterNumber(media.manga!!.selectedChapter!!) MangaNameAdapter.findChapterNumber(media.manga!!.selectedChapter!!)
.toString() .toString()
) )
@ -898,6 +898,47 @@ class MangaReaderActivity : AppCompatActivity() {
} }
} }
@Suppress("UNCHECKED_CAST")
private fun <T> loadReaderSettings(fileName: String, context: Context? = null, toast: Boolean = true): T? {
val a = context ?: currContext()
try {
if (a?.fileList() != null)
if (fileName in a.fileList()) {
val fileIS: FileInputStream = a.openFileInput(fileName)
val objIS = ObjectInputStream(fileIS)
val data = objIS.readObject() as T
objIS.close()
fileIS.close()
return data
}
} catch (e: Exception) {
if (toast) snackString(a?.getString(R.string.error_loading_data, fileName))
//try to delete the file
try {
a?.deleteFile(fileName)
} catch (e: Exception) {
FirebaseCrashlytics.getInstance().log("Failed to delete file $fileName")
FirebaseCrashlytics.getInstance().recordException(e)
}
e.printStackTrace()
}
return null
}
private fun saveReaderSettings(fileName: String, data: Any?, context: Context? = null) {
tryWith {
val a = context ?: currContext()
if (a != null) {
val fos: FileOutputStream = a.openFileOutput(fileName, Context.MODE_PRIVATE)
val os = ObjectOutputStream(fos)
os.writeObject(data)
os.close()
fos.close()
}
}
}
fun getTransformation(mangaImage: MangaImage): BitmapTransformation? { fun getTransformation(mangaImage: MangaImage): BitmapTransformation? {
return model.loadTransformation(mangaImage, media.selected!!.sourceIndex) return model.loadTransformation(mangaImage, media.selected!!.sourceIndex)
} }
@ -908,7 +949,7 @@ class MangaReaderActivity : AppCompatActivity() {
img2: MangaImage?, img2: MangaImage?,
callback: ((ImageViewDialog) -> Unit)? = null callback: ((ImageViewDialog) -> Unit)? = null
): Boolean { ): Boolean {
if (!settings.default.longClickImage) return false if (!defaultSettings.longClickImage) return false
val title = "(Page ${pos + 1}${if (img2 != null) "-${pos + 2}" else ""}) ${ val title = "(Page ${pos + 1}${if (img2 != null) "-${pos + 2}" else ""}) ${
chaptersTitleArr.getOrNull(currentChapterIndex)?.replace(" : ", " - ") ?: "" chaptersTitleArr.getOrNull(currentChapterIndex)?.replace(" : ", " - ") ?: ""
} [${media.userPreferredName}]" } [${media.userPreferredName}]"
@ -922,8 +963,8 @@ class MangaReaderActivity : AppCompatActivity() {
val parserTransformation2 = getTransformation(img2) val parserTransformation2 = getTransformation(img2)
if (parserTransformation2 != null) transforms2.add(parserTransformation2) if (parserTransformation2 != null) transforms2.add(parserTransformation2)
} }
val threshold = settings.default.cropBorderThreshold val threshold = defaultSettings.cropBorderThreshold
if (settings.default.cropBorders) { if (defaultSettings.cropBorders) {
transforms1.add(RemoveBordersTransformation(true, threshold)) transforms1.add(RemoveBordersTransformation(true, threshold))
transforms1.add(RemoveBordersTransformation(false, threshold)) transforms1.add(RemoveBordersTransformation(false, threshold))
if (img2 != null) { if (img2 != null) {

View file

@ -26,7 +26,7 @@ class ReaderSettingsDialogFragment : BottomSheetDialogFragment() {
override fun onViewCreated(view: View, savedInstanceState: Bundle?) { override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
super.onViewCreated(view, savedInstanceState) super.onViewCreated(view, savedInstanceState)
val activity = requireActivity() as MangaReaderActivity val activity = requireActivity() as MangaReaderActivity
val settings = activity.settings.default val settings = activity.defaultSettings
binding.readerDirectionText.text = binding.readerDirectionText.text =
resources.getStringArray(R.array.manga_directions)[settings.direction.ordinal] resources.getStringArray(R.array.manga_directions)[settings.direction.ordinal]

View file

@ -26,14 +26,11 @@ import ani.dantotsu.download.DownloadedType
import ani.dantotsu.download.DownloadsManager import ani.dantotsu.download.DownloadsManager
import ani.dantotsu.download.novel.NovelDownloaderService import ani.dantotsu.download.novel.NovelDownloaderService
import ani.dantotsu.download.novel.NovelServiceDataSingleton import ani.dantotsu.download.novel.NovelServiceDataSingleton
import ani.dantotsu.loadData
import ani.dantotsu.media.Media import ani.dantotsu.media.Media
import ani.dantotsu.media.MediaDetailsViewModel import ani.dantotsu.media.MediaDetailsViewModel
import ani.dantotsu.media.novel.novelreader.NovelReaderActivity import ani.dantotsu.media.novel.novelreader.NovelReaderActivity
import ani.dantotsu.navBarHeight import ani.dantotsu.navBarHeight
import ani.dantotsu.parsers.ShowResponse import ani.dantotsu.parsers.ShowResponse
import ani.dantotsu.saveData
import ani.dantotsu.settings.UserInterfaceSettings
import kotlinx.coroutines.CoroutineScope import kotlinx.coroutines.CoroutineScope
import kotlinx.coroutines.Dispatchers import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.launch import kotlinx.coroutines.launch
@ -61,9 +58,6 @@ class NovelReadFragment : Fragment(),
private var continueEp: Boolean = false private var continueEp: Boolean = false
var loaded = false var loaded = false
val uiSettings = loadData("ui_settings", toast = false)
?: UserInterfaceSettings().apply { saveData("ui_settings", this) }
override fun downloadTrigger(novelDownloadPackage: NovelDownloadPackage) { override fun downloadTrigger(novelDownloadPackage: NovelDownloadPackage) {
Log.e("downloadTrigger", novelDownloadPackage.link) Log.e("downloadTrigger", novelDownloadPackage.link)
val downloadTask = NovelDownloaderService.DownloadTask( val downloadTask = NovelDownloaderService.DownloadTask(
@ -253,7 +247,7 @@ class NovelReadFragment : Fragment(),
if (save) { if (save) {
val selected = model.loadSelected(media) val selected = model.loadSelected(media)
selected.server = query selected.server = query
model.saveSelected(media.id, selected, requireActivity()) model.saveSelected(media.id, selected)
} }
} }
} }
@ -263,7 +257,7 @@ class NovelReadFragment : Fragment(),
selected.sourceIndex = i selected.sourceIndex = i
source = i source = i
selected.server = null selected.server = null
model.saveSelected(media.id, selected, requireActivity()) model.saveSelected(media.id, selected)
media.selected = selected media.selected = selected
} }

View file

@ -35,7 +35,7 @@ class NovelResponseAdapter(
override fun onBindViewHolder(holder: ViewHolder, position: Int) { override fun onBindViewHolder(holder: ViewHolder, position: Int) {
val binding = holder.binding val binding = holder.binding
val novel = list[position] val novel = list[position]
setAnimation(fragment.requireContext(), holder.binding.root, fragment.uiSettings) setAnimation(fragment.requireContext(), holder.binding.root)
val cover = GlideUrl(novel.coverUrl.url) { novel.coverUrl.headers } val cover = GlideUrl(novel.coverUrl.url) { novel.coverUrl.headers }
Glide.with(binding.itemEpisodeImage).load(cover).override(400, 0) Glide.with(binding.itemEpisodeImage).load(cover).override(400, 0)

View file

@ -2,6 +2,7 @@ package ani.dantotsu.media.novel.novelreader
import android.animation.ObjectAnimator import android.animation.ObjectAnimator
import android.annotation.SuppressLint import android.annotation.SuppressLint
import android.content.Context
import android.content.Intent import android.content.Intent
import android.content.pm.ActivityInfo import android.content.pm.ActivityInfo
import android.graphics.Color import android.graphics.Color
@ -28,20 +29,20 @@ import androidx.webkit.WebViewCompat
import ani.dantotsu.GesturesListener import ani.dantotsu.GesturesListener
import ani.dantotsu.NoPaddingArrayAdapter import ani.dantotsu.NoPaddingArrayAdapter
import ani.dantotsu.R import ani.dantotsu.R
import ani.dantotsu.currContext
import ani.dantotsu.databinding.ActivityNovelReaderBinding import ani.dantotsu.databinding.ActivityNovelReaderBinding
import ani.dantotsu.hideSystemBars import ani.dantotsu.hideSystemBars
import ani.dantotsu.loadData
import ani.dantotsu.others.ImageViewDialog import ani.dantotsu.others.ImageViewDialog
import ani.dantotsu.saveData
import ani.dantotsu.setSafeOnClickListener import ani.dantotsu.setSafeOnClickListener
import ani.dantotsu.settings.CurrentNovelReaderSettings import ani.dantotsu.settings.CurrentNovelReaderSettings
import ani.dantotsu.settings.CurrentReaderSettings import ani.dantotsu.settings.CurrentReaderSettings
import ani.dantotsu.settings.ReaderSettings import ani.dantotsu.settings.saving.PrefName
import ani.dantotsu.settings.UserInterfaceSettings import ani.dantotsu.settings.saving.PrefManager
import ani.dantotsu.snackString import ani.dantotsu.snackString
import ani.dantotsu.themes.ThemeManager import ani.dantotsu.themes.ThemeManager
import ani.dantotsu.tryWith import ani.dantotsu.tryWith
import com.google.android.material.slider.Slider import com.google.android.material.slider.Slider
import com.google.firebase.crashlytics.FirebaseCrashlytics
import com.vipulog.ebookreader.Book import com.vipulog.ebookreader.Book
import com.vipulog.ebookreader.EbookReaderEventListener import com.vipulog.ebookreader.EbookReaderEventListener
import com.vipulog.ebookreader.ReaderError import com.vipulog.ebookreader.ReaderError
@ -52,7 +53,10 @@ import com.vipulog.ebookreader.TocItem
import kotlinx.coroutines.Dispatchers import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.launch import kotlinx.coroutines.launch
import java.io.File import java.io.File
import java.io.FileInputStream
import java.io.FileOutputStream import java.io.FileOutputStream
import java.io.ObjectInputStream
import java.io.ObjectOutputStream
import java.util.* import java.util.*
import kotlin.math.min import kotlin.math.min
import kotlin.properties.Delegates import kotlin.properties.Delegates
@ -62,9 +66,6 @@ class NovelReaderActivity : AppCompatActivity(), EbookReaderEventListener {
private lateinit var binding: ActivityNovelReaderBinding private lateinit var binding: ActivityNovelReaderBinding
private val scope = lifecycleScope private val scope = lifecycleScope
lateinit var settings: ReaderSettings
private lateinit var uiSettings: UserInterfaceSettings
private var notchHeight: Int? = null private var notchHeight: Int? = null
var loaded = false var loaded = false
@ -77,6 +78,8 @@ class NovelReaderActivity : AppCompatActivity(), EbookReaderEventListener {
val themes = ArrayList<ReaderTheme>() val themes = ArrayList<ReaderTheme>()
var defaultSettings = CurrentNovelReaderSettings()
init { init {
val forestTheme = ReaderTheme( val forestTheme = ReaderTheme(
@ -174,12 +177,8 @@ class NovelReaderActivity : AppCompatActivity(), EbookReaderEventListener {
ThemeManager(this).applyTheme() ThemeManager(this).applyTheme()
binding = ActivityNovelReaderBinding.inflate(layoutInflater) binding = ActivityNovelReaderBinding.inflate(layoutInflater)
setContentView(binding.root) setContentView(binding.root)
settings = loadData("reader_settings", this)
?: ReaderSettings().apply { saveData("reader_settings", this) }
uiSettings = loadData("ui_settings", this)
?: UserInterfaceSettings().also { saveData("ui_settings", it) }
controllerDuration = (uiSettings.animationSpeed * 200).toLong() controllerDuration = (PrefManager.getVal<Float>(PrefName.AnimationSpeed) * 200).toLong()
setupViews() setupViews()
setupBackPressedHandler() setupBackPressedHandler()
@ -285,12 +284,11 @@ class NovelReaderActivity : AppCompatActivity(), EbookReaderEventListener {
binding.bookReader.getAppearance { binding.bookReader.getAppearance {
currentTheme = it currentTheme = it
themes.add(0, it) themes.add(0, it)
settings.defaultLN = defaultSettings = loadReaderSettings("${sanitizedBookId}_current_settings") ?: defaultSettings
loadData("${sanitizedBookId}_current_settings") ?: settings.defaultLN
applySettings() applySettings()
} }
val cfi = loadData<String>("${sanitizedBookId}_progress") val cfi = PrefManager.getCustomVal("${sanitizedBookId}_progress", null as String?)
cfi?.let { binding.bookReader.goto(it) } cfi?.let { binding.bookReader.goto(it) }
binding.progress.visibility = View.GONE binding.progress.visibility = View.GONE
@ -303,7 +301,7 @@ class NovelReaderActivity : AppCompatActivity(), EbookReaderEventListener {
binding.novelReaderSlider.value = info.fraction.toFloat() binding.novelReaderSlider.value = info.fraction.toFloat()
val pos = info.tocItem?.let { item -> toc.indexOfFirst { it == item } } val pos = info.tocItem?.let { item -> toc.indexOfFirst { it == item } }
if (pos != null) binding.novelReaderChapterSelect.setSelection(pos) if (pos != null) binding.novelReaderChapterSelect.setSelection(pos)
saveData("${sanitizedBookId}_progress", info.cfi) PrefManager.setCustomVal("${sanitizedBookId}_progress", info.cfi)
} }
@ -338,7 +336,7 @@ class NovelReaderActivity : AppCompatActivity(), EbookReaderEventListener {
return when (event.keyCode) { return when (event.keyCode) {
KeyEvent.KEYCODE_VOLUME_UP, KeyEvent.KEYCODE_DPAD_UP, KeyEvent.KEYCODE_PAGE_UP -> { KeyEvent.KEYCODE_VOLUME_UP, KeyEvent.KEYCODE_DPAD_UP, KeyEvent.KEYCODE_PAGE_UP -> {
if (event.keyCode == KeyEvent.KEYCODE_VOLUME_UP) if (event.keyCode == KeyEvent.KEYCODE_VOLUME_UP)
if (!settings.defaultLN.volumeButtons) if (!defaultSettings.volumeButtons)
return false return false
if (event.action == KeyEvent.ACTION_DOWN) { if (event.action == KeyEvent.ACTION_DOWN) {
onVolumeUp?.invoke() onVolumeUp?.invoke()
@ -348,7 +346,7 @@ class NovelReaderActivity : AppCompatActivity(), EbookReaderEventListener {
KeyEvent.KEYCODE_VOLUME_DOWN, KeyEvent.KEYCODE_DPAD_DOWN, KeyEvent.KEYCODE_PAGE_DOWN -> { KeyEvent.KEYCODE_VOLUME_DOWN, KeyEvent.KEYCODE_DPAD_DOWN, KeyEvent.KEYCODE_PAGE_DOWN -> {
if (event.keyCode == KeyEvent.KEYCODE_VOLUME_DOWN) if (event.keyCode == KeyEvent.KEYCODE_VOLUME_DOWN)
if (!settings.defaultLN.volumeButtons) if (!defaultSettings.volumeButtons)
return false return false
if (event.action == KeyEvent.ACTION_DOWN) { if (event.action == KeyEvent.ACTION_DOWN) {
onVolumeDown?.invoke() onVolumeDown?.invoke()
@ -364,18 +362,18 @@ class NovelReaderActivity : AppCompatActivity(), EbookReaderEventListener {
fun applySettings() { fun applySettings() {
saveData("${sanitizedBookId}_current_settings", settings.defaultLN) saveReaderSettings("${sanitizedBookId}_current_settings", defaultSettings)
hideBars() hideBars()
if (settings.defaultLN.useOledTheme) { if (defaultSettings.useOledTheme) {
themes.forEach { theme -> themes.forEach { theme ->
theme.darkBg = Color.parseColor("#000000") theme.darkBg = Color.parseColor("#000000")
} }
} }
currentTheme = currentTheme =
themes.first { it.name.equals(settings.defaultLN.currentThemeName, ignoreCase = true) } themes.first { it.name.equals(defaultSettings.currentThemeName, ignoreCase = true) }
when (settings.defaultLN.layout) { when (defaultSettings.layout) {
CurrentNovelReaderSettings.Layouts.PAGED -> { CurrentNovelReaderSettings.Layouts.PAGED -> {
currentTheme?.flow = ReaderFlow.PAGINATED currentTheme?.flow = ReaderFlow.PAGINATED
} }
@ -386,22 +384,22 @@ class NovelReaderActivity : AppCompatActivity(), EbookReaderEventListener {
} }
requestedOrientation = ActivityInfo.SCREEN_ORIENTATION_USER requestedOrientation = ActivityInfo.SCREEN_ORIENTATION_USER
when (settings.defaultLN.dualPageMode) { when (defaultSettings.dualPageMode) {
CurrentReaderSettings.DualPageModes.No -> currentTheme?.maxColumnCount = 1 CurrentReaderSettings.DualPageModes.No -> currentTheme?.maxColumnCount = 1
CurrentReaderSettings.DualPageModes.Automatic -> currentTheme?.maxColumnCount = 2 CurrentReaderSettings.DualPageModes.Automatic -> currentTheme?.maxColumnCount = 2
CurrentReaderSettings.DualPageModes.Force -> requestedOrientation = CurrentReaderSettings.DualPageModes.Force -> requestedOrientation =
ActivityInfo.SCREEN_ORIENTATION_LANDSCAPE ActivityInfo.SCREEN_ORIENTATION_LANDSCAPE
} }
currentTheme?.lineHeight = settings.defaultLN.lineHeight currentTheme?.lineHeight = defaultSettings.lineHeight
currentTheme?.gap = settings.defaultLN.margin currentTheme?.gap = defaultSettings.margin
currentTheme?.maxInlineSize = settings.defaultLN.maxInlineSize currentTheme?.maxInlineSize = defaultSettings.maxInlineSize
currentTheme?.maxBlockSize = settings.defaultLN.maxBlockSize currentTheme?.maxBlockSize = defaultSettings.maxBlockSize
currentTheme?.useDark = settings.defaultLN.useDarkTheme currentTheme?.useDark = defaultSettings.useDarkTheme
currentTheme?.let { binding.bookReader.setAppearance(it) } currentTheme?.let { binding.bookReader.setAppearance(it) }
if (settings.defaultLN.keepScreenOn) window.addFlags(WindowManager.LayoutParams.FLAG_KEEP_SCREEN_ON) if (defaultSettings.keepScreenOn) window.addFlags(WindowManager.LayoutParams.FLAG_KEEP_SCREEN_ON)
else window.clearFlags(WindowManager.LayoutParams.FLAG_KEEP_SCREEN_ON) else window.clearFlags(WindowManager.LayoutParams.FLAG_KEEP_SCREEN_ON)
} }
@ -431,7 +429,7 @@ class NovelReaderActivity : AppCompatActivity(), EbookReaderEventListener {
fun handleController(shouldShow: Boolean? = null) { fun handleController(shouldShow: Boolean? = null) {
if (!loaded) return if (!loaded) return
if (!settings.showSystemBars) { if (!PrefManager.getVal<Boolean>(PrefName.ShowSystemBars)) {
hideBars() hideBars()
applyNotchMargin() applyNotchMargin()
} }
@ -464,7 +462,7 @@ class NovelReaderActivity : AppCompatActivity(), EbookReaderEventListener {
private fun checkNotch() { private fun checkNotch() {
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.P && !settings.showSystemBars) { if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.P && !PrefManager.getVal<Boolean>(PrefName.ShowSystemBars)) {
val displayCutout = window.decorView.rootWindowInsets.displayCutout val displayCutout = window.decorView.rootWindowInsets.displayCutout
if (displayCutout != null) { if (displayCutout != null) {
if (displayCutout.boundingRects.size > 0) { if (displayCutout.boundingRects.size > 0) {
@ -485,8 +483,49 @@ class NovelReaderActivity : AppCompatActivity(), EbookReaderEventListener {
} }
} }
@Suppress("UNCHECKED_CAST")
private fun <T> loadReaderSettings(fileName: String, context: Context? = null, toast: Boolean = true): T? {
val a = context ?: currContext()
try {
if (a?.fileList() != null)
if (fileName in a.fileList()) {
val fileIS: FileInputStream = a.openFileInput(fileName)
val objIS = ObjectInputStream(fileIS)
val data = objIS.readObject() as T
objIS.close()
fileIS.close()
return data
}
} catch (e: Exception) {
if (toast) snackString(a?.getString(R.string.error_loading_data, fileName))
//try to delete the file
try {
a?.deleteFile(fileName)
} catch (e: Exception) {
FirebaseCrashlytics.getInstance().log("Failed to delete file $fileName")
FirebaseCrashlytics.getInstance().recordException(e)
}
e.printStackTrace()
}
return null
}
private fun saveReaderSettings(fileName: String, data: Any?, context: Context? = null) {
tryWith {
val a = context ?: currContext()
if (a != null) {
val fos: FileOutputStream = a.openFileOutput(fileName, Context.MODE_PRIVATE)
val os = ObjectOutputStream(fos)
os.writeObject(data)
os.close()
fos.close()
}
}
}
private fun hideBars() { private fun hideBars() {
if (!settings.showSystemBars) hideSystemBars() if (!PrefManager.getVal<Boolean>(PrefName.ShowSystemBars)) {
hideSystemBars()
}
} }
} }

View file

@ -30,7 +30,7 @@ class NovelReaderSettingsDialogFragment : BottomSheetDialogFragment() {
override fun onViewCreated(view: View, savedInstanceState: Bundle?) { override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
super.onViewCreated(view, savedInstanceState) super.onViewCreated(view, savedInstanceState)
val activity = requireActivity() as NovelReaderActivity val activity = requireActivity() as NovelReaderActivity
val settings = activity.settings.defaultLN val settings = activity.defaultSettings
val themeLabels = activity.themes.map { it.name } val themeLabels = activity.themes.map { it.name }
binding.themeSelect.adapter = binding.themeSelect.adapter =
NoPaddingArrayAdapter(activity, R.layout.item_dropdown, themeLabels) NoPaddingArrayAdapter(activity, R.layout.item_dropdown, themeLabels)

View file

@ -17,11 +17,9 @@ import androidx.lifecycle.lifecycleScope
import ani.dantotsu.R import ani.dantotsu.R
import ani.dantotsu.Refresh import ani.dantotsu.Refresh
import ani.dantotsu.databinding.ActivityListBinding import ani.dantotsu.databinding.ActivityListBinding
import ani.dantotsu.loadData
import ani.dantotsu.navBarHeight import ani.dantotsu.navBarHeight
import ani.dantotsu.settings.UserInterfaceSettings
import ani.dantotsu.settings.saving.PrefName import ani.dantotsu.settings.saving.PrefName
import ani.dantotsu.settings.saving.PrefWrapper import ani.dantotsu.settings.saving.PrefManager
import ani.dantotsu.statusBarHeight import ani.dantotsu.statusBarHeight
import ani.dantotsu.themes.ThemeManager import ani.dantotsu.themes.ThemeManager
import com.google.android.material.tabs.TabLayout import com.google.android.material.tabs.TabLayout
@ -66,8 +64,7 @@ class ListActivity : AppCompatActivity() {
binding.listTitle.setTextColor(primaryTextColor) binding.listTitle.setTextColor(primaryTextColor)
binding.listTabLayout.setTabTextColors(secondaryTextColor, primaryTextColor) binding.listTabLayout.setTabTextColors(secondaryTextColor, primaryTextColor)
binding.listTabLayout.setSelectedTabIndicatorColor(primaryTextColor) binding.listTabLayout.setSelectedTabIndicatorColor(primaryTextColor)
val uiSettings = loadData<UserInterfaceSettings>("ui_settings") ?: UserInterfaceSettings() if (!PrefManager.getVal<Boolean>(PrefName.ImmersiveMode)) {
if (!uiSettings.immersiveMode) {
this.window.statusBarColor = this.window.statusBarColor =
ContextCompat.getColor(this, R.color.nav_bg_inv) ContextCompat.getColor(this, R.color.nav_bg_inv)
binding.root.fitsSystemWindows = true binding.root.fitsSystemWindows = true
@ -153,7 +150,7 @@ class ListActivity : AppCompatActivity() {
R.id.release -> "release" R.id.release -> "release"
else -> null else -> null
} }
PrefWrapper.setVal( PrefManager.setVal(
if (anime) PrefName.AnimeListSortOrder else PrefName.MangaListSortOrder, if (anime) PrefName.AnimeListSortOrder else PrefName.MangaListSortOrder,
sort ?: "" sort ?: ""
) )

View file

@ -4,12 +4,13 @@ import androidx.lifecycle.LiveData
import androidx.lifecycle.MutableLiveData import androidx.lifecycle.MutableLiveData
import androidx.lifecycle.ViewModel import androidx.lifecycle.ViewModel
import ani.dantotsu.connections.anilist.Anilist import ani.dantotsu.connections.anilist.Anilist
import ani.dantotsu.loadData
import ani.dantotsu.media.Media import ani.dantotsu.media.Media
import ani.dantotsu.settings.saving.PrefName
import ani.dantotsu.settings.saving.PrefManager
import ani.dantotsu.tryWithSuspend import ani.dantotsu.tryWithSuspend
class ListViewModel : ViewModel() { class ListViewModel : ViewModel() {
var grid = MutableLiveData(loadData<Boolean>("listGrid") ?: true) var grid = MutableLiveData(PrefManager.getVal<Boolean>(PrefName.ListGrid))
private val lists = MutableLiveData<MutableMap<String, ArrayList<Media>>>() private val lists = MutableLiveData<MutableMap<String, ArrayList<Media>>>()
fun getLists(): LiveData<MutableMap<String, ArrayList<Media>>> = lists fun getLists(): LiveData<MutableMap<String, ArrayList<Media>>> = lists

View file

@ -1,6 +1,5 @@
package ani.dantotsu.offline package ani.dantotsu.offline
import android.content.Context
import android.os.Bundle import android.os.Bundle
import android.view.LayoutInflater import android.view.LayoutInflater
import android.view.View import android.view.View
@ -12,7 +11,7 @@ import ani.dantotsu.databinding.FragmentOfflineBinding
import ani.dantotsu.isOnline import ani.dantotsu.isOnline
import ani.dantotsu.navBarHeight import ani.dantotsu.navBarHeight
import ani.dantotsu.settings.saving.PrefName import ani.dantotsu.settings.saving.PrefName
import ani.dantotsu.settings.saving.PrefWrapper import ani.dantotsu.settings.saving.PrefManager
import ani.dantotsu.startMainActivity import ani.dantotsu.startMainActivity
import ani.dantotsu.statusBarHeight import ani.dantotsu.statusBarHeight
@ -28,7 +27,7 @@ class OfflineFragment : Fragment() {
topMargin = statusBarHeight topMargin = statusBarHeight
bottomMargin = navBarHeight bottomMargin = navBarHeight
} }
offline = PrefWrapper.getVal(PrefName.OfflineMode, false) offline = PrefManager.getVal(PrefName.OfflineMode)
binding.noInternet.text = binding.noInternet.text =
if (offline) "Offline Mode" else getString(R.string.no_internet) if (offline) "Offline Mode" else getString(R.string.no_internet)
binding.refreshButton.visibility = if (offline) View.GONE else View.VISIBLE binding.refreshButton.visibility = if (offline) View.GONE else View.VISIBLE
@ -42,6 +41,6 @@ class OfflineFragment : Fragment() {
override fun onResume() { override fun onResume() {
super.onResume() super.onResume()
offline = PrefWrapper.getVal(PrefName.OfflineMode, false) offline = PrefManager.getVal(PrefName.OfflineMode)
} }
} }

View file

@ -15,6 +15,7 @@ import androidx.core.content.FileProvider
import androidx.core.content.getSystemService import androidx.core.content.getSystemService
import androidx.fragment.app.FragmentActivity import androidx.fragment.app.FragmentActivity
import ani.dantotsu.* import ani.dantotsu.*
import ani.dantotsu.settings.saving.PrefManager
import io.noties.markwon.Markwon import io.noties.markwon.Markwon
import io.noties.markwon.SoftBreakAddsNewLinePlugin import io.noties.markwon.SoftBreakAddsNewLinePlugin
import kotlinx.coroutines.Dispatchers import kotlinx.coroutines.Dispatchers
@ -50,7 +51,7 @@ object AppUpdater {
} }
logger("Git Version : $version") logger("Git Version : $version")
val dontShow = loadData("dont_ask_for_update_$version") ?: false val dontShow = PrefManager.getCustomVal("dont_ask_for_update_$version", false)
if (compareVersion(version) && !dontShow && !activity.isDestroyed) activity.runOnUiThread { if (compareVersion(version) && !dontShow && !activity.isDestroyed) activity.runOnUiThread {
CustomBottomDialog.newInstance().apply { CustomBottomDialog.newInstance().apply {
setTitleText( setTitleText(
@ -71,7 +72,7 @@ object AppUpdater {
false false
) { isChecked -> ) { isChecked ->
if (isChecked) { if (isChecked) {
saveData("dont_ask_for_update_$version", true) PrefManager.setCustomVal("dont_ask_for_update_$version", true)
} }
} }
setPositiveButton(currContext()!!.getString(R.string.lets_go)) { setPositiveButton(currContext()!!.getString(R.string.lets_go)) {

View file

@ -14,11 +14,10 @@ import ani.dantotsu.FileUrl
import ani.dantotsu.R import ani.dantotsu.R
import ani.dantotsu.currContext import ani.dantotsu.currContext
import ani.dantotsu.defaultHeaders import ani.dantotsu.defaultHeaders
import ani.dantotsu.loadData
import ani.dantotsu.media.anime.Episode import ani.dantotsu.media.anime.Episode
import ani.dantotsu.parsers.Book import ani.dantotsu.parsers.Book
import ani.dantotsu.settings.saving.PrefName import ani.dantotsu.settings.saving.PrefName
import ani.dantotsu.settings.saving.PrefWrapper import ani.dantotsu.settings.saving.PrefManager
import ani.dantotsu.toast import ani.dantotsu.toast
import kotlinx.coroutines.CoroutineScope import kotlinx.coroutines.CoroutineScope
import kotlinx.coroutines.Dispatchers import kotlinx.coroutines.Dispatchers
@ -38,7 +37,7 @@ object Download {
private fun getDownloadDir(context: Context): File { private fun getDownloadDir(context: Context): File {
val direct: File val direct: File
if (PrefWrapper.getVal(PrefName.SdDl, false)) { if (PrefManager.getVal(PrefName.SdDl)) {
val arrayOfFiles = ContextCompat.getExternalFilesDirs(context, null) val arrayOfFiles = ContextCompat.getExternalFilesDirs(context, null)
val parentDirectory = arrayOfFiles[1].toString() val parentDirectory = arrayOfFiles[1].toString()
direct = File(parentDirectory) direct = File(parentDirectory)
@ -94,7 +93,7 @@ object Download {
if (!file.url.startsWith("http")) if (!file.url.startsWith("http"))
toast(context.getString(R.string.invalid_url)) toast(context.getString(R.string.invalid_url))
else else
when (PrefWrapper.getVal(PrefName.DownloadManager, 0)) { when (PrefManager.getVal(PrefName.DownloadManager) as Int) {
1 -> oneDM(context, file, notif ?: fileName) 1 -> oneDM(context, file, notif ?: fileName)
2 -> adm(context, file, fileName, folder) 2 -> adm(context, file, fileName, folder)
else -> defaultDownload(context, file, fileName, folder, notif ?: fileName) else -> defaultDownload(context, file, fileName, folder, notif ?: fileName)
@ -119,7 +118,7 @@ object Download {
request.setNotificationVisibility(DownloadManager.Request.VISIBILITY_VISIBLE_NOTIFY_COMPLETED) request.setNotificationVisibility(DownloadManager.Request.VISIBILITY_VISIBLE_NOTIFY_COMPLETED)
val arrayOfFiles = ContextCompat.getExternalFilesDirs(context, null) val arrayOfFiles = ContextCompat.getExternalFilesDirs(context, null)
if (PrefWrapper.getVal(PrefName.SdDl, false) && arrayOfFiles.size > 1 && arrayOfFiles[0] != null && arrayOfFiles[1] != null) { if (PrefManager.getVal(PrefName.SdDl) && arrayOfFiles.size > 1 && arrayOfFiles[0] != null && arrayOfFiles[1] != null) {
val parentDirectory = arrayOfFiles[1].toString() + folder val parentDirectory = arrayOfFiles[1].toString() + folder
val direct = File(parentDirectory) val direct = File(parentDirectory)
if (!direct.exists()) direct.mkdirs() if (!direct.exists()) direct.mkdirs()

View file

@ -5,9 +5,8 @@ import ani.dantotsu.FileUrl
import ani.dantotsu.R import ani.dantotsu.R
import ani.dantotsu.asyncMap import ani.dantotsu.asyncMap
import ani.dantotsu.currContext import ani.dantotsu.currContext
import ani.dantotsu.loadData
import ani.dantotsu.others.MalSyncBackup import ani.dantotsu.others.MalSyncBackup
import ani.dantotsu.saveData import ani.dantotsu.settings.saving.PrefManager
import ani.dantotsu.tryWithSuspend import ani.dantotsu.tryWithSuspend
import eu.kanade.tachiyomi.animesource.model.SAnime import eu.kanade.tachiyomi.animesource.model.SAnime
import eu.kanade.tachiyomi.animesource.model.SEpisode import eu.kanade.tachiyomi.animesource.model.SEpisode
@ -182,7 +181,7 @@ abstract class AnimeParser : BaseParser() {
override suspend fun loadSavedShowResponse(mediaId: Int): ShowResponse? { override suspend fun loadSavedShowResponse(mediaId: Int): ShowResponse? {
checkIfVariablesAreEmpty() checkIfVariablesAreEmpty()
val dub = if (isDubAvailableSeparately()) "_${if (selectDub) "dub" else "sub"}" else "" val dub = if (isDubAvailableSeparately()) "_${if (selectDub) "dub" else "sub"}" else ""
var loaded = loadData<ShowResponse>("${saveName}${dub}_$mediaId") var loaded = PrefManager.getNullableCustomVal<ShowResponse?>("${saveName}${dub}_$mediaId", null)
if (loaded == null && malSyncBackupName.isNotEmpty()) if (loaded == null && malSyncBackupName.isNotEmpty())
loaded = MalSyncBackup.get(mediaId, malSyncBackupName, selectDub) loaded = MalSyncBackup.get(mediaId, malSyncBackupName, selectDub)
?.also { saveShowResponse(mediaId, it, true) } ?.also { saveShowResponse(mediaId, it, true) }
@ -200,7 +199,7 @@ abstract class AnimeParser : BaseParser() {
} : ${response.name}" } : ${response.name}"
) )
val dub = if (isDubAvailableSeparately()) "_${if (selectDub) "dub" else "sub"}" else "" val dub = if (isDubAvailableSeparately()) "_${if (selectDub) "dub" else "sub"}" else ""
saveData("${saveName}${dub}_$mediaId", response) PrefManager.setCustomVal("${saveName}${dub}_$mediaId", response)
} }
} }
} }

View file

@ -4,7 +4,7 @@ import android.content.Context
import ani.dantotsu.Lazier import ani.dantotsu.Lazier
import ani.dantotsu.lazyList import ani.dantotsu.lazyList
import ani.dantotsu.settings.saving.PrefName import ani.dantotsu.settings.saving.PrefName
import ani.dantotsu.settings.saving.PrefWrapper import ani.dantotsu.settings.saving.PrefManager
import eu.kanade.tachiyomi.extension.anime.model.AnimeExtension import eu.kanade.tachiyomi.extension.anime.model.AnimeExtension
import kotlinx.coroutines.flow.StateFlow import kotlinx.coroutines.flow.StateFlow
import kotlinx.coroutines.flow.first import kotlinx.coroutines.flow.first
@ -14,7 +14,7 @@ object AnimeSources : WatchSources() {
var pinnedAnimeSources: Set<String> = emptySet() var pinnedAnimeSources: Set<String> = emptySet()
suspend fun init(fromExtensions: StateFlow<List<AnimeExtension.Installed>>, context: Context) { suspend fun init(fromExtensions: StateFlow<List<AnimeExtension.Installed>>, context: Context) {
pinnedAnimeSources = PrefWrapper.getVal(PrefName.PinnedAnimeSources, emptySet()) pinnedAnimeSources = PrefManager.getVal(PrefName.PinnedAnimeSources)
// Initialize with the first value from StateFlow // Initialize with the first value from StateFlow
val initialExtensions = fromExtensions.first() val initialExtensions = fromExtensions.first()

View file

@ -3,10 +3,9 @@ package ani.dantotsu.parsers
import ani.dantotsu.FileUrl import ani.dantotsu.FileUrl
import ani.dantotsu.R import ani.dantotsu.R
import ani.dantotsu.currContext import ani.dantotsu.currContext
import ani.dantotsu.loadData
import ani.dantotsu.logger import ani.dantotsu.logger
import ani.dantotsu.media.Media import ani.dantotsu.media.Media
import ani.dantotsu.saveData import ani.dantotsu.settings.saving.PrefManager
import eu.kanade.tachiyomi.animesource.model.SAnime import eu.kanade.tachiyomi.animesource.model.SAnime
import eu.kanade.tachiyomi.source.model.SManga import eu.kanade.tachiyomi.source.model.SManga
import me.xdrop.fuzzywuzzy.FuzzySearch import me.xdrop.fuzzywuzzy.FuzzySearch
@ -135,7 +134,7 @@ abstract class BaseParser {
* **/ * **/
open suspend fun loadSavedShowResponse(mediaId: Int): ShowResponse? { open suspend fun loadSavedShowResponse(mediaId: Int): ShowResponse? {
checkIfVariablesAreEmpty() checkIfVariablesAreEmpty()
return loadData("${saveName}_$mediaId") return PrefManager.getNullableCustomVal<ShowResponse?>("${saveName}_$mediaId", null)
} }
/** /**
@ -151,7 +150,7 @@ abstract class BaseParser {
) )
} : ${response.name}" } : ${response.name}"
) )
saveData("${saveName}_$mediaId", response) PrefManager.setCustomVal("${saveName}_$mediaId", response)
} }
} }

View file

@ -1,10 +1,9 @@
package ani.dantotsu.parsers package ani.dantotsu.parsers
import android.content.Context
import ani.dantotsu.Lazier import ani.dantotsu.Lazier
import ani.dantotsu.lazyList import ani.dantotsu.lazyList
import ani.dantotsu.settings.saving.PrefName import ani.dantotsu.settings.saving.PrefName
import ani.dantotsu.settings.saving.PrefWrapper import ani.dantotsu.settings.saving.PrefManager
import eu.kanade.tachiyomi.extension.manga.model.MangaExtension import eu.kanade.tachiyomi.extension.manga.model.MangaExtension
import kotlinx.coroutines.flow.StateFlow import kotlinx.coroutines.flow.StateFlow
import kotlinx.coroutines.flow.first import kotlinx.coroutines.flow.first
@ -14,7 +13,7 @@ object MangaSources : MangaReadSources() {
var pinnedMangaSources: Set<String> = emptySet() var pinnedMangaSources: Set<String> = emptySet()
suspend fun init(fromExtensions: StateFlow<List<MangaExtension.Installed>>) { suspend fun init(fromExtensions: StateFlow<List<MangaExtension.Installed>>) {
pinnedMangaSources = PrefWrapper.getVal(PrefName.PinnedMangaSources, emptySet()) pinnedMangaSources = PrefManager.getVal(PrefName.PinnedMangaSources)
// Initialize with the first value from StateFlow // Initialize with the first value from StateFlow
val initialExtensions = fromExtensions.first() val initialExtensions = fromExtensions.first()

View file

@ -2,10 +2,9 @@ package ani.dantotsu.parsers.novel
import android.content.Context import android.content.Context
import ani.dantotsu.currContext
import ani.dantotsu.logger import ani.dantotsu.logger
import ani.dantotsu.settings.saving.PrefName import ani.dantotsu.settings.saving.PrefName
import ani.dantotsu.settings.saving.PrefWrapper import ani.dantotsu.settings.saving.PrefManager
import eu.kanade.tachiyomi.extension.ExtensionUpdateNotifier import eu.kanade.tachiyomi.extension.ExtensionUpdateNotifier
import eu.kanade.tachiyomi.extension.anime.model.AnimeExtension import eu.kanade.tachiyomi.extension.anime.model.AnimeExtension
import eu.kanade.tachiyomi.extension.anime.model.AnimeLoadResult import eu.kanade.tachiyomi.extension.anime.model.AnimeLoadResult
@ -28,7 +27,7 @@ class NovelExtensionGithubApi {
private val novelExtensionManager: NovelExtensionManager by injectLazy() private val novelExtensionManager: NovelExtensionManager by injectLazy()
private val json: Json by injectLazy() private val json: Json by injectLazy()
private val lastExtCheck: Long = PrefWrapper.getVal(PrefName.NovelLastExtCheck, 0L) private val lastExtCheck: Long = PrefManager.getVal(PrefName.NovelLastExtCheck)
private var requiresFallbackSource = false private var requiresFallbackSource = false
@ -86,7 +85,7 @@ class NovelExtensionGithubApi {
novelExtensionManager.availableExtensionsFlow.value novelExtensionManager.availableExtensionsFlow.value
} else { } else {
findExtensions().also { findExtensions().also {
PrefWrapper.setVal(PrefName.NovelLastExtCheck, Date().time) PrefManager.setVal(PrefName.NovelLastExtCheck, Date().time)
} }
} }

View file

@ -1,23 +1,27 @@
package ani.dantotsu.settings package ani.dantotsu.settings
import ani.dantotsu.settings.saving.PrefName
import ani.dantotsu.settings.saving.PrefManager
import java.io.Serializable import java.io.Serializable
data class CurrentNovelReaderSettings( data class CurrentNovelReaderSettings(
var currentThemeName: String = "Default", var currentThemeName: String = PrefManager.getVal(PrefName.CurrentThemeName),
var layout: Layouts = Layouts.PAGED, var layout: Layouts = Layouts[PrefManager.getVal(PrefName.LayoutNovel)]
var dualPageMode: CurrentReaderSettings.DualPageModes = CurrentReaderSettings.DualPageModes.Automatic, ?: Layouts.PAGED,
var lineHeight: Float = 1.4f, var dualPageMode: CurrentReaderSettings.DualPageModes = CurrentReaderSettings.DualPageModes[PrefManager.getVal(PrefName.DualPageModeNovel)]
var margin: Float = 0.06f, ?: CurrentReaderSettings.DualPageModes.Automatic,
var justify: Boolean = true, var lineHeight: Float = PrefManager.getVal(PrefName.LineHeight),
var hyphenation: Boolean = true, var margin: Float = PrefManager.getVal(PrefName.Margin),
var useDarkTheme: Boolean = false, var justify: Boolean = PrefManager.getVal(PrefName.Justify),
var useOledTheme: Boolean = false, var hyphenation: Boolean = PrefManager.getVal(PrefName.Hyphenation),
var invert: Boolean = false, var useDarkTheme: Boolean = PrefManager.getVal(PrefName.UseDarkThemeNovel),
var maxInlineSize: Int = 720, var useOledTheme: Boolean = PrefManager.getVal(PrefName.UseOledThemeNovel),
var maxBlockSize: Int = 1440, var invert: Boolean = PrefManager.getVal(PrefName.Invert),
var horizontalScrollBar: Boolean = true, var maxInlineSize: Int = PrefManager.getVal(PrefName.MaxInlineSize),
var keepScreenOn: Boolean = false, var maxBlockSize: Int = PrefManager.getVal(PrefName.MaxBlockSize),
var volumeButtons: Boolean = false, var horizontalScrollBar: Boolean = PrefManager.getVal(PrefName.HorizontalScrollBarNovel),
var keepScreenOn: Boolean = PrefManager.getVal(PrefName.KeepScreenOnNovel),
var volumeButtons: Boolean = PrefManager.getVal(PrefName.VolumeButtonsNovel)
) : Serializable { ) : Serializable {
enum class Layouts(val string: String) { enum class Layouts(val string: String) {

View file

@ -1,23 +1,28 @@
package ani.dantotsu.settings package ani.dantotsu.settings
import ani.dantotsu.settings.saving.PrefName
import ani.dantotsu.settings.saving.PrefManager
import java.io.Serializable import java.io.Serializable
data class CurrentReaderSettings( data class CurrentReaderSettings(
var direction: Directions = Directions.TOP_TO_BOTTOM, var direction: Directions = Directions[PrefManager.getVal(PrefName.Direction)]
var layout: Layouts = Layouts.CONTINUOUS, ?: Directions.TOP_TO_BOTTOM,
var dualPageMode: DualPageModes = DualPageModes.Automatic, var layout: Layouts = Layouts[PrefManager.getVal(PrefName.LayoutReader)]
var overScrollMode: Boolean = true, ?: Layouts.CONTINUOUS,
var trueColors: Boolean = false, var dualPageMode: DualPageModes = DualPageModes[PrefManager.getVal(PrefName.DualPageModeReader)]
var rotation: Boolean = true, ?: DualPageModes.Automatic,
var padding: Boolean = true, var overScrollMode: Boolean = PrefManager.getVal(PrefName.OverScrollMode),
var hidePageNumbers: Boolean = false, var trueColors: Boolean = PrefManager.getVal(PrefName.TrueColors),
var horizontalScrollBar: Boolean = true, var rotation: Boolean = PrefManager.getVal(PrefName.Rotation),
var keepScreenOn: Boolean = false, var padding: Boolean = PrefManager.getVal(PrefName.Padding),
var volumeButtons: Boolean = false, var hidePageNumbers: Boolean = PrefManager.getVal(PrefName.HidePageNumbers),
var wrapImages: Boolean = false, var horizontalScrollBar: Boolean = PrefManager.getVal(PrefName.HorizontalScrollBar),
var longClickImage: Boolean = true, var keepScreenOn: Boolean = PrefManager.getVal(PrefName.KeepScreenOn),
var cropBorders: Boolean = false, var volumeButtons: Boolean = PrefManager.getVal(PrefName.VolumeButtonsReader),
var cropBorderThreshold: Int = 10, var wrapImages: Boolean = PrefManager.getVal(PrefName.WrapImages),
var longClickImage: Boolean = PrefManager.getVal(PrefName.LongClickImage),
var cropBorders: Boolean = PrefManager.getVal(PrefName.CropBorders),
var cropBorderThreshold: Int = PrefManager.getVal(PrefName.CropBorderThreshold)
) : Serializable { ) : Serializable {
enum class Directions { enum class Directions {

View file

@ -4,15 +4,12 @@ import android.view.LayoutInflater
import android.view.ViewGroup import android.view.ViewGroup
import androidx.recyclerview.widget.RecyclerView import androidx.recyclerview.widget.RecyclerView
import ani.dantotsu.databinding.ItemDeveloperBinding import ani.dantotsu.databinding.ItemDeveloperBinding
import ani.dantotsu.loadData
import ani.dantotsu.loadImage import ani.dantotsu.loadImage
import ani.dantotsu.openLinkInBrowser import ani.dantotsu.openLinkInBrowser
import ani.dantotsu.setAnimation import ani.dantotsu.setAnimation
class DevelopersAdapter(private val developers: Array<Developer>) : class DevelopersAdapter(private val developers: Array<Developer>) :
RecyclerView.Adapter<DevelopersAdapter.DeveloperViewHolder>() { RecyclerView.Adapter<DevelopersAdapter.DeveloperViewHolder>() {
private val uiSettings =
loadData<UserInterfaceSettings>("ui_settings") ?: UserInterfaceSettings()
inner class DeveloperViewHolder(val binding: ItemDeveloperBinding) : inner class DeveloperViewHolder(val binding: ItemDeveloperBinding) :
RecyclerView.ViewHolder(binding.root) { RecyclerView.ViewHolder(binding.root) {
@ -35,7 +32,7 @@ class DevelopersAdapter(private val developers: Array<Developer>) :
override fun onBindViewHolder(holder: DeveloperViewHolder, position: Int) { override fun onBindViewHolder(holder: DeveloperViewHolder, position: Int) {
val b = holder.binding val b = holder.binding
setAnimation(b.root.context, b.root, uiSettings) setAnimation(b.root.context, b.root)
val dev = developers[position] val dev = developers[position]
b.devName.text = dev.name b.devName.text = dev.name
b.devProfile.loadImage(dev.pfp) b.devProfile.loadImage(dev.pfp)

View file

@ -18,7 +18,7 @@ import ani.dantotsu.*
import ani.dantotsu.databinding.ActivityExtensionsBinding import ani.dantotsu.databinding.ActivityExtensionsBinding
import ani.dantotsu.others.LanguageMapper import ani.dantotsu.others.LanguageMapper
import ani.dantotsu.settings.saving.PrefName import ani.dantotsu.settings.saving.PrefName
import ani.dantotsu.settings.saving.PrefWrapper import ani.dantotsu.settings.saving.PrefManager
import ani.dantotsu.themes.ThemeManager import ani.dantotsu.themes.ThemeManager
import com.google.android.material.tabs.TabLayout import com.google.android.material.tabs.TabLayout
import com.google.android.material.tabs.TabLayoutMediator import com.google.android.material.tabs.TabLayoutMediator
@ -118,11 +118,11 @@ class ExtensionsActivity : AppCompatActivity() {
binding.languageselect.setOnClickListener { 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 builder = AlertDialog.Builder(currContext(), R.style.MyPopup)
val listOrder = PrefWrapper.getVal(PrefName.LangSort,"all") 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.setTitle("Language")
builder.setSingleChoiceItems(languageOptions, index){ dialog, i -> builder.setSingleChoiceItems(languageOptions, index){ dialog, i ->
PrefWrapper.setVal(PrefName.LangSort, LanguageMapper.Companion.Language.entries[i].code) PrefManager.setVal(PrefName.LangSort, LanguageMapper.Companion.Language.entries[i].code)
dialog.dismiss() dialog.dismiss()
} }
val dialog = builder.show() val dialog = builder.show()

View file

@ -6,7 +6,6 @@ import android.widget.TextView
import androidx.fragment.app.FragmentManager import androidx.fragment.app.FragmentManager
import androidx.recyclerview.widget.RecyclerView import androidx.recyclerview.widget.RecyclerView
import ani.dantotsu.databinding.ItemQuestionBinding import ani.dantotsu.databinding.ItemQuestionBinding
import ani.dantotsu.loadData
import ani.dantotsu.others.CustomBottomDialog import ani.dantotsu.others.CustomBottomDialog
import ani.dantotsu.setAnimation import ani.dantotsu.setAnimation
import io.noties.markwon.Markwon import io.noties.markwon.Markwon
@ -17,8 +16,6 @@ class FAQAdapter(
private val manager: FragmentManager private val manager: FragmentManager
) : ) :
RecyclerView.Adapter<FAQAdapter.FAQViewHolder>() { RecyclerView.Adapter<FAQAdapter.FAQViewHolder>() {
private val uiSettings =
loadData<UserInterfaceSettings>("ui_settings") ?: UserInterfaceSettings()
inner class FAQViewHolder(val binding: ItemQuestionBinding) : inner class FAQViewHolder(val binding: ItemQuestionBinding) :
RecyclerView.ViewHolder(binding.root) RecyclerView.ViewHolder(binding.root)
@ -35,7 +32,7 @@ class FAQAdapter(
override fun onBindViewHolder(holder: FAQViewHolder, position: Int) { override fun onBindViewHolder(holder: FAQViewHolder, position: Int) {
val b = holder.binding.root val b = holder.binding.root
setAnimation(b.context, b, uiSettings) setAnimation(b.context, b)
val faq = questions[position] val faq = questions[position]
b.text = faq.second b.text = faq.second
b.setCompoundDrawablesWithIntrinsicBounds(faq.first, 0, 0, 0) b.setCompoundDrawablesWithIntrinsicBounds(faq.first, 0, 0, 0)

View file

@ -23,11 +23,10 @@ import androidx.recyclerview.widget.RecyclerView
import androidx.viewpager2.widget.ViewPager2 import androidx.viewpager2.widget.ViewPager2
import ani.dantotsu.R import ani.dantotsu.R
import ani.dantotsu.databinding.FragmentAnimeExtensionsBinding import ani.dantotsu.databinding.FragmentAnimeExtensionsBinding
import ani.dantotsu.loadData
import ani.dantotsu.others.LanguageMapper import ani.dantotsu.others.LanguageMapper
import ani.dantotsu.settings.extensionprefs.AnimeSourcePreferencesFragment import ani.dantotsu.settings.extensionprefs.AnimeSourcePreferencesFragment
import ani.dantotsu.settings.saving.PrefName import ani.dantotsu.settings.saving.PrefName
import ani.dantotsu.settings.saving.PrefWrapper import ani.dantotsu.settings.saving.PrefManager
import ani.dantotsu.snackString import ani.dantotsu.snackString
import com.google.android.material.tabs.TabLayout import com.google.android.material.tabs.TabLayout
import com.google.android.material.textfield.TextInputLayout import com.google.android.material.textfield.TextInputLayout
@ -48,7 +47,7 @@ class InstalledAnimeExtensionsFragment : Fragment(), SearchQueryHandler {
private var _binding: FragmentAnimeExtensionsBinding? = null private var _binding: FragmentAnimeExtensionsBinding? = null
private val binding get() = _binding!! private val binding get() = _binding!!
private lateinit var extensionsRecyclerView: RecyclerView private lateinit var extensionsRecyclerView: RecyclerView
private val skipIcons = PrefWrapper.getVal(PrefName.SkipExtensionIcons, false) private val skipIcons: Boolean = PrefManager.getVal(PrefName.SkipExtensionIcons)
private val animeExtensionManager: AnimeExtensionManager = Injekt.get() private val animeExtensionManager: AnimeExtensionManager = Injekt.get()
private val extensionsAdapter = AnimeExtensionsAdapter( private val extensionsAdapter = AnimeExtensionsAdapter(
{ pkg -> { pkg ->

View file

@ -24,11 +24,10 @@ import androidx.recyclerview.widget.RecyclerView
import androidx.viewpager2.widget.ViewPager2 import androidx.viewpager2.widget.ViewPager2
import ani.dantotsu.R import ani.dantotsu.R
import ani.dantotsu.databinding.FragmentMangaExtensionsBinding import ani.dantotsu.databinding.FragmentMangaExtensionsBinding
import ani.dantotsu.loadData
import ani.dantotsu.others.LanguageMapper import ani.dantotsu.others.LanguageMapper
import ani.dantotsu.settings.extensionprefs.MangaSourcePreferencesFragment import ani.dantotsu.settings.extensionprefs.MangaSourcePreferencesFragment
import ani.dantotsu.settings.saving.PrefName import ani.dantotsu.settings.saving.PrefName
import ani.dantotsu.settings.saving.PrefWrapper import ani.dantotsu.settings.saving.PrefManager
import ani.dantotsu.snackString import ani.dantotsu.snackString
import com.google.android.material.tabs.TabLayout import com.google.android.material.tabs.TabLayout
import com.google.android.material.textfield.TextInputLayout import com.google.android.material.textfield.TextInputLayout
@ -47,7 +46,7 @@ class InstalledMangaExtensionsFragment : Fragment(), SearchQueryHandler {
private var _binding: FragmentMangaExtensionsBinding? = null private var _binding: FragmentMangaExtensionsBinding? = null
private val binding get() = _binding!! private val binding get() = _binding!!
private lateinit var extensionsRecyclerView: RecyclerView private lateinit var extensionsRecyclerView: RecyclerView
private val skipIcons = PrefWrapper.getVal(PrefName.SkipExtensionIcons, false) private val skipIcons: Boolean = PrefManager.getVal(PrefName.SkipExtensionIcons)
private val mangaExtensionManager: MangaExtensionManager = Injekt.get() private val mangaExtensionManager: MangaExtensionManager = Injekt.get()
private val extensionsAdapter = MangaExtensionsAdapter( private val extensionsAdapter = MangaExtensionsAdapter(
{ pkg -> { pkg ->

View file

@ -20,12 +20,11 @@ import androidx.recyclerview.widget.RecyclerView
import ani.dantotsu.R import ani.dantotsu.R
import ani.dantotsu.currContext import ani.dantotsu.currContext
import ani.dantotsu.databinding.FragmentNovelExtensionsBinding import ani.dantotsu.databinding.FragmentNovelExtensionsBinding
import ani.dantotsu.loadData
import ani.dantotsu.others.LanguageMapper import ani.dantotsu.others.LanguageMapper
import ani.dantotsu.parsers.novel.NovelExtension import ani.dantotsu.parsers.novel.NovelExtension
import ani.dantotsu.parsers.novel.NovelExtensionManager import ani.dantotsu.parsers.novel.NovelExtensionManager
import ani.dantotsu.settings.saving.PrefName import ani.dantotsu.settings.saving.PrefName
import ani.dantotsu.settings.saving.PrefWrapper import ani.dantotsu.settings.saving.PrefManager
import ani.dantotsu.snackString import ani.dantotsu.snackString
import com.google.firebase.crashlytics.FirebaseCrashlytics import com.google.firebase.crashlytics.FirebaseCrashlytics
import eu.kanade.tachiyomi.data.notification.Notifications import eu.kanade.tachiyomi.data.notification.Notifications
@ -39,7 +38,7 @@ class InstalledNovelExtensionsFragment : Fragment(), SearchQueryHandler {
private var _binding: FragmentNovelExtensionsBinding? = null private var _binding: FragmentNovelExtensionsBinding? = null
private val binding get() = _binding!! private val binding get() = _binding!!
private lateinit var extensionsRecyclerView: RecyclerView private lateinit var extensionsRecyclerView: RecyclerView
val skipIcons = PrefWrapper.getVal(PrefName.SkipExtensionIcons, false) private val skipIcons: Boolean = PrefManager.getVal(PrefName.SkipExtensionIcons)
private val novelExtensionManager: NovelExtensionManager = Injekt.get() private val novelExtensionManager: NovelExtensionManager = Injekt.get()
private val extensionsAdapter = NovelExtensionsAdapter( private val extensionsAdapter = NovelExtensionsAdapter(
{ pkg -> { pkg ->

View file

@ -1,48 +0,0 @@
package ani.dantotsu.settings
import java.io.Serializable
data class PlayerSettings(
var defaultSpeed: Int = 5,
var cursedSpeeds: Boolean = false,
var resize: Int = 0,
//Subtitles
var subtitles: Boolean = true,
var primaryColor: Int = 4,
var secondaryColor: Int = 0,
var outline: Int = 0,
var subBackground: Int = 0,
var subWindow: Int = 0,
var font: Int = 0,
var fontSize: Int = 20,
var locale: Int = 2,
//TimeStamps
var timeStampsEnabled: Boolean = true,
var useProxyForTimeStamps: Boolean = false,
var showTimeStampButton: Boolean = true,
//Auto
var autoSkipOPED: Boolean = false,
var autoPlay: Boolean = true,
var autoSkipFiller: Boolean = false,
//Update Progress
var askIndividual: Boolean = true,
var updateForH: Boolean = false,
var watchPercentage: Float = 0.8f,
//Behaviour
var alwaysContinue: Boolean = true,
var focusPause: Boolean = true,
var gestures: Boolean = true,
var doubleTap: Boolean = true,
var fastforward: Boolean = true,
var seekTime: Int = 10,
var skipTime: Int = 85,
//Other
var cast: Boolean = true,
var pip: Boolean = true
) : Serializable

View file

@ -14,12 +14,12 @@ import androidx.core.widget.addTextChangedListener
import ani.dantotsu.R import ani.dantotsu.R
import ani.dantotsu.databinding.ActivityPlayerSettingsBinding import ani.dantotsu.databinding.ActivityPlayerSettingsBinding
import ani.dantotsu.initActivity import ani.dantotsu.initActivity
import ani.dantotsu.loadData
import ani.dantotsu.media.Media import ani.dantotsu.media.Media
import ani.dantotsu.navBarHeight import ani.dantotsu.navBarHeight
import ani.dantotsu.others.getSerialized import ani.dantotsu.others.getSerialized
import ani.dantotsu.parsers.Subtitle import ani.dantotsu.parsers.Subtitle
import ani.dantotsu.saveData import ani.dantotsu.settings.saving.PrefName
import ani.dantotsu.settings.saving.PrefManager
import ani.dantotsu.snackString import ani.dantotsu.snackString
import ani.dantotsu.statusBarHeight import ani.dantotsu.statusBarHeight
import ani.dantotsu.themes.ThemeManager import ani.dantotsu.themes.ThemeManager
@ -61,12 +61,6 @@ class PlayerSettingsActivity : AppCompatActivity() {
bottomMargin = navBarHeight bottomMargin = navBarHeight
} }
val settings = loadData<PlayerSettings>(player, toast = false) ?: PlayerSettings().apply {
saveData(
player,
this
)
}
binding.playerSettingsBack.setOnClickListener { binding.playerSettingsBack.setOnClickListener {
onBackPressedDispatcher.onBackPressed() onBackPressedDispatcher.onBackPressed()
@ -91,128 +85,113 @@ class PlayerSettingsActivity : AppCompatActivity() {
2f 2f
) )
val cursedSpeeds = arrayOf(1f, 1.25f, 1.5f, 1.75f, 2f, 2.5f, 3f, 4f, 5f, 10f, 25f, 50f) val cursedSpeeds = arrayOf(1f, 1.25f, 1.5f, 1.75f, 2f, 2.5f, 3f, 4f, 5f, 10f, 25f, 50f)
var curSpeedArr = if (settings.cursedSpeeds) cursedSpeeds else speeds //var curSpeedArr = if (settings.cursedSpeeds) cursedSpeeds else speeds
var curSpeedArr = if (PrefManager.getVal(PrefName.CursedSpeeds)) cursedSpeeds else speeds
var speedsName = curSpeedArr.map { "${it}x" }.toTypedArray() var speedsName = curSpeedArr.map { "${it}x" }.toTypedArray()
binding.playerSettingsSpeed.text = binding.playerSettingsSpeed.text =
getString(R.string.default_playback_speed, speedsName[settings.defaultSpeed]) getString(R.string.default_playback_speed, speedsName[PrefManager.getVal(PrefName.DefaultSpeed)])
val speedDialog = AlertDialog.Builder(this, R.style.MyPopup) val speedDialog = AlertDialog.Builder(this, R.style.MyPopup)
.setTitle(getString(R.string.default_speed)) .setTitle(getString(R.string.default_speed))
binding.playerSettingsSpeed.setOnClickListener { binding.playerSettingsSpeed.setOnClickListener {
val dialog = val dialog =
speedDialog.setSingleChoiceItems(speedsName, settings.defaultSpeed) { dialog, i -> speedDialog.setSingleChoiceItems(speedsName, PrefManager.getVal(PrefName.DefaultSpeed)) { dialog, i ->
settings.defaultSpeed = i PrefManager.setVal(PrefName.DefaultSpeed, i)
binding.playerSettingsSpeed.text = binding.playerSettingsSpeed.text =
getString(R.string.default_playback_speed, speedsName[i]) getString(R.string.default_playback_speed, speedsName[i])
saveData(player, settings)
dialog.dismiss() dialog.dismiss()
}.show() }.show()
dialog.window?.setDimAmount(0.8f) dialog.window?.setDimAmount(0.8f)
} }
binding.playerSettingsCursedSpeeds.isChecked = settings.cursedSpeeds binding.playerSettingsCursedSpeeds.isChecked = PrefManager.getVal(PrefName.CursedSpeeds)
binding.playerSettingsCursedSpeeds.setOnCheckedChangeListener { _, isChecked -> binding.playerSettingsCursedSpeeds.setOnCheckedChangeListener { _, isChecked ->
settings.cursedSpeeds = isChecked PrefManager.setVal(PrefName.CursedSpeeds, isChecked)
curSpeedArr = if (settings.cursedSpeeds) cursedSpeeds else speeds curSpeedArr = if (isChecked) cursedSpeeds else speeds
settings.defaultSpeed = if (settings.cursedSpeeds) 0 else 5 val newDefaultSpeed = if (isChecked) 0 else 5
PrefManager.setVal(PrefName.DefaultSpeed, newDefaultSpeed)
speedsName = curSpeedArr.map { "${it}x" }.toTypedArray() speedsName = curSpeedArr.map { "${it}x" }.toTypedArray()
binding.playerSettingsSpeed.text = binding.playerSettingsSpeed.text =
getString(R.string.default_playback_speed, speedsName[settings.defaultSpeed]) getString(R.string.default_playback_speed, speedsName[PrefManager.getVal(PrefName.DefaultSpeed)])
saveData(player, settings)
} }
//Time Stamp
binding.playerSettingsTimeStamps.isChecked = settings.timeStampsEnabled // Time Stamp
binding.playerSettingsTimeStamps.isChecked = PrefManager.getVal(PrefName.TimeStampsEnabled)
binding.playerSettingsTimeStamps.setOnCheckedChangeListener { _, isChecked -> binding.playerSettingsTimeStamps.setOnCheckedChangeListener { _, isChecked ->
settings.timeStampsEnabled = isChecked PrefManager.setVal(PrefName.TimeStampsEnabled, isChecked)
saveData(player, settings)
} }
binding.playerSettingsTimeStampsProxy.isChecked = settings.useProxyForTimeStamps binding.playerSettingsTimeStampsProxy.isChecked = PrefManager.getVal(PrefName.UseProxyForTimeStamps)
binding.playerSettingsTimeStampsProxy.setOnCheckedChangeListener { _, isChecked -> binding.playerSettingsTimeStampsProxy.setOnCheckedChangeListener { _, isChecked ->
settings.useProxyForTimeStamps = isChecked PrefManager.setVal(PrefName.UseProxyForTimeStamps, isChecked)
saveData(player, settings)
} }
binding.playerSettingsShowTimeStamp.isChecked = settings.showTimeStampButton binding.playerSettingsShowTimeStamp.isChecked = PrefManager.getVal(PrefName.ShowTimeStampButton)
binding.playerSettingsShowTimeStamp.setOnCheckedChangeListener { _, isChecked -> binding.playerSettingsShowTimeStamp.setOnCheckedChangeListener { _, isChecked ->
settings.showTimeStampButton = isChecked PrefManager.setVal(PrefName.ShowTimeStampButton, isChecked)
saveData(player, settings)
} }
// Auto
//Auto binding.playerSettingsAutoSkipOpEd.isChecked = PrefManager.getVal(PrefName.AutoSkipOPED)
binding.playerSettingsAutoSkipOpEd.isChecked = settings.autoSkipOPED
binding.playerSettingsAutoSkipOpEd.setOnCheckedChangeListener { _, isChecked -> binding.playerSettingsAutoSkipOpEd.setOnCheckedChangeListener { _, isChecked ->
settings.autoSkipOPED = isChecked PrefManager.setVal(PrefName.AutoSkipOPED, isChecked)
saveData(player, settings)
} }
binding.playerSettingsAutoPlay.isChecked = settings.autoPlay binding.playerSettingsAutoPlay.isChecked = PrefManager.getVal(PrefName.AutoPlay)
binding.playerSettingsAutoPlay.setOnCheckedChangeListener { _, isChecked -> binding.playerSettingsAutoPlay.setOnCheckedChangeListener { _, isChecked ->
settings.autoPlay = isChecked PrefManager.setVal(PrefName.AutoPlay, isChecked)
saveData(player, settings)
} }
binding.playerSettingsAutoSkip.isChecked = settings.autoSkipFiller
binding.playerSettingsAutoSkip.isChecked = PrefManager.getVal(PrefName.AutoSkipFiller)
binding.playerSettingsAutoSkip.setOnCheckedChangeListener { _, isChecked -> binding.playerSettingsAutoSkip.setOnCheckedChangeListener { _, isChecked ->
settings.autoSkipFiller = isChecked PrefManager.setVal(PrefName.AutoSkipFiller, isChecked)
saveData(player, settings)
} }
//Update Progress //Update Progress
binding.playerSettingsAskUpdateProgress.isChecked = settings.askIndividual binding.playerSettingsAskUpdateProgress.isChecked = PrefManager.getVal(PrefName.AskIndividualPlayer)
binding.playerSettingsAskUpdateProgress.setOnCheckedChangeListener { _, isChecked -> binding.playerSettingsAskUpdateProgress.setOnCheckedChangeListener { _, isChecked ->
settings.askIndividual = isChecked PrefManager.setVal(PrefName.AskIndividualPlayer, isChecked)
saveData(player, settings)
} }
binding.playerSettingsAskUpdateHentai.isChecked = settings.updateForH binding.playerSettingsAskUpdateHentai.isChecked = PrefManager.getVal(PrefName.UpdateForHPlayer)
binding.playerSettingsAskUpdateHentai.setOnCheckedChangeListener { _, isChecked -> binding.playerSettingsAskUpdateHentai.setOnCheckedChangeListener { _, isChecked ->
settings.updateForH = isChecked PrefManager.setVal(PrefName.UpdateForHPlayer, isChecked)
if (isChecked) snackString(getString(R.string.very_bold)) if (isChecked) snackString(getString(R.string.very_bold))
saveData(player, settings)
} }
binding.playerSettingsCompletePercentage.value = binding.playerSettingsCompletePercentage.value = (PrefManager.getVal<Float>(PrefName.WatchPercentage) * 100).roundToInt().toFloat()
(settings.watchPercentage * 100).roundToInt().toFloat()
binding.playerSettingsCompletePercentage.addOnChangeListener { _, value, _ -> binding.playerSettingsCompletePercentage.addOnChangeListener { _, value, _ ->
settings.watchPercentage = value / 100 PrefManager.setVal(PrefName.WatchPercentage, value / 100)
saveData(player, settings)
} }
//Behaviour //Behaviour
binding.playerSettingsAlwaysContinue.isChecked = settings.alwaysContinue binding.playerSettingsAlwaysContinue.isChecked = PrefManager.getVal(PrefName.AlwaysContinue)
binding.playerSettingsAlwaysContinue.setOnCheckedChangeListener { _, isChecked -> binding.playerSettingsAlwaysContinue.setOnCheckedChangeListener { _, isChecked ->
settings.alwaysContinue = isChecked PrefManager.setVal(PrefName.AlwaysContinue, isChecked)
saveData(player, settings)
} }
binding.playerSettingsPauseVideo.isChecked = settings.focusPause binding.playerSettingsPauseVideo.isChecked = PrefManager.getVal(PrefName.FocusPause)
binding.playerSettingsPauseVideo.setOnCheckedChangeListener { _, isChecked -> binding.playerSettingsPauseVideo.setOnCheckedChangeListener { _, isChecked ->
settings.focusPause = isChecked PrefManager.setVal(PrefName.FocusPause, isChecked)
saveData(player, settings)
} }
binding.playerSettingsVerticalGestures.isChecked = settings.gestures binding.playerSettingsVerticalGestures.isChecked = PrefManager.getVal(PrefName.Gestures)
binding.playerSettingsVerticalGestures.setOnCheckedChangeListener { _, isChecked -> binding.playerSettingsVerticalGestures.setOnCheckedChangeListener { _, isChecked ->
settings.gestures = isChecked PrefManager.setVal(PrefName.Gestures, isChecked)
saveData(player, settings)
} }
binding.playerSettingsDoubleTap.isChecked = settings.doubleTap binding.playerSettingsDoubleTap.isChecked = PrefManager.getVal(PrefName.DoubleTap)
binding.playerSettingsDoubleTap.setOnCheckedChangeListener { _, isChecked -> binding.playerSettingsDoubleTap.setOnCheckedChangeListener { _, isChecked ->
settings.doubleTap = isChecked PrefManager.setVal(PrefName.DoubleTap, isChecked)
saveData(player, settings)
} }
binding.playerSettingsFastForward.isChecked = settings.fastforward binding.playerSettingsFastForward.isChecked = PrefManager.getVal(PrefName.FastForward)
binding.playerSettingsFastForward.setOnCheckedChangeListener { _, isChecked -> binding.playerSettingsFastForward.setOnCheckedChangeListener { _, isChecked ->
settings.fastforward = isChecked PrefManager.setVal(PrefName.FastForward, isChecked)
saveData(player, settings)
} }
binding.playerSettingsSeekTime.value = settings.seekTime.toFloat() binding.playerSettingsSeekTime.value = PrefManager.getVal<Int>(PrefName.SeekTime).toFloat()
binding.playerSettingsSeekTime.addOnChangeListener { _, value, _ -> binding.playerSettingsSeekTime.addOnChangeListener { _, value, _ ->
settings.seekTime = value.toInt() PrefManager.setVal(PrefName.SeekTime, value.toInt())
saveData(player, settings)
} }
binding.exoSkipTime.setText(settings.skipTime.toString()) binding.exoSkipTime.setText(PrefManager.getVal<Int>(PrefName.SkipTime).toString())
binding.exoSkipTime.setOnEditorActionListener { _, actionId, _ -> binding.exoSkipTime.setOnEditorActionListener { _, actionId, _ ->
if (actionId == EditorInfo.IME_ACTION_DONE) { if (actionId == EditorInfo.IME_ACTION_DONE) {
binding.exoSkipTime.clearFocus() binding.exoSkipTime.clearFocus()
@ -222,8 +201,7 @@ class PlayerSettingsActivity : AppCompatActivity() {
binding.exoSkipTime.addTextChangedListener { binding.exoSkipTime.addTextChangedListener {
val time = binding.exoSkipTime.text.toString().toIntOrNull() val time = binding.exoSkipTime.text.toString().toIntOrNull()
if (time != null) { if (time != null) {
settings.skipTime = time PrefManager.setVal(PrefName.SkipTime, time)
saveData(player, settings)
} }
} }
@ -231,32 +209,29 @@ class PlayerSettingsActivity : AppCompatActivity() {
binding.playerSettingsPiP.apply { binding.playerSettingsPiP.apply {
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.N) { if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.N) {
visibility = View.VISIBLE visibility = View.VISIBLE
isChecked = settings.pip isChecked = PrefManager.getVal(PrefName.Pip)
setOnCheckedChangeListener { _, isChecked -> setOnCheckedChangeListener { _, isChecked ->
settings.pip = isChecked PrefManager.setVal(PrefName.Pip, isChecked)
saveData(player, settings)
} }
} else visibility = View.GONE } else visibility = View.GONE
} }
binding.playerSettingsCast.isChecked = settings.cast binding.playerSettingsCast.isChecked = PrefManager.getVal(PrefName.Cast)
binding.playerSettingsCast.setOnCheckedChangeListener { _, isChecked -> binding.playerSettingsCast.setOnCheckedChangeListener { _, isChecked ->
settings.cast = isChecked PrefManager.setVal(PrefName.Cast, isChecked)
saveData(player, settings)
} }
val resizeModes = arrayOf("Original", "Zoom", "Stretch") val resizeModes = arrayOf("Original", "Zoom", "Stretch")
val resizeDialog = AlertDialog.Builder(this, R.style.MyPopup) val resizeDialog = AlertDialog.Builder(this, R.style.MyPopup)
.setTitle(getString(R.string.default_resize_mode)) .setTitle(getString(R.string.default_resize_mode))
binding.playerResizeMode.setOnClickListener { binding.playerResizeMode.setOnClickListener {
val dialog = val dialog = resizeDialog.setSingleChoiceItems(resizeModes, PrefManager.getVal<Int>(PrefName.Resize)) { dialog, count ->
resizeDialog.setSingleChoiceItems(resizeModes, settings.resize) { dialog, count -> PrefManager.setVal(PrefName.Resize, count)
settings.resize = count dialog.dismiss()
saveData(player, settings) }.show()
dialog.dismiss()
}.show()
dialog.window?.setDimAmount(0.8f) dialog.window?.setDimAmount(0.8f)
} }
fun restartApp() { fun restartApp() {
Snackbar.make( Snackbar.make(
binding.root, binding.root,
@ -311,10 +286,9 @@ class PlayerSettingsActivity : AppCompatActivity() {
false -> 0.5f false -> 0.5f
} }
} }
binding.subSwitch.isChecked = settings.subtitles binding.subSwitch.isChecked = PrefManager.getVal(PrefName.Subtitles)
binding.subSwitch.setOnCheckedChangeListener { _, isChecked -> binding.subSwitch.setOnCheckedChangeListener { _, isChecked ->
settings.subtitles = isChecked PrefManager.setVal(PrefName.Subtitles, isChecked)
saveData(player, settings)
toggleSubOptions(isChecked) toggleSubOptions(isChecked)
restartApp() restartApp()
} }
@ -337,10 +311,9 @@ class PlayerSettingsActivity : AppCompatActivity() {
binding.videoSubColorPrimary.setOnClickListener { binding.videoSubColorPrimary.setOnClickListener {
val dialog = primaryColorDialog.setSingleChoiceItems( val dialog = primaryColorDialog.setSingleChoiceItems(
colorsPrimary, colorsPrimary,
settings.primaryColor PrefManager.getVal(PrefName.PrimaryColor)
) { dialog, count -> ) { dialog, count ->
settings.primaryColor = count PrefManager.setVal(PrefName.PrimaryColor, count)
saveData(player, settings)
dialog.dismiss() dialog.dismiss()
}.show() }.show()
dialog.window?.setDimAmount(0.8f) dialog.window?.setDimAmount(0.8f)
@ -364,10 +337,9 @@ class PlayerSettingsActivity : AppCompatActivity() {
binding.videoSubColorSecondary.setOnClickListener { binding.videoSubColorSecondary.setOnClickListener {
val dialog = secondaryColorDialog.setSingleChoiceItems( val dialog = secondaryColorDialog.setSingleChoiceItems(
colorsSecondary, colorsSecondary,
settings.secondaryColor PrefManager.getVal(PrefName.SecondaryColor)
) { dialog, count -> ) { dialog, count ->
settings.secondaryColor = count PrefManager.setVal(PrefName.SecondaryColor, count)
saveData(player, settings)
dialog.dismiss() dialog.dismiss()
}.show() }.show()
dialog.window?.setDimAmount(0.8f) dialog.window?.setDimAmount(0.8f)
@ -378,10 +350,9 @@ class PlayerSettingsActivity : AppCompatActivity() {
binding.videoSubOutline.setOnClickListener { binding.videoSubOutline.setOnClickListener {
val dialog = outlineDialog.setSingleChoiceItems( val dialog = outlineDialog.setSingleChoiceItems(
typesOutline, typesOutline,
settings.outline PrefManager.getVal(PrefName.Outline)
) { dialog, count -> ) { dialog, count ->
settings.outline = count PrefManager.setVal(PrefName.Outline, count)
saveData(player, settings)
dialog.dismiss() dialog.dismiss()
}.show() }.show()
dialog.window?.setDimAmount(0.8f) dialog.window?.setDimAmount(0.8f)
@ -405,10 +376,9 @@ class PlayerSettingsActivity : AppCompatActivity() {
binding.videoSubColorBackground.setOnClickListener { binding.videoSubColorBackground.setOnClickListener {
val dialog = subBackgroundDialog.setSingleChoiceItems( val dialog = subBackgroundDialog.setSingleChoiceItems(
colorsSubBackground, colorsSubBackground,
settings.subBackground PrefManager.getVal(PrefName.SubBackground)
) { dialog, count -> ) { dialog, count ->
settings.subBackground = count PrefManager.setVal(PrefName.SubBackground, count)
saveData(player, settings)
dialog.dismiss() dialog.dismiss()
}.show() }.show()
dialog.window?.setDimAmount(0.8f) dialog.window?.setDimAmount(0.8f)
@ -433,10 +403,9 @@ class PlayerSettingsActivity : AppCompatActivity() {
binding.videoSubColorWindow.setOnClickListener { binding.videoSubColorWindow.setOnClickListener {
val dialog = subWindowDialog.setSingleChoiceItems( val dialog = subWindowDialog.setSingleChoiceItems(
colorsSubWindow, colorsSubWindow,
settings.subWindow PrefManager.getVal(PrefName.SubWindow)
) { dialog, count -> ) { dialog, count ->
settings.subWindow = count PrefManager.setVal(PrefName.SubWindow, count)
saveData(player, settings)
dialog.dismiss() dialog.dismiss()
}.show() }.show()
dialog.window?.setDimAmount(0.8f) dialog.window?.setDimAmount(0.8f)
@ -452,14 +421,13 @@ class PlayerSettingsActivity : AppCompatActivity() {
val fontDialog = AlertDialog.Builder(this, R.style.MyPopup) val fontDialog = AlertDialog.Builder(this, R.style.MyPopup)
.setTitle(getString(R.string.subtitle_font)) .setTitle(getString(R.string.subtitle_font))
binding.videoSubFont.setOnClickListener { binding.videoSubFont.setOnClickListener {
val dialog = fontDialog.setSingleChoiceItems(fonts, settings.font) { dialog, count -> val dialog = fontDialog.setSingleChoiceItems(fonts, PrefManager.getVal(PrefName.Font)) { dialog, count ->
settings.font = count PrefManager.setVal(PrefName.Font, count)
saveData(player, settings)
dialog.dismiss() dialog.dismiss()
}.show() }.show()
dialog.window?.setDimAmount(0.8f) dialog.window?.setDimAmount(0.8f)
} }
binding.subtitleFontSize.setText(settings.fontSize.toString()) binding.subtitleFontSize.setText(PrefManager.getVal<Int>(PrefName.FontSize).toString())
binding.subtitleFontSize.setOnEditorActionListener { _, actionId, _ -> binding.subtitleFontSize.setOnEditorActionListener { _, actionId, _ ->
if (actionId == EditorInfo.IME_ACTION_DONE) { if (actionId == EditorInfo.IME_ACTION_DONE) {
binding.subtitleFontSize.clearFocus() binding.subtitleFontSize.clearFocus()
@ -469,10 +437,9 @@ class PlayerSettingsActivity : AppCompatActivity() {
binding.subtitleFontSize.addTextChangedListener { binding.subtitleFontSize.addTextChangedListener {
val size = binding.subtitleFontSize.text.toString().toIntOrNull() val size = binding.subtitleFontSize.text.toString().toIntOrNull()
if (size != null) { if (size != null) {
settings.fontSize = size PrefManager.setVal(PrefName.FontSize, size)
saveData(player, settings)
} }
} }
toggleSubOptions(settings.subtitles) toggleSubOptions(PrefManager.getVal(PrefName.Subtitles))
} }
} }

View file

@ -1,15 +0,0 @@
package ani.dantotsu.settings
import java.io.Serializable
data class ReaderSettings(
var showSource: Boolean = true,
var showSystemBars: Boolean = false,
var autoDetectWebtoon: Boolean = true,
var default: CurrentReaderSettings = CurrentReaderSettings(),
var defaultLN: CurrentNovelReaderSettings = CurrentNovelReaderSettings(),
var askIndividual: Boolean = true,
var updateForH: Boolean = false
) : Serializable

View file

@ -7,16 +7,17 @@ import androidx.core.view.updateLayoutParams
import ani.dantotsu.R import ani.dantotsu.R
import ani.dantotsu.databinding.ActivityReaderSettingsBinding import ani.dantotsu.databinding.ActivityReaderSettingsBinding
import ani.dantotsu.initActivity import ani.dantotsu.initActivity
import ani.dantotsu.loadData
import ani.dantotsu.navBarHeight import ani.dantotsu.navBarHeight
import ani.dantotsu.saveData import ani.dantotsu.settings.saving.PrefName
import ani.dantotsu.settings.saving.PrefManager
import ani.dantotsu.snackString import ani.dantotsu.snackString
import ani.dantotsu.statusBarHeight import ani.dantotsu.statusBarHeight
import ani.dantotsu.themes.ThemeManager import ani.dantotsu.themes.ThemeManager
class ReaderSettingsActivity : AppCompatActivity() { class ReaderSettingsActivity : AppCompatActivity() {
lateinit var binding: ActivityReaderSettingsBinding lateinit var binding: ActivityReaderSettingsBinding
private val reader = "reader_settings" private var defaultSettings = CurrentReaderSettings()
private var defaultSettingsLN = CurrentNovelReaderSettings()
override fun onCreate(savedInstanceState: Bundle?) { override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState) super.onCreate(savedInstanceState)
@ -30,34 +31,24 @@ class ReaderSettingsActivity : AppCompatActivity() {
bottomMargin = navBarHeight bottomMargin = navBarHeight
} }
val settings = loadData<ReaderSettings>(reader, toast = false) ?: ReaderSettings().apply {
saveData(
reader,
this
)
}
binding.readerSettingsBack.setOnClickListener { binding.readerSettingsBack.setOnClickListener {
onBackPressedDispatcher.onBackPressed() onBackPressedDispatcher.onBackPressed()
} }
//Manga Settings //Manga Settings
binding.readerSettingsSourceName.isChecked = settings.showSource binding.readerSettingsSourceName.isChecked = PrefManager.getVal(PrefName.ShowSource)
binding.readerSettingsSourceName.setOnCheckedChangeListener { _, isChecked -> binding.readerSettingsSourceName.setOnCheckedChangeListener { _, isChecked ->
settings.showSource = isChecked PrefManager.setVal(PrefName.ShowSource, isChecked)
saveData(reader, settings)
} }
binding.readerSettingsSystemBars.isChecked = settings.showSystemBars binding.readerSettingsSystemBars.isChecked = PrefManager.getVal(PrefName.ShowSystemBars)
binding.readerSettingsSystemBars.setOnCheckedChangeListener { _, isChecked -> binding.readerSettingsSystemBars.setOnCheckedChangeListener { _, isChecked ->
settings.showSystemBars = isChecked PrefManager.setVal(PrefName.ShowSystemBars, isChecked)
saveData(reader, settings)
} }
//Default Manga //Default Manga
binding.readerSettingsAutoWebToon.isChecked = settings.autoDetectWebtoon binding.readerSettingsAutoWebToon.isChecked = PrefManager.getVal(PrefName.AutoDetectWebtoon)
binding.readerSettingsAutoWebToon.setOnCheckedChangeListener { _, isChecked -> binding.readerSettingsAutoWebToon.setOnCheckedChangeListener { _, isChecked ->
settings.autoDetectWebtoon = isChecked PrefManager.setVal(PrefName.AutoDetectWebtoon, isChecked)
saveData(reader, settings)
} }
@ -68,8 +59,8 @@ class ReaderSettingsActivity : AppCompatActivity() {
) )
binding.readerSettingsLayoutText.text = binding.readerSettingsLayoutText.text =
resources.getStringArray(R.array.manga_layouts)[settings.default.layout.ordinal] resources.getStringArray(R.array.manga_layouts)[defaultSettings.layout.ordinal]
var selectedLayout = layoutList[settings.default.layout.ordinal] var selectedLayout = layoutList[defaultSettings.layout.ordinal]
selectedLayout.alpha = 1f selectedLayout.alpha = 1f
layoutList.forEachIndexed { index, imageButton -> layoutList.forEachIndexed { index, imageButton ->
@ -77,25 +68,25 @@ class ReaderSettingsActivity : AppCompatActivity() {
selectedLayout.alpha = 0.33f selectedLayout.alpha = 0.33f
selectedLayout = imageButton selectedLayout = imageButton
selectedLayout.alpha = 1f selectedLayout.alpha = 1f
settings.default.layout = defaultSettings.layout =
CurrentReaderSettings.Layouts[index] ?: CurrentReaderSettings.Layouts.CONTINUOUS CurrentReaderSettings.Layouts[index] ?: CurrentReaderSettings.Layouts.CONTINUOUS
binding.readerSettingsLayoutText.text = binding.readerSettingsLayoutText.text =
resources.getStringArray(R.array.manga_layouts)[settings.default.layout.ordinal] resources.getStringArray(R.array.manga_layouts)[defaultSettings.layout.ordinal]
saveData(reader, settings) PrefManager.setVal(PrefName.LayoutReader, defaultSettings.layout.ordinal)
} }
} }
binding.readerSettingsDirectionText.text = binding.readerSettingsDirectionText.text =
resources.getStringArray(R.array.manga_directions)[settings.default.direction.ordinal] resources.getStringArray(R.array.manga_directions)[defaultSettings.direction.ordinal]
binding.readerSettingsDirection.rotation = 90f * (settings.default.direction.ordinal) binding.readerSettingsDirection.rotation = 90f * (defaultSettings.direction.ordinal)
binding.readerSettingsDirection.setOnClickListener { binding.readerSettingsDirection.setOnClickListener {
settings.default.direction = defaultSettings.direction =
CurrentReaderSettings.Directions[settings.default.direction.ordinal + 1] CurrentReaderSettings.Directions[defaultSettings.direction.ordinal + 1]
?: CurrentReaderSettings.Directions.TOP_TO_BOTTOM ?: CurrentReaderSettings.Directions.TOP_TO_BOTTOM
binding.readerSettingsDirectionText.text = binding.readerSettingsDirectionText.text =
resources.getStringArray(R.array.manga_directions)[settings.default.direction.ordinal] resources.getStringArray(R.array.manga_directions)[defaultSettings.direction.ordinal]
binding.readerSettingsDirection.rotation = 90f * (settings.default.direction.ordinal) binding.readerSettingsDirection.rotation = 90f * (defaultSettings.direction.ordinal)
saveData(reader, settings) PrefManager.setVal(PrefName.Direction, defaultSettings.direction.ordinal)
} }
val dualList = listOf( val dualList = listOf(
@ -104,8 +95,8 @@ class ReaderSettingsActivity : AppCompatActivity() {
binding.readerSettingsDualForce binding.readerSettingsDualForce
) )
binding.readerSettingsDualPageText.text = settings.default.dualPageMode.toString() binding.readerSettingsDualPageText.text = defaultSettings.dualPageMode.toString()
var selectedDual = dualList[settings.default.dualPageMode.ordinal] var selectedDual = dualList[defaultSettings.dualPageMode.ordinal]
selectedDual.alpha = 1f selectedDual.alpha = 1f
dualList.forEachIndexed { index, imageButton -> dualList.forEachIndexed { index, imageButton ->
@ -113,75 +104,75 @@ class ReaderSettingsActivity : AppCompatActivity() {
selectedDual.alpha = 0.33f selectedDual.alpha = 0.33f
selectedDual = imageButton selectedDual = imageButton
selectedDual.alpha = 1f selectedDual.alpha = 1f
settings.default.dualPageMode = CurrentReaderSettings.DualPageModes[index] defaultSettings.dualPageMode = CurrentReaderSettings.DualPageModes[index]
?: CurrentReaderSettings.DualPageModes.Automatic ?: CurrentReaderSettings.DualPageModes.Automatic
binding.readerSettingsDualPageText.text = settings.default.dualPageMode.toString() binding.readerSettingsDualPageText.text = defaultSettings.dualPageMode.toString()
saveData(reader, settings) PrefManager.setVal(PrefName.DualPageModeReader, defaultSettings.dualPageMode.ordinal)
} }
} }
binding.readerSettingsTrueColors.isChecked = settings.default.trueColors binding.readerSettingsTrueColors.isChecked = defaultSettings.trueColors
binding.readerSettingsTrueColors.setOnCheckedChangeListener { _, isChecked -> binding.readerSettingsTrueColors.setOnCheckedChangeListener { _, isChecked ->
settings.default.trueColors = isChecked defaultSettings.trueColors = isChecked
saveData(reader, settings) PrefManager.setVal(PrefName.TrueColors, isChecked)
} }
binding.readerSettingsCropBorders.isChecked = settings.default.cropBorders binding.readerSettingsCropBorders.isChecked = defaultSettings.cropBorders
binding.readerSettingsCropBorders.setOnCheckedChangeListener { _, isChecked -> binding.readerSettingsCropBorders.setOnCheckedChangeListener { _, isChecked ->
settings.default.cropBorders = isChecked defaultSettings.cropBorders = isChecked
saveData(reader, settings) PrefManager.setVal(PrefName.CropBorders, isChecked)
} }
binding.readerSettingsImageRotation.isChecked = settings.default.rotation binding.readerSettingsImageRotation.isChecked = defaultSettings.rotation
binding.readerSettingsImageRotation.setOnCheckedChangeListener { _, isChecked -> binding.readerSettingsImageRotation.setOnCheckedChangeListener { _, isChecked ->
settings.default.rotation = isChecked defaultSettings.rotation = isChecked
saveData(reader, settings) PrefManager.setVal(PrefName.Rotation, isChecked)
} }
binding.readerSettingsHorizontalScrollBar.isChecked = settings.default.horizontalScrollBar binding.readerSettingsHorizontalScrollBar.isChecked = defaultSettings.horizontalScrollBar
binding.readerSettingsHorizontalScrollBar.setOnCheckedChangeListener { _, isChecked -> binding.readerSettingsHorizontalScrollBar.setOnCheckedChangeListener { _, isChecked ->
settings.default.horizontalScrollBar = isChecked defaultSettings.horizontalScrollBar = isChecked
saveData(reader, settings) PrefManager.setVal(PrefName.HorizontalScrollBar, isChecked)
} }
binding.readerSettingsPadding.isChecked = settings.default.padding binding.readerSettingsPadding.isChecked = defaultSettings.padding
binding.readerSettingsPadding.setOnCheckedChangeListener { _, isChecked -> binding.readerSettingsPadding.setOnCheckedChangeListener { _, isChecked ->
settings.default.padding = isChecked defaultSettings.padding = isChecked
saveData(reader, settings) PrefManager.setVal(PrefName.Padding, isChecked)
} }
binding.readerSettingsKeepScreenOn.isChecked = settings.default.keepScreenOn binding.readerSettingsKeepScreenOn.isChecked = defaultSettings.keepScreenOn
binding.readerSettingsKeepScreenOn.setOnCheckedChangeListener { _, isChecked -> binding.readerSettingsKeepScreenOn.setOnCheckedChangeListener { _, isChecked ->
settings.default.keepScreenOn = isChecked defaultSettings.keepScreenOn = isChecked
saveData(reader, settings) PrefManager.setVal(PrefName.KeepScreenOn, isChecked)
} }
binding.readerSettingsHidePageNumbers.isChecked = settings.default.hidePageNumbers binding.readerSettingsHidePageNumbers.isChecked = defaultSettings.hidePageNumbers
binding.readerSettingsHidePageNumbers.setOnCheckedChangeListener { _, isChecked -> binding.readerSettingsHidePageNumbers.setOnCheckedChangeListener { _, isChecked ->
settings.default.hidePageNumbers = isChecked defaultSettings.hidePageNumbers = isChecked
saveData(reader, settings) PrefManager.setVal(PrefName.HidePageNumbers, isChecked)
} }
binding.readerSettingsOverscroll.isChecked = settings.default.overScrollMode binding.readerSettingsOverscroll.isChecked = defaultSettings.overScrollMode
binding.readerSettingsOverscroll.setOnCheckedChangeListener { _, isChecked -> binding.readerSettingsOverscroll.setOnCheckedChangeListener { _, isChecked ->
settings.default.overScrollMode = isChecked defaultSettings.overScrollMode = isChecked
saveData(reader, settings) PrefManager.setVal(PrefName.OverScrollMode, isChecked)
} }
binding.readerSettingsVolumeButton.isChecked = settings.default.volumeButtons binding.readerSettingsVolumeButton.isChecked = defaultSettings.volumeButtons
binding.readerSettingsVolumeButton.setOnCheckedChangeListener { _, isChecked -> binding.readerSettingsVolumeButton.setOnCheckedChangeListener { _, isChecked ->
settings.default.volumeButtons = isChecked defaultSettings.volumeButtons = isChecked
saveData(reader, settings) PrefManager.setVal(PrefName.VolumeButtonsReader, isChecked)
} }
binding.readerSettingsWrapImages.isChecked = settings.default.wrapImages binding.readerSettingsWrapImages.isChecked = defaultSettings.wrapImages
binding.readerSettingsWrapImages.setOnCheckedChangeListener { _, isChecked -> binding.readerSettingsWrapImages.setOnCheckedChangeListener { _, isChecked ->
settings.default.wrapImages = isChecked defaultSettings.wrapImages = isChecked
saveData(reader, settings) PrefManager.setVal(PrefName.WrapImages, isChecked)
} }
binding.readerSettingsLongClickImage.isChecked = settings.default.longClickImage binding.readerSettingsLongClickImage.isChecked = defaultSettings.longClickImage
binding.readerSettingsLongClickImage.setOnCheckedChangeListener { _, isChecked -> binding.readerSettingsLongClickImage.setOnCheckedChangeListener { _, isChecked ->
settings.default.longClickImage = isChecked defaultSettings.longClickImage = isChecked
saveData(reader, settings) PrefManager.setVal(PrefName.LongClickImage, isChecked)
} }
//LN settings //LN settings
@ -190,8 +181,8 @@ class ReaderSettingsActivity : AppCompatActivity() {
binding.LNcontinuous binding.LNcontinuous
) )
binding.LNlayoutText.text = settings.defaultLN.layout.string binding.LNlayoutText.text = defaultSettingsLN.layout.string
var selectedLN = layoutListLN[settings.defaultLN.layout.ordinal] var selectedLN = layoutListLN[defaultSettingsLN.layout.ordinal]
selectedLN.alpha = 1f selectedLN.alpha = 1f
layoutListLN.forEachIndexed { index, imageButton -> layoutListLN.forEachIndexed { index, imageButton ->
@ -199,10 +190,10 @@ class ReaderSettingsActivity : AppCompatActivity() {
selectedLN.alpha = 0.33f selectedLN.alpha = 0.33f
selectedLN = imageButton selectedLN = imageButton
selectedLN.alpha = 1f selectedLN.alpha = 1f
settings.defaultLN.layout = CurrentNovelReaderSettings.Layouts[index] defaultSettingsLN.layout = CurrentNovelReaderSettings.Layouts[index]
?: CurrentNovelReaderSettings.Layouts.PAGED ?: CurrentNovelReaderSettings.Layouts.PAGED
binding.LNlayoutText.text = settings.defaultLN.layout.string binding.LNlayoutText.text = defaultSettingsLN.layout.string
saveData(reader, settings) PrefManager.setVal(PrefName.LayoutNovel, defaultSettingsLN.layout.ordinal)
} }
} }
@ -212,8 +203,8 @@ class ReaderSettingsActivity : AppCompatActivity() {
binding.LNdualForce binding.LNdualForce
) )
binding.LNdualPageText.text = settings.defaultLN.dualPageMode.toString() binding.LNdualPageText.text = defaultSettingsLN.dualPageMode.toString()
var selectedDualLN = dualListLN[settings.defaultLN.dualPageMode.ordinal] var selectedDualLN = dualListLN[defaultSettingsLN.dualPageMode.ordinal]
selectedDualLN.alpha = 1f selectedDualLN.alpha = 1f
dualListLN.forEachIndexed { index, imageButton -> dualListLN.forEachIndexed { index, imageButton ->
@ -221,143 +212,141 @@ class ReaderSettingsActivity : AppCompatActivity() {
selectedDualLN.alpha = 0.33f selectedDualLN.alpha = 0.33f
selectedDualLN = imageButton selectedDualLN = imageButton
selectedDualLN.alpha = 1f selectedDualLN.alpha = 1f
settings.defaultLN.dualPageMode = CurrentReaderSettings.DualPageModes[index] defaultSettingsLN.dualPageMode = CurrentReaderSettings.DualPageModes[index]
?: CurrentReaderSettings.DualPageModes.Automatic ?: CurrentReaderSettings.DualPageModes.Automatic
binding.LNdualPageText.text = settings.defaultLN.dualPageMode.toString() binding.LNdualPageText.text = defaultSettingsLN.dualPageMode.toString()
saveData(reader, settings) PrefManager.setVal(PrefName.DualPageModeNovel, defaultSettingsLN.dualPageMode.ordinal)
} }
} }
binding.LNlineHeight.setText(settings.defaultLN.lineHeight.toString()) binding.LNlineHeight.setText(defaultSettingsLN.lineHeight.toString())
binding.LNlineHeight.setOnFocusChangeListener { _, hasFocus -> binding.LNlineHeight.setOnFocusChangeListener { _, hasFocus ->
if (!hasFocus) { if (!hasFocus) {
val value = binding.LNlineHeight.text.toString().toFloatOrNull() ?: 1.4f val value = binding.LNlineHeight.text.toString().toFloatOrNull() ?: 1.4f
settings.defaultLN.lineHeight = value defaultSettingsLN.lineHeight = value
binding.LNlineHeight.setText(value.toString()) binding.LNlineHeight.setText(value.toString())
saveData(reader, settings) PrefManager.setVal(PrefName.LineHeight, value)
} }
} }
binding.LNincrementLineHeight.setOnClickListener { binding.LNincrementLineHeight.setOnClickListener {
val value = binding.LNlineHeight.text.toString().toFloatOrNull() ?: 1.4f val value = binding.LNlineHeight.text.toString().toFloatOrNull() ?: 1.4f
settings.defaultLN.lineHeight = value + 0.1f defaultSettingsLN.lineHeight = value + 0.1f
binding.LNlineHeight.setText(settings.defaultLN.lineHeight.toString()) binding.LNlineHeight.setText(defaultSettingsLN.lineHeight.toString())
saveData(reader, settings) PrefManager.setVal(PrefName.LineHeight, defaultSettingsLN.lineHeight)
} }
binding.LNdecrementLineHeight.setOnClickListener { binding.LNdecrementLineHeight.setOnClickListener {
val value = binding.LNlineHeight.text.toString().toFloatOrNull() ?: 1.4f val value = binding.LNlineHeight.text.toString().toFloatOrNull() ?: 1.4f
settings.defaultLN.lineHeight = value - 0.1f defaultSettingsLN.lineHeight = value - 0.1f
binding.LNlineHeight.setText(settings.defaultLN.lineHeight.toString()) binding.LNlineHeight.setText(defaultSettingsLN.lineHeight.toString())
saveData(reader, settings) PrefManager.setVal(PrefName.LineHeight, defaultSettingsLN.lineHeight)
} }
binding.LNmargin.setText(settings.defaultLN.margin.toString()) binding.LNmargin.setText(defaultSettingsLN.margin.toString())
binding.LNmargin.setOnFocusChangeListener { _, hasFocus -> binding.LNmargin.setOnFocusChangeListener { _, hasFocus ->
if (!hasFocus) { if (!hasFocus) {
val value = binding.LNmargin.text.toString().toFloatOrNull() ?: 0.06f val value = binding.LNmargin.text.toString().toFloatOrNull() ?: 0.06f
settings.defaultLN.margin = value defaultSettingsLN.margin = value
binding.LNmargin.setText(value.toString()) binding.LNmargin.setText(value.toString())
saveData(reader, settings) PrefManager.setVal(PrefName.Margin, value)
} }
} }
binding.LNincrementMargin.setOnClickListener { binding.LNincrementMargin.setOnClickListener {
val value = binding.LNmargin.text.toString().toFloatOrNull() ?: 0.06f val value = binding.LNmargin.text.toString().toFloatOrNull() ?: 0.06f
settings.defaultLN.margin = value + 0.01f defaultSettingsLN.margin = value + 0.01f
binding.LNmargin.setText(settings.defaultLN.margin.toString()) binding.LNmargin.setText(defaultSettingsLN.margin.toString())
saveData(reader, settings) PrefManager.setVal(PrefName.Margin, defaultSettingsLN.margin)
} }
binding.LNdecrementMargin.setOnClickListener { binding.LNdecrementMargin.setOnClickListener {
val value = binding.LNmargin.text.toString().toFloatOrNull() ?: 0.06f val value = binding.LNmargin.text.toString().toFloatOrNull() ?: 0.06f
settings.defaultLN.margin = value - 0.01f defaultSettingsLN.margin = value - 0.01f
binding.LNmargin.setText(settings.defaultLN.margin.toString()) binding.LNmargin.setText(defaultSettingsLN.margin.toString())
saveData(reader, settings) PrefManager.setVal(PrefName.Margin, defaultSettingsLN.margin)
} }
binding.LNmaxInlineSize.setText(settings.defaultLN.maxInlineSize.toString()) binding.LNmaxInlineSize.setText(defaultSettingsLN.maxInlineSize.toString())
binding.LNmaxInlineSize.setOnFocusChangeListener { _, hasFocus -> binding.LNmaxInlineSize.setOnFocusChangeListener { _, hasFocus ->
if (!hasFocus) { if (!hasFocus) {
val value = binding.LNmaxInlineSize.text.toString().toIntOrNull() ?: 720 val value = binding.LNmaxInlineSize.text.toString().toIntOrNull() ?: 720
settings.defaultLN.maxInlineSize = value defaultSettingsLN.maxInlineSize = value
binding.LNmaxInlineSize.setText(value.toString()) binding.LNmaxInlineSize.setText(value.toString())
saveData(reader, settings) PrefManager.setVal(PrefName.MaxInlineSize, value)
} }
} }
binding.LNincrementMaxInlineSize.setOnClickListener { binding.LNincrementMaxInlineSize.setOnClickListener {
val value = binding.LNmaxInlineSize.text.toString().toIntOrNull() ?: 720 val value = binding.LNmaxInlineSize.text.toString().toIntOrNull() ?: 720
settings.defaultLN.maxInlineSize = value + 10 defaultSettingsLN.maxInlineSize = value + 10
binding.LNmaxInlineSize.setText(settings.defaultLN.maxInlineSize.toString()) binding.LNmaxInlineSize.setText(defaultSettingsLN.maxInlineSize.toString())
saveData(reader, settings) PrefManager.setVal(PrefName.MaxInlineSize, defaultSettingsLN.maxInlineSize)
} }
binding.LNdecrementMaxInlineSize.setOnClickListener { binding.LNdecrementMaxInlineSize.setOnClickListener {
val value = binding.LNmaxInlineSize.text.toString().toIntOrNull() ?: 720 val value = binding.LNmaxInlineSize.text.toString().toIntOrNull() ?: 720
settings.defaultLN.maxInlineSize = value - 10 defaultSettingsLN.maxInlineSize = value - 10
binding.LNmaxInlineSize.setText(settings.defaultLN.maxInlineSize.toString()) binding.LNmaxInlineSize.setText(defaultSettingsLN.maxInlineSize.toString())
saveData(reader, settings) PrefManager.setVal(PrefName.MaxInlineSize, defaultSettingsLN.maxInlineSize)
} }
binding.LNmaxBlockSize.setText(settings.defaultLN.maxBlockSize.toString()) binding.LNmaxBlockSize.setText(defaultSettingsLN.maxBlockSize.toString())
binding.LNmaxBlockSize.setOnFocusChangeListener { _, hasFocus -> binding.LNmaxBlockSize.setOnFocusChangeListener { _, hasFocus ->
if (!hasFocus) { if (!hasFocus) {
val value = binding.LNmaxBlockSize.text.toString().toIntOrNull() ?: 720 val value = binding.LNmaxBlockSize.text.toString().toIntOrNull() ?: 720
settings.defaultLN.maxBlockSize = value defaultSettingsLN.maxBlockSize = value
binding.LNmaxBlockSize.setText(value.toString()) binding.LNmaxBlockSize.setText(value.toString())
saveData(reader, settings) PrefManager.setVal(PrefName.MaxBlockSize, value)
} }
} }
binding.LNincrementMaxBlockSize.setOnClickListener { binding.LNincrementMaxBlockSize.setOnClickListener {
val value = binding.LNmaxBlockSize.text.toString().toIntOrNull() ?: 720 val value = binding.LNmaxBlockSize.text.toString().toIntOrNull() ?: 720
settings.defaultLN.maxInlineSize = value + 10 defaultSettingsLN.maxInlineSize = value + 10
binding.LNmaxBlockSize.setText(settings.defaultLN.maxInlineSize.toString()) binding.LNmaxBlockSize.setText(defaultSettingsLN.maxInlineSize.toString())
saveData(reader, settings) PrefManager.setVal(PrefName.MaxBlockSize, defaultSettingsLN.maxInlineSize)
} }
binding.LNdecrementMaxBlockSize.setOnClickListener { binding.LNdecrementMaxBlockSize.setOnClickListener {
val value = binding.LNmaxBlockSize.text.toString().toIntOrNull() ?: 720 val value = binding.LNmaxBlockSize.text.toString().toIntOrNull() ?: 720
settings.defaultLN.maxBlockSize = value - 10 defaultSettingsLN.maxBlockSize = value - 10
binding.LNmaxBlockSize.setText(settings.defaultLN.maxBlockSize.toString()) binding.LNmaxBlockSize.setText(defaultSettingsLN.maxBlockSize.toString())
saveData(reader, settings) PrefManager.setVal(PrefName.MaxBlockSize, defaultSettingsLN.maxBlockSize)
} }
binding.LNuseDarkTheme.isChecked = settings.defaultLN.useDarkTheme binding.LNuseDarkTheme.isChecked = defaultSettingsLN.useDarkTheme
binding.LNuseDarkTheme.setOnCheckedChangeListener { _, isChecked -> binding.LNuseDarkTheme.setOnCheckedChangeListener { _, isChecked ->
settings.defaultLN.useDarkTheme = isChecked defaultSettingsLN.useDarkTheme = isChecked
saveData(reader, settings) PrefManager.setVal(PrefName.UseDarkThemeNovel, isChecked)
} }
binding.LNuseOledTheme.isChecked = settings.defaultLN.useOledTheme binding.LNuseOledTheme.isChecked = defaultSettingsLN.useOledTheme
binding.LNuseOledTheme.setOnCheckedChangeListener { _, isChecked -> binding.LNuseOledTheme.setOnCheckedChangeListener { _, isChecked ->
settings.defaultLN.useOledTheme = isChecked defaultSettingsLN.useOledTheme = isChecked
saveData(reader, settings) PrefManager.setVal(PrefName.UseOledThemeNovel, isChecked)
} }
binding.LNkeepScreenOn.isChecked = settings.defaultLN.keepScreenOn binding.LNkeepScreenOn.isChecked = defaultSettingsLN.keepScreenOn
binding.LNkeepScreenOn.setOnCheckedChangeListener { _, isChecked -> binding.LNkeepScreenOn.setOnCheckedChangeListener { _, isChecked ->
settings.defaultLN.keepScreenOn = isChecked defaultSettingsLN.keepScreenOn = isChecked
saveData(reader, settings) PrefManager.setVal(PrefName.KeepScreenOnNovel, isChecked)
} }
binding.LNvolumeButton.isChecked = settings.defaultLN.volumeButtons binding.LNvolumeButton.isChecked = defaultSettingsLN.volumeButtons
binding.LNvolumeButton.setOnCheckedChangeListener { _, isChecked -> binding.LNvolumeButton.setOnCheckedChangeListener { _, isChecked ->
settings.defaultLN.volumeButtons = isChecked defaultSettingsLN.volumeButtons = isChecked
saveData(reader, settings) PrefManager.setVal(PrefName.VolumeButtonsNovel, isChecked)
} }
//Update Progress //Update Progress
binding.readerSettingsAskUpdateProgress.isChecked = settings.askIndividual binding.readerSettingsAskUpdateProgress.isChecked = PrefManager.getVal(PrefName.AskIndividualReader)
binding.readerSettingsAskUpdateProgress.setOnCheckedChangeListener { _, isChecked -> binding.readerSettingsAskUpdateProgress.setOnCheckedChangeListener { _, isChecked ->
settings.askIndividual = isChecked PrefManager.setVal(PrefName.AskIndividualReader, isChecked)
saveData(reader, settings)
} }
binding.readerSettingsAskUpdateDoujins.isChecked = settings.updateForH binding.readerSettingsAskUpdateDoujins.isChecked = PrefManager.getVal(PrefName.UpdateForHReader)
binding.readerSettingsAskUpdateDoujins.setOnCheckedChangeListener { _, isChecked -> binding.readerSettingsAskUpdateDoujins.setOnCheckedChangeListener { _, isChecked ->
settings.updateForH = isChecked PrefManager.setVal(PrefName.UpdateForHReader, isChecked)
if (isChecked) snackString(getString(R.string.very_bold)) if (isChecked) snackString(getString(R.string.very_bold))
saveData(reader, settings)
} }
} }

View file

@ -2,9 +2,7 @@ package ani.dantotsu.settings
import android.annotation.SuppressLint import android.annotation.SuppressLint
import android.app.AlertDialog import android.app.AlertDialog
import android.content.Context
import android.content.Intent import android.content.Intent
import android.graphics.Color
import android.graphics.drawable.Animatable import android.graphics.drawable.Animatable
import android.os.Build.* import android.os.Build.*
import android.os.Build.VERSION.* import android.os.Build.VERSION.*
@ -15,6 +13,9 @@ import android.widget.ArrayAdapter
import android.widget.TextView import android.widget.TextView
import android.widget.Toast import android.widget.Toast
import androidx.activity.OnBackPressedCallback 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.annotation.OptIn
import androidx.appcompat.app.AppCompatActivity import androidx.appcompat.app.AppCompatActivity
import androidx.core.content.ContextCompat import androidx.core.content.ContextCompat
@ -23,6 +24,7 @@ import androidx.lifecycle.lifecycleScope
import androidx.media3.common.util.UnstableApi import androidx.media3.common.util.UnstableApi
import androidx.media3.exoplayer.offline.DownloadService import androidx.media3.exoplayer.offline.DownloadService
import ani.dantotsu.* import ani.dantotsu.*
import ani.dantotsu.Mapper.json
import ani.dantotsu.connections.anilist.Anilist import ani.dantotsu.connections.anilist.Anilist
import ani.dantotsu.connections.discord.Discord import ani.dantotsu.connections.discord.Discord
import ani.dantotsu.connections.mal.MAL import ani.dantotsu.connections.mal.MAL
@ -35,7 +37,8 @@ import ani.dantotsu.others.CustomBottomDialog
import ani.dantotsu.parsers.AnimeSources import ani.dantotsu.parsers.AnimeSources
import ani.dantotsu.parsers.MangaSources import ani.dantotsu.parsers.MangaSources
import ani.dantotsu.settings.saving.PrefName import ani.dantotsu.settings.saving.PrefName
import ani.dantotsu.settings.saving.PrefWrapper import ani.dantotsu.settings.saving.PrefManager
import ani.dantotsu.settings.saving.internal.Location
import ani.dantotsu.subcriptions.Notifications import ani.dantotsu.subcriptions.Notifications
import ani.dantotsu.subcriptions.Notifications.Companion.openSettings import ani.dantotsu.subcriptions.Notifications.Companion.openSettings
import ani.dantotsu.subcriptions.Subscription.Companion.defaultTime import ani.dantotsu.subcriptions.Subscription.Companion.defaultTime
@ -44,11 +47,12 @@ import ani.dantotsu.subcriptions.Subscription.Companion.timeMinutes
import ani.dantotsu.themes.ThemeManager import ani.dantotsu.themes.ThemeManager
import com.google.android.material.snackbar.Snackbar import com.google.android.material.snackbar.Snackbar
import com.google.android.material.textfield.TextInputEditText 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
import eltos.simpledialogfragment.SimpleDialog.OnDialogResultListener.BUTTON_POSITIVE import eltos.simpledialogfragment.SimpleDialog.OnDialogResultListener.BUTTON_POSITIVE
import eltos.simpledialogfragment.color.SimpleColorDialog import eltos.simpledialogfragment.color.SimpleColorDialog
import eu.kanade.domain.base.BasePreferences import eu.kanade.domain.base.BasePreferences
import eu.kanade.tachiyomi.network.NetworkPreferences
import io.noties.markwon.Markwon import io.noties.markwon.Markwon
import io.noties.markwon.SoftBreakAddsNewLinePlugin import io.noties.markwon.SoftBreakAddsNewLinePlugin
import kotlinx.coroutines.Dispatchers import kotlinx.coroutines.Dispatchers
@ -65,20 +69,58 @@ class SettingsActivity : AppCompatActivity(), SimpleDialog.OnDialogResultListene
} }
lateinit var binding: ActivitySettingsBinding lateinit var binding: ActivitySettingsBinding
private val extensionInstaller = Injekt.get<BasePreferences>().extensionInstaller() private val extensionInstaller = Injekt.get<BasePreferences>().extensionInstaller()
private val networkPreferences = Injekt.get<NetworkPreferences>()
private var cursedCounter = 0 private var cursedCounter = 0
private lateinit var openDocumentLauncher: ActivityResultLauncher<String>
@OptIn(UnstableApi::class) @OptIn(UnstableApi::class)
@SuppressLint("SetTextI18n") @SuppressLint("SetTextI18n")
override fun onCreate(savedInstanceState: Bundle?) { override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState) super.onCreate(savedInstanceState)
ThemeManager(this).applyTheme() ThemeManager(this).applyTheme()
binding = ActivitySettingsBinding.inflate(layoutInflater) binding = ActivitySettingsBinding.inflate(layoutInflater)
setContentView(binding.root) setContentView(binding.root)
initActivity(this) initActivity(this)
var selectedImpExp = ""
openDocumentLauncher = registerForActivityResult(CreateDocument("*/*")) { uri ->
if (uri != null) {
try {
val jsonString = contentResolver.openInputStream(uri)?.bufferedReader()
.use { it?.readText() }
val location: Location =
Location.entries.find { it.name.lowercase() == selectedImpExp.lowercase() }
?: return@registerForActivityResult
val gson = Gson()
val type = object : TypeToken<Map<String, Map<String, Any>>>() {}.type
val rawMap: Map<String, Map<String, Any>> = gson.fromJson(jsonString, type)
val deserializedMap = mutableMapOf<String, Any?>()
rawMap.forEach { (key, typeValueMap) ->
val typeName = typeValueMap["type"] as? String
val value = typeValueMap["value"]
deserializedMap[key] = when (typeName) { //wierdly null sometimes so cast to string
"kotlin.Int" -> (value as? Double)?.toInt()
"kotlin.String" -> value.toString()
"kotlin.Boolean" -> value as? Boolean
"kotlin.Float" -> value.toString().toFloatOrNull()
"kotlin.Long" -> (value as? Double)?.toLong()
"java.util.HashSet" -> value as? ArrayList<*>
else -> null
}
}
PrefManager.importAllPrefs(deserializedMap, location)
} catch (e: Exception) {
e.printStackTrace()
toast("Error importing settings")
}
}
}
binding.settingsVersion.text = getString(R.string.version_current, BuildConfig.VERSION_NAME) binding.settingsVersion.text = getString(R.string.version_current, BuildConfig.VERSION_NAME)
binding.settingsVersion.setOnLongClickListener { binding.settingsVersion.setOnLongClickListener {
copyToClipboard(getDeviceInfo(), false) copyToClipboard(getDeviceInfo(), false)
@ -97,16 +139,16 @@ class SettingsActivity : AppCompatActivity(), SimpleDialog.OnDialogResultListene
onBackPressedDispatcher.onBackPressed() onBackPressedDispatcher.onBackPressed()
} }
binding.settingsUseMaterialYou.isChecked = PrefWrapper.getVal(PrefName.UseMaterialYou, false) binding.settingsUseMaterialYou.isChecked = PrefManager.getVal(PrefName.UseMaterialYou)
binding.settingsUseMaterialYou.setOnCheckedChangeListener { _, isChecked -> binding.settingsUseMaterialYou.setOnCheckedChangeListener { _, isChecked ->
PrefWrapper.setVal(PrefName.UseMaterialYou, isChecked) PrefManager.setVal(PrefName.UseMaterialYou, isChecked)
if (isChecked) binding.settingsUseCustomTheme.isChecked = false if (isChecked) binding.settingsUseCustomTheme.isChecked = false
restartApp() restartApp()
} }
binding.settingsUseCustomTheme.isChecked = PrefWrapper.getVal(PrefName.UseCustomTheme, false) binding.settingsUseCustomTheme.isChecked = PrefManager.getVal(PrefName.UseCustomTheme)
binding.settingsUseCustomTheme.setOnCheckedChangeListener { _, isChecked -> binding.settingsUseCustomTheme.setOnCheckedChangeListener { _, isChecked ->
PrefWrapper.setVal(PrefName.UseCustomTheme, isChecked) PrefManager.setVal(PrefName.UseCustomTheme, isChecked)
if (isChecked) { if (isChecked) {
binding.settingsUseMaterialYou.isChecked = false binding.settingsUseMaterialYou.isChecked = false
} }
@ -114,19 +156,19 @@ class SettingsActivity : AppCompatActivity(), SimpleDialog.OnDialogResultListene
restartApp() restartApp()
} }
binding.settingsUseSourceTheme.isChecked = PrefWrapper.getVal(PrefName.UseSourceTheme, false) binding.settingsUseSourceTheme.isChecked = PrefManager.getVal(PrefName.UseSourceTheme)
binding.settingsUseSourceTheme.setOnCheckedChangeListener { _, isChecked -> binding.settingsUseSourceTheme.setOnCheckedChangeListener { _, isChecked ->
PrefWrapper.setVal(PrefName.UseSourceTheme, isChecked) PrefManager.setVal(PrefName.UseSourceTheme, isChecked)
restartApp() restartApp()
} }
binding.settingsUseOLED.isChecked = PrefWrapper.getVal(PrefName.UseOLED, false) binding.settingsUseOLED.isChecked = PrefManager.getVal(PrefName.UseOLED)
binding.settingsUseOLED.setOnCheckedChangeListener { _, isChecked -> binding.settingsUseOLED.setOnCheckedChangeListener { _, isChecked ->
PrefWrapper.setVal(PrefName.UseOLED, isChecked) PrefManager.setVal(PrefName.UseOLED, isChecked)
restartApp() restartApp()
} }
val themeString = PrefWrapper.getVal(PrefName.Theme, "PURPLE") val themeString: String = PrefManager.getVal(PrefName.Theme)
binding.themeSwitcher.setText( binding.themeSwitcher.setText(
themeString.substring(0, 1) + themeString.substring(1).lowercase() themeString.substring(0, 1) + themeString.substring(1).lowercase()
) )
@ -140,7 +182,7 @@ class SettingsActivity : AppCompatActivity(), SimpleDialog.OnDialogResultListene
) )
binding.themeSwitcher.setOnItemClickListener { _, _, i, _ -> binding.themeSwitcher.setOnItemClickListener { _, _, i, _ ->
PrefWrapper.setVal(PrefName.Theme, ThemeManager.Companion.Theme.entries[i].theme) PrefManager.setVal(PrefName.Theme, ThemeManager.Companion.Theme.entries[i].theme)
//ActivityHelper.shouldRefreshMainActivity = true //ActivityHelper.shouldRefreshMainActivity = true
binding.themeSwitcher.clearFocus() binding.themeSwitcher.clearFocus()
restartApp() restartApp()
@ -149,7 +191,7 @@ class SettingsActivity : AppCompatActivity(), SimpleDialog.OnDialogResultListene
binding.customTheme.setOnClickListener { binding.customTheme.setOnClickListener {
val originalColor = PrefWrapper.getVal(PrefName.CustomThemeInt, Color.parseColor("#6200EE")) val originalColor: Int = PrefManager.getVal(PrefName.CustomThemeInt)
class CustomColorDialog : SimpleColorDialog() { //idk where to put it class CustomColorDialog : SimpleColorDialog() { //idk where to put it
override fun onPositiveButtonClick() { override fun onPositiveButtonClick() {
@ -176,7 +218,7 @@ class SettingsActivity : AppCompatActivity(), SimpleDialog.OnDialogResultListene
val names = animeSourcesWithoutDownloadsSource.map { it.name } val names = animeSourcesWithoutDownloadsSource.map { it.name }
val pinnedSourcesBoolean = val pinnedSourcesBoolean =
animeSourcesWithoutDownloadsSource.map { it.name in AnimeSources.pinnedAnimeSources } animeSourcesWithoutDownloadsSource.map { it.name in AnimeSources.pinnedAnimeSources }
val pinnedSourcesOriginal = PrefWrapper.getVal(PrefName.PinnedAnimeSources, setOf<String>()) val pinnedSourcesOriginal: Set<String> = PrefManager.getVal(PrefName.PinnedAnimeSources)
val pinnedSources = pinnedSourcesOriginal.toMutableSet() ?: mutableSetOf() val pinnedSources = pinnedSourcesOriginal.toMutableSet() ?: mutableSetOf()
val alertDialog = AlertDialog.Builder(this, R.style.MyPopup) val alertDialog = AlertDialog.Builder(this, R.style.MyPopup)
.setTitle("Pinned Anime Sources") .setTitle("Pinned Anime Sources")
@ -191,7 +233,7 @@ class SettingsActivity : AppCompatActivity(), SimpleDialog.OnDialogResultListene
} }
} }
.setPositiveButton("OK") { dialog, _ -> .setPositiveButton("OK") { dialog, _ ->
PrefWrapper.setVal(PrefName.PinnedAnimeSources, pinnedSources) PrefManager.setVal(PrefName.PinnedAnimeSources, pinnedSources)
AnimeSources.pinnedAnimeSources = pinnedSources AnimeSources.pinnedAnimeSources = pinnedSources
AnimeSources.performReorderAnimeSources() AnimeSources.performReorderAnimeSources()
dialog.dismiss() dialog.dismiss()
@ -208,19 +250,43 @@ class SettingsActivity : AppCompatActivity(), SimpleDialog.OnDialogResultListene
val managers = arrayOf("Default", "1DM", "ADM") val managers = arrayOf("Default", "1DM", "ADM")
val downloadManagerDialog = val downloadManagerDialog =
AlertDialog.Builder(this, R.style.MyPopup).setTitle("Download Manager") AlertDialog.Builder(this, R.style.MyPopup).setTitle("Download Manager")
var downloadManager = PrefWrapper.getVal(PrefName.DownloadManager, 0) var downloadManager: Int = PrefManager.getVal(PrefName.DownloadManager)
binding.settingsDownloadManager.setOnClickListener { binding.settingsDownloadManager.setOnClickListener {
val dialog = downloadManagerDialog.setSingleChoiceItems( val dialog = downloadManagerDialog.setSingleChoiceItems(
managers, managers,
downloadManager downloadManager
) { dialog, count -> ) { dialog, count ->
downloadManager = count downloadManager = count
PrefWrapper.setVal(PrefName.DownloadManager, downloadManager) PrefManager.setVal(PrefName.DownloadManager, downloadManager)
dialog.dismiss() dialog.dismiss()
}.show() }.show()
dialog.window?.setDimAmount(0.8f) dialog.window?.setDimAmount(0.8f)
} }
binding.importExportSettings.setOnClickListener {
val dialog = AlertDialog.Builder(this, R.style.MyPopup)
.setTitle("Import/Export Settings")
.setSingleChoiceItems(Location.entries.map { it.name }.toTypedArray(), 0) { dialog, which ->
selectedImpExp = Location.entries[which].name
}
.setPositiveButton("Import...") { dialog, _ ->
openDocumentLauncher.launch("Select a file")
dialog.dismiss()
}
.setNegativeButton("Export...") { dialog, which ->
savePrefsToDownloads(Location.entries[which].name,
PrefManager.exportAllPrefs(Location.entries[which]),
this@SettingsActivity)
dialog.dismiss()
}
.setNeutralButton("Cancel") { dialog, _ ->
dialog.dismiss()
}
.create()
dialog.window?.setDimAmount(0.8f)
dialog.show()
}
binding.purgeAnimeDownloads.setOnClickListener { binding.purgeAnimeDownloads.setOnClickListener {
val dialog = AlertDialog.Builder(this, R.style.MyPopup) val dialog = AlertDialog.Builder(this, R.style.MyPopup)
.setTitle("Purge Anime Downloads") .setTitle("Purge Anime Downloads")
@ -287,30 +353,29 @@ class SettingsActivity : AppCompatActivity(), SimpleDialog.OnDialogResultListene
} }
} }
binding.skipExtensionIcons.isChecked = PrefWrapper.getVal(PrefName.SkipExtensionIcons, false) binding.skipExtensionIcons.isChecked = PrefManager.getVal(PrefName.SkipExtensionIcons)
binding.skipExtensionIcons.setOnCheckedChangeListener { _, isChecked -> binding.skipExtensionIcons.setOnCheckedChangeListener { _, isChecked ->
PrefWrapper.getVal(PrefName.SkipExtensionIcons, isChecked) PrefManager.getVal(PrefName.SkipExtensionIcons, isChecked)
} }
binding.NSFWExtension.isChecked = PrefWrapper.getVal(PrefName.NSFWExtension, true) binding.NSFWExtension.isChecked = PrefManager.getVal(PrefName.NSFWExtension)
binding.NSFWExtension.setOnCheckedChangeListener { _, isChecked -> binding.NSFWExtension.setOnCheckedChangeListener { _, isChecked ->
PrefWrapper.setVal(PrefName.NSFWExtension,isChecked) PrefManager.setVal(PrefName.NSFWExtension,isChecked)
} }
binding.userAgent.setOnClickListener { binding.userAgent.setOnClickListener {
val dialogView = layoutInflater.inflate(R.layout.dialog_user_agent, null) val dialogView = layoutInflater.inflate(R.layout.dialog_user_agent, null)
val editText = dialogView.findViewById<TextInputEditText>(R.id.userAgentTextBox) val editText = dialogView.findViewById<TextInputEditText>(R.id.userAgentTextBox)
editText.setText(networkPreferences.defaultUserAgent().get()) editText.setText(PrefManager.getVal<String>(PrefName.DefaultUserAgent))
val alertDialog = AlertDialog.Builder(this, R.style.MyPopup) val alertDialog = AlertDialog.Builder(this, R.style.MyPopup)
.setTitle("User Agent") .setTitle("User Agent")
.setView(dialogView) .setView(dialogView)
.setPositiveButton("OK") { dialog, _ -> .setPositiveButton("OK") { dialog, _ ->
networkPreferences.defaultUserAgent().set(editText.text.toString()) PrefManager.setVal(PrefName.DefaultUserAgent, editText.text.toString())
dialog.dismiss() dialog.dismiss()
} }
.setNeutralButton("Reset") { dialog, _ -> .setNeutralButton("Reset") { dialog, _ ->
networkPreferences.defaultUserAgent() PrefManager.removeVal(PrefName.DefaultUserAgent)
.set("Mozilla/5.0 (Windows NT 10.0; Win64; x64; rv:110.0) Gecko/20100101 Firefox/110.0")
editText.setText("") editText.setText("")
dialog.dismiss() dialog.dismiss()
} }
@ -340,45 +405,45 @@ class SettingsActivity : AppCompatActivity(), SimpleDialog.OnDialogResultListene
"Shecan", "Shecan",
"Libre" "Libre"
) )
binding.settingsExtensionDns.setText(exDns[networkPreferences.dohProvider().get()], false) binding.settingsExtensionDns.setText(exDns[PrefManager.getVal(PrefName.DohProvider)])
binding.settingsExtensionDns.setAdapter(ArrayAdapter(this, R.layout.item_dropdown, exDns)) binding.settingsExtensionDns.setAdapter(ArrayAdapter(this, R.layout.item_dropdown, exDns))
binding.settingsExtensionDns.setOnItemClickListener { _, _, i, _ -> binding.settingsExtensionDns.setOnItemClickListener { _, _, i, _ ->
networkPreferences.dohProvider().set(i) PrefManager.setVal(PrefName.DohProvider, i)
binding.settingsExtensionDns.clearFocus() binding.settingsExtensionDns.clearFocus()
Toast.makeText(this, "Restart app to apply changes", Toast.LENGTH_LONG).show() Toast.makeText(this, "Restart app to apply changes", Toast.LENGTH_LONG).show()
} }
binding.settingsDownloadInSd.isChecked = PrefWrapper.getVal(PrefName.SdDl, false) binding.settingsDownloadInSd.isChecked = PrefManager.getVal(PrefName.SdDl)
binding.settingsDownloadInSd.setOnCheckedChangeListener { _, isChecked -> binding.settingsDownloadInSd.setOnCheckedChangeListener { _, isChecked ->
if (isChecked) { if (isChecked) {
val arrayOfFiles = ContextCompat.getExternalFilesDirs(this, null) val arrayOfFiles = ContextCompat.getExternalFilesDirs(this, null)
if (arrayOfFiles.size > 1 && arrayOfFiles[1] != null) { if (arrayOfFiles.size > 1 && arrayOfFiles[1] != null) {
PrefWrapper.setVal(PrefName.SdDl, true) PrefManager.setVal(PrefName.SdDl, true)
} else { } else {
binding.settingsDownloadInSd.isChecked = false binding.settingsDownloadInSd.isChecked = false
PrefWrapper.setVal(PrefName.SdDl, true) PrefManager.setVal(PrefName.SdDl, true)
snackString(getString(R.string.noSdFound)) snackString(getString(R.string.noSdFound))
} }
} else PrefWrapper.setVal(PrefName.SdDl, true) } else PrefManager.setVal(PrefName.SdDl, true)
} }
binding.settingsContinueMedia.isChecked = PrefWrapper.getVal(PrefName.ContinueMedia, true) binding.settingsContinueMedia.isChecked = PrefManager.getVal(PrefName.ContinueMedia)
binding.settingsContinueMedia.setOnCheckedChangeListener { _, isChecked -> binding.settingsContinueMedia.setOnCheckedChangeListener { _, isChecked ->
PrefWrapper.setVal(PrefName.ContinueMedia, isChecked) PrefManager.setVal(PrefName.ContinueMedia, isChecked)
} }
binding.settingsRecentlyListOnly.isChecked = PrefWrapper.getVal(PrefName.RecentlyListOnly, false) binding.settingsRecentlyListOnly.isChecked = PrefManager.getVal(PrefName.RecentlyListOnly)
binding.settingsRecentlyListOnly.setOnCheckedChangeListener { _, isChecked -> binding.settingsRecentlyListOnly.setOnCheckedChangeListener { _, isChecked ->
PrefWrapper.setVal(PrefName.RecentlyListOnly, isChecked) PrefManager.setVal(PrefName.RecentlyListOnly, isChecked)
} }
binding.settingsShareUsername.isChecked = PrefWrapper.getVal(PrefName.SharedUserID, true) binding.settingsShareUsername.isChecked = PrefManager.getVal(PrefName.SharedUserID)
binding.settingsShareUsername.setOnCheckedChangeListener { _, isChecked -> binding.settingsShareUsername.setOnCheckedChangeListener { _, isChecked ->
PrefWrapper.setVal(PrefName.SharedUserID, isChecked) PrefManager.setVal(PrefName.SharedUserID, isChecked)
} }
binding.settingsPreferDub.isChecked = PrefWrapper.getVal(PrefName.SettingsPreferDub, false) binding.settingsPreferDub.isChecked = PrefManager.getVal(PrefName.SettingsPreferDub)
binding.settingsPreferDub.setOnCheckedChangeListener { _, isChecked -> binding.settingsPreferDub.setOnCheckedChangeListener { _, isChecked ->
PrefWrapper.setVal(PrefName.SettingsPreferDub, isChecked) PrefManager.setVal(PrefName.SettingsPreferDub, isChecked)
} }
binding.settingsPinnedMangaSources.setOnClickListener { binding.settingsPinnedMangaSources.setOnClickListener {
@ -387,7 +452,7 @@ class SettingsActivity : AppCompatActivity(), SimpleDialog.OnDialogResultListene
val names = mangaSourcesWithoutDownloadsSource.map { it.name } val names = mangaSourcesWithoutDownloadsSource.map { it.name }
val pinnedSourcesBoolean = val pinnedSourcesBoolean =
mangaSourcesWithoutDownloadsSource.map { it.name in MangaSources.pinnedMangaSources } mangaSourcesWithoutDownloadsSource.map { it.name in MangaSources.pinnedMangaSources }
val pinnedSourcesOriginal = PrefWrapper.getVal(PrefName.PinnedMangaSources, setOf<String>()) val pinnedSourcesOriginal: Set<String> = PrefManager.getVal(PrefName.PinnedMangaSources)
val pinnedSources = pinnedSourcesOriginal.toMutableSet() val pinnedSources = pinnedSourcesOriginal.toMutableSet()
val alertDialog = AlertDialog.Builder(this, R.style.MyPopup) val alertDialog = AlertDialog.Builder(this, R.style.MyPopup)
.setTitle("Pinned Manga Sources") .setTitle("Pinned Manga Sources")
@ -402,7 +467,7 @@ class SettingsActivity : AppCompatActivity(), SimpleDialog.OnDialogResultListene
} }
} }
.setPositiveButton("OK") { dialog, _ -> .setPositiveButton("OK") { dialog, _ ->
PrefWrapper.setVal(PrefName.PinnedMangaSources, pinnedSources) PrefManager.setVal(PrefName.PinnedMangaSources, pinnedSources)
MangaSources.pinnedMangaSources = pinnedSources MangaSources.pinnedMangaSources = pinnedSources
MangaSources.performReorderMangaSources() MangaSources.performReorderMangaSources()
dialog.dismiss() dialog.dismiss()
@ -416,10 +481,7 @@ class SettingsActivity : AppCompatActivity(), SimpleDialog.OnDialogResultListene
startActivity(Intent(this, ReaderSettingsActivity::class.java)) startActivity(Intent(this, ReaderSettingsActivity::class.java))
} }
val uiSettings: UserInterfaceSettings = var previous: View = when (PrefManager.getNullableVal(PrefName.DarkMode, null as Boolean?)) {
loadData("ui_settings", toast = false)
?: UserInterfaceSettings().apply { saveData("ui_settings", this) }
var previous: View = when (uiSettings.darkMode) {
null -> binding.settingsUiAuto null -> binding.settingsUiAuto
true -> binding.settingsUiDark true -> binding.settingsUiDark
false -> binding.settingsUiLight false -> binding.settingsUiLight
@ -429,8 +491,11 @@ class SettingsActivity : AppCompatActivity(), SimpleDialog.OnDialogResultListene
previous.alpha = 0.33f previous.alpha = 0.33f
previous = current previous = current
current.alpha = 1f current.alpha = 1f
uiSettings.darkMode = mode if (mode == null) {
saveData("ui_settings", uiSettings) PrefManager.removeVal(PrefName.DarkMode)
} else {
PrefManager.setVal(PrefName.DarkMode, mode)
}
Refresh.all() Refresh.all()
finish() finish()
startActivity(Intent(this, SettingsActivity::class.java)) startActivity(Intent(this, SettingsActivity::class.java))
@ -450,7 +515,7 @@ class SettingsActivity : AppCompatActivity(), SimpleDialog.OnDialogResultListene
uiTheme(true, it) uiTheme(true, it)
} }
var previousStart: View = when (uiSettings.defaultStartUpTab) { var previousStart: View = when (PrefManager.getVal<Int>(PrefName.DefaultStartUpTab)) {
0 -> binding.uiSettingsAnime 0 -> binding.uiSettingsAnime
1 -> binding.uiSettingsHome 1 -> binding.uiSettingsHome
2 -> binding.uiSettingsManga 2 -> binding.uiSettingsManga
@ -461,8 +526,7 @@ class SettingsActivity : AppCompatActivity(), SimpleDialog.OnDialogResultListene
previousStart.alpha = 0.33f previousStart.alpha = 0.33f
previousStart = current previousStart = current
current.alpha = 1f current.alpha = 1f
uiSettings.defaultStartUpTab = mode PrefManager.setVal(PrefName.DefaultStartUpTab, mode)
saveData("ui_settings", uiSettings)
initActivity(this) initActivity(this)
} }
@ -479,13 +543,12 @@ class SettingsActivity : AppCompatActivity(), SimpleDialog.OnDialogResultListene
uiTheme(2, it) uiTheme(2, it)
} }
binding.settingsShowYt.isChecked = uiSettings.showYtButton binding.settingsShowYt.isChecked = PrefManager.getVal(PrefName.ShowYtButton)
binding.settingsShowYt.setOnCheckedChangeListener { _, isChecked -> binding.settingsShowYt.setOnCheckedChangeListener { _, isChecked ->
uiSettings.showYtButton = isChecked PrefManager.setVal(PrefName.ShowYtButton, isChecked)
saveData("ui_settings", uiSettings)
} }
var previousEp: View = when (uiSettings.animeDefaultView) { var previousEp: View = when (PrefManager.getVal<Int>(PrefName.AnimeDefaultView)) {
0 -> binding.settingsEpList 0 -> binding.settingsEpList
1 -> binding.settingsEpGrid 1 -> binding.settingsEpGrid
2 -> binding.settingsEpCompact 2 -> binding.settingsEpCompact
@ -496,8 +559,7 @@ class SettingsActivity : AppCompatActivity(), SimpleDialog.OnDialogResultListene
previousEp.alpha = 0.33f previousEp.alpha = 0.33f
previousEp = current previousEp = current
current.alpha = 1f current.alpha = 1f
uiSettings.animeDefaultView = mode PrefManager.setVal(PrefName.AnimeDefaultView, mode)
saveData("ui_settings", uiSettings)
} }
binding.settingsEpList.setOnClickListener { binding.settingsEpList.setOnClickListener {
@ -512,7 +574,7 @@ class SettingsActivity : AppCompatActivity(), SimpleDialog.OnDialogResultListene
uiEp(2, it) uiEp(2, it)
} }
var previousChp: View = when (uiSettings.mangaDefaultView) { var previousChp: View = when (PrefManager.getVal<Int>(PrefName.MangaDefaultView)) {
0 -> binding.settingsChpList 0 -> binding.settingsChpList
1 -> binding.settingsChpCompact 1 -> binding.settingsChpCompact
else -> binding.settingsChpList else -> binding.settingsChpList
@ -522,8 +584,7 @@ class SettingsActivity : AppCompatActivity(), SimpleDialog.OnDialogResultListene
previousChp.alpha = 0.33f previousChp.alpha = 0.33f
previousChp = current previousChp = current
current.alpha = 1f current.alpha = 1f
uiSettings.mangaDefaultView = mode PrefManager.setVal(PrefName.MangaDefaultView, mode)
saveData("ui_settings", uiSettings)
} }
binding.settingsChpList.setOnClickListener { binding.settingsChpList.setOnClickListener {
@ -571,7 +632,7 @@ class SettingsActivity : AppCompatActivity(), SimpleDialog.OnDialogResultListene
Toast.makeText(this, "youwu have been cuwsed :pwayge:", Toast.LENGTH_LONG).show() Toast.makeText(this, "youwu have been cuwsed :pwayge:", Toast.LENGTH_LONG).show()
val url = "https://www.youtube.com/watch?v=dQw4w9WgXcQ" val url = "https://www.youtube.com/watch?v=dQw4w9WgXcQ"
openLinkInBrowser(url) openLinkInBrowser(url)
//PrefWrapper.setVal(PrefName.SomethingSpecial, !PrefWrapper.getVal(PrefName.SomethingSpecial, false)) //PrefManager.setVal(PrefName.SomethingSpecial, !PrefManager.getVal(PrefName.SomethingSpecial, false))
} else { } else {
snackString(array[(Math.random() * array.size).toInt()], this) snackString(array[(Math.random() * array.size).toInt()], this)
} }
@ -599,7 +660,7 @@ class SettingsActivity : AppCompatActivity(), SimpleDialog.OnDialogResultListene
} }
} }
var curTime = PrefWrapper.getVal(PrefName.SubscriptionsTimeS, defaultTime) var curTime = PrefManager.getVal(PrefName.SubscriptionsTimeS, defaultTime)
val timeNames = timeMinutes.map { val timeNames = timeMinutes.map {
val mins = it % 60 val mins = it % 60
val hours = it / 60 val hours = it / 60
@ -615,7 +676,7 @@ class SettingsActivity : AppCompatActivity(), SimpleDialog.OnDialogResultListene
curTime = i curTime = i
binding.settingsSubscriptionsTime.text = binding.settingsSubscriptionsTime.text =
getString(R.string.subscriptions_checking_time_s, timeNames[i]) getString(R.string.subscriptions_checking_time_s, timeNames[i])
PrefWrapper.setVal(PrefName.SubscriptionsTimeS, curTime) PrefManager.setVal(PrefName.SubscriptionsTimeS, curTime)
dialog.dismiss() dialog.dismiss()
startSubscription(true) startSubscription(true)
}.show() }.show()
@ -628,9 +689,9 @@ class SettingsActivity : AppCompatActivity(), SimpleDialog.OnDialogResultListene
} }
binding.settingsNotificationsCheckingSubscriptions.isChecked = binding.settingsNotificationsCheckingSubscriptions.isChecked =
PrefWrapper.getVal(PrefName.SubscriptionCheckingNotifications, true) PrefManager.getVal(PrefName.SubscriptionCheckingNotifications)
binding.settingsNotificationsCheckingSubscriptions.setOnCheckedChangeListener { _, isChecked -> binding.settingsNotificationsCheckingSubscriptions.setOnCheckedChangeListener { _, isChecked ->
PrefWrapper.setVal(PrefName.SubscriptionCheckingNotifications, isChecked) PrefManager.setVal(PrefName.SubscriptionCheckingNotifications, isChecked)
if (isChecked) if (isChecked)
Notifications.createChannel( Notifications.createChannel(
this, this,
@ -648,10 +709,9 @@ class SettingsActivity : AppCompatActivity(), SimpleDialog.OnDialogResultListene
} }
binding.settingsCheckUpdate.isChecked = PrefWrapper.getVal(PrefName.CheckUpdate, true) binding.settingsCheckUpdate.isChecked = PrefManager.getVal(PrefName.CheckUpdate)
binding.settingsCheckUpdate.setOnCheckedChangeListener { _, isChecked -> binding.settingsCheckUpdate.setOnCheckedChangeListener { _, isChecked ->
saveData("check_update", isChecked) PrefManager.setVal(PrefName.CheckUpdate, isChecked)
PrefWrapper.setVal(PrefName.CheckUpdate, isChecked)
if (!isChecked) { if (!isChecked) {
snackString(getString(R.string.long_click_to_check_update)) snackString(getString(R.string.long_click_to_check_update))
} }
@ -733,9 +793,9 @@ class SettingsActivity : AppCompatActivity(), SimpleDialog.OnDialogResultListene
} }
if (Discord.token != null) { if (Discord.token != null) {
val id = PrefWrapper.getVal(PrefName.DiscordId, null as String?) val id = PrefManager.getVal(PrefName.DiscordId, null as String?)
val avatar = PrefWrapper.getVal(PrefName.DiscordAvatar, null as String?) val avatar = PrefManager.getVal(PrefName.DiscordAvatar, null as String?)
val username = PrefWrapper.getVal(PrefName.DiscordUserName, null as String?) val username = PrefManager.getVal(PrefName.DiscordUserName, null as String?)
if (id != null && avatar != null) { if (id != null && avatar != null) {
binding.settingsDiscordAvatar.loadImage("https://cdn.discordapp.com/avatars/$id/$avatar.png") binding.settingsDiscordAvatar.loadImage("https://cdn.discordapp.com/avatars/$id/$avatar.png")
} }
@ -790,7 +850,7 @@ class SettingsActivity : AppCompatActivity(), SimpleDialog.OnDialogResultListene
if (which == BUTTON_POSITIVE) { if (which == BUTTON_POSITIVE) {
if (dialogTag == "colorPicker") { if (dialogTag == "colorPicker") {
val color = extras.getInt(SimpleColorDialog.COLOR) val color = extras.getInt(SimpleColorDialog.COLOR)
PrefWrapper.setVal(PrefName.CustomThemeInt, color) PrefManager.setVal(PrefName.CustomThemeInt, color)
logger("Custom Theme: $color") logger("Custom Theme: $color")
} }
} }

View file

@ -26,7 +26,7 @@ import ani.dantotsu.openLinkInBrowser
import ani.dantotsu.others.imagesearch.ImageSearchActivity import ani.dantotsu.others.imagesearch.ImageSearchActivity
import ani.dantotsu.setSafeOnClickListener import ani.dantotsu.setSafeOnClickListener
import ani.dantotsu.settings.saving.PrefName import ani.dantotsu.settings.saving.PrefName
import ani.dantotsu.settings.saving.PrefWrapper import ani.dantotsu.settings.saving.PrefManager
import ani.dantotsu.startMainActivity import ani.dantotsu.startMainActivity
class SettingsDialogFragment : BottomSheetDialogFragment() { class SettingsDialogFragment : BottomSheetDialogFragment() {
@ -76,10 +76,10 @@ class SettingsDialogFragment : BottomSheetDialogFragment() {
} }
binding.settingsIncognito.isChecked = binding.settingsIncognito.isChecked =
PrefWrapper.getVal(PrefName.Incognito, false) PrefManager.getVal(PrefName.Incognito)
binding.settingsIncognito.setOnCheckedChangeListener { _, isChecked -> binding.settingsIncognito.setOnCheckedChangeListener { _, isChecked ->
PrefWrapper.setVal(PrefName.Incognito, isChecked) PrefManager.setVal(PrefName.Incognito, isChecked)
incognitoNotification(requireContext()) incognitoNotification(requireContext())
} }
binding.settingsExtensionSettings.setSafeOnClickListener { binding.settingsExtensionSettings.setSafeOnClickListener {
@ -99,7 +99,7 @@ class SettingsDialogFragment : BottomSheetDialogFragment() {
dismiss() dismiss()
} }
binding.settingsDownloads.isChecked = PrefWrapper.getVal(PrefName.OfflineMode, false) binding.settingsDownloads.isChecked = PrefManager.getVal(PrefName.OfflineMode)
binding.settingsDownloads.setOnCheckedChangeListener { _, isChecked -> binding.settingsDownloads.setOnCheckedChangeListener { _, isChecked ->
when (pageType) { when (pageType) {
PageType.MANGA -> { PageType.MANGA -> {
@ -149,7 +149,7 @@ class SettingsDialogFragment : BottomSheetDialogFragment() {
} }
dismiss() dismiss()
PrefWrapper.setVal(PrefName.OfflineMode, isChecked) PrefManager.setVal(PrefName.OfflineMode, isChecked)
} }
} }

View file

@ -1,30 +0,0 @@
package ani.dantotsu.settings
import java.io.Serializable
data class UserInterfaceSettings(
var darkMode: Boolean? = null,
var showYtButton: Boolean = true,
var animeDefaultView: Int = 0,
var mangaDefaultView: Int = 0,
//App
var immersiveMode: Boolean = false,
var smallView: Boolean = true,
var defaultStartUpTab: Int = 1,
var homeLayoutShow: MutableList<Boolean> = mutableListOf(
true,
false,
false,
true,
false,
false,
true
),
//Animations
var bannerAnimations: Boolean = true,
var layoutAnimations: Boolean = true,
var animationSpeed: Float = 1f
) : Serializable

View file

@ -9,9 +9,9 @@ import androidx.core.view.updateLayoutParams
import ani.dantotsu.R import ani.dantotsu.R
import ani.dantotsu.databinding.ActivityUserInterfaceSettingsBinding import ani.dantotsu.databinding.ActivityUserInterfaceSettingsBinding
import ani.dantotsu.initActivity import ani.dantotsu.initActivity
import ani.dantotsu.loadData
import ani.dantotsu.navBarHeight import ani.dantotsu.navBarHeight
import ani.dantotsu.saveData import ani.dantotsu.settings.saving.PrefName
import ani.dantotsu.settings.saving.PrefManager
import ani.dantotsu.statusBarHeight import ani.dantotsu.statusBarHeight
import ani.dantotsu.themes.ThemeManager import ani.dantotsu.themes.ThemeManager
import com.google.android.material.snackbar.Snackbar import com.google.android.material.snackbar.Snackbar
@ -32,9 +32,6 @@ class UserInterfaceSettingsActivity : AppCompatActivity() {
bottomMargin = navBarHeight bottomMargin = navBarHeight
} }
val settings = loadData<UserInterfaceSettings>(ui, toast = false)
?: UserInterfaceSettings().apply { saveData(ui, this) }
binding.uiSettingsBack.setOnClickListener { binding.uiSettingsBack.setOnClickListener {
onBackPressedDispatcher.onBackPressed() onBackPressedDispatcher.onBackPressed()
} }
@ -45,39 +42,36 @@ class UserInterfaceSettingsActivity : AppCompatActivity() {
.setTitle(getString(R.string.home_layout_show)).apply { .setTitle(getString(R.string.home_layout_show)).apply {
setMultiChoiceItems( setMultiChoiceItems(
views, views,
settings.homeLayoutShow.toBooleanArray() PrefManager.getVal<List<Boolean>>(PrefName.HomeLayoutShow).toBooleanArray()
) { _, i, value -> ) { _, i, value ->
settings.homeLayoutShow[i] = value val set = PrefManager.getVal<List<Boolean>>(PrefName.HomeLayoutShow).toMutableList()
saveData(ui, settings) set[i] = value
PrefManager.setVal(PrefName.HomeLayoutShow, set)
} }
}.show() }.show()
dialog.window?.setDimAmount(0.8f) dialog.window?.setDimAmount(0.8f)
} }
binding.uiSettingsSmallView.isChecked = settings.smallView binding.uiSettingsSmallView.isChecked = PrefManager.getVal(PrefName.SmallView)
binding.uiSettingsSmallView.setOnCheckedChangeListener { _, isChecked -> binding.uiSettingsSmallView.setOnCheckedChangeListener { _, isChecked ->
settings.smallView = isChecked PrefManager.setVal(PrefName.SmallView, isChecked)
saveData(ui, settings)
restartApp() restartApp()
} }
binding.uiSettingsImmersive.isChecked = settings.immersiveMode binding.uiSettingsImmersive.isChecked = PrefManager.getVal(PrefName.ImmersiveMode)
binding.uiSettingsImmersive.setOnCheckedChangeListener { _, isChecked -> binding.uiSettingsImmersive.setOnCheckedChangeListener { _, isChecked ->
settings.immersiveMode = isChecked PrefManager.setVal(PrefName.ImmersiveMode, isChecked)
saveData(ui, settings)
restartApp() restartApp()
} }
binding.uiSettingsBannerAnimation.isChecked = settings.bannerAnimations binding.uiSettingsBannerAnimation.isChecked = PrefManager.getVal(PrefName.BannerAnimations)
binding.uiSettingsBannerAnimation.setOnCheckedChangeListener { _, isChecked -> binding.uiSettingsBannerAnimation.setOnCheckedChangeListener { _, isChecked ->
settings.bannerAnimations = isChecked PrefManager.setVal(PrefName.BannerAnimations, isChecked)
saveData(ui, settings)
restartApp() restartApp()
} }
binding.uiSettingsLayoutAnimation.isChecked = settings.layoutAnimations binding.uiSettingsLayoutAnimation.isChecked = PrefManager.getVal(PrefName.LayoutAnimations)
binding.uiSettingsLayoutAnimation.setOnCheckedChangeListener { _, isChecked -> binding.uiSettingsLayoutAnimation.setOnCheckedChangeListener { _, isChecked ->
settings.layoutAnimations = isChecked PrefManager.setVal(PrefName.LayoutAnimations, isChecked)
saveData(ui, settings)
restartApp() restartApp()
} }
@ -93,10 +87,9 @@ class UserInterfaceSettingsActivity : AppCompatActivity() {
0f to 0f 0f to 0f
) )
val mapReverse = map.map { it.value to it.key }.toMap() val mapReverse = map.map { it.value to it.key }.toMap()
binding.uiSettingsAnimationSpeed.value = mapReverse[settings.animationSpeed] ?: 1f binding.uiSettingsAnimationSpeed.value = mapReverse[PrefManager.getVal(PrefName.AnimationSpeed)] ?: 1f
binding.uiSettingsAnimationSpeed.addOnChangeListener { _, value, _ -> binding.uiSettingsAnimationSpeed.addOnChangeListener { _, value, _ ->
settings.animationSpeed = map[value] ?: 1f PrefManager.setVal(PrefName.AnimationSpeed, map[value] ?: 1f)
saveData(ui, settings)
restartApp() restartApp()
} }

View file

@ -21,7 +21,7 @@ import ani.dantotsu.R
import ani.dantotsu.databinding.ItemExtensionAllBinding import ani.dantotsu.databinding.ItemExtensionAllBinding
import ani.dantotsu.others.LanguageMapper import ani.dantotsu.others.LanguageMapper
import ani.dantotsu.settings.saving.PrefName import ani.dantotsu.settings.saving.PrefName
import ani.dantotsu.settings.saving.PrefWrapper import ani.dantotsu.settings.saving.PrefManager
import com.bumptech.glide.Glide import com.bumptech.glide.Glide
import eu.kanade.tachiyomi.extension.anime.AnimeExtensionManager import eu.kanade.tachiyomi.extension.anime.AnimeExtensionManager
import eu.kanade.tachiyomi.extension.anime.model.AnimeExtension import eu.kanade.tachiyomi.extension.anime.model.AnimeExtension
@ -93,14 +93,14 @@ class AnimeExtensionPagingSource(
val availableExtensions = val availableExtensions =
availableExtensionsFlow.filterNot { it.pkgName in installedExtensions } availableExtensionsFlow.filterNot { it.pkgName in installedExtensions }
val query = searchQuery val query = searchQuery
val isNsfwEnabled: Boolean = PrefWrapper.getVal(PrefName.NSFWExtension,true) val isNsfwEnabled: Boolean = PrefManager.getVal(PrefName.NSFWExtension)
val filteredExtensions = if (query.isEmpty()) { val filteredExtensions = if (query.isEmpty()) {
availableExtensions availableExtensions
} else { } else {
availableExtensions.filter { it.name.contains(query, ignoreCase = true) } availableExtensions.filter { it.name.contains(query, ignoreCase = true) }
} }
val lang = PrefWrapper.getVal(PrefName.LangSort, "all") 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 } val filternfsw = if (isNsfwEnabled) langFilter else langFilter.filterNot { it.isNsfw }
return try { return try {
@ -128,7 +128,7 @@ class AnimeExtensionAdapter(private val clickListener: OnAnimeInstallClickListen
DIFF_CALLBACK DIFF_CALLBACK
) { ) {
private val skipIcons = PrefWrapper.getVal(PrefName.SkipExtensionIcons, false) private val skipIcons: Boolean = PrefManager.getVal(PrefName.SkipExtensionIcons)
companion object { companion object {
private val DIFF_CALLBACK = object : DiffUtil.ItemCallback<AnimeExtension.Available>() { private val DIFF_CALLBACK = object : DiffUtil.ItemCallback<AnimeExtension.Available>() {

View file

@ -19,10 +19,9 @@ import androidx.recyclerview.widget.DiffUtil
import androidx.recyclerview.widget.RecyclerView import androidx.recyclerview.widget.RecyclerView
import ani.dantotsu.R import ani.dantotsu.R
import ani.dantotsu.databinding.ItemExtensionAllBinding import ani.dantotsu.databinding.ItemExtensionAllBinding
import ani.dantotsu.loadData
import ani.dantotsu.others.LanguageMapper import ani.dantotsu.others.LanguageMapper
import ani.dantotsu.settings.saving.PrefName import ani.dantotsu.settings.saving.PrefName
import ani.dantotsu.settings.saving.PrefWrapper import ani.dantotsu.settings.saving.PrefManager
import com.bumptech.glide.Glide import com.bumptech.glide.Glide
import eu.kanade.tachiyomi.extension.manga.MangaExtensionManager import eu.kanade.tachiyomi.extension.manga.MangaExtensionManager
import eu.kanade.tachiyomi.extension.manga.model.MangaExtension import eu.kanade.tachiyomi.extension.manga.model.MangaExtension
@ -94,13 +93,13 @@ class MangaExtensionPagingSource(
val availableExtensions = val availableExtensions =
availableExtensionsFlow.filterNot { it.pkgName in installedExtensions } availableExtensionsFlow.filterNot { it.pkgName in installedExtensions }
val query = searchQuery val query = searchQuery
val isNsfwEnabled: Boolean = PrefWrapper.getVal(PrefName.NSFWExtension,true) val isNsfwEnabled: Boolean = PrefManager.getVal(PrefName.NSFWExtension)
val filteredExtensions = if (query.isEmpty()) { val filteredExtensions = if (query.isEmpty()) {
availableExtensions availableExtensions
} else { } else {
availableExtensions.filter { it.name.contains(query, ignoreCase = true) } availableExtensions.filter { it.name.contains(query, ignoreCase = true) }
} }
val lang = PrefWrapper.getVal(PrefName.LangSort, "all") 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 } val filternfsw = if (isNsfwEnabled) langFilter else langFilter.filterNot { it.isNsfw }
return try { return try {
@ -128,7 +127,7 @@ class MangaExtensionAdapter(private val clickListener: OnMangaInstallClickListen
DIFF_CALLBACK DIFF_CALLBACK
) { ) {
private val skipIcons = PrefWrapper.getVal(PrefName.SkipExtensionIcons, false) private val skipIcons: Boolean = PrefManager.getVal(PrefName.SkipExtensionIcons)
companion object { companion object {
private val DIFF_CALLBACK = object : DiffUtil.ItemCallback<MangaExtension.Available>() { private val DIFF_CALLBACK = object : DiffUtil.ItemCallback<MangaExtension.Available>() {

View file

@ -18,12 +18,11 @@ import androidx.recyclerview.widget.DiffUtil
import androidx.recyclerview.widget.RecyclerView import androidx.recyclerview.widget.RecyclerView
import ani.dantotsu.R import ani.dantotsu.R
import ani.dantotsu.databinding.ItemExtensionAllBinding import ani.dantotsu.databinding.ItemExtensionAllBinding
import ani.dantotsu.loadData
import ani.dantotsu.others.LanguageMapper import ani.dantotsu.others.LanguageMapper
import ani.dantotsu.parsers.novel.NovelExtension import ani.dantotsu.parsers.novel.NovelExtension
import ani.dantotsu.parsers.novel.NovelExtensionManager import ani.dantotsu.parsers.novel.NovelExtensionManager
import ani.dantotsu.settings.saving.PrefName import ani.dantotsu.settings.saving.PrefName
import ani.dantotsu.settings.saving.PrefWrapper import ani.dantotsu.settings.saving.PrefManager
import com.bumptech.glide.Glide import com.bumptech.glide.Glide
import kotlinx.coroutines.CoroutineScope import kotlinx.coroutines.CoroutineScope
import kotlinx.coroutines.Dispatchers import kotlinx.coroutines.Dispatchers
@ -95,7 +94,7 @@ class NovelExtensionPagingSource(
val availableExtensions = val availableExtensions =
availableExtensionsFlow.filterNot { it.pkgName in installedExtensions } availableExtensionsFlow.filterNot { it.pkgName in installedExtensions }
val query = searchQuery val query = searchQuery
val isNsfwEnabled: Boolean = PrefWrapper.getVal(PrefName.NSFWExtension,true) val isNsfwEnabled: Boolean = PrefManager.getVal(PrefName.NSFWExtension)
val filteredExtensions = if (query.isEmpty()) { val filteredExtensions = if (query.isEmpty()) {
availableExtensions availableExtensions
} else { } else {
@ -132,7 +131,7 @@ class NovelExtensionAdapter(private val clickListener: OnNovelInstallClickListen
DIFF_CALLBACK DIFF_CALLBACK
) { ) {
private val skipIcons = PrefWrapper.getVal(PrefName.SkipExtensionIcons, false) private val skipIcons: Boolean = PrefManager.getVal(PrefName.SkipExtensionIcons)
companion object { companion object {
private val DIFF_CALLBACK = object : DiffUtil.ItemCallback<NovelExtension.Available>() { private val DIFF_CALLBACK = object : DiffUtil.ItemCallback<NovelExtension.Available>() {

View file

@ -0,0 +1,362 @@
package ani.dantotsu.settings.saving
import android.content.Context
import android.content.SharedPreferences
import android.util.Base64
import ani.dantotsu.settings.saving.internal.Compat
import ani.dantotsu.settings.saving.internal.Location
import ani.dantotsu.snackString
import java.io.ByteArrayInputStream
import java.io.ByteArrayOutputStream
import java.io.ObjectInputStream
import java.io.ObjectOutputStream
object PrefManager {
private var generalPreferences: SharedPreferences? = null
private var animePreferences: SharedPreferences? = null
private var mangaPreferences: SharedPreferences? = null
private var playerPreferences: SharedPreferences? = null
private var readerPreferences: SharedPreferences? = null
private var irrelevantPreferences: SharedPreferences? = null
private var animeDownloadsPreferences: SharedPreferences? = null
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)
animePreferences = context.getSharedPreferences(Location.Anime.location, Context.MODE_PRIVATE)
mangaPreferences = context.getSharedPreferences(Location.Manga.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)
}
fun <T> setVal(prefName: PrefName, value: T?) {
val pref = getPrefLocation(prefName.data.prefLocation)
with(pref.edit()) {
when (value) {
is Boolean -> putBoolean(prefName.name, value)
is Int -> putInt(prefName.name, value)
is Float -> putFloat(prefName.name, value)
is Long -> putLong(prefName.name, value)
is String -> putString(prefName.name, value)
is Set<*> -> convertAndPutStringSet(prefName.name, value)
null -> remove(prefName.name)
else -> serialzeClass(prefName.name, value)
}
apply()
}
}
@Suppress("UNCHECKED_CAST")
fun <T> getVal(prefName: PrefName, default: T) : T {
return try {
val pref = getPrefLocation(prefName.data.prefLocation)
when (prefName.data.type) {
Boolean::class -> pref.getBoolean(prefName.name, default as Boolean) as T
Int::class -> pref.getInt(prefName.name, default as Int) as T
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 -> deserialzeClass(prefName.name, default) as T
else -> throw IllegalArgumentException("Type not supported")
}
} catch (e: Exception) {
default
}
}
@Suppress("UNCHECKED_CAST")
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
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 -> deserialzeClass(prefName.name, prefName.data.default) as T
else -> throw IllegalArgumentException("Type not supported")
}
} catch (e: Exception) {
prefName.data.default as T
}
}
@Suppress("UNCHECKED_CAST")
fun <T> getNullableVal(prefName: PrefName, default: T?) : 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?
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?
else -> deserialzeClass(prefName.name, default)
}
} catch (e: Exception) {
default
}
}
@Suppress("UNCHECKED_CAST")
fun <T> getCustomVal(key: String, default: T): T {
return try {
when (default) {
is Boolean -> irrelevantPreferences!!.getBoolean(key, default) as T
is Int -> irrelevantPreferences!!.getInt(key, default) as T
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
else -> throw IllegalArgumentException("Type not supported")
}
} catch (e: Exception) {
default
}
}
@Suppress("UNCHECKED_CAST")
fun <T> getNullableCustomVal(key: String, default: T): T? {
return try {
when (default) {
is Boolean -> irrelevantPreferences!!.getBoolean(key, default) as T?
is Int -> irrelevantPreferences!!.getInt(key, default) as T?
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?
else -> deserialzeClass(key, default)
}
} catch (e: Exception) {
default
}
}
fun removeVal(prefName: PrefName) {
val pref = getPrefLocation(prefName.data.prefLocation)
with(pref.edit()) {
remove(prefName.name)
apply()
}
}
fun <T> setCustomVal(key: String, value: T?) {
//for custom force irrelevant
with(irrelevantPreferences!!.edit()) {
when (value) {
is Boolean -> putBoolean(key, value as Boolean)
is Int -> putInt(key, value as Int)
is Float -> putFloat(key, value as Float)
is Long -> putLong(key, value as Long)
is String -> putString(key, value as String)
is Set<*> -> convertAndPutStringSet(key, value)
null -> remove(key)
else -> serialzeClass(key, value)
}
apply()
}
}
fun removeCustomVal(key: String) {
//for custom force irrelevant
with(irrelevantPreferences!!.edit()) {
remove(key)
apply()
}
}
@Suppress("UNCHECKED_CAST")
fun <T> getLiveVal(prefName: PrefName, default: T) : SharedPreferenceLiveData<T> {
val pref = getPrefLocation(prefName.data.prefLocation)
return when (prefName.data.type) {
Boolean::class -> SharedPreferenceBooleanLiveData(
pref,
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")
}
}
fun SharedPreferenceLiveData<*>.asLiveBool(): SharedPreferenceBooleanLiveData =
this as? SharedPreferenceBooleanLiveData
?: throw ClassCastException("Cannot cast to SharedPreferenceLiveData<Boolean>")
fun SharedPreferenceLiveData<*>.asLiveInt(): SharedPreferenceIntLiveData =
this as? SharedPreferenceIntLiveData
?: throw ClassCastException("Cannot cast to SharedPreferenceLiveData<Int>")
fun SharedPreferenceLiveData<*>.asLiveFloat(): SharedPreferenceFloatLiveData =
this as? SharedPreferenceFloatLiveData
?: throw ClassCastException("Cannot cast to SharedPreferenceLiveData<Float>")
fun SharedPreferenceLiveData<*>.asLiveLong(): SharedPreferenceLongLiveData =
this as? SharedPreferenceLongLiveData
?: throw ClassCastException("Cannot cast to SharedPreferenceLiveData<Long>")
fun SharedPreferenceLiveData<*>.asLiveString(): SharedPreferenceStringLiveData =
this as? SharedPreferenceStringLiveData
?: throw ClassCastException("Cannot cast to SharedPreferenceLiveData<String>")
fun SharedPreferenceLiveData<*>.asLiveStringSet(): SharedPreferenceStringSetLiveData =
this as? SharedPreferenceStringSetLiveData
?: throw ClassCastException("Cannot cast to SharedPreferenceLiveData<Set<String>>")
fun getAnimeDownloadPreferences(): SharedPreferences = animeDownloadsPreferences!! //needs to be used externally
fun exportAllPrefs(prefLocation: Location): Map<String, *>{
val pref = getPrefLocation(prefLocation)
val typedMap = mutableMapOf<String, Any>()
pref.all.forEach { (key, value) ->
val typeValueMap = mapOf(
"type" to value?.javaClass?.kotlin?.qualifiedName,
"value" to value
)
typedMap[key] = typeValueMap
}
return typedMap
}
@Suppress("UNCHECKED_CAST")
fun importAllPrefs(prefs: Map<String, *>, prefLocation: Location) {
val pref = getPrefLocation(prefLocation)
with(pref.edit()) {
prefs.forEach { (key, value) ->
when (value) {
is Boolean -> putBoolean(key, value)
is Int -> putInt(key, value)
is Float -> putFloat(key, value)
is Long -> putLong(key, value)
is String -> putString(key, value)
is HashSet<*> -> putStringSet(key, value as Set<String>)
is ArrayList<*> -> putStringSet(key, arrayListToSet(value))
is Set<*> -> putStringSet(key, value as Set<String>)
else -> snackString("Error importing preference: Type not supported")
}
}
apply()
}
}
private fun arrayListToSet(arrayList: ArrayList<*>): Set<String> {
return arrayList.map { it.toString() }.toSet()
}
private fun getPrefLocation(prefLoc: Location): SharedPreferences {
return when (prefLoc) {
Location.General -> generalPreferences
Location.UI -> generalPreferences
Location.Anime -> animePreferences
Location.Manga -> mangaPreferences
Location.Player -> playerPreferences
Location.Reader -> readerPreferences
Location.NovelReader -> readerPreferences
Location.Irrelevant -> irrelevantPreferences
Location.AnimeDownloads -> animeDownloadsPreferences
Location.Protected -> protectedPreferences
}!!
}
private fun <T> convertFromStringSet(stringSet: Set<String>?, default: T): Set<*> {
if (stringSet.isNullOrEmpty()) return default as Set<*>
return try {
val typeIdentifier = stringSet.first()
val convertedSet = stringSet.drop(1) // Remove the type identifier
when (typeIdentifier) {
"Int" -> convertedSet.mapNotNull { it.toIntOrNull() }.toSet()
"Boolean" -> convertedSet.mapNotNull { it.toBooleanStrictOrNull() }.toSet()
"Float" -> convertedSet.mapNotNull { it.toFloatOrNull() }.toSet()
"Long" -> convertedSet.mapNotNull { it.toLongOrNull() }.toSet()
"String" -> convertedSet.toSet()
else -> stringSet
}
} catch (e: Exception) {
snackString("Error converting preference: ${e.message}")
default as Set<*>
}
}
private fun SharedPreferences.Editor.convertAndPutStringSet(key: String, value: Set<*>) {
val typeIdentifier = when (value.firstOrNull()) {
is Int -> "Int"
is Boolean -> "Boolean"
is Float -> "Float"
is Long -> "Long"
is String -> "String"
null -> return
else -> throw IllegalArgumentException("Type not supported")
}
val stringSet = setOf(typeIdentifier) + value.map { it.toString() }
putStringSet(key, stringSet)
}
private fun <T> serialzeClass(key: String, value: T){
try {
val bos = ByteArrayOutputStream()
ObjectOutputStream(bos).use { oos ->
oos.writeObject(value)
}
val serialized = Base64.encodeToString(bos.toByteArray(), Base64.DEFAULT)
irrelevantPreferences!!.edit().putString(key, serialized).apply()
} catch (e: Exception) {
snackString("Error serializing preference: ${e.message}")
}
}
@Suppress("UNCHECKED_CAST")
private fun <T> deserialzeClass(key: String, default: T?): T? {
return try {
val serialized = irrelevantPreferences!!.getString(key, null)
if (serialized != null) {
val data = Base64.decode(serialized, Base64.DEFAULT)
val bis = ByteArrayInputStream(data)
val ois = ObjectInputStream(bis)
val obj = ois.readObject() as T?
obj
} else {
default
}
} catch (e: Exception) {
snackString("Error deserializing preference: ${e.message}")
default
}
}
}

View file

@ -1,196 +0,0 @@
package ani.dantotsu.settings.saving
import android.annotation.SuppressLint
import android.content.Context
import android.content.SharedPreferences
import ani.dantotsu.settings.saving.internal.Compat
import ani.dantotsu.settings.saving.internal.Location
import ani.dantotsu.snackString
object PrefWrapper {
private var generalPreferences: SharedPreferences? = null
private var animePreferences: SharedPreferences? = null
private var mangaPreferences: SharedPreferences? = null
private var playerPreferences: SharedPreferences? = null
private var readerPreferences: SharedPreferences? = null
private var irrelevantPreferences: SharedPreferences? = null
private var animeDownloadsPreferences: SharedPreferences? = null
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)
animePreferences = context.getSharedPreferences(Location.Anime.location, Context.MODE_PRIVATE)
mangaPreferences = context.getSharedPreferences(Location.Manga.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)
}
@Suppress("UNCHECKED_CAST")
fun <T> setVal(prefName: PrefName, value: T) {
val pref = getPrefLocation(prefName)
with(pref.edit()) {
when (prefName.data.type) {
Boolean::class -> putBoolean(prefName.name, value as Boolean)
Int::class -> putInt(prefName.name, value as Int)
Float::class -> putFloat(prefName.name, value as Float)
Long::class -> putLong(prefName.name, value as Long)
String::class -> putString(prefName.name, value as String?)
Set::class -> putStringSet(prefName.name, value as Set<String>)
else -> throw IllegalArgumentException("Type not supported")
}
apply()
}
}
@Suppress("UNCHECKED_CAST")
fun <T> getVal(prefName: PrefName, default: T) : T {
return try {
val pref = getPrefLocation(prefName)
when (prefName.data.type) {
Boolean::class -> pref.getBoolean(prefName.name, default as Boolean) as T
Int::class -> pref.getInt(prefName.name, default as Int) as T
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 -> pref.getStringSet(prefName.name, default as Set<String>) as T
else -> throw IllegalArgumentException("Type not supported")
}
} catch (e: Exception) {
snackString("Error getting preference: ${e.message}")
default
}
}
@Suppress("UNCHECKED_CAST")
fun <T> getLiveVal(prefName: PrefName, default: T) : SharedPreferenceLiveData<T> {
val pref = getPrefLocation(prefName)
return when (prefName.data.type) {
Boolean::class -> SharedPreferenceBooleanLiveData(
pref,
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")
}
}
fun removeVal(prefName: PrefName) {
val pref = getPrefLocation(prefName)
with(pref.edit()) {
remove(prefName.name)
apply()
}
}
@Suppress("UNCHECKED_CAST")
fun <T> setCustomVal(key: String, value: T) {
//for custom force irrelevant
with(irrelevantPreferences!!.edit()) {
when (value) {
is Boolean -> putBoolean(key, value as Boolean)
is Int -> putInt(key, value as Int)
is Float -> putFloat(key, value as Float)
is Long -> putLong(key, value as Long)
is String -> putString(key, value as String)
is Set<*> -> putStringSet(key, value as Set<String>)
else -> throw IllegalArgumentException("Type not supported")
}
apply()
}
}
@Suppress("UNCHECKED_CAST")
fun <T> getCustomVal(key: String, default: T): T {
//for custom force irrelevant
return try {
when (default) {
is Boolean -> irrelevantPreferences!!.getBoolean(key, default) as T
is Int -> irrelevantPreferences!!.getInt(key, default) as T
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<*> -> irrelevantPreferences!!.getStringSet(key, default as Set<String>) as T
else -> throw IllegalArgumentException("Type not supported")
}
} catch (e: Exception) {
default
}
}
fun removeCustomVal(key: String) {
//for custom force irrelevant
with(irrelevantPreferences!!.edit()) {
remove(key)
apply()
}
}
fun SharedPreferenceLiveData<*>.asLiveBool(): SharedPreferenceBooleanLiveData =
this as? SharedPreferenceBooleanLiveData
?: throw ClassCastException("Cannot cast to SharedPreferenceLiveData<Boolean>")
fun SharedPreferenceLiveData<*>.asLiveInt(): SharedPreferenceIntLiveData =
this as? SharedPreferenceIntLiveData
?: throw ClassCastException("Cannot cast to SharedPreferenceLiveData<Int>")
fun SharedPreferenceLiveData<*>.asLiveFloat(): SharedPreferenceFloatLiveData =
this as? SharedPreferenceFloatLiveData
?: throw ClassCastException("Cannot cast to SharedPreferenceLiveData<Float>")
fun SharedPreferenceLiveData<*>.asLiveLong(): SharedPreferenceLongLiveData =
this as? SharedPreferenceLongLiveData
?: throw ClassCastException("Cannot cast to SharedPreferenceLiveData<Long>")
fun SharedPreferenceLiveData<*>.asLiveString(): SharedPreferenceStringLiveData =
this as? SharedPreferenceStringLiveData
?: throw ClassCastException("Cannot cast to SharedPreferenceLiveData<String>")
fun SharedPreferenceLiveData<*>.asLiveStringSet(): SharedPreferenceStringSetLiveData =
this as? SharedPreferenceStringSetLiveData
?: throw ClassCastException("Cannot cast to SharedPreferenceLiveData<Set<String>>")
fun getAnimeDownloadPreferences(): SharedPreferences = animeDownloadsPreferences!! //needs to be used externally
private fun getPrefLocation(prefName: PrefName): SharedPreferences {
return when (prefName.data.prefLocation) {
Location.General -> generalPreferences
Location.Anime -> animePreferences
Location.Manga -> mangaPreferences
Location.Player -> playerPreferences
Location.Reader -> readerPreferences
Location.Irrelevant -> irrelevantPreferences
Location.AnimeDownloads -> animeDownloadsPreferences
Location.Protected -> protectedPreferences
}!!
}
}

View file

@ -1,56 +1,153 @@
package ani.dantotsu.settings.saving 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.Pref
import ani.dantotsu.settings.saving.internal.Location import ani.dantotsu.settings.saving.internal.Location
enum class PrefName(val data: Pref) { enum class PrefName(val data: Pref) { //TODO: Split this into multiple files
//General //General
SharedUserID(Pref(Location.General, Boolean::class)), SharedUserID(Pref(Location.General, Boolean::class, true)),
OfflineView(Pref(Location.General, Int::class)), OfflineView(Pref(Location.General, Int::class, 0)),
UseOLED(Pref(Location.General, Boolean::class)), DownloadManager(Pref(Location.General, Int::class, 0)),
UseCustomTheme(Pref(Location.General, Boolean::class)), NSFWExtension(Pref(Location.General, Boolean::class, false)),
CustomThemeInt(Pref(Location.General, Int::class)), SdDl(Pref(Location.General, Boolean::class, false)),
UseSourceTheme(Pref(Location.General, Boolean::class)), ContinueMedia(Pref(Location.General, Boolean::class, true)),
UseMaterialYou(Pref(Location.General, Boolean::class)), RecentlyListOnly(Pref(Location.General, Boolean::class, false)),
Theme(Pref(Location.General, String::class)), SettingsPreferDub(Pref(Location.General, Boolean::class, false)),
DownloadManager(Pref(Location.General, Int::class)), SubscriptionsTimeS(Pref(Location.General, Int::class, 0)),
NSFWExtension(Pref(Location.General, Boolean::class)), SubscriptionCheckingNotifications(Pref(Location.General, Boolean::class, true)),
SkipExtensionIcons(Pref(Location.General, Boolean::class)), CheckUpdate(Pref(Location.General, Boolean::class, true)),
SdDl(Pref(Location.General, Boolean::class)), VerboseLogging(Pref(Location.General, Boolean::class, false)),
ContinueMedia(Pref(Location.General, Boolean::class)), DohProvider(Pref(Location.General, Int::class, 0)),
RecentlyListOnly(Pref(Location.General, Boolean::class)), DefaultUserAgent(Pref(Location.General, String::class, "Mozilla/5.0 (Windows NT 10.0; Win64; x64; rv:110.0) Gecko/20100101 Firefox/110.0")),
SettingsPreferDub(Pref(Location.General, Boolean::class)),
SubscriptionsTimeS(Pref(Location.General, Int::class)), //User Interface
SubscriptionCheckingNotifications(Pref(Location.General, Boolean::class)), UseOLED(Pref(Location.UI, Boolean::class, false)),
CheckUpdate(Pref(Location.General, Boolean::class)), UseCustomTheme(Pref(Location.UI, Boolean::class, false)),
CustomThemeInt(Pref(Location.UI, Int::class, Color.parseColor("#6200EE"))),
UseSourceTheme(Pref(Location.UI, Boolean::class, false)),
UseMaterialYou(Pref(Location.UI, Boolean::class, false)),
Theme(Pref(Location.UI, String::class, "PURPLE")),
SkipExtensionIcons(Pref(Location.UI, Boolean::class, false)),
DarkMode(Pref(Location.UI, Boolean::class, true)),
ShowYtButton(Pref(Location.UI, Boolean::class, true)),
AnimeDefaultView(Pref(Location.UI, Int::class, 0)),
MangaDefaultView(Pref(Location.UI, Int::class, 0)),
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))),
BannerAnimations(Pref(Location.UI, Boolean::class, true)),
LayoutAnimations(Pref(Location.UI, Boolean::class, true)),
AnimationSpeed(Pref(Location.UI, Float::class, 1f)),
ListGrid(Pref(Location.UI, Boolean::class, true)),
//Anime //Anime
AnimeListSortOrder(Pref(Location.Anime, String::class)), AnimeListSortOrder(Pref(Location.Anime, String::class, "score")),
PinnedAnimeSources(Pref(Location.Anime, Set::class)), PinnedAnimeSources(Pref(Location.Anime, Set::class, setOf<String>())),
PopularAnimeList(Pref(Location.Anime, Boolean::class)), PopularAnimeList(Pref(Location.Anime, Boolean::class, true)),
AnimeSearchHistory(Pref(Location.Anime, Set::class)), AnimeSearchHistory(Pref(Location.Anime, Set::class, setOf<String>())),
//Manga //Manga
MangaListSortOrder(Pref(Location.Manga, String::class)), MangaListSortOrder(Pref(Location.Manga, String::class, "score")),
PinnedMangaSources(Pref(Location.Manga, Set::class)), PinnedMangaSources(Pref(Location.Manga, Set::class, setOf<String>())),
PopularMangaList(Pref(Location.Manga, Boolean::class)), PopularMangaList(Pref(Location.Manga, Boolean::class, true)),
MangaSearchHistory(Pref(Location.Manga, Set::class)), MangaSearchHistory(Pref(Location.Manga, Set::class, setOf<String>())),
//Player
DefaultSpeed(Pref(Location.Player, Int::class, 5)),
CursedSpeeds(Pref(Location.Player, Boolean::class, false)),
Resize(Pref(Location.Player, Int::class, 0)),
Subtitles(Pref(Location.Player, Boolean::class, true)),
PrimaryColor(Pref(Location.Player, Int::class, 4)),
SecondaryColor(Pref(Location.Player, Int::class, 0)),
Outline(Pref(Location.Player, Int::class, 0)),
SubBackground(Pref(Location.Player, Int::class, 0)),
SubWindow(Pref(Location.Player, Int::class, 0)),
Font(Pref(Location.Player, Int::class, 0)),
FontSize(Pref(Location.Player, Int::class, 20)),
Locale(Pref(Location.Player, Int::class, 2)),
TimeStampsEnabled(Pref(Location.Player, Boolean::class, true)),
UseProxyForTimeStamps(Pref(Location.Player, Boolean::class, false)),
ShowTimeStampButton(Pref(Location.Player, Boolean::class, true)),
AutoSkipOPED(Pref(Location.Player, Boolean::class, false)),
AutoPlay(Pref(Location.Player, Boolean::class, true)),
AutoSkipFiller(Pref(Location.Player, Boolean::class, false)),
AskIndividualPlayer(Pref(Location.Player, Boolean::class, true)),
UpdateForHPlayer(Pref(Location.Player, Boolean::class, false)),
WatchPercentage(Pref(Location.Player, Float::class, 0.8f)),
AlwaysContinue(Pref(Location.Player, Boolean::class, true)),
FocusPause(Pref(Location.Player, Boolean::class, true)),
Gestures(Pref(Location.Player, Boolean::class, true)),
DoubleTap(Pref(Location.Player, Boolean::class, true)),
FastForward(Pref(Location.Player, Boolean::class, true)),
SeekTime(Pref(Location.Player, Int::class, 10)),
SkipTime(Pref(Location.Player, Int::class, 85)),
Cast(Pref(Location.Player, Boolean::class, true)),
Pip(Pref(Location.Player, Boolean::class, true)),
ContinueAnime(Pref(Location.Player, Set::class, setOf<Int>())),
//Reader
ShowSource(Pref(Location.Reader, Boolean::class, true)),
ShowSystemBars(Pref(Location.Reader, Boolean::class, false)),
AutoDetectWebtoon(Pref(Location.Reader, Boolean::class, true)),
AskIndividualReader(Pref(Location.Reader, Boolean::class, true)),
UpdateForHReader(Pref(Location.Reader, Boolean::class, false)),
Direction(Pref(Location.Reader, Int::class, 0)),
LayoutReader(Pref(Location.Reader, Int::class, 2)),
DualPageModeReader(Pref(Location.Reader, Int::class, 1)),
OverScrollMode(Pref(Location.Reader, Boolean::class, true)),
TrueColors(Pref(Location.Reader, Boolean::class, false)),
Rotation(Pref(Location.Reader, Boolean::class, true)),
Padding(Pref(Location.Reader, Boolean::class, true)),
HidePageNumbers(Pref(Location.Reader, Boolean::class, false)),
HorizontalScrollBar(Pref(Location.Reader, Boolean::class, true)),
KeepScreenOn(Pref(Location.Reader, Boolean::class, false)),
VolumeButtonsReader(Pref(Location.Reader, Boolean::class, false)),
WrapImages(Pref(Location.Reader, Boolean::class, false)),
LongClickImage(Pref(Location.Reader, Boolean::class, true)),
CropBorders(Pref(Location.Reader, Boolean::class, false)),
CropBorderThreshold(Pref(Location.Reader, Int::class, 10)),
//Novel Reader
CurrentThemeName(Pref(Location.NovelReader, String::class, "Default")),
LayoutNovel(Pref(Location.NovelReader, Int::class, 0)),
DualPageModeNovel(Pref(Location.NovelReader, Int::class, 1)),
LineHeight(Pref(Location.NovelReader, Float::class, 1.4f)),
Margin(Pref(Location.NovelReader, Float::class, 0.06f)),
Justify(Pref(Location.NovelReader, Boolean::class, true)),
Hyphenation(Pref(Location.NovelReader, Boolean::class, true)),
UseDarkThemeNovel(Pref(Location.NovelReader, Boolean::class, false)),
UseOledThemeNovel(Pref(Location.NovelReader, Boolean::class, false)),
Invert(Pref(Location.NovelReader, Boolean::class, false)),
MaxInlineSize(Pref(Location.NovelReader, Int::class, 720)),
MaxBlockSize(Pref(Location.NovelReader, Int::class, 1440)),
HorizontalScrollBarNovel(Pref(Location.NovelReader, Boolean::class, true)),
KeepScreenOnNovel(Pref(Location.NovelReader, Boolean::class, false)),
VolumeButtonsNovel(Pref(Location.NovelReader, Boolean::class, false)),
//Irrelevant //Irrelevant
Incognito(Pref(Location.Irrelevant, Boolean::class)), Incognito(Pref(Location.Irrelevant, Boolean::class, false)),
OfflineMode(Pref(Location.Irrelevant, Boolean::class)), OfflineMode(Pref(Location.Irrelevant, Boolean::class, false)),
DownloadsKeys(Pref(Location.Irrelevant, String::class)), DownloadsKeys(Pref(Location.Irrelevant, String::class, "")),
NovelLastExtCheck(Pref(Location.Irrelevant, Long::class)), NovelLastExtCheck(Pref(Location.Irrelevant, Long::class, 0L)),
SomethingSpecial(Pref(Location.Irrelevant, Boolean::class)), SomethingSpecial(Pref(Location.Irrelevant, Boolean::class, false)),
AllowOpeningLinks(Pref(Location.Irrelevant, Boolean::class)), AllowOpeningLinks(Pref(Location.Irrelevant, Boolean::class, false)),
SearchStyle(Pref(Location.Irrelevant, Int::class)), SearchStyle(Pref(Location.Irrelevant, Int::class, 0)),
HasUpdatedPrefs(Pref(Location.Irrelevant, Boolean::class)), HasUpdatedPrefs(Pref(Location.Irrelevant, Boolean::class, false)),
LangSort(Pref(Location.Irrelevant, String::class)), LangSort(Pref(Location.Irrelevant, String::class, "all")),
GenresList(Pref(Location.Irrelevant, Set::class, setOf<String>())),
TagsListIsAdult(Pref(Location.Irrelevant, Set::class, setOf<String>())),
TagsListNonAdult(Pref(Location.Irrelevant, Set::class, setOf<String>())),
MakeDefault(Pref(Location.Irrelevant, Boolean::class, true)),
//Protected //Protected
DiscordToken(Pref(Location.Protected, String::class)), DiscordToken(Pref(Location.Protected, String::class, "")),
DiscordId(Pref(Location.Protected, String::class)), DiscordId(Pref(Location.Protected, String::class, "")),
DiscordUserName(Pref(Location.Protected, String::class)), DiscordUserName(Pref(Location.Protected, String::class, "")),
DiscordAvatar(Pref(Location.Protected, String::class)), DiscordAvatar(Pref(Location.Protected, String::class, "")),
AnilistUserName(Pref(Location.Protected, String::class)), AnilistUserName(Pref(Location.Protected, String::class, "")),
MALCodeChallenge(Pref(Location.Protected, String::class, "")),
MALToken(Pref(Location.Protected, MAL.ResponseToken::class, "")),
} }

View file

@ -2,17 +2,17 @@ package ani.dantotsu.settings.saving.internal
import android.content.Context import android.content.Context
import ani.dantotsu.settings.saving.PrefName import ani.dantotsu.settings.saving.PrefName
import ani.dantotsu.settings.saving.PrefWrapper import ani.dantotsu.settings.saving.PrefManager
class Compat { class Compat {
companion object { companion object {
fun importOldPrefs(context: Context) { fun importOldPrefs(context: Context) {
if (PrefWrapper.getVal(PrefName.HasUpdatedPrefs, false)) return if (PrefManager.getVal(PrefName.HasUpdatedPrefs)) return
val oldPrefs = context.getSharedPreferences("downloads_pref", Context.MODE_PRIVATE) val oldPrefs = context.getSharedPreferences("downloads_pref", Context.MODE_PRIVATE)
val jsonString = oldPrefs.getString("downloads_key", null) val jsonString = oldPrefs.getString("downloads_key", null)
PrefWrapper.setVal(PrefName.DownloadsKeys, jsonString) PrefManager.setVal(PrefName.DownloadsKeys, jsonString)
oldPrefs.edit().clear().apply() oldPrefs.edit().clear().apply()
PrefWrapper.setVal(PrefName.HasUpdatedPrefs, true) PrefManager.setVal(PrefName.HasUpdatedPrefs, true)
} }
} }
} }

View file

@ -5,14 +5,17 @@ import kotlin.reflect.KClass
data class Pref( data class Pref(
val prefLocation: Location, val prefLocation: Location,
val type: KClass<*> val type: KClass<*>,
val default: Any
) )
enum class Location(val location: String) { enum class Location(val location: String) {
General("ani.dantotsu.general"), General("ani.dantotsu.general"),
UI("ani.dantotsu.ui"),
Anime("ani.dantotsu.anime"), Anime("ani.dantotsu.anime"),
Manga("ani.dantotsu.manga"), Manga("ani.dantotsu.manga"),
Player("ani.dantotsu.player"), Player("ani.dantotsu.player"),
Reader("ani.dantotsu.reader"), Reader("ani.dantotsu.reader"),
NovelReader("ani.dantotsu.novelReader"),
Irrelevant("ani.dantotsu.irrelevant"), Irrelevant("ani.dantotsu.irrelevant"),
AnimeDownloads("animeDownloads"), //different for legacy reasons AnimeDownloads("animeDownloads"), //different for legacy reasons
Protected("ani.dantotsu.protected") Protected("ani.dantotsu.protected")

View file

@ -9,7 +9,7 @@ import ani.dantotsu.currContext
import ani.dantotsu.isOnline import ani.dantotsu.isOnline
import ani.dantotsu.logger import ani.dantotsu.logger
import ani.dantotsu.settings.saving.PrefName import ani.dantotsu.settings.saving.PrefName
import ani.dantotsu.settings.saving.PrefWrapper import ani.dantotsu.settings.saving.PrefManager
import ani.dantotsu.subcriptions.Subscription.Companion.defaultTime import ani.dantotsu.subcriptions.Subscription.Companion.defaultTime
import ani.dantotsu.subcriptions.Subscription.Companion.startSubscription import ani.dantotsu.subcriptions.Subscription.Companion.startSubscription
import ani.dantotsu.subcriptions.Subscription.Companion.timeMinutes import ani.dantotsu.subcriptions.Subscription.Companion.timeMinutes
@ -44,7 +44,7 @@ class AlarmReceiver : BroadcastReceiver() {
PendingIntent.FLAG_IMMUTABLE or PendingIntent.FLAG_UPDATE_CURRENT PendingIntent.FLAG_IMMUTABLE or PendingIntent.FLAG_UPDATE_CURRENT
) )
val alarmManager = context.getSystemService(Context.ALARM_SERVICE) as AlarmManager val alarmManager = context.getSystemService(Context.ALARM_SERVICE) as AlarmManager
val curTime = PrefWrapper.getVal(PrefName.SubscriptionsTimeS, defaultTime) val curTime = PrefManager.getVal(PrefName.SubscriptionsTimeS, defaultTime)
if (timeMinutes[curTime] > 0) if (timeMinutes[curTime] > 0)
alarmManager.setRepeating( alarmManager.setRepeating(

View file

@ -6,13 +6,13 @@ import android.content.Context
import android.content.Intent import android.content.Intent
import ani.dantotsu.INCOGNITO_CHANNEL_ID import ani.dantotsu.INCOGNITO_CHANNEL_ID
import ani.dantotsu.settings.saving.PrefName import ani.dantotsu.settings.saving.PrefName
import ani.dantotsu.settings.saving.PrefWrapper import ani.dantotsu.settings.saving.PrefManager
class NotificationClickReceiver : BroadcastReceiver() { class NotificationClickReceiver : BroadcastReceiver() {
override fun onReceive(context: Context, intent: Intent?) { override fun onReceive(context: Context, intent: Intent?) {
PrefWrapper.setVal(PrefName.Incognito, false) PrefManager.setVal(PrefName.Incognito, false)
val notificationManager = val notificationManager =
context.getSystemService(Context.NOTIFICATION_SERVICE) as NotificationManager context.getSystemService(Context.NOTIFICATION_SERVICE) as NotificationManager
notificationManager.cancel(INCOGNITO_CHANNEL_ID) notificationManager.cancel(INCOGNITO_CHANNEL_ID)

View file

@ -9,7 +9,7 @@ import ani.dantotsu.*
import ani.dantotsu.parsers.Episode import ani.dantotsu.parsers.Episode
import ani.dantotsu.parsers.MangaChapter import ani.dantotsu.parsers.MangaChapter
import ani.dantotsu.settings.saving.PrefName import ani.dantotsu.settings.saving.PrefName
import ani.dantotsu.settings.saving.PrefWrapper import ani.dantotsu.settings.saving.PrefManager
import kotlinx.coroutines.CoroutineScope import kotlinx.coroutines.CoroutineScope
import kotlinx.coroutines.Dispatchers import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.delay import kotlinx.coroutines.delay
@ -37,13 +37,13 @@ class Subscription {
currentlyPerforming = true currentlyPerforming = true
App.context = context App.context = context
val subscriptions = SubscriptionHelper.getSubscriptions(context) val subscriptions = SubscriptionHelper.getSubscriptions()
var i = 0 var i = 0
val index = subscriptions.map { i++; it.key to i }.toMap() val index = subscriptions.map { i++; it.key to i }.toMap()
val notificationManager = NotificationManagerCompat.from(context) val notificationManager = NotificationManagerCompat.from(context)
val progressEnabled = val progressEnabled: Boolean =
PrefWrapper.getVal(PrefName.SubscriptionCheckingNotifications, true) PrefManager.getVal(PrefName.SubscriptionCheckingNotifications)
val progressNotification = if (progressEnabled) getProgressNotification( val progressNotification = if (progressEnabled) getProgressNotification(
context, context,
subscriptions.size subscriptions.size

View file

@ -3,7 +3,6 @@ package ani.dantotsu.subcriptions
import android.content.Context import android.content.Context
import ani.dantotsu.R import ani.dantotsu.R
import ani.dantotsu.currContext import ani.dantotsu.currContext
import ani.dantotsu.loadData
import ani.dantotsu.media.Media import ani.dantotsu.media.Media
import ani.dantotsu.media.Selected import ani.dantotsu.media.Selected
import ani.dantotsu.media.manga.MangaNameAdapter import ani.dantotsu.media.manga.MangaNameAdapter
@ -15,9 +14,8 @@ import ani.dantotsu.parsers.HMangaSources
import ani.dantotsu.parsers.MangaChapter import ani.dantotsu.parsers.MangaChapter
import ani.dantotsu.parsers.MangaParser import ani.dantotsu.parsers.MangaParser
import ani.dantotsu.parsers.MangaSources import ani.dantotsu.parsers.MangaSources
import ani.dantotsu.saveData
import ani.dantotsu.settings.saving.PrefName import ani.dantotsu.settings.saving.PrefName
import ani.dantotsu.settings.saving.PrefWrapper import ani.dantotsu.settings.saving.PrefManager
import ani.dantotsu.tryWithSuspend import ani.dantotsu.tryWithSuspend
import kotlinx.coroutines.withTimeoutOrNull import kotlinx.coroutines.withTimeoutOrNull
@ -29,16 +27,16 @@ class SubscriptionHelper {
isAdult: Boolean, isAdult: Boolean,
isAnime: Boolean isAnime: Boolean
): Selected { ): Selected {
val data = loadData<Selected>("${mediaId}-select", context) ?: Selected().let { val data = PrefManager.getNullableCustomVal<Selected?>("${mediaId}-select", null) ?: Selected().let {
it.sourceIndex = 0 it.sourceIndex = 0
it.preferDub = PrefWrapper.getVal(PrefName.SettingsPreferDub, false) it.preferDub = PrefManager.getVal(PrefName.SettingsPreferDub)
it it
} }
return data return data
} }
private fun saveSelected(context: Context, mediaId: Int, data: Selected) { private fun saveSelected(context: Context, mediaId: Int, data: Selected) {
saveData("$mediaId-select", data, context) PrefManager.setCustomVal("${mediaId}-select", data)
} }
fun getAnimeParser(context: Context, isAdult: Boolean, id: Int): AnimeParser { fun getAnimeParser(context: Context, isAdult: Boolean, id: Int): AnimeParser {
@ -125,12 +123,12 @@ class SubscriptionHelper {
) : java.io.Serializable ) : java.io.Serializable
private const val subscriptions = "subscriptions" private const val subscriptions = "subscriptions"
fun getSubscriptions(context: Context): Map<Int, SubscribeMedia> = fun getSubscriptions(): Map<Int, SubscribeMedia> =
loadData(subscriptions, context) PrefManager.getNullableCustomVal<Map<Int, SubscribeMedia>?>(subscriptions, null)
?: mapOf<Int, SubscribeMedia>().also { saveData(subscriptions, it, context) } ?: mapOf<Int, SubscribeMedia>().also { PrefManager.setCustomVal(subscriptions, it) }
fun saveSubscription(context: Context, media: Media, subscribed: Boolean) { fun saveSubscription(context: Context, media: Media, subscribed: Boolean) {
val data = loadData<Map<Int, SubscribeMedia>>(subscriptions, context)!!.toMutableMap() val data = PrefManager.getNullableCustomVal<Map<Int, SubscribeMedia>?>(subscriptions, null)!!.toMutableMap()
if (subscribed) { if (subscribed) {
if (!data.containsKey(media.id)) { if (!data.containsKey(media.id)) {
val new = SubscribeMedia( val new = SubscribeMedia(
@ -145,7 +143,7 @@ class SubscriptionHelper {
} else { } else {
data.remove(media.id) data.remove(media.id)
} }
saveData(subscriptions, data, context) PrefManager.setCustomVal(subscriptions, data)
} }
} }
} }

View file

@ -8,9 +8,8 @@ import androidx.work.NetworkType
import androidx.work.PeriodicWorkRequest import androidx.work.PeriodicWorkRequest
import androidx.work.WorkManager import androidx.work.WorkManager
import androidx.work.WorkerParameters import androidx.work.WorkerParameters
import ani.dantotsu.loadData
import ani.dantotsu.settings.saving.PrefName import ani.dantotsu.settings.saving.PrefName
import ani.dantotsu.settings.saving.PrefWrapper import ani.dantotsu.settings.saving.PrefManager
import ani.dantotsu.subcriptions.Subscription.Companion.defaultTime import ani.dantotsu.subcriptions.Subscription.Companion.defaultTime
import ani.dantotsu.subcriptions.Subscription.Companion.timeMinutes import ani.dantotsu.subcriptions.Subscription.Companion.timeMinutes
import kotlinx.coroutines.Dispatchers import kotlinx.coroutines.Dispatchers
@ -31,7 +30,7 @@ class SubscriptionWorker(val context: Context, params: WorkerParameters) :
private const val SUBSCRIPTION_WORK_NAME = "work_subscription" private const val SUBSCRIPTION_WORK_NAME = "work_subscription"
fun enqueue(context: Context) { fun enqueue(context: Context) {
val curTime = PrefWrapper.getVal(PrefName.SubscriptionsTimeS, defaultTime) val curTime = PrefManager.getVal(PrefName.SubscriptionsTimeS, defaultTime)
if (timeMinutes[curTime] > 0L) { if (timeMinutes[curTime] > 0L) {
val constraints = val constraints =
Constraints.Builder().setRequiredNetworkType(NetworkType.CONNECTED).build() Constraints.Builder().setRequiredNetworkType(NetworkType.CONNECTED).build()

View file

@ -8,18 +8,18 @@ import android.view.Window
import android.view.WindowManager import android.view.WindowManager
import ani.dantotsu.R import ani.dantotsu.R
import ani.dantotsu.settings.saving.PrefName import ani.dantotsu.settings.saving.PrefName
import ani.dantotsu.settings.saving.PrefWrapper import ani.dantotsu.settings.saving.PrefManager
import com.google.android.material.color.DynamicColors import com.google.android.material.color.DynamicColors
import com.google.android.material.color.DynamicColorsOptions import com.google.android.material.color.DynamicColorsOptions
class ThemeManager(private val context: Activity) { class ThemeManager(private val context: Activity) {
fun applyTheme(fromImage: Bitmap? = null) { fun applyTheme(fromImage: Bitmap? = null) {
val useOLED = PrefWrapper.getVal(PrefName.UseOLED, false) && isDarkThemeActive(context) val useOLED = PrefManager.getVal(PrefName.UseOLED) && isDarkThemeActive(context)
val useCustomTheme = PrefWrapper.getVal(PrefName.UseCustomTheme, false) val useCustomTheme: Boolean = PrefManager.getVal(PrefName.UseCustomTheme)
val customTheme = PrefWrapper.getVal(PrefName.CustomThemeInt, 16712221) val customTheme: Int = PrefManager.getVal(PrefName.CustomThemeInt)
val useSource = PrefWrapper.getVal(PrefName.UseSourceTheme, false) val useSource: Boolean = PrefManager.getVal(PrefName.UseSourceTheme)
val useMaterial = PrefWrapper.getVal(PrefName.UseMaterialYou, false) val useMaterial: Boolean = PrefManager.getVal(PrefName.UseMaterialYou)
if (useSource) { if (useSource) {
val returnedEarly = applyDynamicColors( val returnedEarly = applyDynamicColors(
useMaterial, useMaterial,
@ -37,7 +37,7 @@ class ThemeManager(private val context: Activity) {
val returnedEarly = applyDynamicColors(useMaterial, context, useOLED, useCustom = null) val returnedEarly = applyDynamicColors(useMaterial, context, useOLED, useCustom = null)
if (!returnedEarly) return if (!returnedEarly) return
} }
val theme = PrefWrapper.getVal(PrefName.Theme, "PURPLE") val theme: String = PrefManager.getVal(PrefName.Theme)
val themeToApply = when (theme) { val themeToApply = when (theme) {
"BLUE" -> if (useOLED) R.style.Theme_Dantotsu_BlueOLED else R.style.Theme_Dantotsu_Blue "BLUE" -> if (useOLED) R.style.Theme_Dantotsu_BlueOLED else R.style.Theme_Dantotsu_Blue

View file

@ -3,6 +3,8 @@ package eu.kanade.tachiyomi.network
import android.content.Context import android.content.Context
import android.os.Build import android.os.Build
import ani.dantotsu.Mapper import ani.dantotsu.Mapper
import ani.dantotsu.settings.saving.PrefName
import ani.dantotsu.settings.saving.PrefManager
import com.lagradost.nicehttp.Requests import com.lagradost.nicehttp.Requests
import eu.kanade.tachiyomi.network.interceptor.CloudflareInterceptor import eu.kanade.tachiyomi.network.interceptor.CloudflareInterceptor
import eu.kanade.tachiyomi.network.interceptor.UncaughtExceptionInterceptor import eu.kanade.tachiyomi.network.interceptor.UncaughtExceptionInterceptor
@ -14,8 +16,7 @@ import java.io.File
import java.util.concurrent.TimeUnit import java.util.concurrent.TimeUnit
class NetworkHelper( class NetworkHelper(
context: Context, context: Context
private val preferences: NetworkPreferences,
) { ) {
private val cacheDir = File(context.cacheDir, "network_cache") private val cacheDir = File(context.cacheDir, "network_cache")
@ -39,14 +40,14 @@ class NetworkHelper(
.addInterceptor(UncaughtExceptionInterceptor()) .addInterceptor(UncaughtExceptionInterceptor())
.addInterceptor(userAgentInterceptor) .addInterceptor(userAgentInterceptor)
if (preferences.verboseLogging().get()) { if (PrefManager.getVal(PrefName.VerboseLogging)) {
val httpLoggingInterceptor = HttpLoggingInterceptor().apply { val httpLoggingInterceptor = HttpLoggingInterceptor().apply {
level = HttpLoggingInterceptor.Level.HEADERS level = HttpLoggingInterceptor.Level.HEADERS
} }
builder.addNetworkInterceptor(httpLoggingInterceptor) builder.addNetworkInterceptor(httpLoggingInterceptor)
} }
when (preferences.dohProvider().get()) { when (PrefManager.getVal<Int>(PrefName.DohProvider)) {
PREF_DOH_CLOUDFLARE -> builder.dohCloudflare() PREF_DOH_CLOUDFLARE -> builder.dohCloudflare()
PREF_DOH_GOOGLE -> builder.dohGoogle() PREF_DOH_GOOGLE -> builder.dohGoogle()
PREF_DOH_ADGUARD -> builder.dohAdGuard() PREF_DOH_ADGUARD -> builder.dohAdGuard()
@ -88,5 +89,5 @@ class NetworkHelper(
responseParser = Mapper responseParser = Mapper
) )
fun defaultUserAgentProvider() = preferences.defaultUserAgent().get().trim() fun defaultUserAgentProvider() = PrefManager.getVal<String>(PrefName.DefaultUserAgent)
} }

View file

@ -1,25 +0,0 @@
package eu.kanade.tachiyomi.network
import tachiyomi.core.preference.Preference
import tachiyomi.core.preference.PreferenceStore
class NetworkPreferences(
private val preferenceStore: PreferenceStore,
private val verboseLogging: Boolean = false,
) {
fun verboseLogging(): Preference<Boolean> {
return preferenceStore.getBoolean("verbose_logging", verboseLogging)
}
fun dohProvider(): Preference<Int> {
return preferenceStore.getInt("doh_provider", 0)
}
fun defaultUserAgent(): Preference<String> {
return preferenceStore.getString(
"default_user_agent",
"Mozilla/5.0 (Windows NT 10.0; Win64; x64; rv:110.0) Gecko/20100101 Firefox/110.0"
)
}
}

View file

@ -832,6 +832,37 @@
app:iconSize="24dp" app:iconSize="24dp"
app:iconTint="?attr/colorPrimary" /> app:iconTint="?attr/colorPrimary" />
<View
android:layout_width="match_parent"
android:layout_height="1dp"
android:layout_marginStart="-16dp"
android:layout_marginEnd="-16dp"
android:background="?android:attr/listDivider" />
<Button
android:id="@+id/importExportSettings"
android:layout_width="match_parent"
android:layout_height="64dp"
android:layout_marginStart="-31dp"
android:layout_marginEnd="-31dp"
android:background="@drawable/ui_bg"
android:backgroundTint="?attr/colorSecondary"
android:backgroundTintMode="src_atop"
android:fontFamily="@font/poppins_bold"
android:insetTop="0dp"
android:insetBottom="0dp"
android:paddingStart="31dp"
android:paddingEnd="31dp"
android:text="@string/import_export_settings"
android:textAlignment="viewStart"
android:textAllCaps="false"
android:textColor="?attr/colorOnBackground"
app:cornerRadius="0dp"
app:icon="@drawable/ic_round_download_24"
app:iconPadding="16dp"
app:iconSize="24dp"
app:iconTint="?attr/colorPrimary" />
<View <View
android:layout_width="match_parent" android:layout_width="match_parent"
android:layout_height="1dp" android:layout_height="1dp"
@ -858,6 +889,7 @@
app:cornerRadius="0dp" app:cornerRadius="0dp"
app:drawableTint="?attr/colorPrimary" app:drawableTint="?attr/colorPrimary"
app:showText="false" app:showText="false"
android:enabled="false"
app:thumbTint="@color/button_switch_track" /> app:thumbTint="@color/button_switch_track" />
<TextView <TextView

View file

@ -653,5 +653,6 @@
<string name="requires_android_12">Requires Android 12+</string> <string name="requires_android_12">Requires Android 12+</string>
<string name="share_username_in_crash_reports">Share username in crash reports</string> <string name="share_username_in_crash_reports">Share username in crash reports</string>
<string name="pinned_sources">Pinned Sources</string> <string name="pinned_sources">Pinned Sources</string>
<string name="import_export_settings">Import/Export Settings</string>
</resources> </resources>