refactor(extension/repo): Refactor the ExtensionRepoService to use DTOs

Co-authored-by: MajorTanya <39014446+MajorTanya@users.noreply.github.com>
This commit is contained in:
Ahmad Ansori Palembani 2024-08-26 14:10:20 +07:00
parent c7405e0b33
commit da99cf5cfa
Signed by: null2264
GPG key ID: BA64F8B60AF3EFB6
10 changed files with 43 additions and 61 deletions

View file

@ -9,5 +9,11 @@
## Other ?? Technical stuff, what happened behind the scene ## Other ?? Technical stuff, what happened behind the scene
--> -->
## Additions
- Sync DoH provider list with upstream (added Mullvad, Control D, Njalla, and Shecan)
## Fixes ## Fixes
- Fixed NPE crash on tablets - Fixed only few DoH provider is actually being used (Cloudflare, Google, AdGuard, and Quad9)
## Other
- Simplify network helper code

View file

@ -1,6 +0,0 @@
package yokai.domain.extension.repo.exception
import java.io.IOException
class FetchExtensionRepoException(throwable: Throwable) :
IOException("Failed to retrieve Extension Repo Details", throwable)

View file

@ -5,7 +5,6 @@ import eu.kanade.tachiyomi.network.NetworkHelper
import okhttp3.OkHttpClient import okhttp3.OkHttpClient
import uy.kohesive.injekt.injectLazy import uy.kohesive.injekt.injectLazy
import yokai.domain.extension.repo.ExtensionRepoRepository import yokai.domain.extension.repo.ExtensionRepoRepository
import yokai.domain.extension.repo.exception.FetchExtensionRepoException
import yokai.domain.extension.repo.exception.SaveExtensionRepoException import yokai.domain.extension.repo.exception.SaveExtensionRepoException
import yokai.domain.extension.repo.model.ExtensionRepo import yokai.domain.extension.repo.model.ExtensionRepo
import yokai.domain.extension.repo.service.ExtensionRepoService import yokai.domain.extension.repo.service.ExtensionRepoService
@ -28,11 +27,7 @@ class CreateExtensionRepo(
} }
val baseUrl = repoUrl.removeSuffix("/index.min.json") val baseUrl = repoUrl.removeSuffix("/index.min.json")
return try { return extensionRepoService.fetchRepoDetails(baseUrl)?.let { insert(it) } ?: Result.InvalidUrl
extensionRepoService.fetchRepoDetails(baseUrl)?.let { insert(it) } ?: Result.InvalidUrl
} catch (e: FetchExtensionRepoException) {
Result.RepoFetchFailed
}
} }
private suspend fun insert(repo: ExtensionRepo): Result { private suspend fun insert(repo: ExtensionRepo): Result {
@ -79,7 +74,6 @@ class CreateExtensionRepo(
data class DuplicateFingerprint(val oldRepo: ExtensionRepo, val newRepo: ExtensionRepo) : Result data class DuplicateFingerprint(val oldRepo: ExtensionRepo, val newRepo: ExtensionRepo) : Result
data object InvalidUrl : Result data object InvalidUrl : Result
data object RepoAlreadyExists : Result data object RepoAlreadyExists : Result
data object RepoFetchFailed : Result
data object Success : Result data object Success : Result
data object Error : Result data object Error : Result
} }

View file

@ -1,12 +1,10 @@
package yokai.domain.extension.repo.interactor package yokai.domain.extension.repo.interactor
import co.touchlab.kermit.Logger
import eu.kanade.tachiyomi.network.NetworkHelper import eu.kanade.tachiyomi.network.NetworkHelper
import kotlinx.coroutines.async import kotlinx.coroutines.async
import kotlinx.coroutines.awaitAll import kotlinx.coroutines.awaitAll
import kotlinx.coroutines.coroutineScope import kotlinx.coroutines.coroutineScope
import yokai.domain.extension.repo.ExtensionRepoRepository import yokai.domain.extension.repo.ExtensionRepoRepository
import yokai.domain.extension.repo.exception.FetchExtensionRepoException
import yokai.domain.extension.repo.model.ExtensionRepo import yokai.domain.extension.repo.model.ExtensionRepo
import yokai.domain.extension.repo.service.ExtensionRepoService import yokai.domain.extension.repo.service.ExtensionRepoService
@ -23,18 +21,7 @@ class UpdateExtensionRepo(
} }
suspend fun await(repo: ExtensionRepo) { suspend fun await(repo: ExtensionRepo) {
val newRepo = try { val newRepo = extensionRepoService.fetchRepoDetails(repo.baseUrl) ?: return
extensionRepoService.fetchRepoDetails(repo.baseUrl) ?: return
} catch (e: Exception) {
when (e) {
is FetchExtensionRepoException -> {
// TODO: A way to show user that a repo failed to update
Logger.e(e) { "Failed to fetch repo details" }
return
}
else -> throw e
}
}
if ( if (
repo.signingKeyFingerprint.startsWith("NOFINGERPRINT") || repo.signingKeyFingerprint.startsWith("NOFINGERPRINT") ||
repo.signingKeyFingerprint == newRepo.signingKeyFingerprint repo.signingKeyFingerprint == newRepo.signingKeyFingerprint

View file

@ -1,20 +1,15 @@
package yokai.domain.extension.repo.service package yokai.domain.extension.repo.service
import androidx.core.net.toUri import androidx.core.net.toUri
import co.touchlab.kermit.Logger
import eu.kanade.tachiyomi.network.GET import eu.kanade.tachiyomi.network.GET
import eu.kanade.tachiyomi.network.HttpException
import eu.kanade.tachiyomi.network.awaitSuccess import eu.kanade.tachiyomi.network.awaitSuccess
import eu.kanade.tachiyomi.network.parseAs import eu.kanade.tachiyomi.network.parseAs
import eu.kanade.tachiyomi.util.system.withIOContext import eu.kanade.tachiyomi.util.system.withIOContext
import kotlinx.serialization.json.Json import kotlinx.serialization.json.Json
import kotlinx.serialization.json.JsonObject
import kotlinx.serialization.json.jsonObject
import kotlinx.serialization.json.jsonPrimitive
import okhttp3.OkHttpClient import okhttp3.OkHttpClient
import uy.kohesive.injekt.injectLazy import uy.kohesive.injekt.injectLazy
import yokai.domain.extension.repo.exception.FetchExtensionRepoException
import yokai.domain.extension.repo.model.ExtensionRepo import yokai.domain.extension.repo.model.ExtensionRepo
import java.net.UnknownHostException
class ExtensionRepoService( class ExtensionRepoService(
private val client: OkHttpClient, private val client: OkHttpClient,
@ -29,35 +24,16 @@ class ExtensionRepoService(
val url = "$repo/repo.json".toUri() val url = "$repo/repo.json".toUri()
try { try {
val response = with(json) { with(json) {
client.newCall(GET(url.toString())) client.newCall(GET(url.toString()))
.awaitSuccess() .awaitSuccess()
.parseAs<JsonObject>() .parseAs<ExtensionRepoMetaDto>()
.toExtensionRepo(baseUrl = repo)
} }
response["meta"]
?.jsonObject
?.let { jsonToExtensionRepo(baseUrl = repo, it) }
} catch (e: Exception) { } catch (e: Exception) {
when (e) { Logger.e(e) { "Failed to fetch repo details" }
is HttpException -> null null
is UnknownHostException -> throw FetchExtensionRepoException(e)
else -> throw e
}
} }
} }
} }
private fun jsonToExtensionRepo(baseUrl: String, obj: JsonObject): ExtensionRepo? {
return try {
ExtensionRepo(
baseUrl = baseUrl,
name = obj["name"]!!.jsonPrimitive.content,
shortName = obj["shortName"]?.jsonPrimitive?.content,
website = obj["website"]!!.jsonPrimitive.content,
signingKeyFingerprint = obj["signingKeyFingerprint"]!!.jsonPrimitive.content,
)
} catch (_: NullPointerException) {
null
}
}
} }

View file

@ -54,7 +54,6 @@ class ExtensionRepoViewModel :
is CreateExtensionRepo.Result.Success -> internalEvent.value = ExtensionRepoEvent.Success is CreateExtensionRepo.Result.Success -> internalEvent.value = ExtensionRepoEvent.Success
is CreateExtensionRepo.Result.Error -> internalEvent.value = ExtensionRepoEvent.InvalidUrl is CreateExtensionRepo.Result.Error -> internalEvent.value = ExtensionRepoEvent.InvalidUrl
is CreateExtensionRepo.Result.RepoAlreadyExists -> internalEvent.value = ExtensionRepoEvent.RepoAlreadyExists is CreateExtensionRepo.Result.RepoAlreadyExists -> internalEvent.value = ExtensionRepoEvent.RepoAlreadyExists
is CreateExtensionRepo.Result.RepoFetchFailed -> internalEvent.value = ExtensionRepoEvent.RepoFetchFailed
is CreateExtensionRepo.Result.DuplicateFingerprint -> { is CreateExtensionRepo.Result.DuplicateFingerprint -> {
internalEvent.value = ExtensionRepoEvent.ShowDialog(RepoDialog.Conflict(result.oldRepo, result.newRepo)) internalEvent.value = ExtensionRepoEvent.ShowDialog(RepoDialog.Conflict(result.oldRepo, result.newRepo))
} }
@ -94,7 +93,6 @@ sealed class ExtensionRepoEvent {
sealed class LocalizedMessage(val stringRes: StringResource) : ExtensionRepoEvent() sealed class LocalizedMessage(val stringRes: StringResource) : ExtensionRepoEvent()
data object InvalidUrl : LocalizedMessage(MR.strings.invalid_repo_url) data object InvalidUrl : LocalizedMessage(MR.strings.invalid_repo_url)
data object RepoAlreadyExists : LocalizedMessage(MR.strings.repo_already_exists) data object RepoAlreadyExists : LocalizedMessage(MR.strings.repo_already_exists)
data object RepoFetchFailed : LocalizedMessage(MR.strings.repo_fetch_failed)
data class ShowDialog(val dialog: RepoDialog) : ExtensionRepoEvent() data class ShowDialog(val dialog: RepoDialog) : ExtensionRepoEvent()
data object NoOp : ExtensionRepoEvent() data object NoOp : ExtensionRepoEvent()
data object Success : ExtensionRepoEvent() data object Success : ExtensionRepoEvent()

View file

@ -5,6 +5,7 @@ import java.util.Locale
import yokai.domain.manga.models.MangaUpdate import yokai.domain.manga.models.MangaUpdate
// TODO: Transform into data class // TODO: Transform into data class
@Deprecated("Use data class version", ReplaceWith("yokai.domain.manga.models.Manga"))
interface Manga : SManga { interface Manga : SManga {
var id: Long? var id: Long?

View file

@ -0,0 +1,27 @@
package yokai.domain.extension.repo.service
import kotlinx.serialization.Serializable
import yokai.domain.extension.repo.model.ExtensionRepo
@Serializable
data class ExtensionRepoMetaDto(
val meta: ExtensionRepoDto,
)
@Serializable
data class ExtensionRepoDto(
val name: String,
val shortName: String?,
val website: String,
val signingKeyFingerprint: String,
)
fun ExtensionRepoMetaDto.toExtensionRepo(baseUrl: String): ExtensionRepo {
return ExtensionRepo(
baseUrl = baseUrl,
name = meta.name,
shortName = meta.shortName,
website = meta.website,
signingKeyFingerprint = meta.signingKeyFingerprint,
)
}

View file

@ -883,7 +883,6 @@
<string name="action_add_repo">Add repo</string> <string name="action_add_repo">Add repo</string>
<string name="invalid_repo_url">Invalid repo url</string> <string name="invalid_repo_url">Invalid repo url</string>
<string name="repo_already_exists">Repo already exists!</string> <string name="repo_already_exists">Repo already exists!</string>
<string name="repo_fetch_failed">Failed to retrieve repo details. Please try again later</string>
<string name="information_empty_repos">You haven\'t added any repos yet.</string> <string name="information_empty_repos">You haven\'t added any repos yet.</string>
<string name="confirm_delete_repo_title">Delete repo?</string> <string name="confirm_delete_repo_title">Delete repo?</string>
<string name="confirm_delete_repo">Are you sure you wish to delete the repo \"%s\"?</string> <string name="confirm_delete_repo">Are you sure you wish to delete the repo \"%s\"?</string>