import/export settings

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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