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 {
applicationIdSuffix ".beta"
manifestPlaceholders = [icon_placeholder: "@mipmap/ic_launcher_beta", icon_placeholder_round: "@mipmap/ic_launcher_beta_round"]
debuggable System.getenv("CI") == null
debuggable false
}
release {
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.settings.SettingsActivity
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.firebase.crashlytics.FirebaseCrashlytics
import com.google.firebase.crashlytics.ktx.crashlytics
@ -54,9 +54,9 @@ class App : MultiDexApplication() {
override fun 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) {
DynamicColors.applyToActivitiesIfAvailable(this)
//TODO: HarmonizedColors
@ -64,10 +64,10 @@ class App : MultiDexApplication() {
registerActivityLifecycleCallbacks(mFTActivityLifecycleCallbacks)
Firebase.crashlytics.setCrashlyticsCollectionEnabled(!DisabledReports)
PrefWrapper.getVal(PrefName.SharedUserID, true).let {
(PrefManager.getVal(PrefName.SharedUserID) as Boolean).let {
if (!it) return@let
val dUsername = PrefWrapper.getVal(PrefName.DiscordUserName, null as String?)
val aUsername = PrefWrapper.getVal(PrefName.AnilistUserName, null as String?)
val dUsername = PrefManager.getVal(PrefName.DiscordUserName, null as String?)
val aUsername = PrefManager.getVal(PrefName.AnilistUserName, null as String?)
if (dUsername != null || aUsername != null) {
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.media.Media
import ani.dantotsu.parsers.ShowResponse
import ani.dantotsu.settings.UserInterfaceSettings
import ani.dantotsu.settings.saving.PrefName
import ani.dantotsu.settings.saving.PrefWrapper
import ani.dantotsu.settings.saving.PrefManager
import ani.dantotsu.subcriptions.NotificationClickReceiver
import com.bumptech.glide.Glide
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.snackbar.Snackbar
import com.google.firebase.crashlytics.FirebaseCrashlytics
import com.google.gson.Gson
import eu.kanade.tachiyomi.data.notification.Notifications
import kotlinx.coroutines.*
import nl.joery.animatedbottombar.AnimatedBottomBar
@ -109,11 +109,9 @@ fun logger(e: Any?, print: Boolean = true) {
fun initActivity(a: Activity) {
val window = a.window
WindowCompat.setDecorFitsSystemWindows(window, false)
val uiSettings = loadData<UserInterfaceSettings>("ui_settings", toast = false)
?: UserInterfaceSettings().apply {
saveData("ui_settings", this)
}
uiSettings.darkMode.apply {
val darkMode = PrefManager.getNullableVal(PrefName.DarkMode, null as Boolean?)
val immersiveMode: Boolean = PrefManager.getVal(PrefName.ImmersiveMode)
darkMode.apply {
AppCompatDelegate.setDefaultNightMode(
when (this) {
true -> AppCompatDelegate.MODE_NIGHT_YES
@ -122,7 +120,7 @@ fun initActivity(a: Activity) {
}
)
}
if (uiSettings.immersiveMode) {
if (immersiveMode) {
if (navBarHeight == 0) {
ViewCompat.getRootWindowInsets(window.decorView.findViewById(android.R.id.content))
?.apply {
@ -290,20 +288,19 @@ class InputFilterMinMax(
}
class ZoomOutPageTransformer(private val uiSettings: UserInterfaceSettings) :
class ZoomOutPageTransformer() :
ViewPager2.PageTransformer {
override fun transformPage(view: View, position: Float) {
if (position == 0.0f && uiSettings.layoutAnimations) {
if (position == 0.0f && PrefManager.getVal(PrefName.LayoutAnimations)) {
setAnimation(
view.context,
view,
uiSettings,
300,
floatArrayOf(1.3f, 1f, 1.3f, 1f),
0.5f to 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(
context: Context,
viewToAnimate: View,
uiSettings: UserInterfaceSettings,
duration: Long = 150,
list: FloatArray = floatArrayOf(0.0f, 1.0f, 0.0f, 1.0f),
pivot: Pair<Float, Float> = 0.5f to 0.5f
) {
if (uiSettings.layoutAnimations) {
if (PrefManager.getVal(PrefName.LayoutAnimations)) {
val anim = ScaleAnimation(
list[0],
list[1],
@ -327,7 +323,7 @@ fun setAnimation(
Animation.RELATIVE_TO_SELF,
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)
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) {
val contentUri = FileProvider.getUriForFile(
@ -708,10 +732,11 @@ fun MutableMap<String, Genre>.checkGenreTime(genre: String): Boolean {
return true
}
fun setSlideIn(uiSettings: UserInterfaceSettings) = AnimationSet(false).apply {
if (uiSettings.layoutAnimations) {
fun setSlideIn() = AnimationSet(false).apply {
if (PrefManager.getVal(PrefName.LayoutAnimations)) {
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()
addAnimation(animation)
@ -722,16 +747,17 @@ fun setSlideIn(uiSettings: UserInterfaceSettings) = AnimationSet(false).apply {
Animation.RELATIVE_TO_SELF, 0f
)
animation.duration = (750 * uiSettings.animationSpeed).toLong()
animation.duration = (750 * animationSpeed).toLong()
animation.interpolator = OvershootInterpolator(1.1f)
addAnimation(animation)
}
}
fun setSlideUp(uiSettings: UserInterfaceSettings) = AnimationSet(false).apply {
if (uiSettings.layoutAnimations) {
fun setSlideUp() = AnimationSet(false).apply {
if (PrefManager.getVal(PrefName.LayoutAnimations)) {
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()
addAnimation(animation)
@ -742,7 +768,7 @@ fun setSlideUp(uiSettings: UserInterfaceSettings) = AnimationSet(false).apply {
Animation.RELATIVE_TO_SELF, 0f
)
animation.duration = (750 * uiSettings.animationSpeed).toLong()
animation.duration = (750 * animationSpeed).toLong()
animation.interpolator = OvershootInterpolator(1.1f)
addAnimation(animation)
}
@ -929,7 +955,7 @@ const val INCOGNITO_CHANNEL_ID = 26
fun incognitoNotification(context: Context) {
val notificationManager =
context.getSystemService(Context.NOTIFICATION_SERVICE) as NotificationManager
val incognito = PrefWrapper.getVal(PrefName.Incognito, false)
val incognito: Boolean = PrefManager.getVal(PrefName.Incognito)
if (incognito) {
val intent = Intent(context, NotificationClickReceiver::class.java)
val pendingIntent = PendingIntent.getBroadcast(

View file

@ -44,11 +44,11 @@ import ani.dantotsu.home.MangaFragment
import ani.dantotsu.home.NoInternet
import ani.dantotsu.media.MediaDetailsActivity
import ani.dantotsu.others.CustomBottomDialog
import ani.dantotsu.settings.UserInterfaceSettings
import ani.dantotsu.settings.saving.PrefName
import ani.dantotsu.settings.saving.PrefWrapper
import ani.dantotsu.settings.saving.PrefWrapper.asLiveBool
import ani.dantotsu.settings.saving.PrefManager
import ani.dantotsu.settings.saving.PrefManager.asLiveBool
import ani.dantotsu.settings.saving.SharedPreferenceBooleanLiveData
import ani.dantotsu.settings.saving.internal.Location
import ani.dantotsu.subcriptions.Subscription.Companion.startSubscription
import ani.dantotsu.themes.ThemeManager
import eu.kanade.domain.source.service.SourcePreferences
@ -71,8 +71,6 @@ class MainActivity : AppCompatActivity() {
private val scope = lifecycleScope
private var load = false
private var uiSettings = UserInterfaceSettings()
@SuppressLint("InternalInsetResource", "DiscouragedApi")
@OptIn(UnstableApi::class)
@ -108,7 +106,7 @@ class MainActivity : AppCompatActivity() {
val layoutParams = binding.incognito.layoutParams as ViewGroup.MarginLayoutParams
layoutParams.topMargin = 11 * offset / 12
binding.incognito.layoutParams = layoutParams
incognitoLiveData = PrefWrapper.getLiveVal(
incognitoLiveData = PrefManager.getLiveVal(
PrefName.Incognito,
false
).asLiveBool()
@ -208,7 +206,6 @@ class MainActivity : AppCompatActivity() {
binding.root.doOnAttach {
initActivity(this)
uiSettings = loadData("ui_settings") ?: uiSettings
selectedOption = if (fragment != null) {
when (fragment) {
AnimeFragment::class.java.name -> 0
@ -217,14 +214,14 @@ class MainActivity : AppCompatActivity() {
else -> 1
}
} else {
uiSettings.defaultStartUpTab
PrefManager.getVal(PrefName.DefaultStartUpTab)
}
binding.includedNavbar.navbarContainer.updateLayoutParams<ViewGroup.MarginLayoutParams> {
bottomMargin = navBarHeight
}
}
val offlineMode = PrefWrapper.getVal(PrefName.OfflineMode, false)
val offlineMode: Boolean = PrefManager.getVal(PrefName.OfflineMode)
if (!isOnline(this)) {
snackString(this@MainActivity.getString(R.string.no_internet_connection))
startActivity(Intent(this, NoInternet::class.java))
@ -245,7 +242,7 @@ class MainActivity : AppCompatActivity() {
mainViewPager.isUserInputEnabled = false
mainViewPager.adapter =
ViewPagerAdapter(supportFragmentManager, lifecycle)
mainViewPager.setPageTransformer(ZoomOutPageTransformer(uiSettings))
mainViewPager.setPageTransformer(ZoomOutPageTransformer())
navbar.setOnTabSelectListener(object :
AnimatedBottomBar.OnTabSelectListener {
override fun onTabSelected(
@ -299,7 +296,7 @@ class MainActivity : AppCompatActivity() {
}
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 {
title = "Allow Dantotsu to automatically open Anilist & MAL Links?"
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)) {
PrefWrapper.setVal(PrefName.AllowOpeningLinks, true)
PrefManager.setVal(PrefName.AllowOpeningLinks, true)
dismiss()
}
setPositiveButton(this@MainActivity.getString(R.string.yes)) {
PrefWrapper.setVal(PrefName.AllowOpeningLinks, true)
PrefManager.setVal(PrefName.AllowOpeningLinks, true)
tryWith(true) {
startActivity(
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.manga.MangaExtensionManager
import eu.kanade.tachiyomi.network.NetworkHelper
import eu.kanade.tachiyomi.network.NetworkPreferences
import eu.kanade.tachiyomi.source.anime.AndroidAnimeSourceManager
import eu.kanade.tachiyomi.source.manga.AndroidMangaSourceManager
import kotlinx.serialization.json.Json
@ -36,7 +35,7 @@ class AppModule(val app: Application) : InjektModule {
addSingletonFactory { DownloadsManager(app) }
addSingletonFactory { NetworkHelper(app, get()) }
addSingletonFactory { NetworkHelper(app) }
addSingletonFactory { AnimeExtensionManager(app) }
addSingletonFactory { MangaExtensionManager(app) }
@ -69,13 +68,6 @@ class PreferenceModule(val application: Application) : InjektModule {
AndroidPreferenceStore(application)
}
addSingletonFactory {
NetworkPreferences(
preferenceStore = get(),
verboseLogging = false,
)
}
addSingletonFactory {
SourcePreferences(get())
}

View file

@ -7,14 +7,14 @@ import ani.dantotsu.connections.mal.MAL
import ani.dantotsu.currContext
import ani.dantotsu.media.Media
import ani.dantotsu.settings.saving.PrefName
import ani.dantotsu.settings.saving.PrefWrapper
import ani.dantotsu.settings.saving.PrefManager
import ani.dantotsu.toast
import kotlinx.coroutines.CoroutineScope
import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.launch
fun updateProgress(media: Media, number: String) {
val incognito = PrefWrapper.getVal(PrefName.Incognito, false)
val incognito: Boolean = PrefManager.getVal(PrefName.Incognito)
if (!incognito) {
if (Anilist.userid != null) {
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.currContext
import ani.dantotsu.isOnline
import ani.dantotsu.loadData
import ani.dantotsu.logError
import ani.dantotsu.media.Author
import ani.dantotsu.media.Character
import ani.dantotsu.media.Media
import ani.dantotsu.media.Studio
import ani.dantotsu.others.MalScraper
import ani.dantotsu.saveData
import ani.dantotsu.settings.saving.PrefName
import ani.dantotsu.settings.saving.PrefWrapper
import ani.dantotsu.settings.saving.PrefManager
import ani.dantotsu.snackString
import kotlinx.coroutines.async
import kotlinx.coroutines.awaitAll
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
class AnilistQueries {
@ -36,7 +40,7 @@ class AnilistQueries {
}.also { println("time : $it") }
val user = response?.data?.user ?: return false
PrefWrapper.setVal(PrefName.AnilistUserName, user.name)
PrefManager.setVal(PrefName.AnilistUserName, user.name)
Anilist.userid = user.id
Anilist.username = user.name
@ -277,8 +281,8 @@ class AnilistQueries {
}
statuses.forEach { repeat(it) }
val set = loadData<MutableSet<Int>>("continue_$type")
if (set != null) {
val set = PrefManager.getCustomVal<Set<Int>>("continue_$type", setOf()).toMutableSet()
if (set.isNotEmpty()) {
set.reversed().forEach {
if (map.containsKey(it)) returnArray.add(map[it]!!)
}
@ -351,7 +355,11 @@ class AnilistQueries {
}
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()) {
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 } } } } } """)
@ -362,13 +370,9 @@ class AnilistQueries {
else null
}
}?.flatten()?.randomOrNull() ?: return null
image = BannerImage(
random,
System.currentTimeMillis()
)
saveData("banner_$type", image)
return image.url
PrefManager.setCustomVal("banner_${type}_url", random)
PrefManager.setCustomVal("banner_${type}_time", System.currentTimeMillis())
return random
} else return image.url
}
@ -417,8 +421,8 @@ class AnilistQueries {
sorted["Favourites"]?.sortWith(compareBy { it.userFavOrder })
sorted["All"] = all
val listSort = if (anime) PrefWrapper.getVal(PrefName.AnimeListSortOrder, "score")
else PrefWrapper.getVal(PrefName.MangaListSortOrder, "score")
val listSort: String = if (anime) PrefManager.getVal(PrefName.AnimeListSortOrder)
else PrefManager.getVal(PrefName.MangaListSortOrder)
val sort = listSort ?: sortOrder ?: options?.rowOrder
for (i in sorted.keys) {
when (sort) {
@ -441,10 +445,16 @@ class AnilistQueries {
suspend fun getGenresAndTags(activity: Activity): Boolean {
var genres: ArrayList<String>? = loadData("genres_list", activity)
var tags: Map<Boolean, List<String>>? = loadData("tags_map", activity)
var genres: ArrayList<String>? = PrefManager.getVal<Set<String>>(PrefName.GenresList).toMutableList() as ArrayList<String>?
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>(
"""{GenreCollection}""",
force = true,
@ -454,7 +464,7 @@ class AnilistQueries {
forEach {
genres?.add(it)
}
saveData("genres_list", genres!!)
PrefManager.setVal(PrefName.GenresList, genres?.toSet())
}
}
if (tags == null) {
@ -472,10 +482,11 @@ class AnilistQueries {
true to adult,
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.tags = tags
true
@ -492,8 +503,36 @@ class AnilistQueries {
}
}
private fun <K, V : Serializable> saveSerializableMap(prefKey: String, map: Map<K, V>) {
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 = loadData<MutableMap<String, Genre>>("genre_thumb") ?: mutableMapOf()
val genres: MutableMap<String, Genre> = loadSerializableMap<String, Genre>("genre_thumb")?.toMutableMap()
?: mutableMapOf()
if (genres.checkGenreTime(genre)) {
try {
val genreQuery =
@ -506,7 +545,7 @@ class AnilistQueries {
it.bannerImage!!,
System.currentTimeMillis()
)
saveData("genre_thumb", genres)
saveSerializableMap("genre_thumb", genres)
return genres[genre]
}
}
@ -719,7 +758,7 @@ Page(page:$page,perPage:50) {
if (smaller) {
val response = execute()?.airingSchedules ?: return null
val idArr = mutableListOf<Int>()
val listOnly = PrefWrapper.getVal(PrefName.RecentlyListOnly, false)
val listOnly: Boolean = PrefManager.getVal(PrefName.RecentlyListOnly)
return response.mapNotNull { i ->
i.media?.let {
if (!idArr.contains(it.id))

View file

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

View file

@ -3,11 +3,10 @@ package ani.dantotsu.connections.discord
import android.content.Context
import android.content.Intent
import android.widget.TextView
import androidx.core.content.edit
import ani.dantotsu.R
import ani.dantotsu.others.CustomBottomDialog
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.tryWith
import io.noties.markwon.Markwon
@ -22,17 +21,17 @@ object Discord {
fun getSavedToken(context: Context): Boolean {
token = PrefWrapper.getVal(
token = PrefManager.getVal(
PrefName.DiscordToken, null as String?)
return token != null
}
fun saveToken(context: Context, token: String) {
PrefWrapper.setVal(PrefName.DiscordToken, token)
PrefManager.setVal(PrefName.DiscordToken, token)
}
fun removeSavedToken(context: Context) {
PrefWrapper.removeVal(PrefName.DiscordToken)
PrefManager.removeVal(PrefName.DiscordToken)
tryWith(true) {
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.isOnline
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.JsonObject
import com.google.gson.JsonParser
@ -153,9 +153,9 @@ class DiscordService : Service() {
fun saveProfile(response: String) {
val user = json.decodeFromString<User.Response>(response).d.user
log("User data: $user")
PrefWrapper.setVal(PrefName.DiscordUserName, user.username)
PrefWrapper.setVal(PrefName.DiscordId, user.id)
PrefWrapper.setVal(PrefName.DiscordAvatar, user.avatar)
PrefManager.setVal(PrefName.DiscordUserName, user.username)
PrefManager.setVal(PrefName.DiscordId, user.id)
PrefManager.setVal(PrefName.DiscordAvatar, user.avatar)
}
override fun onBind(p0: Intent?): IBinder? = null
@ -312,7 +312,7 @@ class DiscordService : Service() {
}
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) {
log("WebSocket: 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.connections.mal.MAL.clientId
import ani.dantotsu.connections.mal.MAL.saveResponse
import ani.dantotsu.loadData
import ani.dantotsu.logError
import ani.dantotsu.settings.saving.PrefName
import ani.dantotsu.settings.saving.PrefManager
import ani.dantotsu.snackString
import ani.dantotsu.startMainActivity
import ani.dantotsu.themes.ThemeManager
@ -25,7 +26,7 @@ class Login : AppCompatActivity() {
try {
val data: Uri = intent?.data
?: 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))
val code = data.getQueryParameter("code")
?: 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.client
import ani.dantotsu.currContext
import ani.dantotsu.loadData
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 kotlinx.serialization.SerialName
import kotlinx.serialization.Serializable
import java.io.File
import java.security.SecureRandom
object MAL {
@ -34,7 +33,7 @@ object MAL {
.replace("/", "_")
.replace("\n", "")
saveData("malCodeChallenge", codeChallenge, context)
PrefManager.setVal(PrefName.MALCodeChallenge, codeChallenge)
val request =
"https://myanimelist.net/v1/oauth2/authorize?response_type=code&client_id=$clientId&code_challenge=$codeChallenge"
try {
@ -47,11 +46,9 @@ object MAL {
}
}
private const val MAL_TOKEN = "malToken"
private suspend fun refreshToken(): ResponseToken? {
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))
val res = client.post(
"https://myanimelist.net/v1/oauth2/token",
@ -69,7 +66,7 @@ object MAL {
suspend fun getSavedToken(context: FragmentActivity): Boolean {
return tryWithSuspend(false) {
var res: ResponseToken = loadData(MAL_TOKEN, context)
var res: ResponseToken = PrefManager.getNullableVal<ResponseToken?>(PrefName.MALToken, null)
?: return@tryWithSuspend false
if (System.currentTimeMillis() > res.expiresIn)
res = refreshToken()
@ -84,14 +81,12 @@ object MAL {
username = null
userid = null
avatar = null
if (MAL_TOKEN in context.fileList()) {
File(context.filesDir, MAL_TOKEN).delete()
}
PrefManager.removeVal(PrefName.MALToken)
}
fun saveResponse(res: ResponseToken) {
res.expiresIn += System.currentTimeMillis()
saveData(MAL_TOKEN, res)
PrefManager.setVal(PrefName.MALToken, res)
}
@Serializable

View file

@ -4,7 +4,7 @@ import android.content.Context
import android.os.Environment
import android.widget.Toast
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.reflect.TypeToken
import java.io.File
@ -23,11 +23,11 @@ class DownloadsManager(private val context: Context) {
private fun saveDownloads() {
val jsonString = gson.toJson(downloadsList)
PrefWrapper.setVal(PrefName.DownloadsKeys, jsonString)
PrefManager.setVal(PrefName.DownloadsKeys, jsonString)
}
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) {
val type = object : TypeToken<List<DownloadedType>>() {}.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.parsers.Subtitle
import ani.dantotsu.parsers.Video
import ani.dantotsu.settings.saving.PrefWrapper
import ani.dantotsu.settings.saving.PrefManager
import ani.dantotsu.snackString
import com.google.firebase.crashlytics.FirebaseCrashlytics
import com.google.gson.GsonBuilder
@ -295,7 +295,7 @@ class AnimeDownloaderService : Service() {
builder.setContentText("${task.title} - ${task.episode} Download completed")
notificationManager.notify(NOTIFICATION_ID, builder.build())
snackString("${task.title} - ${task.episode} Download completed")
PrefWrapper.getAnimeDownloadPreferences().edit().putString(
PrefManager.getAnimeDownloadPreferences().edit().putString(
task.getTaskName(),
task.video.file.url
).apply()

View file

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

View file

@ -1,7 +1,6 @@
package ani.dantotsu.download.anime
import android.content.Context
import android.content.Intent
import android.net.Uri
import android.os.Bundle
@ -36,16 +35,14 @@ import ani.dantotsu.currContext
import ani.dantotsu.download.DownloadedType
import ani.dantotsu.download.DownloadsManager
import ani.dantotsu.initActivity
import ani.dantotsu.loadData
import ani.dantotsu.logger
import ani.dantotsu.media.Media
import ani.dantotsu.media.MediaDetailsActivity
import ani.dantotsu.navBarHeight
import ani.dantotsu.setSafeOnClickListener
import ani.dantotsu.settings.SettingsDialogFragment
import ani.dantotsu.settings.UserInterfaceSettings
import ani.dantotsu.settings.saving.PrefName
import ani.dantotsu.settings.saving.PrefWrapper
import ani.dantotsu.settings.saving.PrefManager
import ani.dantotsu.snackString
import com.google.android.material.card.MaterialCardView
import com.google.android.material.imageview.ShapeableImageView
@ -70,8 +67,6 @@ class OfflineAnimeFragment : Fragment(), OfflineAnimeSearchListener {
private lateinit var gridView: GridView
private lateinit var adapter: OfflineAnimeAdapter
private lateinit var total: TextView
private var uiSettings: UserInterfaceSettings =
loadData("ui_settings") ?: UserInterfaceSettings()
override fun onCreateView(
inflater: LayoutInflater,
@ -97,7 +92,7 @@ class OfflineAnimeFragment : Fragment(), OfflineAnimeSearchListener {
SettingsDialogFragment.newInstance(SettingsDialogFragment.Companion.PageType.OfflineANIME)
dialogFragment.show((it.context as AppCompatActivity).supportFragmentManager, "dialog")
}
if (!uiSettings.immersiveMode) {
if (!(PrefManager.getVal(PrefName.ImmersiveMode) as Boolean)) {
view.rootView.fitsSystemWindows = true
}
@ -116,7 +111,7 @@ class OfflineAnimeFragment : Fragment(), OfflineAnimeSearchListener {
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 layoutcompact = view.findViewById<ImageView>(R.id.downloadedGrid)
var selected = when (style) {
@ -135,7 +130,7 @@ class OfflineAnimeFragment : Fragment(), OfflineAnimeSearchListener {
layoutList.setOnClickListener {
selected(it as ImageView)
style = 0
PrefWrapper.setVal(PrefName.OfflineView, style)
PrefManager.setVal(PrefName.OfflineView, style)
gridView.visibility = View.GONE
gridView = view.findViewById(R.id.gridView)
adapter.notifyNewGrid()
@ -145,7 +140,7 @@ class OfflineAnimeFragment : Fragment(), OfflineAnimeSearchListener {
layoutcompact.setOnClickListener {
selected(it as ImageView)
style = 1
PrefWrapper.setVal(PrefName.OfflineView, style)
PrefManager.setVal(PrefName.OfflineView, style)
gridView.visibility = View.GONE
gridView = view.findViewById(R.id.gridView1)
adapter.notifyNewGrid()
@ -212,7 +207,7 @@ class OfflineAnimeFragment : Fragment(), OfflineAnimeSearchListener {
builder.setMessage("Are you sure you want to delete ${item.title}?")
builder.setPositiveButton("Yes") { _, _ ->
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()) {
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 ani.dantotsu.R
import ani.dantotsu.settings.saving.PrefName
import ani.dantotsu.settings.saving.PrefWrapper
import ani.dantotsu.settings.saving.PrefManager
class OfflineMangaAdapter(
@ -23,7 +23,7 @@ class OfflineMangaAdapter(
private val inflater: LayoutInflater =
context.getSystemService(Context.LAYOUT_INFLATER_SERVICE) as LayoutInflater
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 {
return items.size
@ -105,7 +105,7 @@ class OfflineMangaAdapter(
}
fun notifyNewGrid() {
style = PrefWrapper.getVal(PrefName.OfflineView, 0)
style = PrefManager.getVal(PrefName.OfflineView)
notifyDataSetChanged()
}
}

View file

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

View file

@ -13,7 +13,6 @@ import android.util.Log
import androidx.annotation.OptIn
import androidx.core.app.ActivityCompat
import androidx.core.content.ContextCompat
import androidx.core.content.ContextCompat.getString
import androidx.media3.common.C
import androidx.media3.common.MediaItem
import androidx.media3.common.MimeTypes
@ -43,7 +42,7 @@ import ani.dantotsu.parsers.Subtitle
import ani.dantotsu.parsers.SubtitleType
import ani.dantotsu.parsers.Video
import ani.dantotsu.parsers.VideoType
import ani.dantotsu.settings.saving.PrefWrapper
import ani.dantotsu.settings.saving.PrefManager
import eu.kanade.tachiyomi.network.NetworkHelper
import uy.kohesive.injekt.Injekt
import uy.kohesive.injekt.api.get
@ -230,13 +229,13 @@ object Helper {
DownloadService.sendRemoveDownload(
context,
ExoplayerDownloadService::class.java,
PrefWrapper.getAnimeDownloadPreferences().getString(
PrefManager.getAnimeDownloadPreferences().getString(
animeDownloadTask.getTaskName(),
""
) ?: "",
false
)
PrefWrapper.getAnimeDownloadPreferences().edit()
PrefManager.getAnimeDownloadPreferences().edit()
.remove(animeDownloadTask.getTaskName())
.apply()
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.getUserId
import ani.dantotsu.databinding.FragmentAnimeBinding
import ani.dantotsu.loadData
import ani.dantotsu.media.MediaAdaptor
import ani.dantotsu.media.ProgressAdapter
import ani.dantotsu.media.SearchActivity
import ani.dantotsu.navBarHeight
import ani.dantotsu.px
import ani.dantotsu.settings.UserInterfaceSettings
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.statusBarHeight
import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.delay
import kotlinx.coroutines.launch
import kotlinx.coroutines.withContext
import uy.kohesive.injekt.Injekt
import uy.kohesive.injekt.api.get
import kotlin.math.max
import kotlin.math.min
@ -53,9 +49,6 @@ class AnimeFragment : Fragment() {
private val binding get() = _binding!!
private lateinit var animePageAdapter: AnimePageAdapter
private var uiSettings: UserInterfaceSettings =
loadData("ui_settings") ?: UserInterfaceSettings()
val model: AnilistAnimeViewModel by activityViewModels()
override fun onCreateView(
@ -220,7 +213,7 @@ class AnimeFragment : Fragment() {
if (it != null) {
animePageAdapter.updateTrending(
MediaAdaptor(
if (uiSettings.smallView) 3 else 2,
if (PrefManager.getVal(PrefName.SmallView)) 3 else 2,
it,
requireActivity(),
viewPager = animePageAdapter.trendingViewPager
@ -271,8 +264,8 @@ class AnimeFragment : Fragment() {
model.loaded = true
model.loadTrending(1)
model.loadUpdated()
model.loadPopular("ANIME", sort = Anilist.sortBy[1], onList = PrefWrapper.getVal(
PrefName.PopularAnimeList, true))
model.loadPopular("ANIME", sort = Anilist.sortBy[1], onList = PrefManager.getVal(
PrefName.PopularAnimeList))
}
live.postValue(false)
_binding?.animeRefresh?.isRefreshing = false

View file

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

View file

@ -27,7 +27,6 @@ import ani.dantotsu.connections.anilist.AnilistHomeViewModel
import ani.dantotsu.connections.anilist.getUserId
import ani.dantotsu.currContext
import ani.dantotsu.databinding.FragmentHomeBinding
import ani.dantotsu.loadData
import ani.dantotsu.loadImage
import ani.dantotsu.media.Media
import ani.dantotsu.media.MediaAdaptor
@ -37,7 +36,8 @@ import ani.dantotsu.setSafeOnClickListener
import ani.dantotsu.setSlideIn
import ani.dantotsu.setSlideUp
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.statusBarHeight
import kotlinx.coroutines.Dispatchers
@ -70,14 +70,13 @@ class HomeFragment : Fragment() {
override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
val scope = lifecycleScope
var uiSettings = loadData<UserInterfaceSettings>("ui_settings") ?: UserInterfaceSettings()
fun load() {
if (activity != null && _binding != null) lifecycleScope.launch(Dispatchers.Main) {
binding.homeUserName.text = Anilist.username
binding.homeUserEpisodesWatched.text = Anilist.episodesWatched.toString()
binding.homeUserChaptersRead.text = Anilist.chapterRead.toString()
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.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.layoutAnimation =
LayoutAnimationController(setSlideUp(uiSettings), 0.25f)
LayoutAnimationController(setSlideUp(), 0.25f)
binding.homeAnimeList.visibility = View.VISIBLE
binding.homeMangaList.visibility = View.VISIBLE
binding.homeListContainer.layoutAnimation =
LayoutAnimationController(setSlideIn(uiSettings), 0.25f)
LayoutAnimationController(setSlideIn(), 0.25f)
}
else {
snackString(currContext()?.getString(R.string.please_reload))
@ -127,7 +126,7 @@ class HomeFragment : Fragment() {
binding.homeTopContainer.updatePadding(top = statusBarHeight)
var reached = false
val duration = (uiSettings.animationSpeed * 200).toLong()
val duration = ((PrefManager.getVal(PrefName.AnimationSpeed) as Float) * 200).toLong()
binding.homeScroll.setOnScrollChangeListener { _, _, _, _, _ ->
if (!binding.homeScroll.canScrollVertically(1)) {
reached = true
@ -206,13 +205,13 @@ class HomeFragment : Fragment() {
)
recyclerView.visibility = View.VISIBLE
recyclerView.layoutAnimation =
LayoutAnimationController(setSlideIn(uiSettings), 0.25f)
LayoutAnimationController(setSlideIn(), 0.25f)
} else {
empty.visibility = View.VISIBLE
}
title.visibility = View.VISIBLE
title.startAnimation(setSlideUp(uiSettings))
title.startAnimation(setSlideUp())
progress.visibility = View.GONE
}
}
@ -295,12 +294,12 @@ class HomeFragment : Fragment() {
binding.homeRecommended
)
binding.homeUserAvatarContainer.startAnimation(setSlideUp(uiSettings))
binding.homeUserAvatarContainer.startAnimation(setSlideUp())
model.empty.observe(viewLifecycleOwner) {
binding.homeDantotsuContainer.visibility = if (it == true) View.VISIBLE else View.GONE
(binding.homeDantotsuIcon.drawable as Animatable).start()
binding.homeDantotsuContainer.startAnimation(setSlideUp(uiSettings))
binding.homeDantotsuContainer.startAnimation(setSlideUp())
binding.homeDantotsuIcon.setSafeOnClickListener {
(binding.homeDantotsuIcon.drawable as Animatable).start()
}
@ -330,8 +329,6 @@ class HomeFragment : Fragment() {
live.observe(viewLifecycleOwner) {
if (it) {
scope.launch {
uiSettings =
loadData<UserInterfaceSettings>("ui_settings") ?: UserInterfaceSettings()
withContext(Dispatchers.IO) {
//Get userData First
getUserId(requireContext()) {
@ -340,8 +337,9 @@ class HomeFragment : Fragment() {
model.loaded = true
model.setListImages()
var empty = true
val homeLayoutShow: List<Boolean> = PrefManager.getVal(PrefName.HomeLayoutShow)
(array.indices).forEach { i ->
if (uiSettings.homeLayoutShow[i]) {
if (homeLayoutShow.elementAt(i)) {
array[i].run()
empty = false
} 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.getUserId
import ani.dantotsu.databinding.FragmentMangaBinding
import ani.dantotsu.loadData
import ani.dantotsu.media.MediaAdaptor
import ani.dantotsu.media.ProgressAdapter
import ani.dantotsu.navBarHeight
import ani.dantotsu.px
import ani.dantotsu.settings.UserInterfaceSettings
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.statusBarHeight
import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.delay
import kotlinx.coroutines.launch
import kotlinx.coroutines.withContext
import uy.kohesive.injekt.Injekt
import uy.kohesive.injekt.api.get
import kotlin.math.max
import kotlin.math.min
@ -49,9 +45,6 @@ class MangaFragment : Fragment() {
private val binding get() = _binding!!
private lateinit var mangaPageAdapter: MangaPageAdapter
private var uiSettings: UserInterfaceSettings =
loadData("ui_settings") ?: UserInterfaceSettings()
val model: AnilistMangaViewModel by activityViewModels()
override fun onCreateView(
@ -178,7 +171,7 @@ class MangaFragment : Fragment() {
if (it != null) {
mangaPageAdapter.updateTrending(
MediaAdaptor(
if (uiSettings.smallView) 3 else 2,
if (PrefManager.getVal(PrefName.SmallView)) 3 else 2,
it,
requireActivity(),
viewPager = mangaPageAdapter.trendingViewPager
@ -245,8 +238,8 @@ class MangaFragment : Fragment() {
model.loaded = true
model.loadTrending()
model.loadTrendingNovel()
model.loadPopular("MANGA", sort = Anilist.sortBy[1], onList = PrefWrapper.getVal(
PrefName.PopularMangaList, true))
model.loadPopular("MANGA", sort = Anilist.sortBy[1], onList = PrefManager.getVal(
PrefName.PopularMangaList))
}
live.postValue(false)
_binding?.mangaRefresh?.isRefreshing = false

View file

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

View file

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

View file

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

View file

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

View file

@ -17,13 +17,13 @@ import ani.dantotsu.R
import ani.dantotsu.Refresh
import ani.dantotsu.databinding.ActivityCharacterBinding
import ani.dantotsu.initActivity
import ani.dantotsu.loadData
import ani.dantotsu.loadImage
import ani.dantotsu.navBarHeight
import ani.dantotsu.others.ImageViewDialog
import ani.dantotsu.others.getSerialized
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.themes.ThemeManager
import com.google.android.material.appbar.AppBarLayout
@ -37,7 +37,6 @@ class CharacterDetailsActivity : AppCompatActivity(), AppBarLayout.OnOffsetChang
private val model: OtherDetailsViewModel by viewModels()
private lateinit var character: Character
private var loaded = false
val uiSettings = loadData<UserInterfaceSettings>("ui_settings") ?: UserInterfaceSettings()
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
@ -48,11 +47,11 @@ class CharacterDetailsActivity : AppCompatActivity(), AppBarLayout.OnOffsetChang
initActivity(this)
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)
val banner =
if (uiSettings.bannerAnimations) binding.characterBanner else binding.characterBannerNoKen
if (PrefManager.getVal(PrefName.BannerAnimations)) binding.characterBanner else binding.characterBannerNoKen
banner.updateLayoutParams { height += statusBarHeight }
binding.characterClose.updateLayoutParams<ViewGroup.MarginLayoutParams> { topMargin += statusBarHeight }
@ -135,16 +134,16 @@ class CharacterDetailsActivity : AppCompatActivity(), AppBarLayout.OnOffsetChang
binding.characterCover.visibility =
if (binding.characterCover.scaleX == 0f) View.GONE else View.VISIBLE
val immersiveMode: Boolean = PrefManager.getVal(PrefName.ImmersiveMode)
if (percentage >= percent && !isCollapsed) {
isCollapsed = true
if (uiSettings.immersiveMode) this.window.statusBarColor =
if (immersiveMode) this.window.statusBarColor =
ContextCompat.getColor(this, R.color.nav_bg)
binding.characterAppBar.setBackgroundResource(R.color.nav_bg)
}
if (percentage <= percent && isCollapsed) {
isCollapsed = false
if (uiSettings.immersiveMode) this.window.statusBarColor =
if (immersiveMode) this.window.statusBarColor =
ContextCompat.getColor(this, R.color.status)
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.databinding.ActivityGenreBinding
import ani.dantotsu.initActivity
import ani.dantotsu.loadData
import ani.dantotsu.navBarHeight
import ani.dantotsu.settings.saving.PrefName
import ani.dantotsu.settings.saving.PrefManager
import ani.dantotsu.statusBarHeight
import ani.dantotsu.themes.ThemeManager
import kotlinx.coroutines.Dispatchers
@ -53,7 +54,8 @@ class GenreActivity : AppCompatActivity() {
GridLayoutManager(this, (screenWidth / 156f).toInt())
lifecycleScope.launch(Dispatchers.IO) {
model.loadGenres(Anilist.genres ?: loadData("genres_list") ?: arrayListOf()) {
model.loadGenres(Anilist.genres ?:
loadLocalGenres() ?: arrayListOf()) {
MainScope().launch {
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.ItemMediaPageBinding
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.load.engine.DiskCacheStrategy
import com.bumptech.glide.load.model.GlideUrl
@ -44,9 +45,6 @@ class MediaAdaptor(
private val viewPager: ViewPager2? = null,
) : RecyclerView.Adapter<RecyclerView.ViewHolder>() {
private val uiSettings =
loadData<UserInterfaceSettings>("ui_settings") ?: UserInterfaceSettings()
override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): RecyclerView.ViewHolder {
return when (type) {
0 -> MediaViewHolder(
@ -91,7 +89,7 @@ class MediaAdaptor(
when (type) {
0 -> {
val b = (holder as MediaViewHolder).binding
setAnimation(activity, b.root, uiSettings)
setAnimation(activity, b.root)
val media = mediaList?.getOrNull(position)
if (media != null) {
b.itemCompactImage.loadImage(media.cover)
@ -135,7 +133,7 @@ class MediaAdaptor(
1 -> {
val b = (holder as MediaLargeViewHolder).binding
setAnimation(activity, b.root, uiSettings)
setAnimation(activity, b.root)
val media = mediaList?.get(position)
if (media != null) {
b.itemCompactImage.loadImage(media.cover)
@ -178,16 +176,17 @@ class MediaAdaptor(
val b = (holder as MediaPageViewHolder).binding
val media = mediaList?.get(position)
if (media != null) {
val bannerAnimations: Boolean = PrefManager.getVal(PrefName.BannerAnimations)
b.itemCompactImage.loadImage(media.cover)
if (uiSettings.bannerAnimations)
if (bannerAnimations)
b.itemCompactBanner.setTransitionGenerator(
RandomTransitionGenerator(
(10000 + 15000 * (uiSettings.animationSpeed)).toLong(),
(10000 + 15000 * ((PrefManager.getVal(PrefName.AnimationSpeed)) as Float)).toLong(),
AccelerateDecelerateInterpolator()
)
)
val banner =
if (uiSettings.bannerAnimations) b.itemCompactBanner else b.itemCompactBannerNoKen
if (bannerAnimations) b.itemCompactBanner else b.itemCompactBannerNoKen
val context = b.itemCompactBanner.context
if (!(context as Activity).isDestroyed)
Glide.with(context as Context)
@ -234,16 +233,17 @@ class MediaAdaptor(
val b = (holder as MediaPageSmallViewHolder).binding
val media = mediaList?.get(position)
if (media != null) {
val bannerAnimations: Boolean = PrefManager.getVal(PrefName.BannerAnimations)
b.itemCompactImage.loadImage(media.cover)
if (uiSettings.bannerAnimations)
if (bannerAnimations)
b.itemCompactBanner.setTransitionGenerator(
RandomTransitionGenerator(
(10000 + 15000 * (uiSettings.animationSpeed)).toLong(),
(10000 + 15000 * ((PrefManager.getVal(PrefName.AnimationSpeed) as Float))).toLong(),
AccelerateDecelerateInterpolator()
)
)
val banner =
if (uiSettings.bannerAnimations) b.itemCompactBanner else b.itemCompactBannerNoKen
if (bannerAnimations) b.itemCompactBanner else b.itemCompactBannerNoKen
val context = b.itemCompactBanner.context
if (!(context as Activity).isDestroyed)
Glide.with(context as Context)

View file

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

View file

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

View file

@ -2,7 +2,6 @@ package ani.dantotsu.media
import android.animation.ObjectAnimator
import android.annotation.SuppressLint
import android.content.Context
import android.content.Intent
import android.os.Build
import android.os.Bundle
@ -27,7 +26,7 @@ import ani.dantotsu.connections.anilist.Anilist
import ani.dantotsu.connections.anilist.GenresViewModel
import ani.dantotsu.databinding.*
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.SoftBreakAddsNewLinePlugin
import kotlinx.coroutines.Dispatchers
@ -62,7 +61,7 @@ class MediaInfoFragment : Fragment() {
@SuppressLint("SetJavaScriptEnabled")
override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
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.mediaInfoContainer.visibility = if (loaded) View.VISIBLE else View.GONE
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.databinding.ActivitySearchBinding
import ani.dantotsu.settings.saving.PrefName
import ani.dantotsu.settings.saving.PrefWrapper
import ani.dantotsu.settings.saving.PrefManager
import ani.dantotsu.themes.ThemeManager
import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.launch
@ -53,7 +53,7 @@ class SearchActivity : AppCompatActivity() {
bottom = navBarHeight + 80f.px
)
style = PrefWrapper.getVal(PrefName.SearchStyle,0)
style = PrefManager.getVal(PrefName.SearchStyle)
var listOnly: Boolean? = intent.getBooleanExtra("listOnly", false)
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.ItemSearchHeaderBinding
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 kotlinx.coroutines.CoroutineScope
import kotlinx.coroutines.Dispatchers
@ -72,7 +72,7 @@ class SearchAdapter(private val activity: SearchActivity, private val type: Stri
}
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 startIconDrawable: Drawable? =
context?.let { AppCompatResources.getDrawable(it, startIconDrawableRes) }
@ -148,14 +148,14 @@ class SearchAdapter(private val activity: SearchActivity, private val type: Stri
it.alpha = 1f
binding.searchResultList.alpha = 0.33f
activity.style = 0
PrefWrapper.setVal(PrefName.SearchStyle, 0)
PrefManager.setVal(PrefName.SearchStyle, 0)
activity.recycler()
}
binding.searchResultList.setOnClickListener {
it.alpha = 1f
binding.searchResultGrid.alpha = 0.33f
activity.style = 1
PrefWrapper.setVal(PrefName.SearchStyle, 1)
PrefManager.setVal(PrefName.SearchStyle, 1)
activity.recycler()
}

View file

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

View file

@ -1,7 +1,6 @@
package ani.dantotsu.media.anime
import android.annotation.SuppressLint
import android.content.Context
import android.content.Intent
import android.net.Uri
import android.view.LayoutInflater
@ -28,7 +27,7 @@ import ani.dantotsu.parsers.AnimeSources
import ani.dantotsu.parsers.DynamicAnimeParser
import ani.dantotsu.parsers.WatchSources
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.Subscription.Companion.getChannelId
import com.google.android.material.chip.Chip
@ -61,7 +60,7 @@ class AnimeWatchAdapter(
_binding = binding
//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.setOnClickListener {
val intent = Intent(Intent.ACTION_VIEW, Uri.parse(media.anime.youtube))
@ -92,9 +91,8 @@ class AnimeWatchAdapter(
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
@ -200,7 +198,7 @@ class AnimeWatchAdapter(
var refresh = false
var run = false
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.sortText.text = if (reversed) "Down to Up" else "Up to Down"
dialogBinding.animeSourceTop.setOnClickListener {
@ -358,7 +356,7 @@ class AnimeWatchAdapter(
val episodes = media.anime.episodes!!.keys.toTypedArray()
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()
if (episodes.contains(continueEp)) {
@ -370,7 +368,7 @@ class AnimeWatchAdapter(
media.id,
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)
if (e != -1 && e + 1 < episodes.size) {
continueEp = episodes[e + 1]
@ -397,7 +395,7 @@ class AnimeWatchAdapter(
fragment.onEpisodeClick(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()
fragment.continueEp = false
}

View file

@ -40,10 +40,9 @@ import ani.dantotsu.others.LanguageMapper
import ani.dantotsu.parsers.AnimeParser
import ani.dantotsu.parsers.AnimeSources
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.saving.PrefWrapper
import ani.dantotsu.settings.saving.PrefName
import ani.dantotsu.settings.saving.PrefManager
import ani.dantotsu.subcriptions.Notifications
import ani.dantotsu.subcriptions.Notifications.Group.ANIME_GROUP
import ani.dantotsu.subcriptions.Subscription.Companion.getChannelId
@ -86,8 +85,6 @@ class AnimeWatchFragment : Fragment() {
var continueEp: Boolean = false
var loaded = false
lateinit var playerSettings: PlayerSettings
lateinit var uiSettings: UserInterfaceSettings
override fun onCreateView(
inflater: LayoutInflater,
container: ViewGroup?,
@ -120,12 +117,6 @@ class AnimeWatchFragment : Fragment() {
var maxGridSize = (screenWidth / 100f).roundToInt()
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)
gridLayoutManager.spanSizeLookup = object : GridLayoutManager.SpanSizeLookup() {
@ -174,7 +165,7 @@ class AnimeWatchFragment : Fragment() {
media.selected = model.loadSelected(media)
subscribed =
SubscriptionHelper.getSubscriptions(requireContext()).containsKey(media.id)
SubscriptionHelper.getSubscriptions().containsKey(media.id)
style = media.selected!!.recyclerStyle
reverse = media.selected!!.recyclerReversed
@ -191,7 +182,7 @@ class AnimeWatchFragment : Fragment() {
headerAdapter = AnimeWatchAdapter(it, this, model.watchSources!!)
episodeAdapter =
EpisodeAdapter(
style ?: uiSettings.animeDefaultView,
style ?: PrefManager.getVal(PrefName.AnimeDefaultView),
media,
this,
offlineMode = offlineMode
@ -292,7 +283,7 @@ class AnimeWatchFragment : Fragment() {
model.watchSources?.get(selected.sourceIndex)?.showUserTextListener = null
selected.sourceIndex = i
selected.server = null
model.saveSelected(media.id, selected, requireActivity())
model.saveSelected(media.id, selected)
media.selected = selected
return model.watchSources?.get(i)!!
}
@ -300,7 +291,7 @@ class AnimeWatchFragment : Fragment() {
fun onLangChange(i: Int) {
val selected = model.loadSelected(media)
selected.langIndex = i
model.saveSelected(media.id, selected, requireActivity())
model.saveSelected(media.id, selected)
media.selected = selected
}
@ -308,7 +299,7 @@ class AnimeWatchFragment : Fragment() {
val selected = model.loadSelected(media)
model.watchSources?.get(selected.sourceIndex)?.selectDub = checked
selected.preferDub = checked
model.saveSelected(media.id, selected, requireActivity())
model.saveSelected(media.id, selected)
media.selected = selected
lifecycleScope.launch(Dispatchers.IO) {
model.forceLoadEpisode(
@ -327,7 +318,7 @@ class AnimeWatchFragment : Fragment() {
reverse = rev
media.selected!!.recyclerStyle = style
media.selected!!.recyclerReversed = reverse
model.saveSelected(media.id, media.selected!!, requireActivity())
model.saveSelected(media.id, media.selected!!)
reload()
}
@ -335,7 +326,7 @@ class AnimeWatchFragment : Fragment() {
media.selected!!.chip = i
start = s
end = e
model.saveSelected(media.id, media.selected!!, requireActivity())
model.saveSelected(media.id, media.selected!!)
reload()
}
@ -436,7 +427,7 @@ class AnimeWatchFragment : Fragment() {
fun onEpisodeClick(i: String) {
model.continueMedia = false
model.saveSelected(media.id, media.selected!!, requireActivity())
model.saveSelected(media.id, media.selected!!)
model.onEpisodeClick(media, i, requireActivity().supportFragmentManager)
}
@ -475,11 +466,11 @@ class AnimeWatchFragment : Fragment() {
)
)
val taskName = AnimeDownloaderService.AnimeDownloadTask.getTaskName(media.mainName(), i)
val id = PrefWrapper.getAnimeDownloadPreferences().getString(
val id = PrefManager.getAnimeDownloadPreferences().getString(
taskName,
""
) ?: ""
PrefWrapper.getAnimeDownloadPreferences().edit().remove(taskName).apply()
PrefManager.getAnimeDownloadPreferences().edit().remove(taskName).apply()
DownloadService.sendRemoveDownload(
requireContext(),
ExoplayerDownloadService::class.java,
@ -531,7 +522,7 @@ class AnimeWatchFragment : Fragment() {
selected.latest =
media.userProgress?.toFloat()?.takeIf { selected.latest < it } ?: selected.latest
model.saveSelected(media.id, selected, requireActivity())
model.saveSelected(media.id, selected)
headerAdapter.handleEpisodes()
val isDownloaded = model.watchSources!!.isDownloadedSource(media.selected!!.sourceIndex)
episodeAdapter.offlineMode = isDownloaded
@ -547,7 +538,7 @@ class AnimeWatchFragment : Fragment() {
arr = (arr.reversed() as? ArrayList<Episode>) ?: arr
}
episodeAdapter.arr = arr
episodeAdapter.updateType(style ?: uiSettings.animeDefaultView)
episodeAdapter.updateType(style ?: PrefManager.getVal(PrefName.AnimeDefaultView))
episodeAdapter.notifyItemRangeInserted(0, arr.size)
for (download in downloadManager.animeDownloadedTypes) {
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.video.Helper
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.load.model.GlideUrl
import kotlinx.coroutines.delay
@ -29,8 +29,8 @@ import kotlin.math.ln
import kotlin.math.pow
fun handleProgress(cont: LinearLayout, bar: View, empty: View, mediaId: Int, ep: String) {
val curr = loadData<Long>("${mediaId}_${ep}")
val max = loadData<Long>("${mediaId}_${ep}_max")
val curr = PrefManager.getNullableCustomVal("${mediaId}_${ep}", null as Long?)
val max = PrefManager.getNullableCustomVal("${mediaId}_${ep}_max", null as Long?)
if (curr != null && max != null) {
cont.visibility = View.VISIBLE
val div = curr.toFloat() / max.toFloat()
@ -109,7 +109,7 @@ class EpisodeAdapter(
when (holder) {
is EpisodeListViewHolder -> {
val binding = holder.binding
setAnimation(fragment.requireContext(), holder.binding.root, fragment.uiSettings)
setAnimation(fragment.requireContext(), holder.binding.root)
val thumb =
ep.thumb?.let { if (it.url.isNotEmpty()) GlideUrl(it.url) { it.headers } else null }
@ -158,7 +158,7 @@ class EpisodeAdapter(
is EpisodeGridViewHolder -> {
val binding = holder.binding
setAnimation(fragment.requireContext(), holder.binding.root, fragment.uiSettings)
setAnimation(fragment.requireContext(), holder.binding.root)
val thumb =
ep.thumb?.let { if (it.url.isNotEmpty()) GlideUrl(it.url) { it.headers } else null }
@ -201,7 +201,7 @@ class EpisodeAdapter(
is EpisodeCompactViewHolder -> {
val binding = holder.binding
setAnimation(fragment.requireContext(), holder.binding.root, fragment.uiSettings)
setAnimation(fragment.requireContext(), holder.binding.root)
binding.itemEpisodeNumber.text = ep.number
binding.itemEpisodeFillerView.visibility =
if (ep.filler) View.VISIBLE else View.GONE
@ -252,7 +252,7 @@ class EpisodeAdapter(
media.mainName(),
episodeNumber
)
val id = PrefWrapper.getAnimeDownloadPreferences().getString(
val id = PrefManager.getAnimeDownloadPreferences().getString(
taskName,
""
) ?: ""

View file

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

View file

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

View file

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

View file

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

View file

@ -2,7 +2,6 @@ package ani.dantotsu.media.manga
import android.annotation.SuppressLint
import android.app.AlertDialog
import android.content.Context
import android.content.Intent
import android.view.LayoutInflater
import android.view.View
@ -29,7 +28,7 @@ import ani.dantotsu.parsers.DynamicMangaParser
import ani.dantotsu.parsers.MangaReadSources
import ani.dantotsu.parsers.MangaSources
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.Subscription.Companion.getChannelId
import com.google.android.material.chip.Chip
@ -71,7 +70,7 @@ class MangaReadAdapter(
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
binding.animeSourceNameContainer.visibility = offline
@ -161,7 +160,7 @@ class MangaReadAdapter(
var refresh = false
var run = false
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.sortText.text = if (reversed) "Down to Up" else "Up to Down"
dialogBinding.animeSourceTop.setOnClickListener {
@ -390,7 +389,7 @@ class MangaReadAdapter(
if (media.manga?.chapters != null) {
val chapters = media.manga.chapters!!.keys.toTypedArray()
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()
val filteredChapters = chapters.filter { 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.MangaParser
import ani.dantotsu.parsers.MangaSources
import ani.dantotsu.settings.UserInterfaceSettings
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.Group.MANGA_GROUP
import ani.dantotsu.subcriptions.Subscription.Companion.getChannelId
@ -87,9 +88,6 @@ open class MangaReadFragment : Fragment(), ScanlatorSelectionListener {
var continueEp: Boolean = false
var loaded = false
val uiSettings = loadData("ui_settings", toast = false)
?: UserInterfaceSettings().apply { saveData("ui_settings", this) }
override fun onCreateView(
inflater: LayoutInflater,
container: ViewGroup?,
@ -172,7 +170,7 @@ open class MangaReadFragment : Fragment(), ScanlatorSelectionListener {
media.selected = model.loadSelected(media)
subscribed =
SubscriptionHelper.getSubscriptions(requireContext()).containsKey(media.id)
SubscriptionHelper.getSubscriptions().containsKey(media.id)
style = media.selected!!.recyclerStyle
reverse = media.selected!!.recyclerReversed
@ -183,7 +181,7 @@ open class MangaReadFragment : Fragment(), ScanlatorSelectionListener {
headerAdapter = MangaReadAdapter(it, this, model.mangaReadSources!!)
headerAdapter.scanlatorSelectionListener = this
chapterAdapter =
MangaChapterAdapter(style ?: uiSettings.mangaDefaultView, media, this)
MangaChapterAdapter(style ?: PrefManager.getVal(PrefName.MangaDefaultView), media, this)
for (download in downloadManager.mangaDownloadedTypes) {
chapterAdapter.stopDownload(download.chapter)
@ -302,7 +300,7 @@ open class MangaReadFragment : Fragment(), ScanlatorSelectionListener {
model.mangaReadSources?.get(selected.sourceIndex)?.showUserTextListener = null
selected.sourceIndex = i
selected.server = null
model.saveSelected(media.id, selected, requireActivity())
model.saveSelected(media.id, selected)
media.selected = selected
return model.mangaReadSources?.get(i)!!
}
@ -310,14 +308,14 @@ open class MangaReadFragment : Fragment(), ScanlatorSelectionListener {
fun onLangChange(i: Int) {
val selected = model.loadSelected(media)
selected.langIndex = i
model.saveSelected(media.id, selected, requireActivity())
model.saveSelected(media.id, selected)
media.selected = selected
}
fun onScanlatorChange(list: List<String>) {
val selected = model.loadSelected(media)
selected.scanlators = list
model.saveSelected(media.id, selected, requireActivity())
model.saveSelected(media.id, selected)
media.selected = selected
}
@ -330,7 +328,7 @@ open class MangaReadFragment : Fragment(), ScanlatorSelectionListener {
reverse = rev
media.selected!!.recyclerStyle = style
media.selected!!.recyclerReversed = reverse
model.saveSelected(media.id, media.selected!!, requireActivity())
model.saveSelected(media.id, media.selected!!)
reload()
}
@ -338,7 +336,7 @@ open class MangaReadFragment : Fragment(), ScanlatorSelectionListener {
media.selected!!.chip = i
start = s
end = e
model.saveSelected(media.id, media.selected!!, requireActivity())
model.saveSelected(media.id, media.selected!!)
reload()
}
@ -436,7 +434,7 @@ open class MangaReadFragment : Fragment(), ScanlatorSelectionListener {
model.continueMedia = false
media.manga?.chapters?.get(i)?.let {
media.manga?.selectedChapter = i
model.saveSelected(media.id, media.selected!!, requireActivity())
model.saveSelected(media.id, media.selected!!)
ChapterLoaderDialog.newInstance(it, true)
.show(requireActivity().supportFragmentManager, "dialog")
}
@ -574,7 +572,7 @@ open class MangaReadFragment : Fragment(), ScanlatorSelectionListener {
selected.latest =
media.userProgress?.toFloat()?.takeIf { selected.latest < it } ?: selected.latest
model.saveSelected(media.id, selected, requireActivity())
model.saveSelected(media.id, selected)
headerAdapter.handleChapters()
chapterAdapter.notifyItemRangeRemoved(0, chapterAdapter.arr.size)
var arr: ArrayList<MangaChapter> = arrayListOf()
@ -588,7 +586,7 @@ open class MangaReadFragment : Fragment(), ScanlatorSelectionListener {
arr = (arr.reversed() as? ArrayList<MangaChapter>) ?: arr
}
chapterAdapter.arr = arr
chapterAdapter.updateType(style ?: uiSettings.mangaDefaultView)
chapterAdapter.updateType(style ?: PrefManager.getVal(PrefName.MangaDefaultView))
chapterAdapter.notifyItemRangeInserted(0, arr.size)
}

View file

@ -33,8 +33,7 @@ abstract class BaseImageAdapter(
val activity: MangaReaderActivity,
chapter: MangaChapter
) : RecyclerView.Adapter<RecyclerView.ViewHolder>() {
val settings = activity.settings.default
val uiSettings = activity.uiSettings
val settings = activity.defaultSettings
val images = chapter.images()
@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.RIGHT_TO_LEFT
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.davemorrissey.labs.subscaleview.ImageSource
import com.davemorrissey.labs.subscaleview.SubsamplingScaleImageView
@ -83,7 +85,7 @@ open class ImageAdapter(
imageView.minScale = scale
ObjectAnimator.ofFloat(parent, "alpha", 0f, 1f)
.setDuration((400 * uiSettings.animationSpeed).toLong())
.setDuration((400 * PrefManager.getVal<Float>(PrefName.AnimationSpeed)).toLong())
.start()
progress.visibility = View.GONE

View file

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

View file

@ -26,7 +26,7 @@ class ReaderSettingsDialogFragment : BottomSheetDialogFragment() {
override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
super.onViewCreated(view, savedInstanceState)
val activity = requireActivity() as MangaReaderActivity
val settings = activity.settings.default
val settings = activity.defaultSettings
binding.readerDirectionText.text =
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.novel.NovelDownloaderService
import ani.dantotsu.download.novel.NovelServiceDataSingleton
import ani.dantotsu.loadData
import ani.dantotsu.media.Media
import ani.dantotsu.media.MediaDetailsViewModel
import ani.dantotsu.media.novel.novelreader.NovelReaderActivity
import ani.dantotsu.navBarHeight
import ani.dantotsu.parsers.ShowResponse
import ani.dantotsu.saveData
import ani.dantotsu.settings.UserInterfaceSettings
import kotlinx.coroutines.CoroutineScope
import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.launch
@ -61,9 +58,6 @@ class NovelReadFragment : Fragment(),
private var continueEp: Boolean = false
var loaded = false
val uiSettings = loadData("ui_settings", toast = false)
?: UserInterfaceSettings().apply { saveData("ui_settings", this) }
override fun downloadTrigger(novelDownloadPackage: NovelDownloadPackage) {
Log.e("downloadTrigger", novelDownloadPackage.link)
val downloadTask = NovelDownloaderService.DownloadTask(
@ -253,7 +247,7 @@ class NovelReadFragment : Fragment(),
if (save) {
val selected = model.loadSelected(media)
selected.server = query
model.saveSelected(media.id, selected, requireActivity())
model.saveSelected(media.id, selected)
}
}
}
@ -263,7 +257,7 @@ class NovelReadFragment : Fragment(),
selected.sourceIndex = i
source = i
selected.server = null
model.saveSelected(media.id, selected, requireActivity())
model.saveSelected(media.id, selected)
media.selected = selected
}

View file

@ -35,7 +35,7 @@ class NovelResponseAdapter(
override fun onBindViewHolder(holder: ViewHolder, position: Int) {
val binding = holder.binding
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 }
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.annotation.SuppressLint
import android.content.Context
import android.content.Intent
import android.content.pm.ActivityInfo
import android.graphics.Color
@ -28,20 +29,20 @@ import androidx.webkit.WebViewCompat
import ani.dantotsu.GesturesListener
import ani.dantotsu.NoPaddingArrayAdapter
import ani.dantotsu.R
import ani.dantotsu.currContext
import ani.dantotsu.databinding.ActivityNovelReaderBinding
import ani.dantotsu.hideSystemBars
import ani.dantotsu.loadData
import ani.dantotsu.others.ImageViewDialog
import ani.dantotsu.saveData
import ani.dantotsu.setSafeOnClickListener
import ani.dantotsu.settings.CurrentNovelReaderSettings
import ani.dantotsu.settings.CurrentReaderSettings
import ani.dantotsu.settings.ReaderSettings
import ani.dantotsu.settings.UserInterfaceSettings
import ani.dantotsu.settings.saving.PrefName
import ani.dantotsu.settings.saving.PrefManager
import ani.dantotsu.snackString
import ani.dantotsu.themes.ThemeManager
import ani.dantotsu.tryWith
import com.google.android.material.slider.Slider
import com.google.firebase.crashlytics.FirebaseCrashlytics
import com.vipulog.ebookreader.Book
import com.vipulog.ebookreader.EbookReaderEventListener
import com.vipulog.ebookreader.ReaderError
@ -52,7 +53,10 @@ import com.vipulog.ebookreader.TocItem
import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.launch
import java.io.File
import java.io.FileInputStream
import java.io.FileOutputStream
import java.io.ObjectInputStream
import java.io.ObjectOutputStream
import java.util.*
import kotlin.math.min
import kotlin.properties.Delegates
@ -62,9 +66,6 @@ class NovelReaderActivity : AppCompatActivity(), EbookReaderEventListener {
private lateinit var binding: ActivityNovelReaderBinding
private val scope = lifecycleScope
lateinit var settings: ReaderSettings
private lateinit var uiSettings: UserInterfaceSettings
private var notchHeight: Int? = null
var loaded = false
@ -77,6 +78,8 @@ class NovelReaderActivity : AppCompatActivity(), EbookReaderEventListener {
val themes = ArrayList<ReaderTheme>()
var defaultSettings = CurrentNovelReaderSettings()
init {
val forestTheme = ReaderTheme(
@ -174,12 +177,8 @@ class NovelReaderActivity : AppCompatActivity(), EbookReaderEventListener {
ThemeManager(this).applyTheme()
binding = ActivityNovelReaderBinding.inflate(layoutInflater)
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()
setupBackPressedHandler()
@ -285,12 +284,11 @@ class NovelReaderActivity : AppCompatActivity(), EbookReaderEventListener {
binding.bookReader.getAppearance {
currentTheme = it
themes.add(0, it)
settings.defaultLN =
loadData("${sanitizedBookId}_current_settings") ?: settings.defaultLN
defaultSettings = loadReaderSettings("${sanitizedBookId}_current_settings") ?: defaultSettings
applySettings()
}
val cfi = loadData<String>("${sanitizedBookId}_progress")
val cfi = PrefManager.getCustomVal("${sanitizedBookId}_progress", null as String?)
cfi?.let { binding.bookReader.goto(it) }
binding.progress.visibility = View.GONE
@ -303,7 +301,7 @@ class NovelReaderActivity : AppCompatActivity(), EbookReaderEventListener {
binding.novelReaderSlider.value = info.fraction.toFloat()
val pos = info.tocItem?.let { item -> toc.indexOfFirst { it == item } }
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) {
KeyEvent.KEYCODE_VOLUME_UP, KeyEvent.KEYCODE_DPAD_UP, KeyEvent.KEYCODE_PAGE_UP -> {
if (event.keyCode == KeyEvent.KEYCODE_VOLUME_UP)
if (!settings.defaultLN.volumeButtons)
if (!defaultSettings.volumeButtons)
return false
if (event.action == KeyEvent.ACTION_DOWN) {
onVolumeUp?.invoke()
@ -348,7 +346,7 @@ class NovelReaderActivity : AppCompatActivity(), EbookReaderEventListener {
KeyEvent.KEYCODE_VOLUME_DOWN, KeyEvent.KEYCODE_DPAD_DOWN, KeyEvent.KEYCODE_PAGE_DOWN -> {
if (event.keyCode == KeyEvent.KEYCODE_VOLUME_DOWN)
if (!settings.defaultLN.volumeButtons)
if (!defaultSettings.volumeButtons)
return false
if (event.action == KeyEvent.ACTION_DOWN) {
onVolumeDown?.invoke()
@ -364,18 +362,18 @@ class NovelReaderActivity : AppCompatActivity(), EbookReaderEventListener {
fun applySettings() {
saveData("${sanitizedBookId}_current_settings", settings.defaultLN)
saveReaderSettings("${sanitizedBookId}_current_settings", defaultSettings)
hideBars()
if (settings.defaultLN.useOledTheme) {
if (defaultSettings.useOledTheme) {
themes.forEach { theme ->
theme.darkBg = Color.parseColor("#000000")
}
}
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 -> {
currentTheme?.flow = ReaderFlow.PAGINATED
}
@ -386,22 +384,22 @@ class NovelReaderActivity : AppCompatActivity(), EbookReaderEventListener {
}
requestedOrientation = ActivityInfo.SCREEN_ORIENTATION_USER
when (settings.defaultLN.dualPageMode) {
when (defaultSettings.dualPageMode) {
CurrentReaderSettings.DualPageModes.No -> currentTheme?.maxColumnCount = 1
CurrentReaderSettings.DualPageModes.Automatic -> currentTheme?.maxColumnCount = 2
CurrentReaderSettings.DualPageModes.Force -> requestedOrientation =
ActivityInfo.SCREEN_ORIENTATION_LANDSCAPE
}
currentTheme?.lineHeight = settings.defaultLN.lineHeight
currentTheme?.gap = settings.defaultLN.margin
currentTheme?.maxInlineSize = settings.defaultLN.maxInlineSize
currentTheme?.maxBlockSize = settings.defaultLN.maxBlockSize
currentTheme?.useDark = settings.defaultLN.useDarkTheme
currentTheme?.lineHeight = defaultSettings.lineHeight
currentTheme?.gap = defaultSettings.margin
currentTheme?.maxInlineSize = defaultSettings.maxInlineSize
currentTheme?.maxBlockSize = defaultSettings.maxBlockSize
currentTheme?.useDark = defaultSettings.useDarkTheme
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)
}
@ -431,7 +429,7 @@ class NovelReaderActivity : AppCompatActivity(), EbookReaderEventListener {
fun handleController(shouldShow: Boolean? = null) {
if (!loaded) return
if (!settings.showSystemBars) {
if (!PrefManager.getVal<Boolean>(PrefName.ShowSystemBars)) {
hideBars()
applyNotchMargin()
}
@ -464,7 +462,7 @@ class NovelReaderActivity : AppCompatActivity(), EbookReaderEventListener {
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
if (displayCutout != null) {
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() {
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?) {
super.onViewCreated(view, savedInstanceState)
val activity = requireActivity() as NovelReaderActivity
val settings = activity.settings.defaultLN
val settings = activity.defaultSettings
val themeLabels = activity.themes.map { it.name }
binding.themeSelect.adapter =
NoPaddingArrayAdapter(activity, R.layout.item_dropdown, themeLabels)

View file

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

View file

@ -4,12 +4,13 @@ import androidx.lifecycle.LiveData
import androidx.lifecycle.MutableLiveData
import androidx.lifecycle.ViewModel
import ani.dantotsu.connections.anilist.Anilist
import ani.dantotsu.loadData
import ani.dantotsu.media.Media
import ani.dantotsu.settings.saving.PrefName
import ani.dantotsu.settings.saving.PrefManager
import ani.dantotsu.tryWithSuspend
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>>>()
fun getLists(): LiveData<MutableMap<String, ArrayList<Media>>> = lists

View file

@ -1,6 +1,5 @@
package ani.dantotsu.offline
import android.content.Context
import android.os.Bundle
import android.view.LayoutInflater
import android.view.View
@ -12,7 +11,7 @@ import ani.dantotsu.databinding.FragmentOfflineBinding
import ani.dantotsu.isOnline
import ani.dantotsu.navBarHeight
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.statusBarHeight
@ -28,7 +27,7 @@ class OfflineFragment : Fragment() {
topMargin = statusBarHeight
bottomMargin = navBarHeight
}
offline = PrefWrapper.getVal(PrefName.OfflineMode, false)
offline = PrefManager.getVal(PrefName.OfflineMode)
binding.noInternet.text =
if (offline) "Offline Mode" else getString(R.string.no_internet)
binding.refreshButton.visibility = if (offline) View.GONE else View.VISIBLE
@ -42,6 +41,6 @@ class OfflineFragment : Fragment() {
override fun 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.fragment.app.FragmentActivity
import ani.dantotsu.*
import ani.dantotsu.settings.saving.PrefManager
import io.noties.markwon.Markwon
import io.noties.markwon.SoftBreakAddsNewLinePlugin
import kotlinx.coroutines.Dispatchers
@ -50,7 +51,7 @@ object AppUpdater {
}
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 {
CustomBottomDialog.newInstance().apply {
setTitleText(
@ -71,7 +72,7 @@ object AppUpdater {
false
) { 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)) {

View file

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

View file

@ -5,9 +5,8 @@ import ani.dantotsu.FileUrl
import ani.dantotsu.R
import ani.dantotsu.asyncMap
import ani.dantotsu.currContext
import ani.dantotsu.loadData
import ani.dantotsu.others.MalSyncBackup
import ani.dantotsu.saveData
import ani.dantotsu.settings.saving.PrefManager
import ani.dantotsu.tryWithSuspend
import eu.kanade.tachiyomi.animesource.model.SAnime
import eu.kanade.tachiyomi.animesource.model.SEpisode
@ -182,7 +181,7 @@ abstract class AnimeParser : BaseParser() {
override suspend fun loadSavedShowResponse(mediaId: Int): ShowResponse? {
checkIfVariablesAreEmpty()
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())
loaded = MalSyncBackup.get(mediaId, malSyncBackupName, selectDub)
?.also { saveShowResponse(mediaId, it, true) }
@ -200,7 +199,7 @@ abstract class AnimeParser : BaseParser() {
} : ${response.name}"
)
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.lazyList
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 kotlinx.coroutines.flow.StateFlow
import kotlinx.coroutines.flow.first
@ -14,7 +14,7 @@ object AnimeSources : WatchSources() {
var pinnedAnimeSources: Set<String> = emptySet()
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
val initialExtensions = fromExtensions.first()

View file

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

View file

@ -1,10 +1,9 @@
package ani.dantotsu.parsers
import android.content.Context
import ani.dantotsu.Lazier
import ani.dantotsu.lazyList
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 kotlinx.coroutines.flow.StateFlow
import kotlinx.coroutines.flow.first
@ -14,7 +13,7 @@ object MangaSources : MangaReadSources() {
var pinnedMangaSources: Set<String> = emptySet()
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
val initialExtensions = fromExtensions.first()

View file

@ -2,10 +2,9 @@ package ani.dantotsu.parsers.novel
import android.content.Context
import ani.dantotsu.currContext
import ani.dantotsu.logger
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.anime.model.AnimeExtension
import eu.kanade.tachiyomi.extension.anime.model.AnimeLoadResult
@ -28,7 +27,7 @@ class NovelExtensionGithubApi {
private val novelExtensionManager: NovelExtensionManager 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
@ -86,7 +85,7 @@ class NovelExtensionGithubApi {
novelExtensionManager.availableExtensionsFlow.value
} else {
findExtensions().also {
PrefWrapper.setVal(PrefName.NovelLastExtCheck, Date().time)
PrefManager.setVal(PrefName.NovelLastExtCheck, Date().time)
}
}

View file

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

View file

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

View file

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

View file

@ -18,7 +18,7 @@ import ani.dantotsu.*
import ani.dantotsu.databinding.ActivityExtensionsBinding
import ani.dantotsu.others.LanguageMapper
import ani.dantotsu.settings.saving.PrefName
import ani.dantotsu.settings.saving.PrefWrapper
import ani.dantotsu.settings.saving.PrefManager
import ani.dantotsu.themes.ThemeManager
import com.google.android.material.tabs.TabLayout
import com.google.android.material.tabs.TabLayoutMediator
@ -118,11 +118,11 @@ class ExtensionsActivity : AppCompatActivity() {
binding.languageselect.setOnClickListener {
val languageOptions = LanguageMapper.Companion.Language.entries.map{ it.name }.toTypedArray()
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}
builder.setTitle("Language")
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()
}
val dialog = builder.show()

View file

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

View file

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

View file

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

View file

@ -20,12 +20,11 @@ import androidx.recyclerview.widget.RecyclerView
import ani.dantotsu.R
import ani.dantotsu.currContext
import ani.dantotsu.databinding.FragmentNovelExtensionsBinding
import ani.dantotsu.loadData
import ani.dantotsu.others.LanguageMapper
import ani.dantotsu.parsers.novel.NovelExtension
import ani.dantotsu.parsers.novel.NovelExtensionManager
import ani.dantotsu.settings.saving.PrefName
import ani.dantotsu.settings.saving.PrefWrapper
import ani.dantotsu.settings.saving.PrefManager
import ani.dantotsu.snackString
import com.google.firebase.crashlytics.FirebaseCrashlytics
import eu.kanade.tachiyomi.data.notification.Notifications
@ -39,7 +38,7 @@ class InstalledNovelExtensionsFragment : Fragment(), SearchQueryHandler {
private var _binding: FragmentNovelExtensionsBinding? = null
private val binding get() = _binding!!
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 extensionsAdapter = NovelExtensionsAdapter(
{ 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.databinding.ActivityPlayerSettingsBinding
import ani.dantotsu.initActivity
import ani.dantotsu.loadData
import ani.dantotsu.media.Media
import ani.dantotsu.navBarHeight
import ani.dantotsu.others.getSerialized
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.statusBarHeight
import ani.dantotsu.themes.ThemeManager
@ -61,12 +61,6 @@ class PlayerSettingsActivity : AppCompatActivity() {
bottomMargin = navBarHeight
}
val settings = loadData<PlayerSettings>(player, toast = false) ?: PlayerSettings().apply {
saveData(
player,
this
)
}
binding.playerSettingsBack.setOnClickListener {
onBackPressedDispatcher.onBackPressed()
@ -91,128 +85,113 @@ class PlayerSettingsActivity : AppCompatActivity() {
2f
)
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()
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)
.setTitle(getString(R.string.default_speed))
binding.playerSettingsSpeed.setOnClickListener {
val dialog =
speedDialog.setSingleChoiceItems(speedsName, settings.defaultSpeed) { dialog, i ->
settings.defaultSpeed = i
speedDialog.setSingleChoiceItems(speedsName, PrefManager.getVal(PrefName.DefaultSpeed)) { dialog, i ->
PrefManager.setVal(PrefName.DefaultSpeed, i)
binding.playerSettingsSpeed.text =
getString(R.string.default_playback_speed, speedsName[i])
saveData(player, settings)
dialog.dismiss()
}.show()
dialog.window?.setDimAmount(0.8f)
}
binding.playerSettingsCursedSpeeds.isChecked = settings.cursedSpeeds
binding.playerSettingsCursedSpeeds.isChecked = PrefManager.getVal(PrefName.CursedSpeeds)
binding.playerSettingsCursedSpeeds.setOnCheckedChangeListener { _, isChecked ->
settings.cursedSpeeds = isChecked
curSpeedArr = if (settings.cursedSpeeds) cursedSpeeds else speeds
settings.defaultSpeed = if (settings.cursedSpeeds) 0 else 5
PrefManager.setVal(PrefName.CursedSpeeds, isChecked)
curSpeedArr = if (isChecked) cursedSpeeds else speeds
val newDefaultSpeed = if (isChecked) 0 else 5
PrefManager.setVal(PrefName.DefaultSpeed, newDefaultSpeed)
speedsName = curSpeedArr.map { "${it}x" }.toTypedArray()
binding.playerSettingsSpeed.text =
getString(R.string.default_playback_speed, speedsName[settings.defaultSpeed])
saveData(player, settings)
getString(R.string.default_playback_speed, speedsName[PrefManager.getVal(PrefName.DefaultSpeed)])
}
//Time Stamp
binding.playerSettingsTimeStamps.isChecked = settings.timeStampsEnabled
// Time Stamp
binding.playerSettingsTimeStamps.isChecked = PrefManager.getVal(PrefName.TimeStampsEnabled)
binding.playerSettingsTimeStamps.setOnCheckedChangeListener { _, isChecked ->
settings.timeStampsEnabled = isChecked
saveData(player, settings)
PrefManager.setVal(PrefName.TimeStampsEnabled, isChecked)
}
binding.playerSettingsTimeStampsProxy.isChecked = settings.useProxyForTimeStamps
binding.playerSettingsTimeStampsProxy.isChecked = PrefManager.getVal(PrefName.UseProxyForTimeStamps)
binding.playerSettingsTimeStampsProxy.setOnCheckedChangeListener { _, isChecked ->
settings.useProxyForTimeStamps = isChecked
saveData(player, settings)
PrefManager.setVal(PrefName.UseProxyForTimeStamps, isChecked)
}
binding.playerSettingsShowTimeStamp.isChecked = settings.showTimeStampButton
binding.playerSettingsShowTimeStamp.isChecked = PrefManager.getVal(PrefName.ShowTimeStampButton)
binding.playerSettingsShowTimeStamp.setOnCheckedChangeListener { _, isChecked ->
settings.showTimeStampButton = isChecked
saveData(player, settings)
PrefManager.setVal(PrefName.ShowTimeStampButton, isChecked)
}
//Auto
binding.playerSettingsAutoSkipOpEd.isChecked = settings.autoSkipOPED
// Auto
binding.playerSettingsAutoSkipOpEd.isChecked = PrefManager.getVal(PrefName.AutoSkipOPED)
binding.playerSettingsAutoSkipOpEd.setOnCheckedChangeListener { _, isChecked ->
settings.autoSkipOPED = isChecked
saveData(player, settings)
PrefManager.setVal(PrefName.AutoSkipOPED, isChecked)
}
binding.playerSettingsAutoPlay.isChecked = settings.autoPlay
binding.playerSettingsAutoPlay.isChecked = PrefManager.getVal(PrefName.AutoPlay)
binding.playerSettingsAutoPlay.setOnCheckedChangeListener { _, isChecked ->
settings.autoPlay = isChecked
saveData(player, settings)
PrefManager.setVal(PrefName.AutoPlay, isChecked)
}
binding.playerSettingsAutoSkip.isChecked = settings.autoSkipFiller
binding.playerSettingsAutoSkip.isChecked = PrefManager.getVal(PrefName.AutoSkipFiller)
binding.playerSettingsAutoSkip.setOnCheckedChangeListener { _, isChecked ->
settings.autoSkipFiller = isChecked
saveData(player, settings)
PrefManager.setVal(PrefName.AutoSkipFiller, isChecked)
}
//Update Progress
binding.playerSettingsAskUpdateProgress.isChecked = settings.askIndividual
binding.playerSettingsAskUpdateProgress.isChecked = PrefManager.getVal(PrefName.AskIndividualPlayer)
binding.playerSettingsAskUpdateProgress.setOnCheckedChangeListener { _, isChecked ->
settings.askIndividual = isChecked
saveData(player, settings)
PrefManager.setVal(PrefName.AskIndividualPlayer, isChecked)
}
binding.playerSettingsAskUpdateHentai.isChecked = settings.updateForH
binding.playerSettingsAskUpdateHentai.isChecked = PrefManager.getVal(PrefName.UpdateForHPlayer)
binding.playerSettingsAskUpdateHentai.setOnCheckedChangeListener { _, isChecked ->
settings.updateForH = isChecked
PrefManager.setVal(PrefName.UpdateForHPlayer, isChecked)
if (isChecked) snackString(getString(R.string.very_bold))
saveData(player, settings)
}
binding.playerSettingsCompletePercentage.value =
(settings.watchPercentage * 100).roundToInt().toFloat()
binding.playerSettingsCompletePercentage.value = (PrefManager.getVal<Float>(PrefName.WatchPercentage) * 100).roundToInt().toFloat()
binding.playerSettingsCompletePercentage.addOnChangeListener { _, value, _ ->
settings.watchPercentage = value / 100
saveData(player, settings)
PrefManager.setVal(PrefName.WatchPercentage, value / 100)
}
//Behaviour
binding.playerSettingsAlwaysContinue.isChecked = settings.alwaysContinue
binding.playerSettingsAlwaysContinue.isChecked = PrefManager.getVal(PrefName.AlwaysContinue)
binding.playerSettingsAlwaysContinue.setOnCheckedChangeListener { _, isChecked ->
settings.alwaysContinue = isChecked
saveData(player, settings)
PrefManager.setVal(PrefName.AlwaysContinue, isChecked)
}
binding.playerSettingsPauseVideo.isChecked = settings.focusPause
binding.playerSettingsPauseVideo.isChecked = PrefManager.getVal(PrefName.FocusPause)
binding.playerSettingsPauseVideo.setOnCheckedChangeListener { _, isChecked ->
settings.focusPause = isChecked
saveData(player, settings)
PrefManager.setVal(PrefName.FocusPause, isChecked)
}
binding.playerSettingsVerticalGestures.isChecked = settings.gestures
binding.playerSettingsVerticalGestures.isChecked = PrefManager.getVal(PrefName.Gestures)
binding.playerSettingsVerticalGestures.setOnCheckedChangeListener { _, isChecked ->
settings.gestures = isChecked
saveData(player, settings)
PrefManager.setVal(PrefName.Gestures, isChecked)
}
binding.playerSettingsDoubleTap.isChecked = settings.doubleTap
binding.playerSettingsDoubleTap.isChecked = PrefManager.getVal(PrefName.DoubleTap)
binding.playerSettingsDoubleTap.setOnCheckedChangeListener { _, isChecked ->
settings.doubleTap = isChecked
saveData(player, settings)
PrefManager.setVal(PrefName.DoubleTap, isChecked)
}
binding.playerSettingsFastForward.isChecked = settings.fastforward
binding.playerSettingsFastForward.isChecked = PrefManager.getVal(PrefName.FastForward)
binding.playerSettingsFastForward.setOnCheckedChangeListener { _, isChecked ->
settings.fastforward = isChecked
saveData(player, settings)
PrefManager.setVal(PrefName.FastForward, isChecked)
}
binding.playerSettingsSeekTime.value = settings.seekTime.toFloat()
binding.playerSettingsSeekTime.value = PrefManager.getVal<Int>(PrefName.SeekTime).toFloat()
binding.playerSettingsSeekTime.addOnChangeListener { _, value, _ ->
settings.seekTime = value.toInt()
saveData(player, settings)
PrefManager.setVal(PrefName.SeekTime, value.toInt())
}
binding.exoSkipTime.setText(settings.skipTime.toString())
binding.exoSkipTime.setText(PrefManager.getVal<Int>(PrefName.SkipTime).toString())
binding.exoSkipTime.setOnEditorActionListener { _, actionId, _ ->
if (actionId == EditorInfo.IME_ACTION_DONE) {
binding.exoSkipTime.clearFocus()
@ -222,8 +201,7 @@ class PlayerSettingsActivity : AppCompatActivity() {
binding.exoSkipTime.addTextChangedListener {
val time = binding.exoSkipTime.text.toString().toIntOrNull()
if (time != null) {
settings.skipTime = time
saveData(player, settings)
PrefManager.setVal(PrefName.SkipTime, time)
}
}
@ -231,32 +209,29 @@ class PlayerSettingsActivity : AppCompatActivity() {
binding.playerSettingsPiP.apply {
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.N) {
visibility = View.VISIBLE
isChecked = settings.pip
isChecked = PrefManager.getVal(PrefName.Pip)
setOnCheckedChangeListener { _, isChecked ->
settings.pip = isChecked
saveData(player, settings)
PrefManager.setVal(PrefName.Pip, isChecked)
}
} else visibility = View.GONE
}
binding.playerSettingsCast.isChecked = settings.cast
binding.playerSettingsCast.isChecked = PrefManager.getVal(PrefName.Cast)
binding.playerSettingsCast.setOnCheckedChangeListener { _, isChecked ->
settings.cast = isChecked
saveData(player, settings)
PrefManager.setVal(PrefName.Cast, isChecked)
}
val resizeModes = arrayOf("Original", "Zoom", "Stretch")
val resizeDialog = AlertDialog.Builder(this, R.style.MyPopup)
.setTitle(getString(R.string.default_resize_mode))
binding.playerResizeMode.setOnClickListener {
val dialog =
resizeDialog.setSingleChoiceItems(resizeModes, settings.resize) { dialog, count ->
settings.resize = count
saveData(player, settings)
val dialog = resizeDialog.setSingleChoiceItems(resizeModes, PrefManager.getVal<Int>(PrefName.Resize)) { dialog, count ->
PrefManager.setVal(PrefName.Resize, count)
dialog.dismiss()
}.show()
dialog.window?.setDimAmount(0.8f)
}
fun restartApp() {
Snackbar.make(
binding.root,
@ -311,10 +286,9 @@ class PlayerSettingsActivity : AppCompatActivity() {
false -> 0.5f
}
}
binding.subSwitch.isChecked = settings.subtitles
binding.subSwitch.isChecked = PrefManager.getVal(PrefName.Subtitles)
binding.subSwitch.setOnCheckedChangeListener { _, isChecked ->
settings.subtitles = isChecked
saveData(player, settings)
PrefManager.setVal(PrefName.Subtitles, isChecked)
toggleSubOptions(isChecked)
restartApp()
}
@ -337,10 +311,9 @@ class PlayerSettingsActivity : AppCompatActivity() {
binding.videoSubColorPrimary.setOnClickListener {
val dialog = primaryColorDialog.setSingleChoiceItems(
colorsPrimary,
settings.primaryColor
PrefManager.getVal(PrefName.PrimaryColor)
) { dialog, count ->
settings.primaryColor = count
saveData(player, settings)
PrefManager.setVal(PrefName.PrimaryColor, count)
dialog.dismiss()
}.show()
dialog.window?.setDimAmount(0.8f)
@ -364,10 +337,9 @@ class PlayerSettingsActivity : AppCompatActivity() {
binding.videoSubColorSecondary.setOnClickListener {
val dialog = secondaryColorDialog.setSingleChoiceItems(
colorsSecondary,
settings.secondaryColor
PrefManager.getVal(PrefName.SecondaryColor)
) { dialog, count ->
settings.secondaryColor = count
saveData(player, settings)
PrefManager.setVal(PrefName.SecondaryColor, count)
dialog.dismiss()
}.show()
dialog.window?.setDimAmount(0.8f)
@ -378,10 +350,9 @@ class PlayerSettingsActivity : AppCompatActivity() {
binding.videoSubOutline.setOnClickListener {
val dialog = outlineDialog.setSingleChoiceItems(
typesOutline,
settings.outline
PrefManager.getVal(PrefName.Outline)
) { dialog, count ->
settings.outline = count
saveData(player, settings)
PrefManager.setVal(PrefName.Outline, count)
dialog.dismiss()
}.show()
dialog.window?.setDimAmount(0.8f)
@ -405,10 +376,9 @@ class PlayerSettingsActivity : AppCompatActivity() {
binding.videoSubColorBackground.setOnClickListener {
val dialog = subBackgroundDialog.setSingleChoiceItems(
colorsSubBackground,
settings.subBackground
PrefManager.getVal(PrefName.SubBackground)
) { dialog, count ->
settings.subBackground = count
saveData(player, settings)
PrefManager.setVal(PrefName.SubBackground, count)
dialog.dismiss()
}.show()
dialog.window?.setDimAmount(0.8f)
@ -433,10 +403,9 @@ class PlayerSettingsActivity : AppCompatActivity() {
binding.videoSubColorWindow.setOnClickListener {
val dialog = subWindowDialog.setSingleChoiceItems(
colorsSubWindow,
settings.subWindow
PrefManager.getVal(PrefName.SubWindow)
) { dialog, count ->
settings.subWindow = count
saveData(player, settings)
PrefManager.setVal(PrefName.SubWindow, count)
dialog.dismiss()
}.show()
dialog.window?.setDimAmount(0.8f)
@ -452,14 +421,13 @@ class PlayerSettingsActivity : AppCompatActivity() {
val fontDialog = AlertDialog.Builder(this, R.style.MyPopup)
.setTitle(getString(R.string.subtitle_font))
binding.videoSubFont.setOnClickListener {
val dialog = fontDialog.setSingleChoiceItems(fonts, settings.font) { dialog, count ->
settings.font = count
saveData(player, settings)
val dialog = fontDialog.setSingleChoiceItems(fonts, PrefManager.getVal(PrefName.Font)) { dialog, count ->
PrefManager.setVal(PrefName.Font, count)
dialog.dismiss()
}.show()
dialog.window?.setDimAmount(0.8f)
}
binding.subtitleFontSize.setText(settings.fontSize.toString())
binding.subtitleFontSize.setText(PrefManager.getVal<Int>(PrefName.FontSize).toString())
binding.subtitleFontSize.setOnEditorActionListener { _, actionId, _ ->
if (actionId == EditorInfo.IME_ACTION_DONE) {
binding.subtitleFontSize.clearFocus()
@ -469,10 +437,9 @@ class PlayerSettingsActivity : AppCompatActivity() {
binding.subtitleFontSize.addTextChangedListener {
val size = binding.subtitleFontSize.text.toString().toIntOrNull()
if (size != null) {
settings.fontSize = size
saveData(player, settings)
PrefManager.setVal(PrefName.FontSize, size)
}
}
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.databinding.ActivityReaderSettingsBinding
import ani.dantotsu.initActivity
import ani.dantotsu.loadData
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.statusBarHeight
import ani.dantotsu.themes.ThemeManager
class ReaderSettingsActivity : AppCompatActivity() {
lateinit var binding: ActivityReaderSettingsBinding
private val reader = "reader_settings"
private var defaultSettings = CurrentReaderSettings()
private var defaultSettingsLN = CurrentNovelReaderSettings()
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
@ -30,34 +31,24 @@ class ReaderSettingsActivity : AppCompatActivity() {
bottomMargin = navBarHeight
}
val settings = loadData<ReaderSettings>(reader, toast = false) ?: ReaderSettings().apply {
saveData(
reader,
this
)
}
binding.readerSettingsBack.setOnClickListener {
onBackPressedDispatcher.onBackPressed()
}
//Manga Settings
binding.readerSettingsSourceName.isChecked = settings.showSource
binding.readerSettingsSourceName.isChecked = PrefManager.getVal(PrefName.ShowSource)
binding.readerSettingsSourceName.setOnCheckedChangeListener { _, isChecked ->
settings.showSource = isChecked
saveData(reader, settings)
PrefManager.setVal(PrefName.ShowSource, isChecked)
}
binding.readerSettingsSystemBars.isChecked = settings.showSystemBars
binding.readerSettingsSystemBars.isChecked = PrefManager.getVal(PrefName.ShowSystemBars)
binding.readerSettingsSystemBars.setOnCheckedChangeListener { _, isChecked ->
settings.showSystemBars = isChecked
saveData(reader, settings)
PrefManager.setVal(PrefName.ShowSystemBars, isChecked)
}
//Default Manga
binding.readerSettingsAutoWebToon.isChecked = settings.autoDetectWebtoon
binding.readerSettingsAutoWebToon.isChecked = PrefManager.getVal(PrefName.AutoDetectWebtoon)
binding.readerSettingsAutoWebToon.setOnCheckedChangeListener { _, isChecked ->
settings.autoDetectWebtoon = isChecked
saveData(reader, settings)
PrefManager.setVal(PrefName.AutoDetectWebtoon, isChecked)
}
@ -68,8 +59,8 @@ class ReaderSettingsActivity : AppCompatActivity() {
)
binding.readerSettingsLayoutText.text =
resources.getStringArray(R.array.manga_layouts)[settings.default.layout.ordinal]
var selectedLayout = layoutList[settings.default.layout.ordinal]
resources.getStringArray(R.array.manga_layouts)[defaultSettings.layout.ordinal]
var selectedLayout = layoutList[defaultSettings.layout.ordinal]
selectedLayout.alpha = 1f
layoutList.forEachIndexed { index, imageButton ->
@ -77,25 +68,25 @@ class ReaderSettingsActivity : AppCompatActivity() {
selectedLayout.alpha = 0.33f
selectedLayout = imageButton
selectedLayout.alpha = 1f
settings.default.layout =
defaultSettings.layout =
CurrentReaderSettings.Layouts[index] ?: CurrentReaderSettings.Layouts.CONTINUOUS
binding.readerSettingsLayoutText.text =
resources.getStringArray(R.array.manga_layouts)[settings.default.layout.ordinal]
saveData(reader, settings)
resources.getStringArray(R.array.manga_layouts)[defaultSettings.layout.ordinal]
PrefManager.setVal(PrefName.LayoutReader, defaultSettings.layout.ordinal)
}
}
binding.readerSettingsDirectionText.text =
resources.getStringArray(R.array.manga_directions)[settings.default.direction.ordinal]
binding.readerSettingsDirection.rotation = 90f * (settings.default.direction.ordinal)
resources.getStringArray(R.array.manga_directions)[defaultSettings.direction.ordinal]
binding.readerSettingsDirection.rotation = 90f * (defaultSettings.direction.ordinal)
binding.readerSettingsDirection.setOnClickListener {
settings.default.direction =
CurrentReaderSettings.Directions[settings.default.direction.ordinal + 1]
defaultSettings.direction =
CurrentReaderSettings.Directions[defaultSettings.direction.ordinal + 1]
?: CurrentReaderSettings.Directions.TOP_TO_BOTTOM
binding.readerSettingsDirectionText.text =
resources.getStringArray(R.array.manga_directions)[settings.default.direction.ordinal]
binding.readerSettingsDirection.rotation = 90f * (settings.default.direction.ordinal)
saveData(reader, settings)
resources.getStringArray(R.array.manga_directions)[defaultSettings.direction.ordinal]
binding.readerSettingsDirection.rotation = 90f * (defaultSettings.direction.ordinal)
PrefManager.setVal(PrefName.Direction, defaultSettings.direction.ordinal)
}
val dualList = listOf(
@ -104,8 +95,8 @@ class ReaderSettingsActivity : AppCompatActivity() {
binding.readerSettingsDualForce
)
binding.readerSettingsDualPageText.text = settings.default.dualPageMode.toString()
var selectedDual = dualList[settings.default.dualPageMode.ordinal]
binding.readerSettingsDualPageText.text = defaultSettings.dualPageMode.toString()
var selectedDual = dualList[defaultSettings.dualPageMode.ordinal]
selectedDual.alpha = 1f
dualList.forEachIndexed { index, imageButton ->
@ -113,75 +104,75 @@ class ReaderSettingsActivity : AppCompatActivity() {
selectedDual.alpha = 0.33f
selectedDual = imageButton
selectedDual.alpha = 1f
settings.default.dualPageMode = CurrentReaderSettings.DualPageModes[index]
defaultSettings.dualPageMode = CurrentReaderSettings.DualPageModes[index]
?: CurrentReaderSettings.DualPageModes.Automatic
binding.readerSettingsDualPageText.text = settings.default.dualPageMode.toString()
saveData(reader, settings)
binding.readerSettingsDualPageText.text = defaultSettings.dualPageMode.toString()
PrefManager.setVal(PrefName.DualPageModeReader, defaultSettings.dualPageMode.ordinal)
}
}
binding.readerSettingsTrueColors.isChecked = settings.default.trueColors
binding.readerSettingsTrueColors.isChecked = defaultSettings.trueColors
binding.readerSettingsTrueColors.setOnCheckedChangeListener { _, isChecked ->
settings.default.trueColors = isChecked
saveData(reader, settings)
defaultSettings.trueColors = isChecked
PrefManager.setVal(PrefName.TrueColors, isChecked)
}
binding.readerSettingsCropBorders.isChecked = settings.default.cropBorders
binding.readerSettingsCropBorders.isChecked = defaultSettings.cropBorders
binding.readerSettingsCropBorders.setOnCheckedChangeListener { _, isChecked ->
settings.default.cropBorders = isChecked
saveData(reader, settings)
defaultSettings.cropBorders = isChecked
PrefManager.setVal(PrefName.CropBorders, isChecked)
}
binding.readerSettingsImageRotation.isChecked = settings.default.rotation
binding.readerSettingsImageRotation.isChecked = defaultSettings.rotation
binding.readerSettingsImageRotation.setOnCheckedChangeListener { _, isChecked ->
settings.default.rotation = isChecked
saveData(reader, settings)
defaultSettings.rotation = isChecked
PrefManager.setVal(PrefName.Rotation, isChecked)
}
binding.readerSettingsHorizontalScrollBar.isChecked = settings.default.horizontalScrollBar
binding.readerSettingsHorizontalScrollBar.isChecked = defaultSettings.horizontalScrollBar
binding.readerSettingsHorizontalScrollBar.setOnCheckedChangeListener { _, isChecked ->
settings.default.horizontalScrollBar = isChecked
saveData(reader, settings)
defaultSettings.horizontalScrollBar = isChecked
PrefManager.setVal(PrefName.HorizontalScrollBar, isChecked)
}
binding.readerSettingsPadding.isChecked = settings.default.padding
binding.readerSettingsPadding.isChecked = defaultSettings.padding
binding.readerSettingsPadding.setOnCheckedChangeListener { _, isChecked ->
settings.default.padding = isChecked
saveData(reader, settings)
defaultSettings.padding = isChecked
PrefManager.setVal(PrefName.Padding, isChecked)
}
binding.readerSettingsKeepScreenOn.isChecked = settings.default.keepScreenOn
binding.readerSettingsKeepScreenOn.isChecked = defaultSettings.keepScreenOn
binding.readerSettingsKeepScreenOn.setOnCheckedChangeListener { _, isChecked ->
settings.default.keepScreenOn = isChecked
saveData(reader, settings)
defaultSettings.keepScreenOn = isChecked
PrefManager.setVal(PrefName.KeepScreenOn, isChecked)
}
binding.readerSettingsHidePageNumbers.isChecked = settings.default.hidePageNumbers
binding.readerSettingsHidePageNumbers.isChecked = defaultSettings.hidePageNumbers
binding.readerSettingsHidePageNumbers.setOnCheckedChangeListener { _, isChecked ->
settings.default.hidePageNumbers = isChecked
saveData(reader, settings)
defaultSettings.hidePageNumbers = isChecked
PrefManager.setVal(PrefName.HidePageNumbers, isChecked)
}
binding.readerSettingsOverscroll.isChecked = settings.default.overScrollMode
binding.readerSettingsOverscroll.isChecked = defaultSettings.overScrollMode
binding.readerSettingsOverscroll.setOnCheckedChangeListener { _, isChecked ->
settings.default.overScrollMode = isChecked
saveData(reader, settings)
defaultSettings.overScrollMode = isChecked
PrefManager.setVal(PrefName.OverScrollMode, isChecked)
}
binding.readerSettingsVolumeButton.isChecked = settings.default.volumeButtons
binding.readerSettingsVolumeButton.isChecked = defaultSettings.volumeButtons
binding.readerSettingsVolumeButton.setOnCheckedChangeListener { _, isChecked ->
settings.default.volumeButtons = isChecked
saveData(reader, settings)
defaultSettings.volumeButtons = isChecked
PrefManager.setVal(PrefName.VolumeButtonsReader, isChecked)
}
binding.readerSettingsWrapImages.isChecked = settings.default.wrapImages
binding.readerSettingsWrapImages.isChecked = defaultSettings.wrapImages
binding.readerSettingsWrapImages.setOnCheckedChangeListener { _, isChecked ->
settings.default.wrapImages = isChecked
saveData(reader, settings)
defaultSettings.wrapImages = isChecked
PrefManager.setVal(PrefName.WrapImages, isChecked)
}
binding.readerSettingsLongClickImage.isChecked = settings.default.longClickImage
binding.readerSettingsLongClickImage.isChecked = defaultSettings.longClickImage
binding.readerSettingsLongClickImage.setOnCheckedChangeListener { _, isChecked ->
settings.default.longClickImage = isChecked
saveData(reader, settings)
defaultSettings.longClickImage = isChecked
PrefManager.setVal(PrefName.LongClickImage, isChecked)
}
//LN settings
@ -190,8 +181,8 @@ class ReaderSettingsActivity : AppCompatActivity() {
binding.LNcontinuous
)
binding.LNlayoutText.text = settings.defaultLN.layout.string
var selectedLN = layoutListLN[settings.defaultLN.layout.ordinal]
binding.LNlayoutText.text = defaultSettingsLN.layout.string
var selectedLN = layoutListLN[defaultSettingsLN.layout.ordinal]
selectedLN.alpha = 1f
layoutListLN.forEachIndexed { index, imageButton ->
@ -199,10 +190,10 @@ class ReaderSettingsActivity : AppCompatActivity() {
selectedLN.alpha = 0.33f
selectedLN = imageButton
selectedLN.alpha = 1f
settings.defaultLN.layout = CurrentNovelReaderSettings.Layouts[index]
defaultSettingsLN.layout = CurrentNovelReaderSettings.Layouts[index]
?: CurrentNovelReaderSettings.Layouts.PAGED
binding.LNlayoutText.text = settings.defaultLN.layout.string
saveData(reader, settings)
binding.LNlayoutText.text = defaultSettingsLN.layout.string
PrefManager.setVal(PrefName.LayoutNovel, defaultSettingsLN.layout.ordinal)
}
}
@ -212,8 +203,8 @@ class ReaderSettingsActivity : AppCompatActivity() {
binding.LNdualForce
)
binding.LNdualPageText.text = settings.defaultLN.dualPageMode.toString()
var selectedDualLN = dualListLN[settings.defaultLN.dualPageMode.ordinal]
binding.LNdualPageText.text = defaultSettingsLN.dualPageMode.toString()
var selectedDualLN = dualListLN[defaultSettingsLN.dualPageMode.ordinal]
selectedDualLN.alpha = 1f
dualListLN.forEachIndexed { index, imageButton ->
@ -221,143 +212,141 @@ class ReaderSettingsActivity : AppCompatActivity() {
selectedDualLN.alpha = 0.33f
selectedDualLN = imageButton
selectedDualLN.alpha = 1f
settings.defaultLN.dualPageMode = CurrentReaderSettings.DualPageModes[index]
defaultSettingsLN.dualPageMode = CurrentReaderSettings.DualPageModes[index]
?: CurrentReaderSettings.DualPageModes.Automatic
binding.LNdualPageText.text = settings.defaultLN.dualPageMode.toString()
saveData(reader, settings)
binding.LNdualPageText.text = defaultSettingsLN.dualPageMode.toString()
PrefManager.setVal(PrefName.DualPageModeNovel, defaultSettingsLN.dualPageMode.ordinal)
}
}
binding.LNlineHeight.setText(settings.defaultLN.lineHeight.toString())
binding.LNlineHeight.setText(defaultSettingsLN.lineHeight.toString())
binding.LNlineHeight.setOnFocusChangeListener { _, hasFocus ->
if (!hasFocus) {
val value = binding.LNlineHeight.text.toString().toFloatOrNull() ?: 1.4f
settings.defaultLN.lineHeight = value
defaultSettingsLN.lineHeight = value
binding.LNlineHeight.setText(value.toString())
saveData(reader, settings)
PrefManager.setVal(PrefName.LineHeight, value)
}
}
binding.LNincrementLineHeight.setOnClickListener {
val value = binding.LNlineHeight.text.toString().toFloatOrNull() ?: 1.4f
settings.defaultLN.lineHeight = value + 0.1f
binding.LNlineHeight.setText(settings.defaultLN.lineHeight.toString())
saveData(reader, settings)
defaultSettingsLN.lineHeight = value + 0.1f
binding.LNlineHeight.setText(defaultSettingsLN.lineHeight.toString())
PrefManager.setVal(PrefName.LineHeight, defaultSettingsLN.lineHeight)
}
binding.LNdecrementLineHeight.setOnClickListener {
val value = binding.LNlineHeight.text.toString().toFloatOrNull() ?: 1.4f
settings.defaultLN.lineHeight = value - 0.1f
binding.LNlineHeight.setText(settings.defaultLN.lineHeight.toString())
saveData(reader, settings)
defaultSettingsLN.lineHeight = value - 0.1f
binding.LNlineHeight.setText(defaultSettingsLN.lineHeight.toString())
PrefManager.setVal(PrefName.LineHeight, defaultSettingsLN.lineHeight)
}
binding.LNmargin.setText(settings.defaultLN.margin.toString())
binding.LNmargin.setText(defaultSettingsLN.margin.toString())
binding.LNmargin.setOnFocusChangeListener { _, hasFocus ->
if (!hasFocus) {
val value = binding.LNmargin.text.toString().toFloatOrNull() ?: 0.06f
settings.defaultLN.margin = value
defaultSettingsLN.margin = value
binding.LNmargin.setText(value.toString())
saveData(reader, settings)
PrefManager.setVal(PrefName.Margin, value)
}
}
binding.LNincrementMargin.setOnClickListener {
val value = binding.LNmargin.text.toString().toFloatOrNull() ?: 0.06f
settings.defaultLN.margin = value + 0.01f
binding.LNmargin.setText(settings.defaultLN.margin.toString())
saveData(reader, settings)
defaultSettingsLN.margin = value + 0.01f
binding.LNmargin.setText(defaultSettingsLN.margin.toString())
PrefManager.setVal(PrefName.Margin, defaultSettingsLN.margin)
}
binding.LNdecrementMargin.setOnClickListener {
val value = binding.LNmargin.text.toString().toFloatOrNull() ?: 0.06f
settings.defaultLN.margin = value - 0.01f
binding.LNmargin.setText(settings.defaultLN.margin.toString())
saveData(reader, settings)
defaultSettingsLN.margin = value - 0.01f
binding.LNmargin.setText(defaultSettingsLN.margin.toString())
PrefManager.setVal(PrefName.Margin, defaultSettingsLN.margin)
}
binding.LNmaxInlineSize.setText(settings.defaultLN.maxInlineSize.toString())
binding.LNmaxInlineSize.setText(defaultSettingsLN.maxInlineSize.toString())
binding.LNmaxInlineSize.setOnFocusChangeListener { _, hasFocus ->
if (!hasFocus) {
val value = binding.LNmaxInlineSize.text.toString().toIntOrNull() ?: 720
settings.defaultLN.maxInlineSize = value
defaultSettingsLN.maxInlineSize = value
binding.LNmaxInlineSize.setText(value.toString())
saveData(reader, settings)
PrefManager.setVal(PrefName.MaxInlineSize, value)
}
}
binding.LNincrementMaxInlineSize.setOnClickListener {
val value = binding.LNmaxInlineSize.text.toString().toIntOrNull() ?: 720
settings.defaultLN.maxInlineSize = value + 10
binding.LNmaxInlineSize.setText(settings.defaultLN.maxInlineSize.toString())
saveData(reader, settings)
defaultSettingsLN.maxInlineSize = value + 10
binding.LNmaxInlineSize.setText(defaultSettingsLN.maxInlineSize.toString())
PrefManager.setVal(PrefName.MaxInlineSize, defaultSettingsLN.maxInlineSize)
}
binding.LNdecrementMaxInlineSize.setOnClickListener {
val value = binding.LNmaxInlineSize.text.toString().toIntOrNull() ?: 720
settings.defaultLN.maxInlineSize = value - 10
binding.LNmaxInlineSize.setText(settings.defaultLN.maxInlineSize.toString())
saveData(reader, settings)
defaultSettingsLN.maxInlineSize = value - 10
binding.LNmaxInlineSize.setText(defaultSettingsLN.maxInlineSize.toString())
PrefManager.setVal(PrefName.MaxInlineSize, defaultSettingsLN.maxInlineSize)
}
binding.LNmaxBlockSize.setText(settings.defaultLN.maxBlockSize.toString())
binding.LNmaxBlockSize.setText(defaultSettingsLN.maxBlockSize.toString())
binding.LNmaxBlockSize.setOnFocusChangeListener { _, hasFocus ->
if (!hasFocus) {
val value = binding.LNmaxBlockSize.text.toString().toIntOrNull() ?: 720
settings.defaultLN.maxBlockSize = value
defaultSettingsLN.maxBlockSize = value
binding.LNmaxBlockSize.setText(value.toString())
saveData(reader, settings)
PrefManager.setVal(PrefName.MaxBlockSize, value)
}
}
binding.LNincrementMaxBlockSize.setOnClickListener {
val value = binding.LNmaxBlockSize.text.toString().toIntOrNull() ?: 720
settings.defaultLN.maxInlineSize = value + 10
binding.LNmaxBlockSize.setText(settings.defaultLN.maxInlineSize.toString())
saveData(reader, settings)
defaultSettingsLN.maxInlineSize = value + 10
binding.LNmaxBlockSize.setText(defaultSettingsLN.maxInlineSize.toString())
PrefManager.setVal(PrefName.MaxBlockSize, defaultSettingsLN.maxInlineSize)
}
binding.LNdecrementMaxBlockSize.setOnClickListener {
val value = binding.LNmaxBlockSize.text.toString().toIntOrNull() ?: 720
settings.defaultLN.maxBlockSize = value - 10
binding.LNmaxBlockSize.setText(settings.defaultLN.maxBlockSize.toString())
saveData(reader, settings)
defaultSettingsLN.maxBlockSize = value - 10
binding.LNmaxBlockSize.setText(defaultSettingsLN.maxBlockSize.toString())
PrefManager.setVal(PrefName.MaxBlockSize, defaultSettingsLN.maxBlockSize)
}
binding.LNuseDarkTheme.isChecked = settings.defaultLN.useDarkTheme
binding.LNuseDarkTheme.isChecked = defaultSettingsLN.useDarkTheme
binding.LNuseDarkTheme.setOnCheckedChangeListener { _, isChecked ->
settings.defaultLN.useDarkTheme = isChecked
saveData(reader, settings)
defaultSettingsLN.useDarkTheme = isChecked
PrefManager.setVal(PrefName.UseDarkThemeNovel, isChecked)
}
binding.LNuseOledTheme.isChecked = settings.defaultLN.useOledTheme
binding.LNuseOledTheme.isChecked = defaultSettingsLN.useOledTheme
binding.LNuseOledTheme.setOnCheckedChangeListener { _, isChecked ->
settings.defaultLN.useOledTheme = isChecked
saveData(reader, settings)
defaultSettingsLN.useOledTheme = isChecked
PrefManager.setVal(PrefName.UseOledThemeNovel, isChecked)
}
binding.LNkeepScreenOn.isChecked = settings.defaultLN.keepScreenOn
binding.LNkeepScreenOn.isChecked = defaultSettingsLN.keepScreenOn
binding.LNkeepScreenOn.setOnCheckedChangeListener { _, isChecked ->
settings.defaultLN.keepScreenOn = isChecked
saveData(reader, settings)
defaultSettingsLN.keepScreenOn = isChecked
PrefManager.setVal(PrefName.KeepScreenOnNovel, isChecked)
}
binding.LNvolumeButton.isChecked = settings.defaultLN.volumeButtons
binding.LNvolumeButton.isChecked = defaultSettingsLN.volumeButtons
binding.LNvolumeButton.setOnCheckedChangeListener { _, isChecked ->
settings.defaultLN.volumeButtons = isChecked
saveData(reader, settings)
defaultSettingsLN.volumeButtons = isChecked
PrefManager.setVal(PrefName.VolumeButtonsNovel, isChecked)
}
//Update Progress
binding.readerSettingsAskUpdateProgress.isChecked = settings.askIndividual
binding.readerSettingsAskUpdateProgress.isChecked = PrefManager.getVal(PrefName.AskIndividualReader)
binding.readerSettingsAskUpdateProgress.setOnCheckedChangeListener { _, isChecked ->
settings.askIndividual = isChecked
saveData(reader, settings)
PrefManager.setVal(PrefName.AskIndividualReader, isChecked)
}
binding.readerSettingsAskUpdateDoujins.isChecked = settings.updateForH
binding.readerSettingsAskUpdateDoujins.isChecked = PrefManager.getVal(PrefName.UpdateForHReader)
binding.readerSettingsAskUpdateDoujins.setOnCheckedChangeListener { _, isChecked ->
settings.updateForH = isChecked
PrefManager.setVal(PrefName.UpdateForHReader, isChecked)
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.app.AlertDialog
import android.content.Context
import android.content.Intent
import android.graphics.Color
import android.graphics.drawable.Animatable
import android.os.Build.*
import android.os.Build.VERSION.*
@ -15,6 +13,9 @@ import android.widget.ArrayAdapter
import android.widget.TextView
import android.widget.Toast
import androidx.activity.OnBackPressedCallback
import androidx.activity.result.ActivityResultLauncher
import androidx.activity.result.contract.ActivityResultContracts
import androidx.activity.result.contract.ActivityResultContracts.CreateDocument
import androidx.annotation.OptIn
import androidx.appcompat.app.AppCompatActivity
import androidx.core.content.ContextCompat
@ -23,6 +24,7 @@ import androidx.lifecycle.lifecycleScope
import androidx.media3.common.util.UnstableApi
import androidx.media3.exoplayer.offline.DownloadService
import ani.dantotsu.*
import ani.dantotsu.Mapper.json
import ani.dantotsu.connections.anilist.Anilist
import ani.dantotsu.connections.discord.Discord
import ani.dantotsu.connections.mal.MAL
@ -35,7 +37,8 @@ import ani.dantotsu.others.CustomBottomDialog
import ani.dantotsu.parsers.AnimeSources
import ani.dantotsu.parsers.MangaSources
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.Companion.openSettings
import ani.dantotsu.subcriptions.Subscription.Companion.defaultTime
@ -44,11 +47,12 @@ import ani.dantotsu.subcriptions.Subscription.Companion.timeMinutes
import ani.dantotsu.themes.ThemeManager
import com.google.android.material.snackbar.Snackbar
import com.google.android.material.textfield.TextInputEditText
import com.google.gson.Gson
import com.google.gson.reflect.TypeToken
import eltos.simpledialogfragment.SimpleDialog
import eltos.simpledialogfragment.SimpleDialog.OnDialogResultListener.BUTTON_POSITIVE
import eltos.simpledialogfragment.color.SimpleColorDialog
import eu.kanade.domain.base.BasePreferences
import eu.kanade.tachiyomi.network.NetworkPreferences
import io.noties.markwon.Markwon
import io.noties.markwon.SoftBreakAddsNewLinePlugin
import kotlinx.coroutines.Dispatchers
@ -65,20 +69,58 @@ class SettingsActivity : AppCompatActivity(), SimpleDialog.OnDialogResultListene
}
lateinit var binding: ActivitySettingsBinding
private val extensionInstaller = Injekt.get<BasePreferences>().extensionInstaller()
private val networkPreferences = Injekt.get<NetworkPreferences>()
private var cursedCounter = 0
private lateinit var openDocumentLauncher: ActivityResultLauncher<String>
@OptIn(UnstableApi::class)
@SuppressLint("SetTextI18n")
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
ThemeManager(this).applyTheme()
binding = ActivitySettingsBinding.inflate(layoutInflater)
setContentView(binding.root)
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.setOnLongClickListener {
copyToClipboard(getDeviceInfo(), false)
@ -97,16 +139,16 @@ class SettingsActivity : AppCompatActivity(), SimpleDialog.OnDialogResultListene
onBackPressedDispatcher.onBackPressed()
}
binding.settingsUseMaterialYou.isChecked = PrefWrapper.getVal(PrefName.UseMaterialYou, false)
binding.settingsUseMaterialYou.isChecked = PrefManager.getVal(PrefName.UseMaterialYou)
binding.settingsUseMaterialYou.setOnCheckedChangeListener { _, isChecked ->
PrefWrapper.setVal(PrefName.UseMaterialYou, isChecked)
PrefManager.setVal(PrefName.UseMaterialYou, isChecked)
if (isChecked) binding.settingsUseCustomTheme.isChecked = false
restartApp()
}
binding.settingsUseCustomTheme.isChecked = PrefWrapper.getVal(PrefName.UseCustomTheme, false)
binding.settingsUseCustomTheme.isChecked = PrefManager.getVal(PrefName.UseCustomTheme)
binding.settingsUseCustomTheme.setOnCheckedChangeListener { _, isChecked ->
PrefWrapper.setVal(PrefName.UseCustomTheme, isChecked)
PrefManager.setVal(PrefName.UseCustomTheme, isChecked)
if (isChecked) {
binding.settingsUseMaterialYou.isChecked = false
}
@ -114,19 +156,19 @@ class SettingsActivity : AppCompatActivity(), SimpleDialog.OnDialogResultListene
restartApp()
}
binding.settingsUseSourceTheme.isChecked = PrefWrapper.getVal(PrefName.UseSourceTheme, false)
binding.settingsUseSourceTheme.isChecked = PrefManager.getVal(PrefName.UseSourceTheme)
binding.settingsUseSourceTheme.setOnCheckedChangeListener { _, isChecked ->
PrefWrapper.setVal(PrefName.UseSourceTheme, isChecked)
PrefManager.setVal(PrefName.UseSourceTheme, isChecked)
restartApp()
}
binding.settingsUseOLED.isChecked = PrefWrapper.getVal(PrefName.UseOLED, false)
binding.settingsUseOLED.isChecked = PrefManager.getVal(PrefName.UseOLED)
binding.settingsUseOLED.setOnCheckedChangeListener { _, isChecked ->
PrefWrapper.setVal(PrefName.UseOLED, isChecked)
PrefManager.setVal(PrefName.UseOLED, isChecked)
restartApp()
}
val themeString = PrefWrapper.getVal(PrefName.Theme, "PURPLE")
val themeString: String = PrefManager.getVal(PrefName.Theme)
binding.themeSwitcher.setText(
themeString.substring(0, 1) + themeString.substring(1).lowercase()
)
@ -140,7 +182,7 @@ class SettingsActivity : AppCompatActivity(), SimpleDialog.OnDialogResultListene
)
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
binding.themeSwitcher.clearFocus()
restartApp()
@ -149,7 +191,7 @@ class SettingsActivity : AppCompatActivity(), SimpleDialog.OnDialogResultListene
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
override fun onPositiveButtonClick() {
@ -176,7 +218,7 @@ class SettingsActivity : AppCompatActivity(), SimpleDialog.OnDialogResultListene
val names = animeSourcesWithoutDownloadsSource.map { it.name }
val pinnedSourcesBoolean =
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 alertDialog = AlertDialog.Builder(this, R.style.MyPopup)
.setTitle("Pinned Anime Sources")
@ -191,7 +233,7 @@ class SettingsActivity : AppCompatActivity(), SimpleDialog.OnDialogResultListene
}
}
.setPositiveButton("OK") { dialog, _ ->
PrefWrapper.setVal(PrefName.PinnedAnimeSources, pinnedSources)
PrefManager.setVal(PrefName.PinnedAnimeSources, pinnedSources)
AnimeSources.pinnedAnimeSources = pinnedSources
AnimeSources.performReorderAnimeSources()
dialog.dismiss()
@ -208,19 +250,43 @@ class SettingsActivity : AppCompatActivity(), SimpleDialog.OnDialogResultListene
val managers = arrayOf("Default", "1DM", "ADM")
val downloadManagerDialog =
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 {
val dialog = downloadManagerDialog.setSingleChoiceItems(
managers,
downloadManager
) { dialog, count ->
downloadManager = count
PrefWrapper.setVal(PrefName.DownloadManager, downloadManager)
PrefManager.setVal(PrefName.DownloadManager, downloadManager)
dialog.dismiss()
}.show()
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 {
val dialog = AlertDialog.Builder(this, R.style.MyPopup)
.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 ->
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 ->
PrefWrapper.setVal(PrefName.NSFWExtension,isChecked)
PrefManager.setVal(PrefName.NSFWExtension,isChecked)
}
binding.userAgent.setOnClickListener {
val dialogView = layoutInflater.inflate(R.layout.dialog_user_agent, null)
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)
.setTitle("User Agent")
.setView(dialogView)
.setPositiveButton("OK") { dialog, _ ->
networkPreferences.defaultUserAgent().set(editText.text.toString())
PrefManager.setVal(PrefName.DefaultUserAgent, editText.text.toString())
dialog.dismiss()
}
.setNeutralButton("Reset") { dialog, _ ->
networkPreferences.defaultUserAgent()
.set("Mozilla/5.0 (Windows NT 10.0; Win64; x64; rv:110.0) Gecko/20100101 Firefox/110.0")
PrefManager.removeVal(PrefName.DefaultUserAgent)
editText.setText("")
dialog.dismiss()
}
@ -340,45 +405,45 @@ class SettingsActivity : AppCompatActivity(), SimpleDialog.OnDialogResultListene
"Shecan",
"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.setOnItemClickListener { _, _, i, _ ->
networkPreferences.dohProvider().set(i)
PrefManager.setVal(PrefName.DohProvider, i)
binding.settingsExtensionDns.clearFocus()
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 ->
if (isChecked) {
val arrayOfFiles = ContextCompat.getExternalFilesDirs(this, null)
if (arrayOfFiles.size > 1 && arrayOfFiles[1] != null) {
PrefWrapper.setVal(PrefName.SdDl, true)
PrefManager.setVal(PrefName.SdDl, true)
} else {
binding.settingsDownloadInSd.isChecked = false
PrefWrapper.setVal(PrefName.SdDl, true)
PrefManager.setVal(PrefName.SdDl, true)
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 ->
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 ->
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 ->
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 ->
PrefWrapper.setVal(PrefName.SettingsPreferDub, isChecked)
PrefManager.setVal(PrefName.SettingsPreferDub, isChecked)
}
binding.settingsPinnedMangaSources.setOnClickListener {
@ -387,7 +452,7 @@ class SettingsActivity : AppCompatActivity(), SimpleDialog.OnDialogResultListene
val names = mangaSourcesWithoutDownloadsSource.map { it.name }
val pinnedSourcesBoolean =
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 alertDialog = AlertDialog.Builder(this, R.style.MyPopup)
.setTitle("Pinned Manga Sources")
@ -402,7 +467,7 @@ class SettingsActivity : AppCompatActivity(), SimpleDialog.OnDialogResultListene
}
}
.setPositiveButton("OK") { dialog, _ ->
PrefWrapper.setVal(PrefName.PinnedMangaSources, pinnedSources)
PrefManager.setVal(PrefName.PinnedMangaSources, pinnedSources)
MangaSources.pinnedMangaSources = pinnedSources
MangaSources.performReorderMangaSources()
dialog.dismiss()
@ -416,10 +481,7 @@ class SettingsActivity : AppCompatActivity(), SimpleDialog.OnDialogResultListene
startActivity(Intent(this, ReaderSettingsActivity::class.java))
}
val uiSettings: UserInterfaceSettings =
loadData("ui_settings", toast = false)
?: UserInterfaceSettings().apply { saveData("ui_settings", this) }
var previous: View = when (uiSettings.darkMode) {
var previous: View = when (PrefManager.getNullableVal(PrefName.DarkMode, null as Boolean?)) {
null -> binding.settingsUiAuto
true -> binding.settingsUiDark
false -> binding.settingsUiLight
@ -429,8 +491,11 @@ class SettingsActivity : AppCompatActivity(), SimpleDialog.OnDialogResultListene
previous.alpha = 0.33f
previous = current
current.alpha = 1f
uiSettings.darkMode = mode
saveData("ui_settings", uiSettings)
if (mode == null) {
PrefManager.removeVal(PrefName.DarkMode)
} else {
PrefManager.setVal(PrefName.DarkMode, mode)
}
Refresh.all()
finish()
startActivity(Intent(this, SettingsActivity::class.java))
@ -450,7 +515,7 @@ class SettingsActivity : AppCompatActivity(), SimpleDialog.OnDialogResultListene
uiTheme(true, it)
}
var previousStart: View = when (uiSettings.defaultStartUpTab) {
var previousStart: View = when (PrefManager.getVal<Int>(PrefName.DefaultStartUpTab)) {
0 -> binding.uiSettingsAnime
1 -> binding.uiSettingsHome
2 -> binding.uiSettingsManga
@ -461,8 +526,7 @@ class SettingsActivity : AppCompatActivity(), SimpleDialog.OnDialogResultListene
previousStart.alpha = 0.33f
previousStart = current
current.alpha = 1f
uiSettings.defaultStartUpTab = mode
saveData("ui_settings", uiSettings)
PrefManager.setVal(PrefName.DefaultStartUpTab, mode)
initActivity(this)
}
@ -479,13 +543,12 @@ class SettingsActivity : AppCompatActivity(), SimpleDialog.OnDialogResultListene
uiTheme(2, it)
}
binding.settingsShowYt.isChecked = uiSettings.showYtButton
binding.settingsShowYt.isChecked = PrefManager.getVal(PrefName.ShowYtButton)
binding.settingsShowYt.setOnCheckedChangeListener { _, isChecked ->
uiSettings.showYtButton = isChecked
saveData("ui_settings", uiSettings)
PrefManager.setVal(PrefName.ShowYtButton, isChecked)
}
var previousEp: View = when (uiSettings.animeDefaultView) {
var previousEp: View = when (PrefManager.getVal<Int>(PrefName.AnimeDefaultView)) {
0 -> binding.settingsEpList
1 -> binding.settingsEpGrid
2 -> binding.settingsEpCompact
@ -496,8 +559,7 @@ class SettingsActivity : AppCompatActivity(), SimpleDialog.OnDialogResultListene
previousEp.alpha = 0.33f
previousEp = current
current.alpha = 1f
uiSettings.animeDefaultView = mode
saveData("ui_settings", uiSettings)
PrefManager.setVal(PrefName.AnimeDefaultView, mode)
}
binding.settingsEpList.setOnClickListener {
@ -512,7 +574,7 @@ class SettingsActivity : AppCompatActivity(), SimpleDialog.OnDialogResultListene
uiEp(2, it)
}
var previousChp: View = when (uiSettings.mangaDefaultView) {
var previousChp: View = when (PrefManager.getVal<Int>(PrefName.MangaDefaultView)) {
0 -> binding.settingsChpList
1 -> binding.settingsChpCompact
else -> binding.settingsChpList
@ -522,8 +584,7 @@ class SettingsActivity : AppCompatActivity(), SimpleDialog.OnDialogResultListene
previousChp.alpha = 0.33f
previousChp = current
current.alpha = 1f
uiSettings.mangaDefaultView = mode
saveData("ui_settings", uiSettings)
PrefManager.setVal(PrefName.MangaDefaultView, mode)
}
binding.settingsChpList.setOnClickListener {
@ -571,7 +632,7 @@ class SettingsActivity : AppCompatActivity(), SimpleDialog.OnDialogResultListene
Toast.makeText(this, "youwu have been cuwsed :pwayge:", Toast.LENGTH_LONG).show()
val url = "https://www.youtube.com/watch?v=dQw4w9WgXcQ"
openLinkInBrowser(url)
//PrefWrapper.setVal(PrefName.SomethingSpecial, !PrefWrapper.getVal(PrefName.SomethingSpecial, false))
//PrefManager.setVal(PrefName.SomethingSpecial, !PrefManager.getVal(PrefName.SomethingSpecial, false))
} else {
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 mins = it % 60
val hours = it / 60
@ -615,7 +676,7 @@ class SettingsActivity : AppCompatActivity(), SimpleDialog.OnDialogResultListene
curTime = i
binding.settingsSubscriptionsTime.text =
getString(R.string.subscriptions_checking_time_s, timeNames[i])
PrefWrapper.setVal(PrefName.SubscriptionsTimeS, curTime)
PrefManager.setVal(PrefName.SubscriptionsTimeS, curTime)
dialog.dismiss()
startSubscription(true)
}.show()
@ -628,9 +689,9 @@ class SettingsActivity : AppCompatActivity(), SimpleDialog.OnDialogResultListene
}
binding.settingsNotificationsCheckingSubscriptions.isChecked =
PrefWrapper.getVal(PrefName.SubscriptionCheckingNotifications, true)
PrefManager.getVal(PrefName.SubscriptionCheckingNotifications)
binding.settingsNotificationsCheckingSubscriptions.setOnCheckedChangeListener { _, isChecked ->
PrefWrapper.setVal(PrefName.SubscriptionCheckingNotifications, isChecked)
PrefManager.setVal(PrefName.SubscriptionCheckingNotifications, isChecked)
if (isChecked)
Notifications.createChannel(
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 ->
saveData("check_update", isChecked)
PrefWrapper.setVal(PrefName.CheckUpdate, isChecked)
PrefManager.setVal(PrefName.CheckUpdate, isChecked)
if (!isChecked) {
snackString(getString(R.string.long_click_to_check_update))
}
@ -733,9 +793,9 @@ class SettingsActivity : AppCompatActivity(), SimpleDialog.OnDialogResultListene
}
if (Discord.token != null) {
val id = PrefWrapper.getVal(PrefName.DiscordId, null as String?)
val avatar = PrefWrapper.getVal(PrefName.DiscordAvatar, null as String?)
val username = PrefWrapper.getVal(PrefName.DiscordUserName, null as String?)
val id = PrefManager.getVal(PrefName.DiscordId, null as String?)
val avatar = PrefManager.getVal(PrefName.DiscordAvatar, null as String?)
val username = PrefManager.getVal(PrefName.DiscordUserName, null as String?)
if (id != null && avatar != null) {
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 (dialogTag == "colorPicker") {
val color = extras.getInt(SimpleColorDialog.COLOR)
PrefWrapper.setVal(PrefName.CustomThemeInt, color)
PrefManager.setVal(PrefName.CustomThemeInt, color)
logger("Custom Theme: $color")
}
}

View file

@ -26,7 +26,7 @@ import ani.dantotsu.openLinkInBrowser
import ani.dantotsu.others.imagesearch.ImageSearchActivity
import ani.dantotsu.setSafeOnClickListener
import ani.dantotsu.settings.saving.PrefName
import ani.dantotsu.settings.saving.PrefWrapper
import ani.dantotsu.settings.saving.PrefManager
import ani.dantotsu.startMainActivity
class SettingsDialogFragment : BottomSheetDialogFragment() {
@ -76,10 +76,10 @@ class SettingsDialogFragment : BottomSheetDialogFragment() {
}
binding.settingsIncognito.isChecked =
PrefWrapper.getVal(PrefName.Incognito, false)
PrefManager.getVal(PrefName.Incognito)
binding.settingsIncognito.setOnCheckedChangeListener { _, isChecked ->
PrefWrapper.setVal(PrefName.Incognito, isChecked)
PrefManager.setVal(PrefName.Incognito, isChecked)
incognitoNotification(requireContext())
}
binding.settingsExtensionSettings.setSafeOnClickListener {
@ -99,7 +99,7 @@ class SettingsDialogFragment : BottomSheetDialogFragment() {
dismiss()
}
binding.settingsDownloads.isChecked = PrefWrapper.getVal(PrefName.OfflineMode, false)
binding.settingsDownloads.isChecked = PrefManager.getVal(PrefName.OfflineMode)
binding.settingsDownloads.setOnCheckedChangeListener { _, isChecked ->
when (pageType) {
PageType.MANGA -> {
@ -149,7 +149,7 @@ class SettingsDialogFragment : BottomSheetDialogFragment() {
}
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.databinding.ActivityUserInterfaceSettingsBinding
import ani.dantotsu.initActivity
import ani.dantotsu.loadData
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.themes.ThemeManager
import com.google.android.material.snackbar.Snackbar
@ -32,9 +32,6 @@ class UserInterfaceSettingsActivity : AppCompatActivity() {
bottomMargin = navBarHeight
}
val settings = loadData<UserInterfaceSettings>(ui, toast = false)
?: UserInterfaceSettings().apply { saveData(ui, this) }
binding.uiSettingsBack.setOnClickListener {
onBackPressedDispatcher.onBackPressed()
}
@ -45,39 +42,36 @@ class UserInterfaceSettingsActivity : AppCompatActivity() {
.setTitle(getString(R.string.home_layout_show)).apply {
setMultiChoiceItems(
views,
settings.homeLayoutShow.toBooleanArray()
PrefManager.getVal<List<Boolean>>(PrefName.HomeLayoutShow).toBooleanArray()
) { _, i, value ->
settings.homeLayoutShow[i] = value
saveData(ui, settings)
val set = PrefManager.getVal<List<Boolean>>(PrefName.HomeLayoutShow).toMutableList()
set[i] = value
PrefManager.setVal(PrefName.HomeLayoutShow, set)
}
}.show()
dialog.window?.setDimAmount(0.8f)
}
binding.uiSettingsSmallView.isChecked = settings.smallView
binding.uiSettingsSmallView.isChecked = PrefManager.getVal(PrefName.SmallView)
binding.uiSettingsSmallView.setOnCheckedChangeListener { _, isChecked ->
settings.smallView = isChecked
saveData(ui, settings)
PrefManager.setVal(PrefName.SmallView, isChecked)
restartApp()
}
binding.uiSettingsImmersive.isChecked = settings.immersiveMode
binding.uiSettingsImmersive.isChecked = PrefManager.getVal(PrefName.ImmersiveMode)
binding.uiSettingsImmersive.setOnCheckedChangeListener { _, isChecked ->
settings.immersiveMode = isChecked
saveData(ui, settings)
PrefManager.setVal(PrefName.ImmersiveMode, isChecked)
restartApp()
}
binding.uiSettingsBannerAnimation.isChecked = settings.bannerAnimations
binding.uiSettingsBannerAnimation.isChecked = PrefManager.getVal(PrefName.BannerAnimations)
binding.uiSettingsBannerAnimation.setOnCheckedChangeListener { _, isChecked ->
settings.bannerAnimations = isChecked
saveData(ui, settings)
PrefManager.setVal(PrefName.BannerAnimations, isChecked)
restartApp()
}
binding.uiSettingsLayoutAnimation.isChecked = settings.layoutAnimations
binding.uiSettingsLayoutAnimation.isChecked = PrefManager.getVal(PrefName.LayoutAnimations)
binding.uiSettingsLayoutAnimation.setOnCheckedChangeListener { _, isChecked ->
settings.layoutAnimations = isChecked
saveData(ui, settings)
PrefManager.setVal(PrefName.LayoutAnimations, isChecked)
restartApp()
}
@ -93,10 +87,9 @@ class UserInterfaceSettingsActivity : AppCompatActivity() {
0f to 0f
)
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, _ ->
settings.animationSpeed = map[value] ?: 1f
saveData(ui, settings)
PrefManager.setVal(PrefName.AnimationSpeed, map[value] ?: 1f)
restartApp()
}

View file

@ -21,7 +21,7 @@ import ani.dantotsu.R
import ani.dantotsu.databinding.ItemExtensionAllBinding
import ani.dantotsu.others.LanguageMapper
import ani.dantotsu.settings.saving.PrefName
import ani.dantotsu.settings.saving.PrefWrapper
import ani.dantotsu.settings.saving.PrefManager
import com.bumptech.glide.Glide
import eu.kanade.tachiyomi.extension.anime.AnimeExtensionManager
import eu.kanade.tachiyomi.extension.anime.model.AnimeExtension
@ -93,14 +93,14 @@ class AnimeExtensionPagingSource(
val availableExtensions =
availableExtensionsFlow.filterNot { it.pkgName in installedExtensions }
val query = searchQuery
val isNsfwEnabled: Boolean = PrefWrapper.getVal(PrefName.NSFWExtension,true)
val isNsfwEnabled: Boolean = PrefManager.getVal(PrefName.NSFWExtension)
val filteredExtensions = if (query.isEmpty()) {
availableExtensions
} else {
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 filternfsw = if (isNsfwEnabled) langFilter else langFilter.filterNot { it.isNsfw }
return try {
@ -128,7 +128,7 @@ class AnimeExtensionAdapter(private val clickListener: OnAnimeInstallClickListen
DIFF_CALLBACK
) {
private val skipIcons = PrefWrapper.getVal(PrefName.SkipExtensionIcons, false)
private val skipIcons: Boolean = PrefManager.getVal(PrefName.SkipExtensionIcons)
companion object {
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 ani.dantotsu.R
import ani.dantotsu.databinding.ItemExtensionAllBinding
import ani.dantotsu.loadData
import ani.dantotsu.others.LanguageMapper
import ani.dantotsu.settings.saving.PrefName
import ani.dantotsu.settings.saving.PrefWrapper
import ani.dantotsu.settings.saving.PrefManager
import com.bumptech.glide.Glide
import eu.kanade.tachiyomi.extension.manga.MangaExtensionManager
import eu.kanade.tachiyomi.extension.manga.model.MangaExtension
@ -94,13 +93,13 @@ class MangaExtensionPagingSource(
val availableExtensions =
availableExtensionsFlow.filterNot { it.pkgName in installedExtensions }
val query = searchQuery
val isNsfwEnabled: Boolean = PrefWrapper.getVal(PrefName.NSFWExtension,true)
val isNsfwEnabled: Boolean = PrefManager.getVal(PrefName.NSFWExtension)
val filteredExtensions = if (query.isEmpty()) {
availableExtensions
} else {
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 filternfsw = if (isNsfwEnabled) langFilter else langFilter.filterNot { it.isNsfw }
return try {
@ -128,7 +127,7 @@ class MangaExtensionAdapter(private val clickListener: OnMangaInstallClickListen
DIFF_CALLBACK
) {
private val skipIcons = PrefWrapper.getVal(PrefName.SkipExtensionIcons, false)
private val skipIcons: Boolean = PrefManager.getVal(PrefName.SkipExtensionIcons)
companion object {
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 ani.dantotsu.R
import ani.dantotsu.databinding.ItemExtensionAllBinding
import ani.dantotsu.loadData
import ani.dantotsu.others.LanguageMapper
import ani.dantotsu.parsers.novel.NovelExtension
import ani.dantotsu.parsers.novel.NovelExtensionManager
import ani.dantotsu.settings.saving.PrefName
import ani.dantotsu.settings.saving.PrefWrapper
import ani.dantotsu.settings.saving.PrefManager
import com.bumptech.glide.Glide
import kotlinx.coroutines.CoroutineScope
import kotlinx.coroutines.Dispatchers
@ -95,7 +94,7 @@ class NovelExtensionPagingSource(
val availableExtensions =
availableExtensionsFlow.filterNot { it.pkgName in installedExtensions }
val query = searchQuery
val isNsfwEnabled: Boolean = PrefWrapper.getVal(PrefName.NSFWExtension,true)
val isNsfwEnabled: Boolean = PrefManager.getVal(PrefName.NSFWExtension)
val filteredExtensions = if (query.isEmpty()) {
availableExtensions
} else {
@ -132,7 +131,7 @@ class NovelExtensionAdapter(private val clickListener: OnNovelInstallClickListen
DIFF_CALLBACK
) {
private val skipIcons = PrefWrapper.getVal(PrefName.SkipExtensionIcons, false)
private val skipIcons: Boolean = PrefManager.getVal(PrefName.SkipExtensionIcons)
companion object {
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
import android.graphics.Color
import ani.dantotsu.connections.mal.MAL
import ani.dantotsu.settings.saving.internal.Pref
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
SharedUserID(Pref(Location.General, Boolean::class)),
OfflineView(Pref(Location.General, Int::class)),
UseOLED(Pref(Location.General, Boolean::class)),
UseCustomTheme(Pref(Location.General, Boolean::class)),
CustomThemeInt(Pref(Location.General, Int::class)),
UseSourceTheme(Pref(Location.General, Boolean::class)),
UseMaterialYou(Pref(Location.General, Boolean::class)),
Theme(Pref(Location.General, String::class)),
DownloadManager(Pref(Location.General, Int::class)),
NSFWExtension(Pref(Location.General, Boolean::class)),
SkipExtensionIcons(Pref(Location.General, Boolean::class)),
SdDl(Pref(Location.General, Boolean::class)),
ContinueMedia(Pref(Location.General, Boolean::class)),
RecentlyListOnly(Pref(Location.General, Boolean::class)),
SettingsPreferDub(Pref(Location.General, Boolean::class)),
SubscriptionsTimeS(Pref(Location.General, Int::class)),
SubscriptionCheckingNotifications(Pref(Location.General, Boolean::class)),
CheckUpdate(Pref(Location.General, Boolean::class)),
SharedUserID(Pref(Location.General, Boolean::class, true)),
OfflineView(Pref(Location.General, Int::class, 0)),
DownloadManager(Pref(Location.General, Int::class, 0)),
NSFWExtension(Pref(Location.General, Boolean::class, false)),
SdDl(Pref(Location.General, Boolean::class, false)),
ContinueMedia(Pref(Location.General, Boolean::class, true)),
RecentlyListOnly(Pref(Location.General, Boolean::class, false)),
SettingsPreferDub(Pref(Location.General, Boolean::class, false)),
SubscriptionsTimeS(Pref(Location.General, Int::class, 0)),
SubscriptionCheckingNotifications(Pref(Location.General, Boolean::class, true)),
CheckUpdate(Pref(Location.General, Boolean::class, true)),
VerboseLogging(Pref(Location.General, Boolean::class, false)),
DohProvider(Pref(Location.General, Int::class, 0)),
DefaultUserAgent(Pref(Location.General, String::class, "Mozilla/5.0 (Windows NT 10.0; Win64; x64; rv:110.0) Gecko/20100101 Firefox/110.0")),
//User Interface
UseOLED(Pref(Location.UI, Boolean::class, false)),
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
AnimeListSortOrder(Pref(Location.Anime, String::class)),
PinnedAnimeSources(Pref(Location.Anime, Set::class)),
PopularAnimeList(Pref(Location.Anime, Boolean::class)),
AnimeSearchHistory(Pref(Location.Anime, Set::class)),
AnimeListSortOrder(Pref(Location.Anime, String::class, "score")),
PinnedAnimeSources(Pref(Location.Anime, Set::class, setOf<String>())),
PopularAnimeList(Pref(Location.Anime, Boolean::class, true)),
AnimeSearchHistory(Pref(Location.Anime, Set::class, setOf<String>())),
//Manga
MangaListSortOrder(Pref(Location.Manga, String::class)),
PinnedMangaSources(Pref(Location.Manga, Set::class)),
PopularMangaList(Pref(Location.Manga, Boolean::class)),
MangaSearchHistory(Pref(Location.Manga, Set::class)),
MangaListSortOrder(Pref(Location.Manga, String::class, "score")),
PinnedMangaSources(Pref(Location.Manga, Set::class, setOf<String>())),
PopularMangaList(Pref(Location.Manga, Boolean::class, true)),
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
Incognito(Pref(Location.Irrelevant, Boolean::class)),
OfflineMode(Pref(Location.Irrelevant, Boolean::class)),
DownloadsKeys(Pref(Location.Irrelevant, String::class)),
NovelLastExtCheck(Pref(Location.Irrelevant, Long::class)),
SomethingSpecial(Pref(Location.Irrelevant, Boolean::class)),
AllowOpeningLinks(Pref(Location.Irrelevant, Boolean::class)),
SearchStyle(Pref(Location.Irrelevant, Int::class)),
HasUpdatedPrefs(Pref(Location.Irrelevant, Boolean::class)),
LangSort(Pref(Location.Irrelevant, String::class)),
Incognito(Pref(Location.Irrelevant, Boolean::class, false)),
OfflineMode(Pref(Location.Irrelevant, Boolean::class, false)),
DownloadsKeys(Pref(Location.Irrelevant, String::class, "")),
NovelLastExtCheck(Pref(Location.Irrelevant, Long::class, 0L)),
SomethingSpecial(Pref(Location.Irrelevant, Boolean::class, false)),
AllowOpeningLinks(Pref(Location.Irrelevant, Boolean::class, false)),
SearchStyle(Pref(Location.Irrelevant, Int::class, 0)),
HasUpdatedPrefs(Pref(Location.Irrelevant, Boolean::class, false)),
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
DiscordToken(Pref(Location.Protected, String::class)),
DiscordId(Pref(Location.Protected, String::class)),
DiscordUserName(Pref(Location.Protected, String::class)),
DiscordAvatar(Pref(Location.Protected, String::class)),
AnilistUserName(Pref(Location.Protected, String::class)),
DiscordToken(Pref(Location.Protected, String::class, "")),
DiscordId(Pref(Location.Protected, String::class, "")),
DiscordUserName(Pref(Location.Protected, String::class, "")),
DiscordAvatar(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 ani.dantotsu.settings.saving.PrefName
import ani.dantotsu.settings.saving.PrefWrapper
import ani.dantotsu.settings.saving.PrefManager
class Compat {
companion object {
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 jsonString = oldPrefs.getString("downloads_key", null)
PrefWrapper.setVal(PrefName.DownloadsKeys, jsonString)
PrefManager.setVal(PrefName.DownloadsKeys, jsonString)
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(
val prefLocation: Location,
val type: KClass<*>
val type: KClass<*>,
val default: Any
)
enum class Location(val location: String) {
General("ani.dantotsu.general"),
UI("ani.dantotsu.ui"),
Anime("ani.dantotsu.anime"),
Manga("ani.dantotsu.manga"),
Player("ani.dantotsu.player"),
Reader("ani.dantotsu.reader"),
NovelReader("ani.dantotsu.novelReader"),
Irrelevant("ani.dantotsu.irrelevant"),
AnimeDownloads("animeDownloads"), //different for legacy reasons
Protected("ani.dantotsu.protected")

View file

@ -9,7 +9,7 @@ import ani.dantotsu.currContext
import ani.dantotsu.isOnline
import ani.dantotsu.logger
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.startSubscription
import ani.dantotsu.subcriptions.Subscription.Companion.timeMinutes
@ -44,7 +44,7 @@ class AlarmReceiver : BroadcastReceiver() {
PendingIntent.FLAG_IMMUTABLE or PendingIntent.FLAG_UPDATE_CURRENT
)
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)
alarmManager.setRepeating(

View file

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

View file

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

View file

@ -3,7 +3,6 @@ package ani.dantotsu.subcriptions
import android.content.Context
import ani.dantotsu.R
import ani.dantotsu.currContext
import ani.dantotsu.loadData
import ani.dantotsu.media.Media
import ani.dantotsu.media.Selected
import ani.dantotsu.media.manga.MangaNameAdapter
@ -15,9 +14,8 @@ import ani.dantotsu.parsers.HMangaSources
import ani.dantotsu.parsers.MangaChapter
import ani.dantotsu.parsers.MangaParser
import ani.dantotsu.parsers.MangaSources
import ani.dantotsu.saveData
import ani.dantotsu.settings.saving.PrefName
import ani.dantotsu.settings.saving.PrefWrapper
import ani.dantotsu.settings.saving.PrefManager
import ani.dantotsu.tryWithSuspend
import kotlinx.coroutines.withTimeoutOrNull
@ -29,16 +27,16 @@ class SubscriptionHelper {
isAdult: Boolean,
isAnime: Boolean
): Selected {
val data = loadData<Selected>("${mediaId}-select", context) ?: Selected().let {
val data = PrefManager.getNullableCustomVal<Selected?>("${mediaId}-select", null) ?: Selected().let {
it.sourceIndex = 0
it.preferDub = PrefWrapper.getVal(PrefName.SettingsPreferDub, false)
it.preferDub = PrefManager.getVal(PrefName.SettingsPreferDub)
it
}
return data
}
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 {
@ -125,12 +123,12 @@ class SubscriptionHelper {
) : java.io.Serializable
private const val subscriptions = "subscriptions"
fun getSubscriptions(context: Context): Map<Int, SubscribeMedia> =
loadData(subscriptions, context)
?: mapOf<Int, SubscribeMedia>().also { saveData(subscriptions, it, context) }
fun getSubscriptions(): Map<Int, SubscribeMedia> =
PrefManager.getNullableCustomVal<Map<Int, SubscribeMedia>?>(subscriptions, null)
?: mapOf<Int, SubscribeMedia>().also { PrefManager.setCustomVal(subscriptions, it) }
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 (!data.containsKey(media.id)) {
val new = SubscribeMedia(
@ -145,7 +143,7 @@ class SubscriptionHelper {
} else {
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.WorkManager
import androidx.work.WorkerParameters
import ani.dantotsu.loadData
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.timeMinutes
import kotlinx.coroutines.Dispatchers
@ -31,7 +30,7 @@ class SubscriptionWorker(val context: Context, params: WorkerParameters) :
private const val SUBSCRIPTION_WORK_NAME = "work_subscription"
fun enqueue(context: Context) {
val curTime = PrefWrapper.getVal(PrefName.SubscriptionsTimeS, defaultTime)
val curTime = PrefManager.getVal(PrefName.SubscriptionsTimeS, defaultTime)
if (timeMinutes[curTime] > 0L) {
val constraints =
Constraints.Builder().setRequiredNetworkType(NetworkType.CONNECTED).build()

View file

@ -8,18 +8,18 @@ import android.view.Window
import android.view.WindowManager
import ani.dantotsu.R
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.DynamicColorsOptions
class ThemeManager(private val context: Activity) {
fun applyTheme(fromImage: Bitmap? = null) {
val useOLED = PrefWrapper.getVal(PrefName.UseOLED, false) && isDarkThemeActive(context)
val useCustomTheme = PrefWrapper.getVal(PrefName.UseCustomTheme, false)
val customTheme = PrefWrapper.getVal(PrefName.CustomThemeInt, 16712221)
val useSource = PrefWrapper.getVal(PrefName.UseSourceTheme, false)
val useMaterial = PrefWrapper.getVal(PrefName.UseMaterialYou, false)
val useOLED = PrefManager.getVal(PrefName.UseOLED) && isDarkThemeActive(context)
val useCustomTheme: Boolean = PrefManager.getVal(PrefName.UseCustomTheme)
val customTheme: Int = PrefManager.getVal(PrefName.CustomThemeInt)
val useSource: Boolean = PrefManager.getVal(PrefName.UseSourceTheme)
val useMaterial: Boolean = PrefManager.getVal(PrefName.UseMaterialYou)
if (useSource) {
val returnedEarly = applyDynamicColors(
useMaterial,
@ -37,7 +37,7 @@ class ThemeManager(private val context: Activity) {
val returnedEarly = applyDynamicColors(useMaterial, context, useOLED, useCustom = null)
if (!returnedEarly) return
}
val theme = PrefWrapper.getVal(PrefName.Theme, "PURPLE")
val theme: String = PrefManager.getVal(PrefName.Theme)
val themeToApply = when (theme) {
"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.os.Build
import ani.dantotsu.Mapper
import ani.dantotsu.settings.saving.PrefName
import ani.dantotsu.settings.saving.PrefManager
import com.lagradost.nicehttp.Requests
import eu.kanade.tachiyomi.network.interceptor.CloudflareInterceptor
import eu.kanade.tachiyomi.network.interceptor.UncaughtExceptionInterceptor
@ -14,8 +16,7 @@ import java.io.File
import java.util.concurrent.TimeUnit
class NetworkHelper(
context: Context,
private val preferences: NetworkPreferences,
context: Context
) {
private val cacheDir = File(context.cacheDir, "network_cache")
@ -39,14 +40,14 @@ class NetworkHelper(
.addInterceptor(UncaughtExceptionInterceptor())
.addInterceptor(userAgentInterceptor)
if (preferences.verboseLogging().get()) {
if (PrefManager.getVal(PrefName.VerboseLogging)) {
val httpLoggingInterceptor = HttpLoggingInterceptor().apply {
level = HttpLoggingInterceptor.Level.HEADERS
}
builder.addNetworkInterceptor(httpLoggingInterceptor)
}
when (preferences.dohProvider().get()) {
when (PrefManager.getVal<Int>(PrefName.DohProvider)) {
PREF_DOH_CLOUDFLARE -> builder.dohCloudflare()
PREF_DOH_GOOGLE -> builder.dohGoogle()
PREF_DOH_ADGUARD -> builder.dohAdGuard()
@ -88,5 +89,5 @@ class NetworkHelper(
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: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
android:layout_width="match_parent"
android:layout_height="1dp"
@ -858,6 +889,7 @@
app:cornerRadius="0dp"
app:drawableTint="?attr/colorPrimary"
app:showText="false"
android:enabled="false"
app:thumbTint="@color/button_switch_track" />
<TextView

View file

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