diff --git a/app/build.gradle b/app/build.gradle index 42dce3be..70bf9c9d 100644 --- a/app/build.gradle +++ b/app/build.gradle @@ -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"] diff --git a/app/src/main/java/ani/dantotsu/App.kt b/app/src/main/java/ani/dantotsu/App.kt index 0fef61f2..3a844578 100644 --- a/app/src/main/java/ani/dantotsu/App.kt +++ b/app/src/main/java/ani/dantotsu/App.kt @@ -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") } diff --git a/app/src/main/java/ani/dantotsu/Functions.kt b/app/src/main/java/ani/dantotsu/Functions.kt index 86fa6ef8..61bfaa46 100644 --- a/app/src/main/java/ani/dantotsu/Functions.kt +++ b/app/src/main/java/ani/dantotsu/Functions.kt @@ -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("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 = 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, context: Context) { + FileProvider.getUriForFile( + context, + "$APPLICATION_ID.provider", + savePrefs( + map, + Environment.getExternalStoragePublicDirectory(Environment.DIRECTORY_DOWNLOADS).absolutePath, + title, + context + ) ?: return + ) +} + +fun savePrefs(map: Map, 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.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( diff --git a/app/src/main/java/ani/dantotsu/MainActivity.kt b/app/src/main/java/ani/dantotsu/MainActivity.kt index 705783af..11790fab 100644 --- a/app/src/main/java/ani/dantotsu/MainActivity.kt +++ b/app/src/main/java/ani/dantotsu/MainActivity.kt @@ -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 { 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) diff --git a/app/src/main/java/ani/dantotsu/aniyomi/anime/custom/InjektModules.kt b/app/src/main/java/ani/dantotsu/aniyomi/anime/custom/InjektModules.kt index d0f52269..38032311 100644 --- a/app/src/main/java/ani/dantotsu/aniyomi/anime/custom/InjektModules.kt +++ b/app/src/main/java/ani/dantotsu/aniyomi/anime/custom/InjektModules.kt @@ -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()) } diff --git a/app/src/main/java/ani/dantotsu/connections/UpdateProgress.kt b/app/src/main/java/ani/dantotsu/connections/UpdateProgress.kt index 72338f58..20ff176a 100644 --- a/app/src/main/java/ani/dantotsu/connections/UpdateProgress.kt +++ b/app/src/main/java/ani/dantotsu/connections/UpdateProgress.kt @@ -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 { diff --git a/app/src/main/java/ani/dantotsu/connections/anilist/AnilistQueries.kt b/app/src/main/java/ani/dantotsu/connections/anilist/AnilistQueries.kt index 5086cb17..6d12c1d5 100644 --- a/app/src/main/java/ani/dantotsu/connections/anilist/AnilistQueries.kt +++ b/app/src/main/java/ani/dantotsu/connections/anilist/AnilistQueries.kt @@ -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>("continue_$type") - if (set != null) { + val set = PrefManager.getCustomVal>("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("banner_$type") + //var image = loadData("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("""{ 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? = loadData("genres_list", activity) - var tags: Map>? = loadData("tags_map", activity) + var genres: ArrayList? = PrefManager.getVal>(PrefName.GenresList).toMutableList() as ArrayList? + val adultTags = PrefManager.getVal>(PrefName.TagsListIsAdult).toMutableList() + val nonAdultTags = PrefManager.getVal>(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( """{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 suspend fun getGenreThumbnail(genre: String): Genre? { - val genres = loadData>("genre_thumb") ?: mutableMapOf() + private fun saveSerializableMap(prefKey: String, map: Map) { + 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 loadSerializableMap(prefKey: String): Map? { + 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 + } + } catch (e: Exception) { + return null + } + } + + private suspend fun getGenreThumbnail(genre: String): Genre? { + val genres: MutableMap = loadSerializableMap("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() - 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)) diff --git a/app/src/main/java/ani/dantotsu/connections/anilist/AnilistViewModel.kt b/app/src/main/java/ani/dantotsu/connections/anilist/AnilistViewModel.kt index 825b982d..721b7384 100644 --- a/app/src/main/java/ani/dantotsu/connections/anilist/AnilistViewModel.kt +++ b/app/src/main/java/ani/dantotsu/connections/anilist/AnilistViewModel.kt @@ -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)) } diff --git a/app/src/main/java/ani/dantotsu/connections/discord/Discord.kt b/app/src/main/java/ani/dantotsu/connections/discord/Discord.kt index d3adc2ff..c6b4fbed 100644 --- a/app/src/main/java/ani/dantotsu/connections/discord/Discord.kt +++ b/app/src/main/java/ani/dantotsu/connections/discord/Discord.kt @@ -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") diff --git a/app/src/main/java/ani/dantotsu/connections/discord/DiscordService.kt b/app/src/main/java/ani/dantotsu/connections/discord/DiscordService.kt index 5023ca70..f310e134 100644 --- a/app/src/main/java/ani/dantotsu/connections/discord/DiscordService.kt +++ b/app/src/main/java/ani/dantotsu/connections/discord/DiscordService.kt @@ -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(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") diff --git a/app/src/main/java/ani/dantotsu/connections/mal/Login.kt b/app/src/main/java/ani/dantotsu/connections/mal/Login.kt index b38baaa5..0b5ac515 100644 --- a/app/src/main/java/ani/dantotsu/connections/mal/Login.kt +++ b/app/src/main/java/ani/dantotsu/connections/mal/Login.kt @@ -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)) diff --git a/app/src/main/java/ani/dantotsu/connections/mal/MAL.kt b/app/src/main/java/ani/dantotsu/connections/mal/MAL.kt index 0391cd47..71fdfedb 100644 --- a/app/src/main/java/ani/dantotsu/connections/mal/MAL.kt +++ b/app/src/main/java/ani/dantotsu/connections/mal/MAL.kt @@ -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(MAL_TOKEN) + val token = PrefManager.getNullableVal(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(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 diff --git a/app/src/main/java/ani/dantotsu/download/DownloadsManager.kt b/app/src/main/java/ani/dantotsu/download/DownloadsManager.kt index 1e1a4e64..fdeebaec 100644 --- a/app/src/main/java/ani/dantotsu/download/DownloadsManager.kt +++ b/app/src/main/java/ani/dantotsu/download/DownloadsManager.kt @@ -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 { - 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>() {}.type gson.fromJson(jsonString, type) diff --git a/app/src/main/java/ani/dantotsu/download/anime/AnimeDownloaderService.kt b/app/src/main/java/ani/dantotsu/download/anime/AnimeDownloaderService.kt index 6b254bec..5dc2a3d1 100644 --- a/app/src/main/java/ani/dantotsu/download/anime/AnimeDownloaderService.kt +++ b/app/src/main/java/ani/dantotsu/download/anime/AnimeDownloaderService.kt @@ -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() diff --git a/app/src/main/java/ani/dantotsu/download/anime/OfflineAnimeAdapter.kt b/app/src/main/java/ani/dantotsu/download/anime/OfflineAnimeAdapter.kt index de5c9503..79f86ad9 100644 --- a/app/src/main/java/ani/dantotsu/download/anime/OfflineAnimeAdapter.kt +++ b/app/src/main/java/ani/dantotsu/download/anime/OfflineAnimeAdapter.kt @@ -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 = 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() } } \ No newline at end of file diff --git a/app/src/main/java/ani/dantotsu/download/anime/OfflineAnimeFragment.kt b/app/src/main/java/ani/dantotsu/download/anime/OfflineAnimeFragment.kt index 8a2a780b..d1e0d0d6 100644 --- a/app/src/main/java/ani/dantotsu/download/anime/OfflineAnimeFragment.kt +++ b/app/src/main/java/ani/dantotsu/download/anime/OfflineAnimeFragment.kt @@ -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(R.id.downloadedList) val layoutcompact = view.findViewById(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 } diff --git a/app/src/main/java/ani/dantotsu/download/manga/OfflineMangaAdapter.kt b/app/src/main/java/ani/dantotsu/download/manga/OfflineMangaAdapter.kt index a885355f..c9ecd330 100644 --- a/app/src/main/java/ani/dantotsu/download/manga/OfflineMangaAdapter.kt +++ b/app/src/main/java/ani/dantotsu/download/manga/OfflineMangaAdapter.kt @@ -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 = 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() } } \ No newline at end of file diff --git a/app/src/main/java/ani/dantotsu/download/manga/OfflineMangaFragment.kt b/app/src/main/java/ani/dantotsu/download/manga/OfflineMangaFragment.kt index b0fdeddf..35fec9f5 100644 --- a/app/src/main/java/ani/dantotsu/download/manga/OfflineMangaFragment.kt +++ b/app/src/main/java/ani/dantotsu/download/manga/OfflineMangaFragment.kt @@ -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(R.id.downloadedList) val layoutcompact = view.findViewById(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() diff --git a/app/src/main/java/ani/dantotsu/download/video/Helper.kt b/app/src/main/java/ani/dantotsu/download/video/Helper.kt index 5ad05c16..7f92eda6 100644 --- a/app/src/main/java/ani/dantotsu/download/video/Helper.kt +++ b/app/src/main/java/ani/dantotsu/download/video/Helper.kt @@ -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( diff --git a/app/src/main/java/ani/dantotsu/home/AnimeFragment.kt b/app/src/main/java/ani/dantotsu/home/AnimeFragment.kt index 1f5061bd..6994e0af 100644 --- a/app/src/main/java/ani/dantotsu/home/AnimeFragment.kt +++ b/app/src/main/java/ani/dantotsu/home/AnimeFragment.kt @@ -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 diff --git a/app/src/main/java/ani/dantotsu/home/AnimePageAdapter.kt b/app/src/main/java/ani/dantotsu/home/AnimePageAdapter.kt index 40299a4b..e0731e60 100644 --- a/app/src/main/java/ani/dantotsu/home/AnimePageAdapter.kt +++ b/app/src/main/java/ani/dantotsu/home/AnimePageAdapter.kt @@ -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 { + if (PrefManager.getVal(PrefName.SmallView)) binding.animeTrendingContainer.updateLayoutParams { bottomMargin = (-108f).px } @@ -130,12 +125,12 @@ class AnimePageAdapter : RecyclerView.Adapter 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("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("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 = 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) { diff --git a/app/src/main/java/ani/dantotsu/home/MangaFragment.kt b/app/src/main/java/ani/dantotsu/home/MangaFragment.kt index cdaed640..7b3e5948 100644 --- a/app/src/main/java/ani/dantotsu/home/MangaFragment.kt +++ b/app/src/main/java/ani/dantotsu/home/MangaFragment.kt @@ -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 diff --git a/app/src/main/java/ani/dantotsu/home/MangaPageAdapter.kt b/app/src/main/java/ani/dantotsu/home/MangaPageAdapter.kt index 617752d5..82fb5bc0 100644 --- a/app/src/main/java/ani/dantotsu/home/MangaPageAdapter.kt +++ b/app/src/main/java/ani/dantotsu/home/MangaPageAdapter.kt @@ -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 { + if (PrefManager.getVal(PrefName.SmallView)) binding.mangaTrendingContainer.updateLayoutParams { bottomMargin = (-108f).px } @@ -123,12 +118,12 @@ class MangaPageAdapter : RecyclerView.Adapter 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 { 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( diff --git a/app/src/main/java/ani/dantotsu/media/CalendarActivity.kt b/app/src/main/java/ani/dantotsu/media/CalendarActivity.kt index 632058ff..1a5bb6c3 100644 --- a/app/src/main/java/ani/dantotsu/media/CalendarActivity.kt +++ b/app/src/main/java/ani/dantotsu/media/CalendarActivity.kt @@ -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("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 diff --git a/app/src/main/java/ani/dantotsu/media/CharacterAdapter.kt b/app/src/main/java/ani/dantotsu/media/CharacterAdapter.kt index 63223023..d8c4961c 100644 --- a/app/src/main/java/ani/dantotsu/media/CharacterAdapter.kt +++ b/app/src/main/java/ani/dantotsu/media/CharacterAdapter.kt @@ -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("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) diff --git a/app/src/main/java/ani/dantotsu/media/CharacterDetailsActivity.kt b/app/src/main/java/ani/dantotsu/media/CharacterDetailsActivity.kt index 601c5719..00771dce 100644 --- a/app/src/main/java/ani/dantotsu/media/CharacterDetailsActivity.kt +++ b/app/src/main/java/ani/dantotsu/media/CharacterDetailsActivity.kt @@ -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("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 { 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) } diff --git a/app/src/main/java/ani/dantotsu/media/GenreActivity.kt b/app/src/main/java/ani/dantotsu/media/GenreActivity.kt index 728dacb2..6b7ee40a 100644 --- a/app/src/main/java/ani/dantotsu/media/GenreActivity.kt +++ b/app/src/main/java/ani/dantotsu/media/GenreActivity.kt @@ -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? { + val genres = PrefManager.getVal>(PrefName.GenresList).toMutableList() as ArrayList? + return if (genres.isNullOrEmpty()) { + null + } else { + genres + } + } } \ No newline at end of file diff --git a/app/src/main/java/ani/dantotsu/media/MediaAdaptor.kt b/app/src/main/java/ani/dantotsu/media/MediaAdaptor.kt index e3cd6618..f8cef3f9 100644 --- a/app/src/main/java/ani/dantotsu/media/MediaAdaptor.kt +++ b/app/src/main/java/ani/dantotsu/media/MediaAdaptor.kt @@ -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() { - private val uiSettings = - loadData("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) diff --git a/app/src/main/java/ani/dantotsu/media/MediaDetailsActivity.kt b/app/src/main/java/ani/dantotsu/media/MediaDetailsActivity.kt index 07ff41cd..4724e026 100644 --- a/app/src/main/java/ani/dantotsu/media/MediaDetailsActivity.kt +++ b/app/src/main/java/ani/dantotsu/media/MediaDetailsActivity.kt @@ -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("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 diff --git a/app/src/main/java/ani/dantotsu/media/MediaDetailsViewModel.kt b/app/src/main/java/ani/dantotsu/media/MediaDetailsViewModel.kt index 498227a0..35aa6415 100644 --- a/app/src/main/java/ani/dantotsu/media/MediaDetailsViewModel.kt +++ b/app/src/main/java/ani/dantotsu/media/MediaDetailsViewModel.kt @@ -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("${media.id}-select") ?: Selected().let { + val data = PrefManager.getNullableCustomVal("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 } diff --git a/app/src/main/java/ani/dantotsu/media/MediaInfoFragment.kt b/app/src/main/java/ani/dantotsu/media/MediaInfoFragment.kt index af375143..213ed19e 100644 --- a/app/src/main/java/ani/dantotsu/media/MediaInfoFragment.kt +++ b/app/src/main/java/ani/dantotsu/media/MediaInfoFragment.kt @@ -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 { bottomMargin += 128f.px + navBarHeight } diff --git a/app/src/main/java/ani/dantotsu/media/SearchActivity.kt b/app/src/main/java/ani/dantotsu/media/SearchActivity.kt index 5e72c9bb..3a32083d 100644 --- a/app/src/main/java/ani/dantotsu/media/SearchActivity.kt +++ b/app/src/main/java/ani/dantotsu/media/SearchActivity.kt @@ -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 diff --git a/app/src/main/java/ani/dantotsu/media/SearchAdapter.kt b/app/src/main/java/ani/dantotsu/media/SearchAdapter.kt index d8c803ee..3a294296 100644 --- a/app/src/main/java/ani/dantotsu/media/SearchAdapter.kt +++ b/app/src/main/java/ani/dantotsu/media/SearchAdapter.kt @@ -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() } diff --git a/app/src/main/java/ani/dantotsu/media/SearchHistoryAdapter.kt b/app/src/main/java/ani/dantotsu/media/SearchHistoryAdapter.kt index 46028527..45ac2347 100644 --- a/app/src/main/java/ani/dantotsu/media/SearchHistoryAdapter.kt +++ b/app/src/main/java/ani/dantotsu/media/SearchHistoryAdapter.kt @@ -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()).asLiveStringSet() + searchHistoryLiveData = PrefManager.getLiveVal(historyType, mutableSetOf()).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( diff --git a/app/src/main/java/ani/dantotsu/media/anime/AnimeWatchAdapter.kt b/app/src/main/java/ani/dantotsu/media/anime/AnimeWatchAdapter.kt index 3734a51e..5026829e 100644 --- a/app/src/main/java/ani/dantotsu/media/anime/AnimeWatchAdapter.kt +++ b/app/src/main/java/ani/dantotsu/media/anime/AnimeWatchAdapter.kt @@ -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("${media.id}_current_ep")?.toIntOrNull() ?: 1 + val appEp = PrefManager.getNullableCustomVal("${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(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(PrefName.WatchPercentage)) { binding.animeSourceContinue.performClick() fragment.continueEp = false } diff --git a/app/src/main/java/ani/dantotsu/media/anime/AnimeWatchFragment.kt b/app/src/main/java/ani/dantotsu/media/anime/AnimeWatchFragment.kt index a8a1b6a1..bf83544b 100644 --- a/app/src/main/java/ani/dantotsu/media/anime/AnimeWatchFragment.kt +++ b/app/src/main/java/ani/dantotsu/media/anime/AnimeWatchFragment.kt @@ -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) ?: 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()) { diff --git a/app/src/main/java/ani/dantotsu/media/anime/EpisodeAdapters.kt b/app/src/main/java/ani/dantotsu/media/anime/EpisodeAdapters.kt index 261ebe9c..dc61a781 100644 --- a/app/src/main/java/ani/dantotsu/media/anime/EpisodeAdapters.kt +++ b/app/src/main/java/ani/dantotsu/media/anime/EpisodeAdapters.kt @@ -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("${mediaId}_${ep}") - val max = loadData("${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, "" ) ?: "" diff --git a/app/src/main/java/ani/dantotsu/media/anime/ExoplayerView.kt b/app/src/main/java/ani/dantotsu/media/anime/ExoplayerView.kt index 0025987b..dde8b7cc 100644 --- a/app/src/main/java/ani/dantotsu/media/anime/ExoplayerView.kt +++ b/app/src/main/java/ani/dantotsu/media/anime/ExoplayerView.kt @@ -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(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(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(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(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(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(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) @@ -332,7 +327,7 @@ class ExoplayerView : AppCompatActivity(), Player.Listener, SessionAvailabilityL override fun onCreate(savedInstanceState: Bundle?) { super.onCreate(savedInstanceState) - + ThemeManager(this).applyTheme() binding = ActivityExoplayerBinding.inflate(layoutInflater) setContentView(binding.root) @@ -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(PrefName.Subtitles)) { true -> 1f false -> 0f } - val fontSize = settings.fontSize.toFloat() + val fontSize = PrefManager.getVal(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(R.id.exo_skip_time).text = settings.skipTime.toString() + var skipTime = PrefManager.getVal(PrefName.SkipTime) + if (skipTime > 0) { + exoSkip.findViewById(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(R.id.seekbar).value = settings.skipTime.toFloat() + if (skipTime <= 120) { + dialog.findViewById(R.id.seekbar).value = skipTime.toFloat() } else { dialog.findViewById(R.id.seekbar).value = 120f } dialog.findViewById(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(R.id.exo_skip_time).text = - settings.skipTime.toString() + skipTime.toString() dialog.findViewById(R.id.seekbar_value).text = - settings.skipTime.toString() + skipTime.toString() } dialog.findViewById(R.id.seekbar) .addOnSliderTouchListener(object : Slider.OnSliderTouchListener { @@ -574,7 +559,7 @@ class ExoplayerView : AppCompatActivity(), Player.Listener, SessionAvailabilityL dialog.findViewById(R.id.seekbar_title).text = getString(R.string.skip_time) dialog.findViewById(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(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(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(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(PrefName.DoubleTap)) { playerView.findViewById(R.id.exo_fast_forward_button_cont).visibility = View.VISIBLE playerView.findViewById(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(PrefName.Gestures) || PrefManager.getVal(PrefName.DoubleTap)) { fun doubleTap(forward: Boolean, event: MotionEvent) { - if (!locked && isInitialized && settings.doubleTap) { + if (!locked && isInitialized && PrefManager.getVal(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(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(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("${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( + 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>("continue_ANIME", this) ?: mutableSetOf() + val set = PrefManager.getVal>(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(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("${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( + 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(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("${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( + 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() } } diff --git a/app/src/main/java/ani/dantotsu/media/anime/SelectorDialogFragment.kt b/app/src/main/java/ani/dantotsu/media/anime/SelectorDialogFragment.kt index f7945fb8..70273a2c 100644 --- a/app/src/main/java/ani/dantotsu/media/anime/SelectorDialogFragment.kt +++ b/app/src/main/java/ani/dantotsu/media/anime/SelectorDialogFragment.kt @@ -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!!) } diff --git a/app/src/main/java/ani/dantotsu/media/anime/SubtitleDialogFragment.kt b/app/src/main/java/ani/dantotsu/media/anime/SubtitleDialogFragment.kt index 6cc97157..88c7bd4a 100644 --- a/app/src/main/java/ani/dantotsu/media/anime/SubtitleDialogFragment.kt +++ b/app/src/main/java/ani/dantotsu/media/anime/SubtitleDialogFragment.kt @@ -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("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("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() } diff --git a/app/src/main/java/ani/dantotsu/media/manga/MangaChapterAdapter.kt b/app/src/main/java/ani/dantotsu/media/manga/MangaChapterAdapter.kt index 6d0b3677..73229660 100644 --- a/app/src/main/java/ani/dantotsu/media/manga/MangaChapterAdapter.kt +++ b/app/src/main/java/ani/dantotsu/media/manga/MangaChapterAdapter.kt @@ -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 diff --git a/app/src/main/java/ani/dantotsu/media/manga/MangaReadAdapter.kt b/app/src/main/java/ani/dantotsu/media/manga/MangaReadAdapter.kt index 77051e19..8e931503 100644 --- a/app/src/main/java/ani/dantotsu/media/manga/MangaReadAdapter.kt +++ b/app/src/main/java/ani/dantotsu/media/manga/MangaReadAdapter.kt @@ -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("${media.id}_current_chp")?.toIntOrNull() ?: 1 + val appEp = PrefManager.getNullableCustomVal("${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]!! diff --git a/app/src/main/java/ani/dantotsu/media/manga/MangaReadFragment.kt b/app/src/main/java/ani/dantotsu/media/manga/MangaReadFragment.kt index 40e85f82..722e8ab0 100644 --- a/app/src/main/java/ani/dantotsu/media/manga/MangaReadFragment.kt +++ b/app/src/main/java/ani/dantotsu/media/manga/MangaReadFragment.kt @@ -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) { 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 = arrayListOf() @@ -588,7 +586,7 @@ open class MangaReadFragment : Fragment(), ScanlatorSelectionListener { arr = (arr.reversed() as? ArrayList) ?: arr } chapterAdapter.arr = arr - chapterAdapter.updateType(style ?: uiSettings.mangaDefaultView) + chapterAdapter.updateType(style ?: PrefManager.getVal(PrefName.MangaDefaultView)) chapterAdapter.notifyItemRangeInserted(0, arr.size) } diff --git a/app/src/main/java/ani/dantotsu/media/manga/mangareader/BaseImageAdapter.kt b/app/src/main/java/ani/dantotsu/media/manga/mangareader/BaseImageAdapter.kt index 952db619..c313d71d 100644 --- a/app/src/main/java/ani/dantotsu/media/manga/mangareader/BaseImageAdapter.kt +++ b/app/src/main/java/ani/dantotsu/media/manga/mangareader/BaseImageAdapter.kt @@ -33,8 +33,7 @@ abstract class BaseImageAdapter( val activity: MangaReaderActivity, chapter: MangaChapter ) : RecyclerView.Adapter() { - val settings = activity.settings.default - val uiSettings = activity.uiSettings + val settings = activity.defaultSettings val images = chapter.images() @SuppressLint("ClickableViewAccessibility") diff --git a/app/src/main/java/ani/dantotsu/media/manga/mangareader/ImageAdapter.kt b/app/src/main/java/ani/dantotsu/media/manga/mangareader/ImageAdapter.kt index 58b48038..68870d5c 100644 --- a/app/src/main/java/ani/dantotsu/media/manga/mangareader/ImageAdapter.kt +++ b/app/src/main/java/ani/dantotsu/media/manga/mangareader/ImageAdapter.kt @@ -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(PrefName.AnimationSpeed)).toLong()) .start() progress.visibility = View.GONE diff --git a/app/src/main/java/ani/dantotsu/media/manga/mangareader/MangaReaderActivity.kt b/app/src/main/java/ani/dantotsu/media/manga/mangareader/MangaReaderActivity.kt index 3f7e3df1..3fc72fba 100644 --- a/app/src/main/java/ani/dantotsu/media/manga/mangareader/MangaReaderActivity.kt +++ b/app/src/main/java/ani/dantotsu/media/manga/mangareader/MangaReaderActivity.kt @@ -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 @@ -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(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(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("${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 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.. 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(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("${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(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,9 +885,9 @@ class MangaReaderActivity : AppCompatActivity() { .create() .show() } else { - if (!incognito && loadData("${media.id}_save_progress") != false && if (media.isAdult) settings.updateForH else true) - updateProgress( - media, + if (!incognito && PrefManager.getCustomVal("${media.id}_save_progress", true) && if (media.isAdult) PrefManager.getVal(PrefName.UpdateForHReader) else true) + updateProgress( + media, MangaNameAdapter.findChapterNumber(media.manga!!.selectedChapter!!) .toString() ) @@ -898,6 +898,47 @@ class MangaReaderActivity : AppCompatActivity() { } } + + @Suppress("UNCHECKED_CAST") + private fun 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) { diff --git a/app/src/main/java/ani/dantotsu/media/manga/mangareader/ReaderSettingsDialogFragment.kt b/app/src/main/java/ani/dantotsu/media/manga/mangareader/ReaderSettingsDialogFragment.kt index fc399e19..c9c42aab 100644 --- a/app/src/main/java/ani/dantotsu/media/manga/mangareader/ReaderSettingsDialogFragment.kt +++ b/app/src/main/java/ani/dantotsu/media/manga/mangareader/ReaderSettingsDialogFragment.kt @@ -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] diff --git a/app/src/main/java/ani/dantotsu/media/novel/NovelReadFragment.kt b/app/src/main/java/ani/dantotsu/media/novel/NovelReadFragment.kt index 0c654c16..369f446e 100644 --- a/app/src/main/java/ani/dantotsu/media/novel/NovelReadFragment.kt +++ b/app/src/main/java/ani/dantotsu/media/novel/NovelReadFragment.kt @@ -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 } diff --git a/app/src/main/java/ani/dantotsu/media/novel/NovelResponseAdapter.kt b/app/src/main/java/ani/dantotsu/media/novel/NovelResponseAdapter.kt index 49b3fc61..0ab80e14 100644 --- a/app/src/main/java/ani/dantotsu/media/novel/NovelResponseAdapter.kt +++ b/app/src/main/java/ani/dantotsu/media/novel/NovelResponseAdapter.kt @@ -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) diff --git a/app/src/main/java/ani/dantotsu/media/novel/novelreader/NovelReaderActivity.kt b/app/src/main/java/ani/dantotsu/media/novel/novelreader/NovelReaderActivity.kt index d344ed83..5b305033 100644 --- a/app/src/main/java/ani/dantotsu/media/novel/novelreader/NovelReaderActivity.kt +++ b/app/src/main/java/ani/dantotsu/media/novel/novelreader/NovelReaderActivity.kt @@ -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() + 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(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("${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(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(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 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(PrefName.ShowSystemBars)) { + hideSystemBars() + } } } \ No newline at end of file diff --git a/app/src/main/java/ani/dantotsu/media/novel/novelreader/NovelReaderSettingsDialogFragment.kt b/app/src/main/java/ani/dantotsu/media/novel/novelreader/NovelReaderSettingsDialogFragment.kt index 760c7eb3..67fc2ff3 100644 --- a/app/src/main/java/ani/dantotsu/media/novel/novelreader/NovelReaderSettingsDialogFragment.kt +++ b/app/src/main/java/ani/dantotsu/media/novel/novelreader/NovelReaderSettingsDialogFragment.kt @@ -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) diff --git a/app/src/main/java/ani/dantotsu/media/user/ListActivity.kt b/app/src/main/java/ani/dantotsu/media/user/ListActivity.kt index fb75d22e..b504c13f 100644 --- a/app/src/main/java/ani/dantotsu/media/user/ListActivity.kt +++ b/app/src/main/java/ani/dantotsu/media/user/ListActivity.kt @@ -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("ui_settings") ?: UserInterfaceSettings() - if (!uiSettings.immersiveMode) { + if (!PrefManager.getVal(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 ?: "" ) diff --git a/app/src/main/java/ani/dantotsu/media/user/ListViewModel.kt b/app/src/main/java/ani/dantotsu/media/user/ListViewModel.kt index 87071791..9753d3aa 100644 --- a/app/src/main/java/ani/dantotsu/media/user/ListViewModel.kt +++ b/app/src/main/java/ani/dantotsu/media/user/ListViewModel.kt @@ -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("listGrid") ?: true) + var grid = MutableLiveData(PrefManager.getVal(PrefName.ListGrid)) private val lists = MutableLiveData>>() fun getLists(): LiveData>> = lists diff --git a/app/src/main/java/ani/dantotsu/offline/OfflineFragment.kt b/app/src/main/java/ani/dantotsu/offline/OfflineFragment.kt index c7386a09..9b6bbc24 100644 --- a/app/src/main/java/ani/dantotsu/offline/OfflineFragment.kt +++ b/app/src/main/java/ani/dantotsu/offline/OfflineFragment.kt @@ -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) } } \ No newline at end of file diff --git a/app/src/main/java/ani/dantotsu/others/AppUpdater.kt b/app/src/main/java/ani/dantotsu/others/AppUpdater.kt index eea658e0..655d66b1 100644 --- a/app/src/main/java/ani/dantotsu/others/AppUpdater.kt +++ b/app/src/main/java/ani/dantotsu/others/AppUpdater.kt @@ -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)) { diff --git a/app/src/main/java/ani/dantotsu/others/Download.kt b/app/src/main/java/ani/dantotsu/others/Download.kt index f176c629..010d2a3f 100644 --- a/app/src/main/java/ani/dantotsu/others/Download.kt +++ b/app/src/main/java/ani/dantotsu/others/Download.kt @@ -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() diff --git a/app/src/main/java/ani/dantotsu/parsers/AnimeParser.kt b/app/src/main/java/ani/dantotsu/parsers/AnimeParser.kt index dc9464e2..001197db 100644 --- a/app/src/main/java/ani/dantotsu/parsers/AnimeParser.kt +++ b/app/src/main/java/ani/dantotsu/parsers/AnimeParser.kt @@ -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("${saveName}${dub}_$mediaId") + var loaded = PrefManager.getNullableCustomVal("${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) } } } diff --git a/app/src/main/java/ani/dantotsu/parsers/AnimeSources.kt b/app/src/main/java/ani/dantotsu/parsers/AnimeSources.kt index 138f4697..c3969d54 100644 --- a/app/src/main/java/ani/dantotsu/parsers/AnimeSources.kt +++ b/app/src/main/java/ani/dantotsu/parsers/AnimeSources.kt @@ -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 = emptySet() suspend fun init(fromExtensions: StateFlow>, context: Context) { - pinnedAnimeSources = PrefWrapper.getVal(PrefName.PinnedAnimeSources, emptySet()) + pinnedAnimeSources = PrefManager.getVal(PrefName.PinnedAnimeSources) // Initialize with the first value from StateFlow val initialExtensions = fromExtensions.first() diff --git a/app/src/main/java/ani/dantotsu/parsers/BaseParser.kt b/app/src/main/java/ani/dantotsu/parsers/BaseParser.kt index 40ce4601..b47ebc56 100644 --- a/app/src/main/java/ani/dantotsu/parsers/BaseParser.kt +++ b/app/src/main/java/ani/dantotsu/parsers/BaseParser.kt @@ -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("${saveName}_$mediaId", null) } /** @@ -151,7 +150,7 @@ abstract class BaseParser { ) } : ${response.name}" ) - saveData("${saveName}_$mediaId", response) + PrefManager.setCustomVal("${saveName}_$mediaId", response) } } diff --git a/app/src/main/java/ani/dantotsu/parsers/MangaSources.kt b/app/src/main/java/ani/dantotsu/parsers/MangaSources.kt index 93cc1ac7..44b21482 100644 --- a/app/src/main/java/ani/dantotsu/parsers/MangaSources.kt +++ b/app/src/main/java/ani/dantotsu/parsers/MangaSources.kt @@ -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 = emptySet() suspend fun init(fromExtensions: StateFlow>) { - pinnedMangaSources = PrefWrapper.getVal(PrefName.PinnedMangaSources, emptySet()) + pinnedMangaSources = PrefManager.getVal(PrefName.PinnedMangaSources) // Initialize with the first value from StateFlow val initialExtensions = fromExtensions.first() diff --git a/app/src/main/java/ani/dantotsu/parsers/novel/NovelExtensionGithubApi.kt b/app/src/main/java/ani/dantotsu/parsers/novel/NovelExtensionGithubApi.kt index 665f84f5..f65639d8 100644 --- a/app/src/main/java/ani/dantotsu/parsers/novel/NovelExtensionGithubApi.kt +++ b/app/src/main/java/ani/dantotsu/parsers/novel/NovelExtensionGithubApi.kt @@ -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) } } diff --git a/app/src/main/java/ani/dantotsu/settings/CurrentNovelReaderSettings.kt b/app/src/main/java/ani/dantotsu/settings/CurrentNovelReaderSettings.kt index b1cd429b..fc6174b6 100644 --- a/app/src/main/java/ani/dantotsu/settings/CurrentNovelReaderSettings.kt +++ b/app/src/main/java/ani/dantotsu/settings/CurrentNovelReaderSettings.kt @@ -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) { diff --git a/app/src/main/java/ani/dantotsu/settings/CurrentReaderSettings.kt b/app/src/main/java/ani/dantotsu/settings/CurrentReaderSettings.kt index bfa2b4d8..8d14aac5 100644 --- a/app/src/main/java/ani/dantotsu/settings/CurrentReaderSettings.kt +++ b/app/src/main/java/ani/dantotsu/settings/CurrentReaderSettings.kt @@ -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 { diff --git a/app/src/main/java/ani/dantotsu/settings/DevelopersAdapter.kt b/app/src/main/java/ani/dantotsu/settings/DevelopersAdapter.kt index 7375d101..7f42017d 100644 --- a/app/src/main/java/ani/dantotsu/settings/DevelopersAdapter.kt +++ b/app/src/main/java/ani/dantotsu/settings/DevelopersAdapter.kt @@ -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) : RecyclerView.Adapter() { - private val uiSettings = - loadData("ui_settings") ?: UserInterfaceSettings() inner class DeveloperViewHolder(val binding: ItemDeveloperBinding) : RecyclerView.ViewHolder(binding.root) { @@ -35,7 +32,7 @@ class DevelopersAdapter(private val developers: Array) : 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) diff --git a/app/src/main/java/ani/dantotsu/settings/ExtensionsActivity.kt b/app/src/main/java/ani/dantotsu/settings/ExtensionsActivity.kt index f0be5db2..cf1c0ee9 100644 --- a/app/src/main/java/ani/dantotsu/settings/ExtensionsActivity.kt +++ b/app/src/main/java/ani/dantotsu/settings/ExtensionsActivity.kt @@ -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() diff --git a/app/src/main/java/ani/dantotsu/settings/FAQAdapter.kt b/app/src/main/java/ani/dantotsu/settings/FAQAdapter.kt index f854bd89..66425417 100644 --- a/app/src/main/java/ani/dantotsu/settings/FAQAdapter.kt +++ b/app/src/main/java/ani/dantotsu/settings/FAQAdapter.kt @@ -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() { - private val uiSettings = - loadData("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) diff --git a/app/src/main/java/ani/dantotsu/settings/InstalledAnimeExtensionsFragment.kt b/app/src/main/java/ani/dantotsu/settings/InstalledAnimeExtensionsFragment.kt index dab800c7..5bdce222 100644 --- a/app/src/main/java/ani/dantotsu/settings/InstalledAnimeExtensionsFragment.kt +++ b/app/src/main/java/ani/dantotsu/settings/InstalledAnimeExtensionsFragment.kt @@ -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 -> diff --git a/app/src/main/java/ani/dantotsu/settings/InstalledMangaExtensionsFragment.kt b/app/src/main/java/ani/dantotsu/settings/InstalledMangaExtensionsFragment.kt index 90fbe618..4f19c60f 100644 --- a/app/src/main/java/ani/dantotsu/settings/InstalledMangaExtensionsFragment.kt +++ b/app/src/main/java/ani/dantotsu/settings/InstalledMangaExtensionsFragment.kt @@ -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 -> diff --git a/app/src/main/java/ani/dantotsu/settings/InstalledNovelExtensionsFragment.kt b/app/src/main/java/ani/dantotsu/settings/InstalledNovelExtensionsFragment.kt index 2f951376..d31bf584 100644 --- a/app/src/main/java/ani/dantotsu/settings/InstalledNovelExtensionsFragment.kt +++ b/app/src/main/java/ani/dantotsu/settings/InstalledNovelExtensionsFragment.kt @@ -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 -> diff --git a/app/src/main/java/ani/dantotsu/settings/PlayerSettings.kt b/app/src/main/java/ani/dantotsu/settings/PlayerSettings.kt deleted file mode 100644 index 21d7a3b6..00000000 --- a/app/src/main/java/ani/dantotsu/settings/PlayerSettings.kt +++ /dev/null @@ -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 diff --git a/app/src/main/java/ani/dantotsu/settings/PlayerSettingsActivity.kt b/app/src/main/java/ani/dantotsu/settings/PlayerSettingsActivity.kt index 23d960f1..1b3ab882 100644 --- a/app/src/main/java/ani/dantotsu/settings/PlayerSettingsActivity.kt +++ b/app/src/main/java/ani/dantotsu/settings/PlayerSettingsActivity.kt @@ -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(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(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(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(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) - dialog.dismiss() - }.show() + val dialog = resizeDialog.setSingleChoiceItems(resizeModes, PrefManager.getVal(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(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)) } } diff --git a/app/src/main/java/ani/dantotsu/settings/ReaderSettings.kt b/app/src/main/java/ani/dantotsu/settings/ReaderSettings.kt deleted file mode 100644 index e0a91af8..00000000 --- a/app/src/main/java/ani/dantotsu/settings/ReaderSettings.kt +++ /dev/null @@ -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 \ No newline at end of file diff --git a/app/src/main/java/ani/dantotsu/settings/ReaderSettingsActivity.kt b/app/src/main/java/ani/dantotsu/settings/ReaderSettingsActivity.kt index ebf7b836..e154d9ff 100644 --- a/app/src/main/java/ani/dantotsu/settings/ReaderSettingsActivity.kt +++ b/app/src/main/java/ani/dantotsu/settings/ReaderSettingsActivity.kt @@ -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(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) } } diff --git a/app/src/main/java/ani/dantotsu/settings/SettingsActivity.kt b/app/src/main/java/ani/dantotsu/settings/SettingsActivity.kt index 38cc70cb..e1f7acc7 100644 --- a/app/src/main/java/ani/dantotsu/settings/SettingsActivity.kt +++ b/app/src/main/java/ani/dantotsu/settings/SettingsActivity.kt @@ -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().extensionInstaller() - private val networkPreferences = Injekt.get() private var cursedCounter = 0 + private lateinit var openDocumentLauncher: ActivityResultLauncher @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>>() {}.type + val rawMap: Map> = gson.fromJson(jsonString, type) + + val deserializedMap = mutableMapOf() + + 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()) + val pinnedSourcesOriginal: Set = 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(R.id.userAgentTextBox) - editText.setText(networkPreferences.defaultUserAgent().get()) + editText.setText(PrefManager.getVal(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()) + val pinnedSourcesOriginal: Set = 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(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(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(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") } } diff --git a/app/src/main/java/ani/dantotsu/settings/SettingsDialogFragment.kt b/app/src/main/java/ani/dantotsu/settings/SettingsDialogFragment.kt index f7b6d782..4d920238 100644 --- a/app/src/main/java/ani/dantotsu/settings/SettingsDialogFragment.kt +++ b/app/src/main/java/ani/dantotsu/settings/SettingsDialogFragment.kt @@ -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) } } diff --git a/app/src/main/java/ani/dantotsu/settings/UserInterfaceSettings.kt b/app/src/main/java/ani/dantotsu/settings/UserInterfaceSettings.kt deleted file mode 100644 index 39dd18b1..00000000 --- a/app/src/main/java/ani/dantotsu/settings/UserInterfaceSettings.kt +++ /dev/null @@ -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 = mutableListOf( - true, - false, - false, - true, - false, - false, - true - ), - - //Animations - var bannerAnimations: Boolean = true, - var layoutAnimations: Boolean = true, - var animationSpeed: Float = 1f - -) : Serializable \ No newline at end of file diff --git a/app/src/main/java/ani/dantotsu/settings/UserInterfaceSettingsActivity.kt b/app/src/main/java/ani/dantotsu/settings/UserInterfaceSettingsActivity.kt index 7e97d3a3..f7f53c82 100644 --- a/app/src/main/java/ani/dantotsu/settings/UserInterfaceSettingsActivity.kt +++ b/app/src/main/java/ani/dantotsu/settings/UserInterfaceSettingsActivity.kt @@ -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(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>(PrefName.HomeLayoutShow).toBooleanArray() ) { _, i, value -> - settings.homeLayoutShow[i] = value - saveData(ui, settings) + val set = PrefManager.getVal>(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() } diff --git a/app/src/main/java/ani/dantotsu/settings/paging/AnimePagingSource.kt b/app/src/main/java/ani/dantotsu/settings/paging/AnimePagingSource.kt index 065fa58b..6edd17c7 100644 --- a/app/src/main/java/ani/dantotsu/settings/paging/AnimePagingSource.kt +++ b/app/src/main/java/ani/dantotsu/settings/paging/AnimePagingSource.kt @@ -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() { diff --git a/app/src/main/java/ani/dantotsu/settings/paging/MangaPagingSource.kt b/app/src/main/java/ani/dantotsu/settings/paging/MangaPagingSource.kt index d8f0a0e4..673eac1c 100644 --- a/app/src/main/java/ani/dantotsu/settings/paging/MangaPagingSource.kt +++ b/app/src/main/java/ani/dantotsu/settings/paging/MangaPagingSource.kt @@ -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() { diff --git a/app/src/main/java/ani/dantotsu/settings/paging/NovelPagingSource.kt b/app/src/main/java/ani/dantotsu/settings/paging/NovelPagingSource.kt index c9f2a01f..df064875 100644 --- a/app/src/main/java/ani/dantotsu/settings/paging/NovelPagingSource.kt +++ b/app/src/main/java/ani/dantotsu/settings/paging/NovelPagingSource.kt @@ -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() { diff --git a/app/src/main/java/ani/dantotsu/settings/saving/PrefManager.kt b/app/src/main/java/ani/dantotsu/settings/saving/PrefManager.kt new file mode 100644 index 00000000..28a07c79 --- /dev/null +++ b/app/src/main/java/ani/dantotsu/settings/saving/PrefManager.kt @@ -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 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 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 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 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 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 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 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 getLiveVal(prefName: PrefName, default: T) : SharedPreferenceLiveData { + val pref = getPrefLocation(prefName.data.prefLocation) + return when (prefName.data.type) { + Boolean::class -> SharedPreferenceBooleanLiveData( + pref, + prefName.name, + default as Boolean + ) as SharedPreferenceLiveData + Int::class -> SharedPreferenceIntLiveData( + pref, + prefName.name, + default as Int + ) as SharedPreferenceLiveData + Float::class -> SharedPreferenceFloatLiveData( + pref, + prefName.name, + default as Float + ) as SharedPreferenceLiveData + Long::class -> SharedPreferenceLongLiveData( + pref, + prefName.name, + default as Long + ) as SharedPreferenceLiveData + String::class -> SharedPreferenceStringLiveData( + pref, + prefName.name, + default as String + ) as SharedPreferenceLiveData + Set::class -> SharedPreferenceStringSetLiveData( + pref, + prefName.name, + default as Set + ) as SharedPreferenceLiveData + else -> throw IllegalArgumentException("Type not supported") + } + } + + fun SharedPreferenceLiveData<*>.asLiveBool(): SharedPreferenceBooleanLiveData = + this as? SharedPreferenceBooleanLiveData + ?: throw ClassCastException("Cannot cast to SharedPreferenceLiveData") + + fun SharedPreferenceLiveData<*>.asLiveInt(): SharedPreferenceIntLiveData = + this as? SharedPreferenceIntLiveData + ?: throw ClassCastException("Cannot cast to SharedPreferenceLiveData") + + fun SharedPreferenceLiveData<*>.asLiveFloat(): SharedPreferenceFloatLiveData = + this as? SharedPreferenceFloatLiveData + ?: throw ClassCastException("Cannot cast to SharedPreferenceLiveData") + + fun SharedPreferenceLiveData<*>.asLiveLong(): SharedPreferenceLongLiveData = + this as? SharedPreferenceLongLiveData + ?: throw ClassCastException("Cannot cast to SharedPreferenceLiveData") + + fun SharedPreferenceLiveData<*>.asLiveString(): SharedPreferenceStringLiveData = + this as? SharedPreferenceStringLiveData + ?: throw ClassCastException("Cannot cast to SharedPreferenceLiveData") + + fun SharedPreferenceLiveData<*>.asLiveStringSet(): SharedPreferenceStringSetLiveData = + this as? SharedPreferenceStringSetLiveData + ?: throw ClassCastException("Cannot cast to SharedPreferenceLiveData>") + + fun getAnimeDownloadPreferences(): SharedPreferences = animeDownloadsPreferences!! //needs to be used externally + + fun exportAllPrefs(prefLocation: Location): Map{ + val pref = getPrefLocation(prefLocation) + val typedMap = mutableMapOf() + 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, 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) + is ArrayList<*> -> putStringSet(key, arrayListToSet(value)) + is Set<*> -> putStringSet(key, value as Set) + else -> snackString("Error importing preference: Type not supported") + } + } + apply() + } + } + + private fun arrayListToSet(arrayList: ArrayList<*>): Set { + 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 convertFromStringSet(stringSet: Set?, 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 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 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 + } + } +} \ No newline at end of file diff --git a/app/src/main/java/ani/dantotsu/settings/saving/PrefWrapper.kt b/app/src/main/java/ani/dantotsu/settings/saving/PrefWrapper.kt deleted file mode 100644 index b5193a07..00000000 --- a/app/src/main/java/ani/dantotsu/settings/saving/PrefWrapper.kt +++ /dev/null @@ -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 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) - else -> throw IllegalArgumentException("Type not supported") - } - apply() - } - } - - @Suppress("UNCHECKED_CAST") - fun 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) as T - else -> throw IllegalArgumentException("Type not supported") - } - } catch (e: Exception) { - snackString("Error getting preference: ${e.message}") - default - } - } - - @Suppress("UNCHECKED_CAST") - fun getLiveVal(prefName: PrefName, default: T) : SharedPreferenceLiveData { - val pref = getPrefLocation(prefName) - return when (prefName.data.type) { - Boolean::class -> SharedPreferenceBooleanLiveData( - pref, - prefName.name, - default as Boolean - ) as SharedPreferenceLiveData - Int::class -> SharedPreferenceIntLiveData( - pref, - prefName.name, - default as Int - ) as SharedPreferenceLiveData - Float::class -> SharedPreferenceFloatLiveData( - pref, - prefName.name, - default as Float - ) as SharedPreferenceLiveData - Long::class -> SharedPreferenceLongLiveData( - pref, - prefName.name, - default as Long - ) as SharedPreferenceLiveData - String::class -> SharedPreferenceStringLiveData( - pref, - prefName.name, - default as String - ) as SharedPreferenceLiveData - Set::class -> SharedPreferenceStringSetLiveData( - pref, - prefName.name, - default as Set - ) as SharedPreferenceLiveData - 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 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) - else -> throw IllegalArgumentException("Type not supported") - } - apply() - } - } - - @Suppress("UNCHECKED_CAST") - fun 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) 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") - - fun SharedPreferenceLiveData<*>.asLiveInt(): SharedPreferenceIntLiveData = - this as? SharedPreferenceIntLiveData - ?: throw ClassCastException("Cannot cast to SharedPreferenceLiveData") - - fun SharedPreferenceLiveData<*>.asLiveFloat(): SharedPreferenceFloatLiveData = - this as? SharedPreferenceFloatLiveData - ?: throw ClassCastException("Cannot cast to SharedPreferenceLiveData") - - fun SharedPreferenceLiveData<*>.asLiveLong(): SharedPreferenceLongLiveData = - this as? SharedPreferenceLongLiveData - ?: throw ClassCastException("Cannot cast to SharedPreferenceLiveData") - - fun SharedPreferenceLiveData<*>.asLiveString(): SharedPreferenceStringLiveData = - this as? SharedPreferenceStringLiveData - ?: throw ClassCastException("Cannot cast to SharedPreferenceLiveData") - - fun SharedPreferenceLiveData<*>.asLiveStringSet(): SharedPreferenceStringSetLiveData = - this as? SharedPreferenceStringSetLiveData - ?: throw ClassCastException("Cannot cast to SharedPreferenceLiveData>") - - 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 - }!! - } -} \ No newline at end of file diff --git a/app/src/main/java/ani/dantotsu/settings/saving/Preferences.kt b/app/src/main/java/ani/dantotsu/settings/saving/Preferences.kt index f8bf4cb5..2e897486 100644 --- a/app/src/main/java/ani/dantotsu/settings/saving/Preferences.kt +++ b/app/src/main/java/ani/dantotsu/settings/saving/Preferences.kt @@ -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())), + PopularAnimeList(Pref(Location.Anime, Boolean::class, true)), + AnimeSearchHistory(Pref(Location.Anime, Set::class, setOf())), //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())), + PopularMangaList(Pref(Location.Manga, Boolean::class, true)), + MangaSearchHistory(Pref(Location.Manga, Set::class, setOf())), + + //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())), + + //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())), + TagsListIsAdult(Pref(Location.Irrelevant, Set::class, setOf())), + TagsListNonAdult(Pref(Location.Irrelevant, Set::class, setOf())), + 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, "")), } \ No newline at end of file diff --git a/app/src/main/java/ani/dantotsu/settings/saving/internal/Compat.kt b/app/src/main/java/ani/dantotsu/settings/saving/internal/Compat.kt index 8afdee78..d063da48 100644 --- a/app/src/main/java/ani/dantotsu/settings/saving/internal/Compat.kt +++ b/app/src/main/java/ani/dantotsu/settings/saving/internal/Compat.kt @@ -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) } } } \ No newline at end of file diff --git a/app/src/main/java/ani/dantotsu/settings/saving/internal/PreferenceInternal.kt b/app/src/main/java/ani/dantotsu/settings/saving/internal/PreferenceInternal.kt index b44fb07f..084d6c06 100644 --- a/app/src/main/java/ani/dantotsu/settings/saving/internal/PreferenceInternal.kt +++ b/app/src/main/java/ani/dantotsu/settings/saving/internal/PreferenceInternal.kt @@ -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") diff --git a/app/src/main/java/ani/dantotsu/subcriptions/AlarmReceiver.kt b/app/src/main/java/ani/dantotsu/subcriptions/AlarmReceiver.kt index 2529c418..71e78c7d 100644 --- a/app/src/main/java/ani/dantotsu/subcriptions/AlarmReceiver.kt +++ b/app/src/main/java/ani/dantotsu/subcriptions/AlarmReceiver.kt @@ -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( diff --git a/app/src/main/java/ani/dantotsu/subcriptions/NotificationClickReceiver.kt b/app/src/main/java/ani/dantotsu/subcriptions/NotificationClickReceiver.kt index c35af707..571a55b4 100644 --- a/app/src/main/java/ani/dantotsu/subcriptions/NotificationClickReceiver.kt +++ b/app/src/main/java/ani/dantotsu/subcriptions/NotificationClickReceiver.kt @@ -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) diff --git a/app/src/main/java/ani/dantotsu/subcriptions/Subscription.kt b/app/src/main/java/ani/dantotsu/subcriptions/Subscription.kt index c0551f7d..a7d7d05a 100644 --- a/app/src/main/java/ani/dantotsu/subcriptions/Subscription.kt +++ b/app/src/main/java/ani/dantotsu/subcriptions/Subscription.kt @@ -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 diff --git a/app/src/main/java/ani/dantotsu/subcriptions/SubscriptionHelper.kt b/app/src/main/java/ani/dantotsu/subcriptions/SubscriptionHelper.kt index 9aeda2e5..bdf74660 100644 --- a/app/src/main/java/ani/dantotsu/subcriptions/SubscriptionHelper.kt +++ b/app/src/main/java/ani/dantotsu/subcriptions/SubscriptionHelper.kt @@ -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("${mediaId}-select", context) ?: Selected().let { + val data = PrefManager.getNullableCustomVal("${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 = - loadData(subscriptions, context) - ?: mapOf().also { saveData(subscriptions, it, context) } + fun getSubscriptions(): Map = + PrefManager.getNullableCustomVal?>(subscriptions, null) + ?: mapOf().also { PrefManager.setCustomVal(subscriptions, it) } fun saveSubscription(context: Context, media: Media, subscribed: Boolean) { - val data = loadData>(subscriptions, context)!!.toMutableMap() + val data = PrefManager.getNullableCustomVal?>(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) } } } \ No newline at end of file diff --git a/app/src/main/java/ani/dantotsu/subcriptions/SubscriptionWorker.kt b/app/src/main/java/ani/dantotsu/subcriptions/SubscriptionWorker.kt index 4286d438..72d77f90 100644 --- a/app/src/main/java/ani/dantotsu/subcriptions/SubscriptionWorker.kt +++ b/app/src/main/java/ani/dantotsu/subcriptions/SubscriptionWorker.kt @@ -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() diff --git a/app/src/main/java/ani/dantotsu/themes/ThemeManager.kt b/app/src/main/java/ani/dantotsu/themes/ThemeManager.kt index bc9ac598..befd9db9 100644 --- a/app/src/main/java/ani/dantotsu/themes/ThemeManager.kt +++ b/app/src/main/java/ani/dantotsu/themes/ThemeManager.kt @@ -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 diff --git a/app/src/main/java/eu/kanade/tachiyomi/network/NetworkHelper.kt b/app/src/main/java/eu/kanade/tachiyomi/network/NetworkHelper.kt index e73b97d2..28fc717e 100644 --- a/app/src/main/java/eu/kanade/tachiyomi/network/NetworkHelper.kt +++ b/app/src/main/java/eu/kanade/tachiyomi/network/NetworkHelper.kt @@ -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(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(PrefName.DefaultUserAgent) } diff --git a/app/src/main/java/eu/kanade/tachiyomi/network/NetworkPreferences.kt b/app/src/main/java/eu/kanade/tachiyomi/network/NetworkPreferences.kt deleted file mode 100644 index 1dce7afd..00000000 --- a/app/src/main/java/eu/kanade/tachiyomi/network/NetworkPreferences.kt +++ /dev/null @@ -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 { - return preferenceStore.getBoolean("verbose_logging", verboseLogging) - } - - fun dohProvider(): Preference { - return preferenceStore.getInt("doh_provider", 0) - } - - fun defaultUserAgent(): Preference { - return preferenceStore.getString( - "default_user_agent", - "Mozilla/5.0 (Windows NT 10.0; Win64; x64; rv:110.0) Gecko/20100101 Firefox/110.0" - ) - } -} diff --git a/app/src/main/res/layout/activity_settings.xml b/app/src/main/res/layout/activity_settings.xml index 51168cb3..1ec4b195 100644 --- a/app/src/main/res/layout/activity_settings.xml +++ b/app/src/main/res/layout/activity_settings.xml @@ -832,6 +832,37 @@ app:iconSize="24dp" app:iconTint="?attr/colorPrimary" /> + + +