Merge branch 'main' into detekt

This commit is contained in:
Theodoro Mota 2024-01-28 15:56:18 -03:00
commit 082b9beeeb
67 changed files with 631 additions and 372 deletions

View File

@ -1,11 +1,5 @@
blank_issues_enabled: false
contact_links:
- name: ⚠️ Extension/source issue
url: https://github.com/tachiyomiorg/extensions/issues/new/choose
about: Issues and requests for official extensions and sources should be opened in the extensions repository instead
- name: 📦 Mihon extensions
url: https://mihon.app/extensions/
about: List of all available extensions with download links
- name: 🖥️ Mihon website
url: https://mihon.app/
about: Guides, troubleshooting, and answers to common questions

View File

@ -94,8 +94,6 @@ body:
required: true
- label: I have written a short but informative title.
required: true
- label: If this is an issue with an official extension, I should be opening an issue in the [extensions repository](https://github.com/tachiyomiorg/extensions/issues/new/choose).
required: true
- label: I have gone through the [FAQ](https://mihon.app/docs/faq/general) and [troubleshooting guide](https://mihon.app/docs/guides/troubleshooting/).
required: true
- label: I have updated the app to version **[0.16.1](https://github.com/mihonapp/mihon/releases/latest)**.

View File

@ -31,8 +31,6 @@ body:
required: true
- label: I have written a short but informative title.
required: true
- label: If this is an issue with an official extension, I should be opening an issue in the [extensions repository](https://github.com/tachiyomiorg/extensions/issues/new/choose).
required: true
- label: I have updated the app to version **[0.16.1](https://github.com/mihonapp/mihon/releases/latest)**.
required: true
- label: I will fill out all of the requested information in this form.

View File

@ -22,8 +22,8 @@ android {
defaultConfig {
applicationId = "app.mihon"
versionCode = 2
versionName = "0.16.1"
versionCode = 3
versionName = "0.16.2"
buildConfigField("String", "COMMIT_COUNT", "\"${getCommitCount()}\"")
buildConfigField("String", "COMMIT_SHA", "\"${getGitSha()}\"")

View File

@ -30,9 +30,9 @@ class RefreshTracks(
.map { (track, service) ->
async {
return@async try {
val updatedTrack = service!!.refresh(track.toDbTrack())
insertTrack.await(updatedTrack.toDomainTrack()!!)
syncChapterProgressWithTrack.await(mangaId, track, service)
val updatedTrack = service!!.refresh(track.toDbTrack()).toDomainTrack()!!
insertTrack.await(updatedTrack)
syncChapterProgressWithTrack.await(mangaId, updatedTrack, service)
null
} catch (e: Throwable) {
service to e

View File

@ -19,10 +19,10 @@ fun Track.toDbTrack(): DbTrack = DbTrack.create(trackerId).also {
it.remote_id = remoteId
it.library_id = libraryId
it.title = title
it.last_chapter_read = lastChapterRead.toFloat()
it.total_chapters = totalChapters.toInt()
it.status = status.toInt()
it.score = score.toFloat()
it.last_chapter_read = lastChapterRead
it.total_chapters = totalChapters
it.status = status
it.score = score
it.tracking_url = remoteUrl
it.started_reading_date = startDate
it.finished_reading_date = finishDate
@ -33,16 +33,14 @@ fun DbTrack.toDomainTrack(idRequired: Boolean = true): Track? {
return Track(
id = trackId,
mangaId = manga_id,
trackerId = tracker_id.toLong(),
trackerId = tracker_id,
remoteId = remote_id,
libraryId = library_id,
title = title,
lastChapterRead = last_chapter_read.toDouble(),
totalChapters = total_chapters.toLong(),
status = status.toLong(),
// Jank workaround due to precision issues while converting
// See https://github.com/tachiyomiorg/tachiyomi/issues/10343
score = score.toString().toDouble(),
lastChapterRead = last_chapter_read,
totalChapters = total_chapters,
status = status,
score = score,
remoteUrl = tracking_url,
startDate = started_reading_date,
finishDate = finished_reading_date,

View File

@ -19,9 +19,15 @@ class TrackPreferences(
"",
)
fun trackAuthExpired(tracker: Tracker) = preferenceStore.getBoolean(
Preference.privateKey("pref_tracker_auth_expired_${tracker.id}"),
false,
)
fun setCredentials(tracker: Tracker, username: String, password: String) {
trackUsername(tracker).set(username)
trackPassword(tracker).set(password)
trackAuthExpired(tracker).set(false)
}
fun trackToken(tracker: Tracker) = preferenceStore.getString(Preference.privateKey("track_token_${tracker.id}"), "")

View File

@ -97,5 +97,5 @@ fun AdaptiveSheet(
private val dialogProperties = DialogProperties(
usePlatformDefaultWidth = false,
decorFitsSystemWindows = false,
decorFitsSystemWindows = true,
)

View File

@ -42,7 +42,7 @@ internal fun ColumnScope.GeneralPage(screenModel: ReaderSettingsScreenModel) {
pref = screenModel.preferences.fullscreen(),
)
if (screenModel.hasDisplayCutout) {
if (screenModel.hasDisplayCutout && screenModel.preferences.fullscreen().get()) {
CheckboxItem(
label = stringResource(MR.strings.pref_cutout_short),
pref = screenModel.preferences.cutoutShort(),

View File

@ -88,7 +88,7 @@ fun TrackInfoDialogHome(
TrackInfoItem(
title = item.track.title,
tracker = item.tracker,
status = item.tracker.getStatus(item.track.status.toInt()),
status = item.tracker.getStatus(item.track.status),
onStatusClick = { onStatusClick(item) },
chapters = "${item.track.lastChapterRead.toInt()}".let {
val totalChapters = item.track.totalChapters

View File

@ -48,9 +48,9 @@ import tachiyomi.presentation.core.util.isScrolledToStart
@Composable
fun TrackStatusSelector(
selection: Int,
onSelectionChange: (Int) -> Unit,
selections: Map<Int, StringResource?>,
selection: Long,
onSelectionChange: (Long) -> Unit,
selections: Map<Long, StringResource?>,
onConfirm: () -> Unit,
onDismissRequest: () -> Unit,
) {
@ -236,12 +236,12 @@ private fun TrackStatusSelectorPreviews() {
onSelectionChange = {},
selections = persistentMapOf(
// Anilist values
1 to MR.strings.reading,
2 to MR.strings.plan_to_read,
3 to MR.strings.completed,
4 to MR.strings.on_hold,
5 to MR.strings.dropped,
6 to MR.strings.repeating,
1L to MR.strings.reading,
2L to MR.strings.plan_to_read,
3L to MR.strings.completed,
4L to MR.strings.on_hold,
5L to MR.strings.dropped,
6L to MR.strings.repeating,
),
onConfirm = {},
onDismissRequest = {},

View File

@ -301,7 +301,7 @@ private fun SearchResultItem(
text = status,
)
}
if (trackSearch.score != -1f) {
if (trackSearch.score != -1.0) {
SearchResultItemDetails(
title = stringResource(MR.strings.score),
text = trackSearch.score.toString(),

View File

@ -62,14 +62,14 @@ internal class TrackerSearchPreviewProvider : PreviewParameterProvider<@Composab
private fun randTrackSearch() = TrackSearch().let {
it.id = Random.nextLong()
it.manga_id = Random.nextLong()
it.tracker_id = Random.nextInt()
it.tracker_id = Random.nextLong()
it.remote_id = Random.nextLong()
it.library_id = Random.nextLong()
it.title = lorem((1..10).random()).joinToString()
it.last_chapter_read = (0..100).random().toFloat()
it.total_chapters = (100..1000).random()
it.score = (0..10).random().toFloat()
it.status = Random.nextInt()
it.last_chapter_read = (0..100).random().toDouble()
it.total_chapters = (100L..1000L).random()
it.score = (0..10).random().toDouble()
it.status = Random.nextLong()
it.started_reading_date = 0L
it.finished_reading_date = 0L
it.tracking_url = "https://example.com/tracker-example"

View File

@ -8,7 +8,7 @@ interface Track : Serializable {
var manga_id: Long
var tracker_id: Int
var tracker_id: Long
var remote_id: Long
@ -16,13 +16,13 @@ interface Track : Serializable {
var title: String
var last_chapter_read: Float
var last_chapter_read: Double
var total_chapters: Int
var total_chapters: Long
var score: Float
var score: Double
var status: Int
var status: Long
var started_reading_date: Long
@ -40,7 +40,7 @@ interface Track : Serializable {
companion object {
fun create(serviceId: Long): Track = TrackImpl().apply {
tracker_id = serviceId.toInt()
tracker_id = serviceId
}
}
}

View File

@ -6,7 +6,7 @@ class TrackImpl : Track {
override var manga_id: Long = 0
override var tracker_id: Int = 0
override var tracker_id: Long = 0
override var remote_id: Long = 0
@ -14,13 +14,13 @@ class TrackImpl : Track {
override lateinit var title: String
override var last_chapter_read: Float = 0F
override var last_chapter_read: Double = 0.0
override var total_chapters: Int = 0
override var total_chapters: Long = 0
override var score: Float = 0f
override var score: Double = 0.0
override var status: Int = 0
override var status: Long = 0
override var started_reading_date: Long = 0

View File

@ -384,7 +384,7 @@ class LibraryUpdateJob(private val context: Context, workerParams: WorkerParamet
private fun writeErrorFile(errors: List<Pair<Manga, String?>>): File {
try {
if (errors.isNotEmpty()) {
val file = context.createFileInCacheDir("tachiyomi_update_errors.txt")
val file = context.createFileInCacheDir("mihon_update_errors.txt")
file.bufferedWriter().use { out ->
out.write(context.stringResource(MR.strings.library_errors_help, ERROR_LOG_HELP_URL) + "\n\n")
// Error file format:

View File

@ -40,8 +40,8 @@ abstract class BaseTracker(
return track.score
}
override fun indexToScore(index: Int): Float {
return index.toFloat()
override fun indexToScore(index: Int): Double {
return index.toDouble()
}
@CallSuper
@ -70,24 +70,24 @@ abstract class BaseTracker(
}
}
override suspend fun setRemoteStatus(track: Track, status: Int) {
override suspend fun setRemoteStatus(track: Track, status: Long) {
track.status = status
if (track.status == getCompletionStatus() && track.total_chapters != 0) {
track.last_chapter_read = track.total_chapters.toFloat()
if (track.status == getCompletionStatus() && track.total_chapters != 0L) {
track.last_chapter_read = track.total_chapters.toDouble()
}
updateRemote(track)
}
override suspend fun setRemoteLastChapterRead(track: Track, chapterNumber: Int) {
if (
track.last_chapter_read == 0f &&
track.last_chapter_read == 0.0 &&
track.last_chapter_read < chapterNumber &&
track.status != getRereadingStatus()
) {
track.status = getReadingStatus()
}
track.last_chapter_read = chapterNumber.toFloat()
if (track.total_chapters != 0 && track.last_chapter_read.toInt() == track.total_chapters) {
track.last_chapter_read = chapterNumber.toDouble()
if (track.total_chapters != 0L && track.last_chapter_read.toLong() == track.total_chapters) {
track.status = getCompletionStatus()
track.finished_reading_date = System.currentTimeMillis()
}

View File

@ -27,22 +27,22 @@ interface Tracker {
@DrawableRes
fun getLogo(): Int
fun getStatusList(): List<Int>
fun getStatusList(): List<Long>
fun getStatus(status: Int): StringResource?
fun getStatus(status: Long): StringResource?
fun getReadingStatus(): Int
fun getReadingStatus(): Long
fun getRereadingStatus(): Int
fun getRereadingStatus(): Long
fun getCompletionStatus(): Int
fun getCompletionStatus(): Long
fun getScoreList(): ImmutableList<String>
// TODO: Store all scores as 10 point in the future maybe?
fun get10PointScore(track: DomainTrack): Double
fun indexToScore(index: Int): Float
fun indexToScore(index: Int): Double
fun displayScore(track: DomainTrack): String
@ -70,7 +70,7 @@ interface Tracker {
// TODO: move this to an interactor, and update all trackers based on common data
suspend fun register(item: Track, mangaId: Long)
suspend fun setRemoteStatus(track: Track, status: Int)
suspend fun setRemoteStatus(track: Track, status: Long)
suspend fun setRemoteLastChapterRead(track: Track, chapterNumber: Int)

View File

@ -20,12 +20,12 @@ import tachiyomi.domain.track.model.Track as DomainTrack
class Anilist(id: Long) : BaseTracker(id, "AniList"), DeletableTracker {
companion object {
const val READING = 1
const val COMPLETED = 2
const val ON_HOLD = 3
const val DROPPED = 4
const val PLAN_TO_READ = 5
const val REREADING = 6
const val READING = 1L
const val COMPLETED = 2L
const val ON_HOLD = 3L
const val DROPPED = 4L
const val PLAN_TO_READ = 5L
const val REREADING = 6L
const val POINT_100 = "POINT_100"
const val POINT_10 = "POINT_10"
@ -58,11 +58,11 @@ class Anilist(id: Long) : BaseTracker(id, "AniList"), DeletableTracker {
override fun getLogoColor() = Color.rgb(18, 25, 35)
override fun getStatusList(): List<Int> {
override fun getStatusList(): List<Long> {
return listOf(READING, COMPLETED, ON_HOLD, DROPPED, PLAN_TO_READ, REREADING)
}
override fun getStatus(status: Int): StringResource? = when (status) {
override fun getStatus(status: Long): StringResource? = when (status) {
READING -> MR.strings.reading
PLAN_TO_READ -> MR.strings.plan_to_read
COMPLETED -> MR.strings.completed
@ -72,11 +72,11 @@ class Anilist(id: Long) : BaseTracker(id, "AniList"), DeletableTracker {
else -> null
}
override fun getReadingStatus(): Int = READING
override fun getReadingStatus(): Long = READING
override fun getRereadingStatus(): Int = REREADING
override fun getRereadingStatus(): Long = REREADING
override fun getCompletionStatus(): Int = COMPLETED
override fun getCompletionStatus(): Long = COMPLETED
override fun getScoreList(): ImmutableList<String> {
return when (scorePreference.get()) {
@ -99,24 +99,24 @@ class Anilist(id: Long) : BaseTracker(id, "AniList"), DeletableTracker {
return track.score / 10.0
}
override fun indexToScore(index: Int): Float {
override fun indexToScore(index: Int): Double {
return when (scorePreference.get()) {
// 10 point
POINT_10 -> index * 10f
POINT_10 -> index * 10.0
// 100 point
POINT_100 -> index.toFloat()
POINT_100 -> index.toDouble()
// 5 stars
POINT_5 -> when (index) {
0 -> 0f
else -> index * 20f - 10f
0 -> 0.0
else -> index * 20.0 - 10.0
}
// Smiley
POINT_3 -> when (index) {
0 -> 0f
else -> index * 25f + 10f
0 -> 0.0
else -> index * 25.0 + 10.0
}
// 10 point decimal
POINT_10_DECIMAL -> index.toFloat()
POINT_10_DECIMAL -> index.toDouble()
else -> throw Exception("Unknown score type")
}
}
@ -153,12 +153,12 @@ class Anilist(id: Long) : BaseTracker(id, "AniList"), DeletableTracker {
if (track.status != COMPLETED) {
if (didReadChapter) {
if (track.last_chapter_read.toInt() == track.total_chapters && track.total_chapters > 0) {
if (track.last_chapter_read.toLong() == track.total_chapters && track.total_chapters > 0) {
track.status = COMPLETED
track.finished_reading_date = System.currentTimeMillis()
} else if (track.status != REREADING) {
track.status = READING
if (track.last_chapter_read == 1F) {
if (track.last_chapter_read == 1.0) {
track.started_reading_date = System.currentTimeMillis()
}
}
@ -192,7 +192,7 @@ class Anilist(id: Long) : BaseTracker(id, "AniList"), DeletableTracker {
} else {
// Set default fields if it's not found in the list
track.status = if (hasReadChapters) READING else PLAN_TO_READ
track.score = 0F
track.score = 0.0
add(track)
}
}

View File

@ -20,6 +20,7 @@ import kotlinx.serialization.json.jsonArray
import kotlinx.serialization.json.jsonObject
import kotlinx.serialization.json.jsonPrimitive
import kotlinx.serialization.json.long
import kotlinx.serialization.json.longOrNull
import kotlinx.serialization.json.put
import kotlinx.serialization.json.putJsonObject
import okhttp3.OkHttpClient
@ -312,7 +313,7 @@ class AnilistApi(val client: OkHttpClient, interceptor: AnilistInterceptor) {
struct["format"]!!.jsonPrimitive.content.replace("_", "-"),
struct["status"]!!.jsonPrimitive.contentOrNull ?: "",
parseDate(struct, "startDate"),
struct["chapters"]!!.jsonPrimitive.intOrNull ?: 0,
struct["chapters"]!!.jsonPrimitive.longOrNull ?: 0,
struct["averageScore"]?.jsonPrimitive?.intOrNull ?: -1,
)
}

View File

@ -19,7 +19,7 @@ data class ALManga(
val format: String,
val publishing_status: String,
val start_date_fuzzy: Long,
val total_chapters: Int,
val total_chapters: Long,
val average_score: Int,
) {
@ -29,7 +29,7 @@ data class ALManga(
total_chapters = this@ALManga.total_chapters
cover_url = image_url_lge
summary = description?.htmlDecode() ?: ""
score = average_score.toFloat()
score = average_score.toDouble()
tracking_url = AnilistApi.mangaUrl(remote_id)
publishing_status = this@ALManga.publishing_status
publishing_type = format
@ -58,10 +58,10 @@ data class ALUserManga(
remote_id = manga.remote_id
title = manga.title_user_pref
status = toTrackStatus()
score = score_raw.toFloat()
score = score_raw.toDouble()
started_reading_date = start_date_fuzzy
finished_reading_date = completed_date_fuzzy
last_chapter_read = chapters_read.toFloat()
last_chapter_read = chapters_read.toDouble()
library_id = this@ALUserManga.library_id
total_chapters = manga.total_chapters
}

View File

@ -35,7 +35,7 @@ class Bangumi(id: Long) : BaseTracker(id, "Bangumi") {
override suspend fun update(track: Track, didReadChapter: Boolean): Track {
if (track.status != COMPLETED) {
if (didReadChapter) {
if (track.last_chapter_read.toInt() == track.total_chapters && track.total_chapters > 0) {
if (track.last_chapter_read.toLong() == track.total_chapters && track.total_chapters > 0) {
track.status = COMPLETED
} else {
track.status = READING
@ -64,7 +64,7 @@ class Bangumi(id: Long) : BaseTracker(id, "Bangumi") {
} else {
// Set default fields if it's not found in the list
track.status = if (hasReadChapters) READING else PLAN_TO_READ
track.score = 0F
track.score = 0.0
add(track)
update(track)
}
@ -87,11 +87,11 @@ class Bangumi(id: Long) : BaseTracker(id, "Bangumi") {
override fun getLogoColor() = Color.rgb(240, 145, 153)
override fun getStatusList(): List<Int> {
override fun getStatusList(): List<Long> {
return listOf(READING, COMPLETED, ON_HOLD, DROPPED, PLAN_TO_READ)
}
override fun getStatus(status: Int): StringResource? = when (status) {
override fun getStatus(status: Long): StringResource? = when (status) {
READING -> MR.strings.reading
PLAN_TO_READ -> MR.strings.plan_to_read
COMPLETED -> MR.strings.completed
@ -100,11 +100,11 @@ class Bangumi(id: Long) : BaseTracker(id, "Bangumi") {
else -> null
}
override fun getReadingStatus(): Int = READING
override fun getReadingStatus(): Long = READING
override fun getRereadingStatus(): Int = -1
override fun getRereadingStatus(): Long = -1
override fun getCompletionStatus(): Int = COMPLETED
override fun getCompletionStatus(): Long = COMPLETED
override suspend fun login(username: String, password: String) = login(password)
@ -137,11 +137,11 @@ class Bangumi(id: Long) : BaseTracker(id, "Bangumi") {
}
companion object {
const val READING = 3
const val COMPLETED = 2
const val ON_HOLD = 4
const val DROPPED = 5
const val PLAN_TO_READ = 1
const val READING = 3L
const val COMPLETED = 2L
const val ON_HOLD = 4L
const val DROPPED = 5L
const val PLAN_TO_READ = 1L
private val SCORE_LIST = IntRange(0, 10)
.map(Int::toString)

View File

@ -11,7 +11,7 @@ import eu.kanade.tachiyomi.network.parseAs
import kotlinx.serialization.json.Json
import kotlinx.serialization.json.JsonObject
import kotlinx.serialization.json.contentOrNull
import kotlinx.serialization.json.floatOrNull
import kotlinx.serialization.json.doubleOrNull
import kotlinx.serialization.json.int
import kotlinx.serialization.json.jsonArray
import kotlinx.serialization.json.jsonObject
@ -105,11 +105,11 @@ class BangumiApi(
""
}
val totalChapters = if (obj["eps_count"] != null) {
obj["eps_count"]!!.jsonPrimitive.int
obj["eps_count"]!!.jsonPrimitive.long
} else {
0
}
val rating = obj["rating"]?.jsonObject?.get("score")?.jsonPrimitive?.floatOrNull ?: -1f
val rating = obj["rating"]?.jsonObject?.get("score")?.jsonPrimitive?.doubleOrNull ?: -1.0
return TrackSearch.create(trackId).apply {
remote_id = obj["id"]!!.jsonPrimitive.long
title = obj["name_cn"]!!.jsonPrimitive.content
@ -152,7 +152,7 @@ class BangumiApi(
} else {
json.decodeFromString<Collection>(responseBody).let {
track.status = it.status?.id!!
track.last_chapter_read = it.ep_status!!.toFloat()
track.last_chapter_read = it.ep_status!!.toDouble()
track.score = it.rating!!
track
}

View File

@ -16,7 +16,7 @@ data class Collection(
val comment: String? = "",
val ep_status: Int? = 0,
val lasttouch: Int? = 0,
val rating: Float? = 0f,
val rating: Double? = 0.0,
val status: Status? = Status(),
val tag: List<String?>? = emptyList(),
val user: User? = User(),
@ -25,7 +25,7 @@ data class Collection(
@Serializable
data class Status(
val id: Int? = 0,
val id: Long? = 0,
val name: String? = "",
val type: String? = "",
)

View File

@ -22,9 +22,9 @@ import tachiyomi.domain.track.model.Track as DomainTrack
class Kavita(id: Long) : BaseTracker(id, "Kavita"), EnhancedTracker {
companion object {
const val UNREAD = 1
const val READING = 2
const val COMPLETED = 3
const val UNREAD = 1L
const val READING = 2L
const val COMPLETED = 3L
}
var authentications: OAuth? = null
@ -38,20 +38,20 @@ class Kavita(id: Long) : BaseTracker(id, "Kavita"), EnhancedTracker {
override fun getLogoColor() = Color.rgb(74, 198, 148)
override fun getStatusList() = listOf(UNREAD, READING, COMPLETED)
override fun getStatusList(): List<Long> = listOf(UNREAD, READING, COMPLETED)
override fun getStatus(status: Int): StringResource? = when (status) {
override fun getStatus(status: Long): StringResource? = when (status) {
UNREAD -> MR.strings.unread
READING -> MR.strings.reading
COMPLETED -> MR.strings.completed
else -> null
}
override fun getReadingStatus(): Int = READING
override fun getReadingStatus(): Long = READING
override fun getRereadingStatus(): Int = -1
override fun getRereadingStatus(): Long = -1
override fun getCompletionStatus(): Int = COMPLETED
override fun getCompletionStatus(): Long = COMPLETED
override fun getScoreList(): ImmutableList<String> = persistentListOf()
@ -60,7 +60,7 @@ class Kavita(id: Long) : BaseTracker(id, "Kavita"), EnhancedTracker {
override suspend fun update(track: Track, didReadChapter: Boolean): Track {
if (track.status != COMPLETED) {
if (didReadChapter) {
if (track.last_chapter_read.toInt() == track.total_chapters && track.total_chapters > 0) {
if (track.last_chapter_read.toLong() == track.total_chapters && track.total_chapters > 0) {
track.status = COMPLETED
} else {
track.status = READING

View File

@ -93,7 +93,7 @@ class KavitaApi(private val client: OkHttpClient, interceptor: KavitaInterceptor
* Ignores volumes.
* Volumes consisting of 1 file treated as chapter
*/
private fun getTotalChapters(url: String): Int {
private fun getTotalChapters(url: String): Long {
val requestUrl = getApiVolumesUrl(url)
try {
val listVolumeDto = with(json) {
@ -101,13 +101,13 @@ class KavitaApi(private val client: OkHttpClient, interceptor: KavitaInterceptor
.execute()
.parseAs<List<VolumeDto>>()
}
var volumeNumber = 0
var maxChapterNumber = 0
var volumeNumber = 0L
var maxChapterNumber = 0L
for (volume in listVolumeDto) {
if (volume.chapters.maxOf { it.number!!.toFloat() } == 0f) {
volumeNumber++
} else if (maxChapterNumber < volume.chapters.maxOf { it.number!!.toFloat() }) {
maxChapterNumber = volume.chapters.maxOf { it.number!!.toFloat().toInt() }
maxChapterNumber = volume.chapters.maxOf { it.number!!.toFloat().toLong() }
}
}
@ -118,17 +118,17 @@ class KavitaApi(private val client: OkHttpClient, interceptor: KavitaInterceptor
}
}
private fun getLatestChapterRead(url: String): Float {
private fun getLatestChapterRead(url: String): Double {
val seriesId = getIdFromUrl(url)
val requestUrl = "${getApiFromUrl(url)}/Tachiyomi/latest-chapter?seriesId=$seriesId"
try {
with(json) {
authClient.newCall(GET(requestUrl)).execute().use {
if (it.code == 200) {
return it.parseAs<ChapterDto>().number!!.replace(",", ".").toFloat()
return it.parseAs<ChapterDto>().number!!.replace(",", ".").toDouble()
}
if (it.code == 204) {
return 0F
return 0.0
}
}
}
@ -139,7 +139,7 @@ class KavitaApi(private val client: OkHttpClient, interceptor: KavitaInterceptor
) { "Exception getting latest chapter read. Could not get itemRequest: $requestUrl" }
throw e
}
return 0F
return 0.0
}
suspend fun getTrackSearch(url: String): TrackSearch = withIOContext {

View File

@ -19,11 +19,11 @@ import tachiyomi.domain.track.model.Track as DomainTrack
class Kitsu(id: Long) : BaseTracker(id, "Kitsu"), DeletableTracker {
companion object {
const val READING = 1
const val COMPLETED = 2
const val ON_HOLD = 3
const val DROPPED = 4
const val PLAN_TO_READ = 5
const val READING = 1L
const val COMPLETED = 2L
const val ON_HOLD = 3L
const val DROPPED = 4L
const val PLAN_TO_READ = 5L
}
override val supportsReadingDates: Boolean = true
@ -38,11 +38,11 @@ class Kitsu(id: Long) : BaseTracker(id, "Kitsu"), DeletableTracker {
override fun getLogoColor() = Color.rgb(51, 37, 50)
override fun getStatusList(): List<Int> {
override fun getStatusList(): List<Long> {
return listOf(READING, COMPLETED, ON_HOLD, DROPPED, PLAN_TO_READ)
}
override fun getStatus(status: Int): StringResource? = when (status) {
override fun getStatus(status: Long): StringResource? = when (status) {
READING -> MR.strings.reading
PLAN_TO_READ -> MR.strings.plan_to_read
COMPLETED -> MR.strings.completed
@ -51,19 +51,19 @@ class Kitsu(id: Long) : BaseTracker(id, "Kitsu"), DeletableTracker {
else -> null
}
override fun getReadingStatus(): Int = READING
override fun getReadingStatus(): Long = READING
override fun getRereadingStatus(): Int = -1
override fun getRereadingStatus(): Long = -1
override fun getCompletionStatus(): Int = COMPLETED
override fun getCompletionStatus(): Long = COMPLETED
override fun getScoreList(): ImmutableList<String> {
val df = DecimalFormat("0.#")
return (listOf("0") + IntRange(2, 20).map { df.format(it / 2f) }).toImmutableList()
}
override fun indexToScore(index: Int): Float {
return if (index > 0) (index + 1) / 2f else 0f
override fun indexToScore(index: Int): Double {
return if (index > 0) (index + 1) / 2.0 else 0.0
}
override fun displayScore(track: DomainTrack): String {
@ -78,12 +78,12 @@ class Kitsu(id: Long) : BaseTracker(id, "Kitsu"), DeletableTracker {
override suspend fun update(track: Track, didReadChapter: Boolean): Track {
if (track.status != COMPLETED) {
if (didReadChapter) {
if (track.last_chapter_read.toInt() == track.total_chapters && track.total_chapters > 0) {
if (track.last_chapter_read.toLong() == track.total_chapters && track.total_chapters > 0) {
track.status = COMPLETED
track.finished_reading_date = System.currentTimeMillis()
} else {
track.status = READING
if (track.last_chapter_read == 1F) {
if (track.last_chapter_read == 1.0) {
track.started_reading_date = System.currentTimeMillis()
}
}
@ -110,7 +110,7 @@ class Kitsu(id: Long) : BaseTracker(id, "Kitsu"), DeletableTracker {
update(track)
} else {
track.status = if (hasReadChapters) READING else PLAN_TO_READ
track.score = 0F
track.score = 0.0
add(track)
}
}

View File

@ -8,10 +8,10 @@ import kotlinx.serialization.Serializable
import kotlinx.serialization.json.JsonObject
import kotlinx.serialization.json.contentOrNull
import kotlinx.serialization.json.int
import kotlinx.serialization.json.intOrNull
import kotlinx.serialization.json.jsonObject
import kotlinx.serialization.json.jsonPrimitive
import kotlinx.serialization.json.long
import kotlinx.serialization.json.longOrNull
import java.text.SimpleDateFormat
import java.util.Date
import java.util.Locale
@ -19,7 +19,7 @@ import java.util.Locale
class KitsuSearchManga(obj: JsonObject) {
val id = obj["id"]!!.jsonPrimitive.long
private val canonicalTitle = obj["canonicalTitle"]!!.jsonPrimitive.content
private val chapterCount = obj["chapterCount"]?.jsonPrimitive?.intOrNull
private val chapterCount = obj["chapterCount"]?.jsonPrimitive?.longOrNull
val subType = obj["subtype"]?.jsonPrimitive?.contentOrNull
val original = try {
obj["posterImage"]?.jsonObject?.get("original")?.jsonPrimitive?.content
@ -28,7 +28,7 @@ class KitsuSearchManga(obj: JsonObject) {
null
}
private val synopsis = obj["synopsis"]?.jsonPrimitive?.contentOrNull
private val rating = obj["averageRating"]?.jsonPrimitive?.contentOrNull?.toFloatOrNull()
private val rating = obj["averageRating"]?.jsonPrimitive?.contentOrNull?.toDoubleOrNull()
private var startDate = obj["startDate"]?.jsonPrimitive?.contentOrNull?.let {
val outputDf = SimpleDateFormat("yyyy-MM-dd", Locale.US)
outputDf.format(Date(it.toLong() * 1000))
@ -43,7 +43,7 @@ class KitsuSearchManga(obj: JsonObject) {
cover_url = original ?: ""
summary = synopsis ?: ""
tracking_url = KitsuApi.mangaUrl(remote_id)
score = rating ?: -1f
score = rating ?: -1.0
publishing_status = if (endDate == null) {
"Publishing"
} else {
@ -57,7 +57,7 @@ class KitsuSearchManga(obj: JsonObject) {
class KitsuLibManga(obj: JsonObject, manga: JsonObject) {
val id = manga["id"]!!.jsonPrimitive.int
private val canonicalTitle = manga["attributes"]!!.jsonObject["canonicalTitle"]!!.jsonPrimitive.content
private val chapterCount = manga["attributes"]!!.jsonObject["chapterCount"]?.jsonPrimitive?.intOrNull
private val chapterCount = manga["attributes"]!!.jsonObject["chapterCount"]?.jsonPrimitive?.longOrNull
val type = manga["attributes"]!!.jsonObject["mangaType"]?.jsonPrimitive?.contentOrNull.orEmpty()
val original = manga["attributes"]!!.jsonObject["posterImage"]!!.jsonObject["original"]!!.jsonPrimitive.content
private val synopsis = manga["attributes"]!!.jsonObject["synopsis"]!!.jsonPrimitive.content
@ -82,8 +82,8 @@ class KitsuLibManga(obj: JsonObject, manga: JsonObject) {
started_reading_date = KitsuDateHelper.parse(startedAt)
finished_reading_date = KitsuDateHelper.parse(finishedAt)
status = toTrackStatus()
score = ratingTwenty?.let { it.toInt() / 2f } ?: 0f
last_chapter_read = progress.toFloat()
score = ratingTwenty?.let { it.toInt() / 2.0 } ?: 0.0
last_chapter_read = progress.toDouble()
}
private fun toTrackStatus() = when (status) {

View File

@ -19,9 +19,9 @@ import tachiyomi.domain.track.model.Track as DomainTrack
class Komga(id: Long) : BaseTracker(id, "Komga"), EnhancedTracker {
companion object {
const val UNREAD = 1
const val READING = 2
const val COMPLETED = 3
const val UNREAD = 1L
const val READING = 2L
const val COMPLETED = 3L
}
override val client: OkHttpClient =
@ -35,20 +35,20 @@ class Komga(id: Long) : BaseTracker(id, "Komga"), EnhancedTracker {
override fun getLogoColor() = Color.rgb(51, 37, 50)
override fun getStatusList() = listOf(UNREAD, READING, COMPLETED)
override fun getStatusList(): List<Long> = listOf(UNREAD, READING, COMPLETED)
override fun getStatus(status: Int): StringResource? = when (status) {
override fun getStatus(status: Long): StringResource? = when (status) {
UNREAD -> MR.strings.unread
READING -> MR.strings.reading
COMPLETED -> MR.strings.completed
else -> null
}
override fun getReadingStatus(): Int = READING
override fun getReadingStatus(): Long = READING
override fun getRereadingStatus(): Int = -1
override fun getRereadingStatus(): Long = -1
override fun getCompletionStatus(): Int = COMPLETED
override fun getCompletionStatus(): Long = COMPLETED
override fun getScoreList(): ImmutableList<String> = persistentListOf()
@ -57,7 +57,7 @@ class Komga(id: Long) : BaseTracker(id, "Komga"), EnhancedTracker {
override suspend fun update(track: Track, didReadChapter: Boolean): Track {
if (track.status != COMPLETED) {
if (didReadChapter) {
if (track.last_chapter_read.toInt() == track.total_chapters && track.total_chapters > 0) {
if (track.last_chapter_read.toLong() == track.total_chapters && track.total_chapters > 0) {
track.status = COMPLETED
} else {
track.status = READING

View File

@ -67,7 +67,7 @@ class KomgaApi(
track.apply {
cover_url = "$url/thumbnail"
tracking_url = url
total_chapters = progress.maxNumberSort.toInt()
total_chapters = progress.maxNumberSort.toLong()
status = when (progress.booksCount) {
progress.booksUnreadCount -> Komga.UNREAD
progress.booksReadCount -> Komga.COMPLETED

View File

@ -65,7 +65,7 @@ data class ReadProgressUpdateDto(
@Serializable
data class ReadProgressUpdateV2Dto(
val lastBookNumberSortRead: Float,
val lastBookNumberSortRead: Double,
)
@Serializable
@ -91,7 +91,7 @@ data class ReadProgressDto(
booksReadCount,
booksUnreadCount,
booksInProgressCount,
lastReadContinuousIndex.toFloat(),
lastReadContinuousIndex.toDouble(),
booksCount.toFloat(),
)
}
@ -102,6 +102,6 @@ data class ReadProgressV2Dto(
val booksReadCount: Int,
val booksUnreadCount: Int,
val booksInProgressCount: Int,
val lastReadContinuousNumberSort: Float,
val lastReadContinuousNumberSort: Double,
val maxNumberSort: Float,
)

View File

@ -19,11 +19,11 @@ import tachiyomi.domain.track.model.Track as DomainTrack
class MangaUpdates(id: Long) : BaseTracker(id, "MangaUpdates"), DeletableTracker {
companion object {
const val READING_LIST = 0
const val WISH_LIST = 1
const val COMPLETE_LIST = 2
const val UNFINISHED_LIST = 3
const val ON_HOLD_LIST = 4
const val READING_LIST = 0L
const val WISH_LIST = 1L
const val COMPLETE_LIST = 2L
const val UNFINISHED_LIST = 3L
const val ON_HOLD_LIST = 4L
private val SCORE_LIST = (0..10)
.flatMap { decimal ->
@ -46,11 +46,11 @@ class MangaUpdates(id: Long) : BaseTracker(id, "MangaUpdates"), DeletableTracker
override fun getLogoColor(): Int = Color.rgb(146, 160, 173)
override fun getStatusList(): List<Int> {
override fun getStatusList(): List<Long> {
return listOf(READING_LIST, COMPLETE_LIST, ON_HOLD_LIST, UNFINISHED_LIST, WISH_LIST)
}
override fun getStatus(status: Int): StringResource? = when (status) {
override fun getStatus(status: Long): StringResource? = when (status) {
READING_LIST -> MR.strings.reading_list
WISH_LIST -> MR.strings.wish_list
COMPLETE_LIST -> MR.strings.complete_list
@ -59,15 +59,15 @@ class MangaUpdates(id: Long) : BaseTracker(id, "MangaUpdates"), DeletableTracker
else -> null
}
override fun getReadingStatus(): Int = READING_LIST
override fun getReadingStatus(): Long = READING_LIST
override fun getRereadingStatus(): Int = -1
override fun getRereadingStatus(): Long = -1
override fun getCompletionStatus(): Int = COMPLETE_LIST
override fun getCompletionStatus(): Long = COMPLETE_LIST
override fun getScoreList(): ImmutableList<String> = SCORE_LIST
override fun indexToScore(index: Int): Float = if (index == 0) 0f else SCORE_LIST[index].toFloat()
override fun indexToScore(index: Int): Double = if (index == 0) 0.0 else SCORE_LIST[index].toDouble()
override fun displayScore(track: DomainTrack): String = track.score.toString()
@ -88,7 +88,7 @@ class MangaUpdates(id: Long) : BaseTracker(id, "MangaUpdates"), DeletableTracker
val (series, rating) = api.getSeriesListItem(track)
track.copyFrom(series, rating)
} catch (e: Exception) {
track.score = 0f
track.score = 0.0
api.addSeriesToList(track, hasReadChapters)
track
}
@ -108,7 +108,7 @@ class MangaUpdates(id: Long) : BaseTracker(id, "MangaUpdates"), DeletableTracker
private fun Track.copyFrom(item: ListItem, rating: Rating?): Track = apply {
item.copyTo(this)
score = rating?.rating ?: 0f
score = rating?.rating ?: 0.0
}
override suspend fun login(username: String, password: String) {

View File

@ -79,7 +79,7 @@ class MangaUpdatesApi(
.let {
if (it.code == 200) {
track.status = status
track.last_chapter_read = 1f
track.last_chapter_read = 1.0
}
}
}
@ -133,7 +133,8 @@ class MangaUpdatesApi(
}
private suspend fun updateSeriesRating(track: Track) {
if (track.score != 0f) {
if (track.score < 0.0) return
if (track.score != 0.0) {
val body = buildJsonObject {
put("rating", track.score)
}

View File

@ -9,7 +9,7 @@ import kotlinx.serialization.Serializable
data class ListItem(
val series: Series? = null,
@SerialName("list_id")
val listId: Int? = null,
val listId: Long? = null,
val status: Status? = null,
val priority: Int? = null,
)
@ -17,6 +17,6 @@ data class ListItem(
fun ListItem.copyTo(track: Track): Track {
return track.apply {
this.status = listId ?: READING_LIST
this.last_chapter_read = this@copyTo.status?.chapter?.toFloat() ?: 0f
this.last_chapter_read = this@copyTo.status?.chapter?.toDouble() ?: 0.0
}
}

View File

@ -5,11 +5,11 @@ import kotlinx.serialization.Serializable
@Serializable
data class Rating(
val rating: Float? = null,
val rating: Double? = null,
)
fun Rating.copyTo(track: Track): Track {
return track.apply {
this.score = rating ?: 0f
this.score = rating ?: 0.0
}
}

View File

@ -8,7 +8,7 @@ class TrackSearch : Track {
override var manga_id: Long = 0
override var tracker_id: Int = 0
override var tracker_id: Long = 0
override var remote_id: Long = 0
@ -16,13 +16,13 @@ class TrackSearch : Track {
override lateinit var title: String
override var last_chapter_read: Float = 0F
override var last_chapter_read: Double = 0.0
override var total_chapters: Int = 0
override var total_chapters: Long = 0
override var score: Float = -1f
override var score: Double = -1.0
override var status: Int = 0
override var status: Long = 0
override var started_reading_date: Long = 0
@ -55,14 +55,14 @@ class TrackSearch : Track {
override fun hashCode(): Int {
var result = manga_id.hashCode()
result = 31 * result + tracker_id
result = 31 * result + tracker_id.hashCode()
result = 31 * result + remote_id.hashCode()
return result
}
companion object {
fun create(serviceId: Long): TrackSearch = TrackSearch().apply {
tracker_id = serviceId.toInt()
tracker_id = serviceId
}
}
}

View File

@ -18,12 +18,12 @@ import tachiyomi.domain.track.model.Track as DomainTrack
class MyAnimeList(id: Long) : BaseTracker(id, "MyAnimeList"), DeletableTracker {
companion object {
const val READING = 1
const val COMPLETED = 2
const val ON_HOLD = 3
const val DROPPED = 4
const val PLAN_TO_READ = 6
const val REREADING = 7
const val READING = 1L
const val COMPLETED = 2L
const val ON_HOLD = 3L
const val DROPPED = 4L
const val PLAN_TO_READ = 6L
const val REREADING = 7L
private const val SEARCH_ID_PREFIX = "id:"
private const val SEARCH_LIST_PREFIX = "my:"
@ -35,7 +35,7 @@ class MyAnimeList(id: Long) : BaseTracker(id, "MyAnimeList"), DeletableTracker {
private val json: Json by injectLazy()
private val interceptor by lazy { MyAnimeListInterceptor(this, getPassword()) }
private val interceptor by lazy { MyAnimeListInterceptor(this) }
private val api by lazy { MyAnimeListApi(id, client, interceptor) }
override val supportsReadingDates: Boolean = true
@ -44,11 +44,11 @@ class MyAnimeList(id: Long) : BaseTracker(id, "MyAnimeList"), DeletableTracker {
override fun getLogoColor() = Color.rgb(46, 81, 162)
override fun getStatusList(): List<Int> {
override fun getStatusList(): List<Long> {
return listOf(READING, COMPLETED, ON_HOLD, DROPPED, PLAN_TO_READ, REREADING)
}
override fun getStatus(status: Int): StringResource? = when (status) {
override fun getStatus(status: Long): StringResource? = when (status) {
READING -> MR.strings.reading
PLAN_TO_READ -> MR.strings.plan_to_read
COMPLETED -> MR.strings.completed
@ -58,11 +58,11 @@ class MyAnimeList(id: Long) : BaseTracker(id, "MyAnimeList"), DeletableTracker {
else -> null
}
override fun getReadingStatus(): Int = READING
override fun getReadingStatus(): Long = READING
override fun getRereadingStatus(): Int = REREADING
override fun getRereadingStatus(): Long = REREADING
override fun getCompletionStatus(): Int = COMPLETED
override fun getCompletionStatus(): Long = COMPLETED
override fun getScoreList(): ImmutableList<String> = SCORE_LIST
@ -77,12 +77,12 @@ class MyAnimeList(id: Long) : BaseTracker(id, "MyAnimeList"), DeletableTracker {
override suspend fun update(track: Track, didReadChapter: Boolean): Track {
if (track.status != COMPLETED) {
if (didReadChapter) {
if (track.last_chapter_read.toInt() == track.total_chapters && track.total_chapters > 0) {
if (track.last_chapter_read.toLong() == track.total_chapters && track.total_chapters > 0) {
track.status = COMPLETED
track.finished_reading_date = System.currentTimeMillis()
} else if (track.status != REREADING) {
track.status = READING
if (track.last_chapter_read == 1F) {
if (track.last_chapter_read == 1.0) {
track.started_reading_date = System.currentTimeMillis()
}
}
@ -111,7 +111,7 @@ class MyAnimeList(id: Long) : BaseTracker(id, "MyAnimeList"), DeletableTracker {
} else {
// Set default fields if it's not found in the list
track.status = if (hasReadChapters) READING else PLAN_TO_READ
track.score = 0F
track.score = 0.0
add(track)
}
}
@ -155,6 +155,14 @@ class MyAnimeList(id: Long) : BaseTracker(id, "MyAnimeList"), DeletableTracker {
interceptor.setAuth(null)
}
fun getIfAuthExpired(): Boolean {
return trackPreferences.trackAuthExpired(this).get()
}
fun setAuthExpired() {
trackPreferences.trackAuthExpired(this).set(true)
}
fun saveOAuth(oAuth: OAuth?) {
trackPreferences.trackToken(this).set(json.encodeToString(oAuth))
}

View File

@ -16,8 +16,8 @@ import kotlinx.serialization.json.Json
import kotlinx.serialization.json.JsonObject
import kotlinx.serialization.json.boolean
import kotlinx.serialization.json.contentOrNull
import kotlinx.serialization.json.float
import kotlinx.serialization.json.floatOrNull
import kotlinx.serialization.json.double
import kotlinx.serialization.json.doubleOrNull
import kotlinx.serialization.json.int
import kotlinx.serialization.json.jsonArray
import kotlinx.serialization.json.jsonObject
@ -47,13 +47,13 @@ class MyAnimeListApi(
suspend fun getAccessToken(authCode: String): OAuth {
return withIOContext {
val formBody: RequestBody = FormBody.Builder()
.add("client_id", clientId)
.add("client_id", CLIENT_ID)
.add("code", authCode)
.add("code_verifier", codeVerifier)
.add("grant_type", "authorization_code")
.build()
with(json) {
client.newCall(POST("$baseOAuthUrl/token", body = formBody))
client.newCall(POST("$BASE_OAUTH_URL/token", body = formBody))
.awaitSuccess()
.parseAs()
}
@ -63,7 +63,7 @@ class MyAnimeListApi(
suspend fun getCurrentUser(): String {
return withIOContext {
val request = Request.Builder()
.url("$baseApiUrl/users/@me")
.url("$BASE_API_URL/users/@me")
.get()
.build()
with(json) {
@ -77,7 +77,7 @@ class MyAnimeListApi(
suspend fun search(query: String): List<TrackSearch> {
return withIOContext {
val url = "$baseApiUrl/manga".toUri().buildUpon()
val url = "$BASE_API_URL/manga".toUri().buildUpon()
// MAL API throws a 400 when the query is over 64 characters...
.appendQueryParameter("q", query.take(64))
.appendQueryParameter("nsfw", "true")
@ -102,7 +102,7 @@ class MyAnimeListApi(
suspend fun getMangaDetails(id: Int): TrackSearch {
return withIOContext {
val url = "$baseApiUrl/manga".toUri().buildUpon()
val url = "$BASE_API_URL/manga".toUri().buildUpon()
.appendPath(id.toString())
.appendQueryParameter(
"fields",
@ -119,8 +119,8 @@ class MyAnimeListApi(
remote_id = obj["id"]!!.jsonPrimitive.long
title = obj["title"]!!.jsonPrimitive.content
summary = obj["synopsis"]?.jsonPrimitive?.content ?: ""
total_chapters = obj["num_chapters"]!!.jsonPrimitive.int
score = obj["mean"]?.jsonPrimitive?.floatOrNull ?: -1f
total_chapters = obj["num_chapters"]!!.jsonPrimitive.long
score = obj["mean"]?.jsonPrimitive?.doubleOrNull ?: -1.0
cover_url =
obj["main_picture"]?.jsonObject?.get("large")?.jsonPrimitive?.content
?: ""
@ -178,7 +178,7 @@ class MyAnimeListApi(
suspend fun findListItem(track: Track): Track? {
return withIOContext {
val uri = "$baseApiUrl/manga".toUri().buildUpon()
val uri = "$BASE_API_URL/manga".toUri().buildUpon()
.appendPath(track.remote_id.toString())
.appendQueryParameter("fields", "num_chapters,my_list_status{start_date,finish_date}")
.build()
@ -187,7 +187,7 @@ class MyAnimeListApi(
.awaitSuccess()
.parseAs<JsonObject>()
.let { obj ->
track.total_chapters = obj["num_chapters"]!!.jsonPrimitive.int
track.total_chapters = obj["num_chapters"]!!.jsonPrimitive.long
obj.jsonObject["my_list_status"]?.jsonObject?.let {
parseMangaItem(it, track)
}
@ -216,7 +216,7 @@ class MyAnimeListApi(
// Check next page if there's more
if (!obj["paging"]!!.jsonObject["next"]?.jsonPrimitive?.contentOrNull.isNullOrBlank()) {
matches + findListItems(query, offset + listPaginationAmount)
matches + findListItems(query, offset + LIST_PAGINATION_AMOUNT)
} else {
matches
}
@ -225,9 +225,9 @@ class MyAnimeListApi(
private suspend fun getListPage(offset: Int): JsonObject {
return withIOContext {
val urlBuilder = "$baseApiUrl/users/@me/mangalist".toUri().buildUpon()
val urlBuilder = "$BASE_API_URL/users/@me/mangalist".toUri().buildUpon()
.appendQueryParameter("fields", "list_status{start_date,finish_date}")
.appendQueryParameter("limit", listPaginationAmount.toString())
.appendQueryParameter("limit", LIST_PAGINATION_AMOUNT.toString())
if (offset > 0) {
urlBuilder.appendQueryParameter("offset", offset.toString())
}
@ -249,8 +249,8 @@ class MyAnimeListApi(
return track.apply {
val isRereading = obj["is_rereading"]!!.jsonPrimitive.boolean
status = if (isRereading) MyAnimeList.REREADING else getStatus(obj["status"]?.jsonPrimitive?.content)
last_chapter_read = obj["num_chapters_read"]!!.jsonPrimitive.float
score = obj["score"]!!.jsonPrimitive.int.toFloat()
last_chapter_read = obj["num_chapters_read"]!!.jsonPrimitive.double
score = obj["score"]!!.jsonPrimitive.int.toDouble()
obj["start_date"]?.let {
started_reading_date = parseDate(it.jsonPrimitive.content)
}
@ -277,30 +277,29 @@ class MyAnimeListApi(
}
companion object {
// Registered under arkon's MAL account
private const val clientId = "f46004a9c16483b6d87b5bf10de56d97"
private const val CLIENT_ID = "c46c9e24640a64dad5be5ca7a1a53a0f"
private const val baseOAuthUrl = "https://myanimelist.net/v1/oauth2"
private const val baseApiUrl = "https://api.myanimelist.net/v2"
private const val BASE_OAUTH_URL = "https://myanimelist.net/v1/oauth2"
private const val BASE_API_URL = "https://api.myanimelist.net/v2"
private const val listPaginationAmount = 250
private const val LIST_PAGINATION_AMOUNT = 250
private var codeVerifier: String = ""
fun authUrl(): Uri = "$baseOAuthUrl/authorize".toUri().buildUpon()
.appendQueryParameter("client_id", clientId)
fun authUrl(): Uri = "$BASE_OAUTH_URL/authorize".toUri().buildUpon()
.appendQueryParameter("client_id", CLIENT_ID)
.appendQueryParameter("code_challenge", getPkceChallengeCode())
.appendQueryParameter("response_type", "code")
.build()
fun mangaUrl(id: Long): Uri = "$baseApiUrl/manga".toUri().buildUpon()
fun mangaUrl(id: Long): Uri = "$BASE_API_URL/manga".toUri().buildUpon()
.appendPath(id.toString())
.appendPath("my_list_status")
.build()
fun refreshTokenRequest(oauth: OAuth): Request {
val formBody: RequestBody = FormBody.Builder()
.add("client_id", clientId)
.add("client_id", CLIENT_ID)
.add("refresh_token", oauth.refresh_token)
.add("grant_type", "refresh_token")
.build()
@ -312,7 +311,7 @@ class MyAnimeListApi(
.add("Authorization", "Bearer ${oauth.access_token}")
.build()
return POST("$baseOAuthUrl/token", body = formBody, headers = headers)
return POST("$BASE_OAUTH_URL/token", body = formBody, headers = headers)
}
private fun getPkceChallengeCode(): String {

View File

@ -8,28 +8,26 @@ import okhttp3.Response
import uy.kohesive.injekt.injectLazy
import java.io.IOException
class MyAnimeListInterceptor(private val myanimelist: MyAnimeList, private var token: String?) : Interceptor {
class MyAnimeListInterceptor(private val myanimelist: MyAnimeList) : Interceptor {
private val json: Json by injectLazy()
private var oauth: OAuth? = null
private var oauth: OAuth? = myanimelist.loadOAuth()
private val tokenExpired get() = myanimelist.getIfAuthExpired()
override fun intercept(chain: Interceptor.Chain): Response {
if (tokenExpired) {
throw MALTokenExpired()
}
val originalRequest = chain.request()
if (token.isNullOrEmpty()) {
throw IOException("Not authenticated with MyAnimeList")
}
if (oauth == null) {
oauth = myanimelist.loadOAuth()
}
// Refresh access token if expired
if (oauth != null && oauth!!.isExpired()) {
setAuth(refreshToken(chain))
}
if (oauth == null) {
throw IOException("No authentication token")
throw IOException("MAL: User is not authenticated")
}
// Add the authorization header to the original request
@ -66,15 +64,16 @@ class MyAnimeListInterceptor(private val myanimelist: MyAnimeList, private var t
* and the oauth object.
*/
fun setAuth(oauth: OAuth?) {
token = oauth?.access_token
this.oauth = oauth
myanimelist.saveOAuth(oauth)
}
private fun refreshToken(chain: Interceptor.Chain): OAuth {
val newOauth = runCatching {
return runCatching {
val oauthResponse = chain.proceed(MyAnimeListApi.refreshTokenRequest(oauth!!))
if (oauthResponse.code == 401) {
myanimelist.setAuthExpired()
}
if (oauthResponse.isSuccessful) {
with(json) { oauthResponse.parseAs<OAuth>() }
} else {
@ -82,11 +81,9 @@ class MyAnimeListInterceptor(private val myanimelist: MyAnimeList, private var t
null
}
}
if (newOauth.getOrNull() == null) {
throw IOException("Failed to refresh the access token")
}
return newOauth.getOrNull()!!
.getOrNull()
?: throw MALTokenExpired()
}
}
class MALTokenExpired : IOException("MAL: Login has expired")

View File

@ -18,12 +18,12 @@ import tachiyomi.domain.track.model.Track as DomainTrack
class Shikimori(id: Long) : BaseTracker(id, "Shikimori"), DeletableTracker {
companion object {
const val READING = 1
const val COMPLETED = 2
const val ON_HOLD = 3
const val DROPPED = 4
const val PLAN_TO_READ = 5
const val REREADING = 6
const val READING = 1L
const val COMPLETED = 2L
const val ON_HOLD = 3L
const val DROPPED = 4L
const val PLAN_TO_READ = 5L
const val REREADING = 6L
private val SCORE_LIST = IntRange(0, 10)
.map(Int::toString)
@ -49,7 +49,7 @@ class Shikimori(id: Long) : BaseTracker(id, "Shikimori"), DeletableTracker {
override suspend fun update(track: Track, didReadChapter: Boolean): Track {
if (track.status != COMPLETED) {
if (didReadChapter) {
if (track.last_chapter_read.toInt() == track.total_chapters && track.total_chapters > 0) {
if (track.last_chapter_read.toLong() == track.total_chapters && track.total_chapters > 0) {
track.status = COMPLETED
} else if (track.status != REREADING) {
track.status = READING
@ -79,7 +79,7 @@ class Shikimori(id: Long) : BaseTracker(id, "Shikimori"), DeletableTracker {
} else {
// Set default fields if it's not found in the list
track.status = if (hasReadChapters) READING else PLAN_TO_READ
track.score = 0F
track.score = 0.0
add(track)
}
}
@ -101,11 +101,11 @@ class Shikimori(id: Long) : BaseTracker(id, "Shikimori"), DeletableTracker {
override fun getLogoColor() = Color.rgb(40, 40, 40)
override fun getStatusList(): List<Int> {
override fun getStatusList(): List<Long> {
return listOf(READING, COMPLETED, ON_HOLD, DROPPED, PLAN_TO_READ, REREADING)
}
override fun getStatus(status: Int): StringResource? = when (status) {
override fun getStatus(status: Long): StringResource? = when (status) {
READING -> MR.strings.reading
PLAN_TO_READ -> MR.strings.plan_to_read
COMPLETED -> MR.strings.completed
@ -115,11 +115,11 @@ class Shikimori(id: Long) : BaseTracker(id, "Shikimori"), DeletableTracker {
else -> null
}
override fun getReadingStatus(): Int = READING
override fun getReadingStatus(): Long = READING
override fun getRereadingStatus(): Int = REREADING
override fun getRereadingStatus(): Long = REREADING
override fun getCompletionStatus(): Int = COMPLETED
override fun getCompletionStatus(): Long = COMPLETED
override suspend fun login(username: String, password: String) = login(password)

View File

@ -15,7 +15,7 @@ import kotlinx.serialization.json.JsonArray
import kotlinx.serialization.json.JsonObject
import kotlinx.serialization.json.buildJsonObject
import kotlinx.serialization.json.contentOrNull
import kotlinx.serialization.json.float
import kotlinx.serialization.json.double
import kotlinx.serialization.json.int
import kotlinx.serialization.json.jsonObject
import kotlinx.serialization.json.jsonPrimitive
@ -102,10 +102,10 @@ class ShikimoriApi(
return TrackSearch.create(trackId).apply {
remote_id = obj["id"]!!.jsonPrimitive.long
title = obj["name"]!!.jsonPrimitive.content
total_chapters = obj["chapters"]!!.jsonPrimitive.int
total_chapters = obj["chapters"]!!.jsonPrimitive.long
cover_url = baseUrl + obj["image"]!!.jsonObject["preview"]!!.jsonPrimitive.content
summary = ""
score = obj["score"]!!.jsonPrimitive.float
score = obj["score"]!!.jsonPrimitive.double
tracking_url = baseUrl + obj["url"]!!.jsonPrimitive.content
publishing_status = obj["status"]!!.jsonPrimitive.content
publishing_type = obj["kind"]!!.jsonPrimitive.content
@ -117,10 +117,10 @@ class ShikimoriApi(
return Track.create(trackId).apply {
title = mangas["name"]!!.jsonPrimitive.content
remote_id = obj["id"]!!.jsonPrimitive.long
total_chapters = mangas["chapters"]!!.jsonPrimitive.int
total_chapters = mangas["chapters"]!!.jsonPrimitive.long
library_id = obj["id"]!!.jsonPrimitive.long
last_chapter_read = obj["chapters"]!!.jsonPrimitive.float
score = (obj["score"]!!.jsonPrimitive.int).toFloat()
last_chapter_read = obj["chapters"]!!.jsonPrimitive.double
score = obj["score"]!!.jsonPrimitive.int.toDouble()
status = toTrackStatus(obj["status"]!!.jsonPrimitive.content)
tracking_url = baseUrl + mangas["url"]!!.jsonPrimitive.content
}

View File

@ -23,25 +23,25 @@ class Suwayomi(id: Long) : BaseTracker(id, "Suwayomi"), EnhancedTracker {
override fun getLogoColor() = Color.rgb(255, 35, 35) // TODO
companion object {
const val UNREAD = 1
const val READING = 2
const val COMPLETED = 3
const val UNREAD = 1L
const val READING = 2L
const val COMPLETED = 3L
}
override fun getStatusList() = listOf(UNREAD, READING, COMPLETED)
override fun getStatusList(): List<Long> = listOf(UNREAD, READING, COMPLETED)
override fun getStatus(status: Int): StringResource? = when (status) {
override fun getStatus(status: Long): StringResource? = when (status) {
UNREAD -> MR.strings.unread
READING -> MR.strings.reading
COMPLETED -> MR.strings.completed
else -> null
}
override fun getReadingStatus(): Int = READING
override fun getReadingStatus(): Long = READING
override fun getRereadingStatus(): Int = -1
override fun getRereadingStatus(): Long = -1
override fun getCompletionStatus(): Int = COMPLETED
override fun getCompletionStatus(): Long = COMPLETED
override fun getScoreList(): ImmutableList<String> = persistentListOf()
@ -50,7 +50,7 @@ class Suwayomi(id: Long) : BaseTracker(id, "Suwayomi"), EnhancedTracker {
override suspend fun update(track: Track, didReadChapter: Boolean): Track {
if (track.status != COMPLETED) {
if (didReadChapter) {
if (track.last_chapter_read.toInt() == track.total_chapters && track.total_chapters > 0) {
if (track.last_chapter_read.toLong() == track.total_chapters && track.total_chapters > 0) {
track.status = COMPLETED
} else {
track.status = READING

View File

@ -66,9 +66,9 @@ class SuwayomiApi(private val trackId: Long) {
cover_url = "$url/thumbnail"
summary = manga.description.orEmpty()
tracking_url = url
total_chapters = manga.chapterCount.toInt()
total_chapters = manga.chapterCount
publishing_status = manga.status
last_chapter_read = manga.lastChapterRead?.chapterNumber ?: 0F
last_chapter_read = manga.lastChapterRead?.chapterNumber ?: 0.0
status = when (manga.unreadCount) {
manga.chapterCount -> Suwayomi.UNREAD
0L -> Suwayomi.COMPLETED

View File

@ -64,7 +64,7 @@ data class ChapterDataClass(
val url: String,
val name: String,
val uploadDate: Long,
val chapterNumber: Float,
val chapterNumber: Double,
val scanlator: String?,
val mangaId: Int,

View File

@ -285,13 +285,13 @@ private data class TrackStatusSelectorScreen(
private class Model(
private val track: Track,
private val tracker: Tracker,
) : StateScreenModel<Model.State>(State(track.status.toInt())) {
) : StateScreenModel<Model.State>(State(track.status)) {
fun getSelections(): Map<Int, StringResource?> {
fun getSelections(): Map<Long, StringResource?> {
return tracker.getStatusList().associateWith { tracker.getStatus(it) }
}
fun setSelection(selection: Int) {
fun setSelection(selection: Long) {
mutableState.update { it.copy(selection = selection) }
}
@ -303,7 +303,7 @@ private data class TrackStatusSelectorScreen(
@Immutable
data class State(
val selection: Int,
val selection: Long,
)
}
}

View File

@ -21,7 +21,7 @@ class CrashLogUtil(
suspend fun dumpLogs() = withNonCancellableContext {
try {
val file = context.createFileInCacheDir("tachiyomi_crash_logs.txt")
val file = context.createFileInCacheDir("mihon_crash_logs.txt")
file.appendText(getDebugInfo() + "\n\n")
getExtensionsInfo()?.let { file.appendText("$it\n\n") }

View File

@ -18,10 +18,10 @@ data class DummyTracker(
override val isLoggedIn: Boolean = false,
val valLogoColor: Int = Color.rgb(18, 25, 35),
val valLogo: Int = R.drawable.ic_tracker_anilist,
val valStatuses: List<Int> = (1..6).toList(),
val valReadingStatus: Int = 1,
val valRereadingStatus: Int = 1,
val valCompletionStatus: Int = 2,
val valStatuses: List<Long> = (1L..6L).toList(),
val valReadingStatus: Long = 1L,
val valRereadingStatus: Long = 1L,
val valCompletionStatus: Long = 2L,
val valScoreList: ImmutableList<String> = (0..10).map(Int::toString).toImmutableList(),
val val10PointScore: Double = 5.4,
val valSearchResults: List<TrackSearch> = listOf(),
@ -34,29 +34,29 @@ data class DummyTracker(
override fun getLogo(): Int = valLogo
override fun getStatusList(): List<Int> = valStatuses
override fun getStatusList(): List<Long> = valStatuses
override fun getStatus(status: Int): StringResource? = when (status) {
1 -> MR.strings.reading
2 -> MR.strings.plan_to_read
3 -> MR.strings.completed
4 -> MR.strings.on_hold
5 -> MR.strings.dropped
6 -> MR.strings.repeating
override fun getStatus(status: Long): StringResource? = when (status) {
1L -> MR.strings.reading
2L -> MR.strings.plan_to_read
3L -> MR.strings.completed
4L -> MR.strings.on_hold
5L -> MR.strings.dropped
6L -> MR.strings.repeating
else -> null
}
override fun getReadingStatus(): Int = valReadingStatus
override fun getReadingStatus(): Long = valReadingStatus
override fun getRereadingStatus(): Int = valRereadingStatus
override fun getRereadingStatus(): Long = valRereadingStatus
override fun getCompletionStatus(): Int = valCompletionStatus
override fun getCompletionStatus(): Long = valCompletionStatus
override fun getScoreList(): ImmutableList<String> = valScoreList
override fun get10PointScore(track: Track): Double = val10PointScore
override fun indexToScore(index: Int): Float = getScoreList()[index].toFloat()
override fun indexToScore(index: Int): Double = getScoreList()[index].toDouble()
override fun displayScore(track: Track): String =
track.score.toString()
@ -94,7 +94,7 @@ data class DummyTracker(
override suspend fun setRemoteStatus(
track: eu.kanade.tachiyomi.data.database.models.Track,
status: Int,
status: Long,
) = Unit
override suspend fun setRemoteLastChapterRead(

View File

@ -1,5 +1,5 @@
[versions]
agp_version = "8.2.1"
agp_version = "8.2.2"
lifecycle_version = "2.6.2"
paging_version = "3.2.1"

View File

@ -128,4 +128,12 @@
<item quantity="many">%d يومًا</item>
<item quantity="other">%d يوم</item>
</plurals>
<plurals name="num_repos">
<item quantity="zero">%d</item>
<item quantity="one">مستودع</item>
<item quantity="two">مستودعان</item>
<item quantity="few">%d مستودعات</item>
<item quantity="many">%d مستودعات</item>
<item quantity="other"></item>
</plurals>
</resources>

View File

@ -232,7 +232,7 @@
<string name="label_extensions">الإضافات</string>
<string name="label_extension_info">معلومات الإضافة</string>
<string name="action_display_download_badge">الفصول المحملة</string>
<string name="ext_update">تحديث</string>
<string name="ext_update">حدث</string>
<string name="ext_install">تثبيت</string>
<string name="ext_pending">المُعلقة</string>
<string name="ext_downloading">جارى التنزيل</string>
@ -242,11 +242,9 @@
<string name="ext_untrusted">غير موثوق فيه</string>
<string name="ext_uninstall">إلغاء التثبيت</string>
<string name="untrusted_extension">إضافة ذات ريبة</string>
<string name="untrusted_extension_message">هذه اﻹضافة موقَّعة بشهادة ذات ريبة ولم تفعَّل.
<string name="untrusted_extension_message">يمكن للملحقات الخبيثة قراءة أي بيانات اعتماد مخزنة لتسجيل الدخول أو تنفيذ تعليمات برمجية عشوائية.
\n
\nيمكن لأي إضافة خبيثة قراءة بيانات اعتماد تسجيل الدخول المخزَّنة أو تنفيذ تعليمات برمجية عشوائية.
\n
\nأنت تقبل هذه المخاطر إن وثقت بالشهادة.</string>
\nمن خلال الوثوق بهذا الامتداد، فإنك تقبل هذه المخاطر.</string>
<string name="pref_double_tap_anim_speed">سرعة مؤثر النقر المزدوج</string>
<string name="pager_viewer">عارض الصفحات</string>
<string name="double_tap_anim_speed_0">لا مؤثرات</string>
@ -372,7 +370,7 @@
<string name="label_data">البيانات</string>
<string name="backup_restore_missing_sources">المصادر المفقودة:</string>
<string name="invalid_backup_file_missing_manga">النسخة الإحتياطية لا تحتوي على أيّة إدخالات المكتبة.</string>
<string name="invalid_backup_file">ملفُّ النسخ الاحتياطيِّ غير صالح</string>
<string name="invalid_backup_file">ملف النسخ الاحتياطي غير صالح:</string>
<string name="tracking_info">مزامنة أحادية تُحدِّث قراءة الفصول في المتتبعات الخارجية، ولك تعيين التتبِّع لكلِّ مدخلة على حدى، وذلك من زرِّ التتبع فيهم.</string>
<string name="pref_library_update_refresh_metadata_summary">تحقق من وجود غلاف جديد وتفاصيل جديدة عند تحديث المكتبة</string>
<string name="pref_library_update_refresh_metadata">تحديث البيانات الوصفية تلقائياً</string>
@ -456,9 +454,7 @@
<string name="action_order_by_upload_date">حسب تاريخ الرفع</string>
<string name="action_order_by_chapter_number">حسب رقم الفصل</string>
<string name="pref_dns_over_https">إستخدام DNS عبر HTTPS (DoH)</string>
<string name="backup_restore_content_full">تم استيراد البيانات من ملف نسخ الاحتياطي.
\n
\nيتوجب تثبيت الإضافات المفقودة و تسجيل الدخول إلى منصات التعقب تالياً لاستعمالهم.</string>
<string name="backup_restore_content_full">قد تحتاج إلى تثبيت أي إضافات مفقودة وتسجيل الدخول إلى خدمات التتبع بعد ذلك لاستخدامها.</string>
<string name="nav_zone_right">يمين</string>
<string name="nav_zone_left">يسار</string>
<string name="nav_zone_next">التالي</string>
@ -773,4 +769,33 @@
\nوالأحسن أن يكون المجلَّد مخصوصًا لذلك.
\n
\nالمجلَّد المحدَّد: %2$s</string>
<string name="onboarding_permission_install_apps">إذن تثبيت التطبيقات</string>
<string name="onboarding_permission_install_apps_description">لتثبيت ملحقات المصدر.</string>
<string name="onboarding_permission_notifications">إذن الإشعار</string>
<string name="onboarding_permission_notifications_description">احصل على تنبيهات لتحديثات المكتبة والمزيد.</string>
<string name="onboarding_permission_ignore_battery_opts">استخدام البطارية في الخلفية</string>
<string name="onboarding_permission_action_grant">منح</string>
<string name="ext_permission_install_apps_warning">الأذونات مطلوبة لتثبيت الإضافات. انقر هنا لمنحها.</string>
<string name="ext_revoke_trust">إبطال الإضافات غير المعروفة الموثوق بها</string>
<string name="label_extension_repos">مستودع الإضافات</string>
<string name="label_add_repo_input">رابط المستودع</string>
<string name="action_add_repo_message">إضافة مستودعات إضافية إلى ميهون. يجب أن يكون هذا الرابط ينتهي بـ \"index.min.json\".</string>
<string name="error_repo_exists">هذا المستودع موجود بالفعل!</string>
<string name="action_delete_repo">حذف المستودع</string>
<string name="invalid_repo_name">رابط المستودع غير صالح</string>
<string name="delete_repo_confirmation">هل ترغب في حذف \"1%s\" من المستودع؟</string>
<string name="action_open_repo">مستودع مفتوح المصدر</string>
<string name="invalid_backup_file_error">الخطأ الكامل:</string>
<string name="private_settings">تضمين إعدادات حساسة (على سبيل المثال، رموز تسجيل دخول المتتبع)</string>
<string name="manga_interval_expected_update_soon">قريباً</string>
<string name="manga_interval_custom_amount">تكرار تحديث مخصص:</string>
<string name="onboarding_storage_help_info">هل تقوم بالتحديث من إصدار أقدم ولست متأكداً مما تختاره؟ ارجع إلى دليل التخزين لمزيد من المعلومات.</string>
<string name="onboarding_storage_help_action">دليل التخزين</string>
<string name="onboarding_permission_ignore_battery_opts_description">تجنّب الانقطاعات في تحديثات المكتبة الطويلة الأمد والتنزيلات واستعادة النسخ الاحتياطية.</string>
<string name="pref_library_update_smart_update">تحديث ذكي</string>
<string name="theme_nord">Nord</string>
<string name="information_empty_repos">لم يتم تعيين أي مستودع .</string>
<string name="action_add_repo">إضافة مستودع</string>
<string name="manga_interval_expected_update">من المتوقع أن يتم إصدار فصول جديدة في حوالي 1%1$s، والتحقق من كل 2%2$s .</string>
<string name="available_disk_space_info">متاح: %1$s / الكل: %2$s</string>
</resources>

View File

@ -29,12 +29,12 @@
<item quantity="other">Ҫӗнӗ сыпӑксем %d хайлав валли тупӑннӑ</item>
</plurals>
<plurals name="manga_num_chapters">
<item quantity="one">1 сыпӑк</item>
<item quantity="one">%1$s сыпӑк</item>
<item quantity="other">%1$s сыпӑк</item>
</plurals>
<plurals name="download_queue_summary">
<item quantity="one">1 юлчӗ</item>
<item quantity="other">%1$s юлчӗ</item>
<item quantity="one">%1$s йулчӗ</item>
<item quantity="other">%1$s йулчӗ</item>
</plurals>
<plurals name="num_trackers">
<item quantity="one">1 сӑнану</item>
@ -48,4 +48,20 @@
<item quantity="one">Ӗнер</item>
<item quantity="other">%1$d кун кайалла</item>
</plurals>
<plurals name="next_unread_chapters">
<item quantity="one">Тепӗр вуламан сыпӑк</item>
<item quantity="other">Тепӗр %d вуламан сыпӑк</item>
</plurals>
<plurals name="day">
<item quantity="one">1 кун</item>
<item quantity="other">%d кун</item>
</plurals>
<plurals name="missing_chapters">
<item quantity="one">%1$s сыпӑк ҫук</item>
<item quantity="other">%1$s сыпӑк ҫук</item>
</plurals>
<plurals name="download_amount">
<item quantity="one">Тепӗр сыпӑк</item>
<item quantity="other">Тепӗр %d сыпӑк</item>
</plurals>
</resources>

View File

@ -128,16 +128,16 @@
<string name="fifth_to_last">Ab fünftletzt gelesenem Kapitel</string>
<string name="pref_download_new">Neue Kapitel herunterladen</string>
<string name="services">Tracker</string>
<string name="pref_create_backup">Sicherung erstellen</string>
<string name="pref_create_backup">Datensicherung erstellen</string>
<string name="pref_create_backup_summ">Kann benutzt werden, um die aktuelle Bibliothek wiederherzustellen</string>
<string name="pref_restore_backup">Sicherung wiederherstellen</string>
<string name="pref_restore_backup">Datensicherung wiederherstellen</string>
<string name="pref_restore_backup_summ">Bibliothek mit Hilfe einer Datensicherung wiederherstellen</string>
<string name="pref_backup_interval">Automatische Sicherungshäufigkeit</string>
<string name="backup_created">Sicherung erstellt</string>
<string name="backup_created">Datensicherung erstellt</string>
<string name="restore_completed">Wiederherstellen abgeschlossen</string>
<string name="backup_choice">Was möchtest du sichern\?</string>
<string name="restoring_backup">Sicherung wird wiederhergestellt</string>
<string name="creating_backup">Sicherung wird erstellt</string>
<string name="restoring_backup">Datensicherung wird wiederhergestellt</string>
<string name="creating_backup">Datensicherung wird erstellt</string>
<string name="pref_clear_chapter_cache">Kapitel-Zwischenspeicher leeren</string>
<string name="used_cache">Belegt: %1$s</string>
<string name="cache_deleted">Zwischenspeicher geleert, %1$d Dateien gelöscht</string>
@ -351,11 +351,11 @@
<string name="website">Webseite</string>
<string name="label_downloaded_only">Nur Heruntergeladenes</string>
<string name="recent_manga_time">Kap. %1$s - %2$s</string>
<string name="restoring_backup_error">Sicherungswiederherstellung fehlgeschlagen</string>
<string name="creating_backup_error">Sicherung fehlgeschlagen</string>
<string name="restoring_backup_error">Datensicherungswiederherstellung fehlgeschlagen</string>
<string name="creating_backup_error">Datensicherung fehlgeschlagen</string>
<string name="restoring_backup_canceled">Wiederherstellung abgebrochen</string>
<string name="restore_in_progress">Wiederherstellung wird bereits durchgeführt</string>
<string name="backup_in_progress">Sicherung wird bereits durchgeführt</string>
<string name="backup_in_progress">Datensicherung wird bereits durchgeführt</string>
<string name="check_for_updates">Nach Aktualisierungen suchen</string>
<string name="last_used_source">Zuletzt genutzt</string>
<string name="local_source_help_guide">Anleitung für lokale Quellen</string>
@ -371,7 +371,7 @@
<string name="sort_by_upload_date">Nach Uploaddatum</string>
<string name="label_data">Daten</string>
<string name="backup_restore_missing_sources">Fehlende Quellen:</string>
<string name="invalid_backup_file_missing_manga">Sicherung beinhaltet keinerlei Bibliothekseinträge.</string>
<string name="invalid_backup_file_missing_manga">Datensicherung beinhaltet keinerlei Bibliothekseinträge.</string>
<string name="invalid_backup_file">Ungültige Sicherungsdatei:</string>
<string name="pref_library_update_refresh_metadata_summary">Auf neue Cover und Details überprüfen, wenn die Bibliothek aktualisiert wird</string>
<string name="pref_library_update_refresh_metadata">Metadaten automatisch aktualisieren</string>
@ -542,7 +542,7 @@
<string name="action_display_language_badge">Sprache</string>
<string name="label_warning">Warnung</string>
<string name="notification_size_warning">Große Aktualisierungen schaden Quellen und könnten zu langsameren Aktualisierungen sowie höherem Akkuverbrauch führen. Tippe, um mehr zu erfahren.</string>
<string name="backup_info">Du solltest Kopien der Sicherungen auch an anderen Orten aufbewahren. Sicherungen beinhalten möglicherweise sensible Daten, einschließlich gespeicherter Passwörter. Sei vorsichtig beim Teilen.</string>
<string name="backup_info">Du solltest Kopien der Datensicherungen auch an anderen Orten aufbewahren. Datensicherungen beinhalten möglicherweise sensible Daten, einschließlich gespeicherter Passwörter. Sei vorsichtig beim Teilen.</string>
<string name="connected_to_wifi">Nur über WLAN</string>
<string name="update_72hour">Alle 3 Tage</string>
<string name="download_queue_size_warning">Achtung: Große Downloads könnten dazu führen, dass Quellen langsamer werden und/oder Mihon blockieren. Tippe, um mehr zu erfahren.</string>
@ -793,7 +793,7 @@
<string name="label_add_repo_input">Repository-URL</string>
<string name="action_add_repo_message">Füge zusätzliche Repositorys zu Mihon hinzu. Deren URL sollte mit „index.min.json“ enden.</string>
<string name="invalid_repo_name">Ungültige Repository-URL</string>
<string name="manga_interval_expected_update">Neue Kapitel vsl. in ca. %1$s, überprüfe ca. alle %2$s</string>
<string name="manga_interval_expected_update">Ca. %1$s bis zur Veröffentlichung neuer Kapitel, wird ca. alle %2$s überprüft.</string>
<string name="theme_nord">Nord</string>
<string name="action_open_repo">Open-Source-Repository</string>
<string name="manga_interval_expected_update_soon">Bald</string>

View File

@ -622,4 +622,40 @@
<string name="updates_last_update_info">آخرین به روز رسانی کتابخانه: %s</string>
<string name="pref_update_only_in_release_period">خارج از دوره انتشار موزد انتظار</string>
<string name="pref_double_tap_zoom">برای بزرگ نمایی دوبار ضربه بزنید</string>
<string name="action_filter_interval_custom">تناوب به روز رسانی شخسی سازی شده</string>
<string name="onboarding_heading">خوش آمدید!</string>
<string name="onboarding_description">بیاید برخی چیز ها را تنظیم کنیم. شما همیشه میتوانید این تنظیمات را در بخش تنظیمات تغییر دهید.</string>
<string name="onboarding_action_next">بعدی</string>
<string name="onboarding_permission_install_apps_description">برای نصب افزانه منبع.</string>
<string name="onboarding_permission_notifications">دسترسی اعلان ها</string>
<string name="onboarding_permission_notifications_description">برای به روز رسانی های کتابخانه و بیشتر مطلع شوید.</string>
<string name="onboarding_permission_ignore_battery_opts">استفاده از باطری</string>
<string name="onboarding_permission_ignore_battery_opts_description">از وقفه در به روز رسانی های کتاب خانه، بارگیری و پشتیبان گیری های طولانی اجتناب کنید.</string>
<string name="onboarding_permission_action_grant">اعطا کردن</string>
<string name="onboarding_guides_new_user">به %s نا آشنا هستید؟ ما پیشنهاد میکنیم تا یک سر به راهنمای شروع بزنید.</string>
<string name="onboarding_guides_returning_user">نصب مجدد %s؟</string>
<string name="pref_relative_format">زمان بندی های نسبی</string>
<string name="pref_library_update_smart_update">به روز رسانی هوشمند</string>
<string name="pref_chapter_swipe">کشیدن قسمت</string>
<string name="ext_revoke_trust">لغو اعتماد افزونه های ناشناخته</string>
<string name="label_extension_repos">مخازن افزونه ها</string>
<string name="action_add_repo">اضافه کردن مخزن</string>
<string name="label_add_repo_input">آدرس مخزن</string>
<string name="error_repo_exists">این مخزن در حال حاضر وجود دارد!</string>
<string name="action_delete_repo">حذف مخزن</string>
<string name="invalid_repo_name">آدرس مخزن بی اعتبار است</string>
<string name="delete_repo_confirmation">آشا شما میخواهید تا \"%s\" مخزن را حذف کنید؟</string>
<string name="pref_page_rotate_invert">جهت چرخش صفحات گسترده را برعکس کن</string>
<string name="no_location_set">مکان ذخیره سازی تنظیم نشده است</string>
<string name="split_tall_images">عکس های بلند را تقسیم کن</string>
<string name="track_activity_name">ورود به ناضر</string>
<string name="pref_hide_in_library_items">اجرای داخل کتاب خانه را مخفی کن</string>
<string name="pref_storage_location">محل زخیره سازی</string>
<string name="onboarding_action_finish">شروع کنید</string>
<string name="onboarding_action_skip">پرش</string>
<string name="ext_permission_install_apps_warning">مجوز برای نصب افزونه ها لازم است. به اینجا ضربه بزنید تا اعطا کنید.</string>
<string name="action_add_repo_message">به میهون مخازن اضافی اضافه کنید. این باید یک آدرس باشد که با \"index.min.json\" تمام شود.</string>
<string name="information_empty_repos">شما هیچ مخزنی برای تنظیم ندارید.</string>
<string name="action_open_repo">مخزن منبع باز</string>
<string name="pref_flash_page_summ">مقدار رد باقی مانده در نمایش گر های E-ink کاهش میابد</string>
</resources>

View File

@ -72,7 +72,7 @@
<string name="label_extensions">Laajennukset</string>
<string name="label_extension_info">Laajennuksen tiedot</string>
<string name="action_filter">Suodatus</string>
<string name="action_filter_bookmarked">Kirjanmerkki</string>
<string name="action_filter_bookmarked">Kirjanmerkityt</string>
<string name="action_filter_unread">Lukemattomat</string>
<string name="action_filter_empty">Poista suodattimet</string>
<string name="action_sort_alpha">Aakkosjärjestyksessä</string>
@ -103,7 +103,7 @@
<string name="action_install">Asenna</string>
<string name="action_share">Jaa</string>
<string name="action_save">Tallenna</string>
<string name="action_reset">Resetoi</string>
<string name="action_reset">Nollaa</string>
<string name="action_undo">Kumoa</string>
<string name="action_open_log">Avaa loki</string>
<string name="action_restore">Palauta</string>
@ -447,7 +447,7 @@
<string name="pref_dump_crash_logs_summary">Tallentaa virhelokit tiedostoon jaettavaksi kehittäjien kanssa</string>
<string name="action_desc">Laskeva</string>
<string name="action_asc">Nouseva</string>
<string name="action_order_by_chapter_number">Luvunumeron mukaan</string>
<string name="action_order_by_chapter_number">Lukunumeron mukaan</string>
<string name="action_order_by_upload_date">Lisäyspäivämäärän mukaan</string>
<string name="action_filter_tracked">Seuratut</string>
<string name="action_display_show_number_of_items">Näytä kohteiden määrä</string>
@ -615,4 +615,35 @@
<string name="backup_info">Varmuuskopioita kannattaa säilyttää myös muissa paikoissa.</string>
<string name="wish_list">Toivelista</string>
<string name="cant_open_last_read_chapter">Viimeksi luettua lukua ei voitu avata</string>
</resources>
<string name="selected">Valitut</string>
<string name="scanlator">Skanlaattori</string>
<string name="label_data_storage">Data ja tallennustila</string>
<string name="label_stats">Tilastotiedot</string>
<string name="label_downloaded">Ladattu</string>
<string name="action_sort_next_updated">Seuraava odotettu päivitys</string>
<string name="action_sort_tracker_score">Seurannan pisteytys</string>
<string name="action_update_category">Päivitä kategoria</string>
<string name="action_sort_category">Järjestä kategoriat</string>
<string name="action_display_show_continue_reading_button">Jatka lukemista painike</string>
<string name="action_apply">Käytä</string>
<string name="action_ok">OK</string>
<string name="action_revert_to_default">Palauta oletus</string>
<string name="crash_screen_description">%s kohtasi odottamattoman virheen. Ehdotamme että jaat kaatumisen lokitiedot tukikanavallemme Discordissa.</string>
<string name="delete_downloaded">Poista ladatut</string>
<string name="create_backup_file_error">Varmuuskopiotiedoston luonti epäonnistui</string>
<string name="confirm_add_duplicate_manga">Kirjastossasi on jo samanniminen merkintä.
\n
\nHaluatko silti jatkaa?</string>
<string name="crash_screen_title">Hupsista!</string>
<string name="copied_to_clipboard_plain">Kopioitu leikepöydälle</string>
<string name="crash_screen_restart_application">Uudelleenkäynnistä applikaatio</string>
<string name="custom_cover">Mukautettu kansikuva</string>
<string name="not_selected">Ei valitut</string>
<string name="action_menu_overflow_description">Lisää asetuksia</string>
<string name="label_local">Paikallinen</string>
<string name="label_started">Aloitettu</string>
<string name="action_open_random_manga">Avaa satunnainen merkintä</string>
<string name="sort_category_confirmation">Haluatko järjestää kategoriat aakkosjärjestykseen?</string>
<string name="action_copy_to_clipboard">Kopioi leikepöydälle</string>
<string name="action_move_to_bottom_all_for_series">Siirrä sarja pohjimmaiseksi</string>
</resources>

View File

@ -728,7 +728,7 @@
<string name="action_move_to_bottom_all_for_series">Pindahkan seri ke bawah</string>
<string name="pref_relative_format">Penanda waktu</string>
<string name="pref_relative_format_summary">\"%1$s\" seharusnya \"%2$s\"</string>
<string name="action_sort_category">Mengurutkan kategori</string>
<string name="action_sort_category">Urutkan kategori</string>
<string name="notification_updating_progress">Memperbarui pustaka... (%s)</string>
<string name="sort_category_confirmation">Apakah Anda ingin mengurutkan kategori menurut abjad\?</string>
<string name="file_null_uri_error">Tidak ada file yang dipilih</string>

View File

@ -199,7 +199,7 @@
<string name="update_weekly">Ogni settimana</string>
<string name="default_category">Categoria predefinita</string>
<string name="track">Tracking</string>
<string name="pref_category_tracking">Tracking</string>
<string name="pref_category_tracking">Tracciamento</string>
<string name="default_category_summary">Chiedi sempre</string>
<string name="pref_crop_borders">Ritaglia bordi</string>
<string name="pref_read_with_volume_keys_inverted">Inverti i tasti del volume</string>
@ -236,11 +236,9 @@
<string name="ext_untrusted">Non attendibile</string>
<string name="ext_uninstall">Disinstalla</string>
<string name="untrusted_extension">Estensione non attendibile</string>
<string name="untrusted_extension_message">Questa estensione è stata firmata con un certificato non attendibile e non è stata attivata.
<string name="untrusted_extension_message">Le estensioni dannose possono leggere le credenziali di accesso memorizzate o eseguire codice arbitrario.
\n
\nUn\'estensione maliziosa potrebbe leggere credenziali di accesso salvate o eseguire codice dannoso.
\n
\nFidandoti di questo certificato accetti questi rischi.</string>
\nFidandoti di questa estensione, accetti questi rischi.</string>
<string name="pref_double_tap_anim_speed">Velocità animazioni doppio tocco</string>
<string name="pager_viewer">Per pagina</string>
<string name="double_tap_anim_speed_0">Senza animazione</string>
@ -783,4 +781,23 @@
<string name="private_settings">Includi impostazioni sensibili (es. token di login dei tracker)</string>
<string name="onboarding_permission_action_grant">Consenti</string>
<string name="exclude_scanlators">Escludi scanlator</string>
<string name="onboarding_storage_help_action">Guida all\'archiviazione</string>
<string name="label_extension_repos">Repository delle estensioni</string>
<string name="action_add_repo">Aggiungi repository</string>
<string name="label_add_repo_input">URL repository</string>
<string name="error_repo_exists">Questa repository esiste già!</string>
<string name="action_delete_repo">Elimina repository</string>
<string name="invalid_repo_name">URL repository non valida</string>
<string name="action_open_repo">Repository open source</string>
<string name="manga_interval_expected_update_soon">Presto</string>
<string name="manga_interval_custom_amount">Frequenza di aggiornamento personalizzata:</string>
<string name="onboarding_storage_help_info">State aggiornando da una versione precedente e non siete sicuri di cosa selezionare? Per ulteriori informazioni, consultare la guida all\'archiviazione</string>
<string name="theme_nord">Nord</string>
<string name="pref_library_update_smart_update">Aggiornamento intelligente</string>
<string name="ext_revoke_trust">Revoca le estensioni sconosciute affidabili</string>
<string name="information_empty_repos">Non hai repository impostate.</string>
<string name="action_add_repo_message">Aggiungi altri repository a Mihon. Questo dovrebbe essere un URL che termina con \"index.min.json\".</string>
<string name="delete_repo_confirmation">Vuoi eleminare la repository \"%s\"?</string>
<string name="invalid_backup_file_error">Errore completo:</string>
<string name="manga_interval_expected_update">Si prevede che i nuovi capitoli saranno rilasciati tra circa %1$s, con controlli ogni %2$s.</string>
</resources>

View File

@ -500,7 +500,7 @@
<string name="rotation_landscape">横向き</string>
<string name="rotation_portrait">縦向き</string>
<string name="pref_dark_theme_pure_black">真っ黒モード</string>
<string name="theme_yotsuba">Yotsuba</string>
<string name="theme_yotsuba">四つ葉</string>
<string name="theme_yinyang">陰陽</string>
<string name="theme_tako">Tako</string>
<string name="theme_strawberrydaiquiri">ストロベリーダイキリ</string>
@ -620,7 +620,7 @@
<string name="theme_tidalwave">津波</string>
<string name="download_ahead">事前ダウンロード</string>
<string name="auto_download_while_reading">読書中に自動でダウンロード</string>
<string name="download_ahead_info">現在のと次の章は既にダウンロード済みの場合のみ有効です</string>
<string name="download_ahead_info">現在のと次の章は既にダウンロード済みの場合のみ有効です</string>
<string name="are_you_sure">本当に実行しますか?</string>
<string name="multi_lang">多言語</string>
<string name="updates_last_update_info">前回のライブラリ更新: %s</string>

View File

@ -210,7 +210,7 @@
<string name="tapping_inverted_both">दुबै</string>
<string name="pref_reader_actions">कार्यहरू</string>
<string name="pref_read_with_long_tap">लामो ट्यापमा कार्यहरू देखाउनुहोस्</string>
<string name="pref_reader_theme">पृष्ठभूमि रङ</string>
<string name="pref_reader_theme">ब्याकग्राउण्ड रङ</string>
<string name="gray_background">खैरो</string>
<string name="black_background">कालो</string>
<string name="automatic_background">स्वत</string>
@ -595,7 +595,7 @@
<string name="multi_lang">थुप्रै</string>
<string name="pref_library_update_show_tab_badge">अपडेटहरू आइकनमा नपढिएको गणना देखाउनुहोस्</string>
<string name="pref_skip_dupe_chapters">डुप्लिकेट अध्यायहरू छोड्नुहोस्</string>
<string name="action_display_show_continue_reading_button">जारी राख्नुहोस् बटन</string>
<string name="action_display_show_continue_reading_button">जारी राख्न बटन</string>
<string name="label_stats">तथ्याङ्क</string>
<string name="label_started">सुरु गरिएको</string>
<string name="label_local">लोकल</string>
@ -705,7 +705,7 @@
<string name="pref_double_tap_zoom">जूम गर्न डबल ट्याप गर्नुहोस्</string>
<string name="pref_library_columns_per_row">%d प्रति पङ्क्ति</string>
<string name="action_set_interval">अन्तराल सेट गर्नुहोस्</string>
<string name="action_filter_interval_custom">कस्टम गरिएको ल्याउने अन्तराल</string>
<string name="action_filter_interval_custom">कस्टम गरिएको अपडेट फ्रिक्वेन्सी</string>
<string name="manga_display_modified_interval_title">प्रत्येक अपडेट गर्न सेट गर्नुहोस्</string>
<string name="skipped_reason_not_in_release_period">छोडियो किनभने आज कुनै रिलीज अपेक्षित थिएन</string>
<string name="intervals_header">अन्तरालहरू</string>
@ -715,8 +715,8 @@
<string name="track_delete_title">%s ट्र्याकिङ हटाउने हो\?</string>
<string name="track_delete_remote_text">%s बाट पनि हटाउनुहोस्</string>
<string name="track_delete_text">यसले लोकल रूपमा ट्र्याकिङ हटाउनेछ।</string>
<string name="action_ok">क छ</string>
<string name="delete_downloaded">डाउनलोड गरिएको मेट्नुहोस्</string>
<string name="action_ok">िक छ</string>
<string name="delete_downloaded">डाउनलोड गरिएको हटाउनुहोस्</string>
<string name="has_results">परिणामहरू भएको</string>
<string name="library_sync_complete">पुस्तकालय सिङ्क सम्पन्न भयो</string>
<string name="syncing_library">पुस्तकालय सिङ्क गर्दै</string>
@ -745,11 +745,61 @@
<string name="file_null_uri_error">फाइल पिकर एपमा फाइल फर्काउन असफल भयो</string>
<string name="selected">चयन गरिएको</string>
<string name="not_selected">चयन नगरिएको</string>
<string name="action_sort_tracker_score">ट्र्याकर मुल्यन्कन</string>
<string name="scanlator">स्क्यानले</string>
<string name="action_sort_tracker_score">ट्र्याकर मूल्याङ्कन</string>
<string name="scanlator">स्क्यानले</string>
<string name="action_menu_overflow_description">अरु मेनु</string>
<string name="onboarding_heading">स्वागत!</string>
<string name="onboarding_heading">स्वागत!</string>
<string name="onboarding_action_next">अर्को</string>
<string name="onboarding_action_finish">सुरु</string>
<string name="onboarding_action_skip">छोड</string>
<string name="onboarding_storage_selection_required">एउटा फोल्डर चयन गर्नुपर्छ</string>
<string name="onboarding_storage_help_action">भण्डारण गाइड</string>
<string name="onboarding_permission_notifications">सूचना अनुमति</string>
<string name="onboarding_permission_action_grant">प्रदान गर्नुहोस्</string>
<string name="onboarding_guides_new_user">%s मा नयाँ हुनुहुन्छ? हामी स्टार्टिङ गाइड जाँच गर्न सिफारिस गर्छौं।</string>
<string name="theme_nord">नोर्ड</string>
<string name="pref_library_update_smart_update">स्मार्ट अपडेट</string>
<string name="error_repo_exists">यो रिपो पहिले नै अवस्थित छ!</string>
<string name="action_delete_repo">रिपो हटाउनुहोस्</string>
<string name="invalid_repo_name">रिपो URL अवैध छ</string>
<string name="action_bar_up_description">माथि नेभिगेट गर्नुहोस्</string>
<string name="action_revert_to_default">पूर्वनिर्धारितमा फर्कनुहोस्</string>
<string name="pref_onboarding_guide">अनबोर्डिङ गाइड</string>
<string name="onboarding_description">पहिले केहि चीजहरू सेट गरौं। तपाईं पछि पनि सेटिङहरूमा गएर यसलाई परिवर्तन गर्न सक्नुहुन्छ।</string>
<string name="onboarding_storage_info">एउटा फोल्डर चयन गर्नुहोस् जहाँ %1$s ले अध्याय डाउनलोड, ब्याकअप, र थप भण्डारण गर्नेछ।
\n
\nएक समर्पित फोल्डर सिफारिस गरिएको छ।
\n
\nचयन गरिएको फोल्डर: %2$s</string>
<string name="onboarding_storage_action_select">फोल्डर चयन गर्नुहोस्</string>
<string name="onboarding_permission_install_apps">एप स्थापना गर्ने अनुमति</string>
<string name="onboarding_permission_install_apps_description">स्रोत एक्सटेन्शन स्थापना गर्न को लागि।</string>
<string name="onboarding_permission_notifications_description">पुस्तकालय अपडेट र थपका लागि सूचना प्राप्त गर्नुहोस्।</string>
<string name="onboarding_permission_ignore_battery_opts_description">लामो समयदेखि चलिरहेको पुस्तकालय अपडेटहरू, डाउनलोडहरू, र ब्याकअप रिस्टोरमा अवरोधहरू बेवास्ता गर्नुहोस्।</string>
<string name="onboarding_storage_help_info">पुरानो संस्करणबाट अपडेट गर्दै र के चयन गर्ने निश्चित छैन? थप जानकारीको लागि भण्डारण गाइड हेर्नुहोस्।</string>
<string name="onboarding_permission_ignore_battery_opts">ब्याकग्राउण्ड ब्याट्री प्रयोग</string>
<string name="onboarding_guides_returning_user">%s पुन: स्थापना गर्दै हुनुहुन्छ?</string>
<string name="ext_permission_install_apps_warning">एक्सटेन्शनहरू स्थापना गर्न अनुमति आवश्यक छ। प्रदान गर्न यहाँ ट्याप गर्नुहोस्।</string>
<string name="ext_revoke_trust">विश्वसनीय अज्ञात एक्सटेन्शनहरू रद्द गर्नुहोस्</string>
<string name="information_empty_repos">तपाईंले कुनै पनि रिपो सेट गर्नु भएको छैन।</string>
<string name="label_add_repo_input">रिपो URL</string>
<string name="label_extension_repos">एक्सटेन्शन रिपो</string>
<string name="action_add_repo">रिपो थप्नुहोस्</string>
<string name="action_add_repo_message">Mihon मा अतिरिक्त रिपो थप्नुहोस्। URL को अन्त्यमा \"index.min.json\" हुनुपर्छ।</string>
<string name="action_apply">अप्लाई</string>
<string name="delete_repo_confirmation">के तपाइँ रिपो \"%s\" हटाउन चाहनुहुन्छ?</string>
<string name="action_open_repo">खुला स्रोत रिपो</string>
<string name="pref_storage_location">भण्डारण स्थान</string>
<string name="available_disk_space_info">उपलब्ध: %1$s / कुल: %2$s</string>
<string name="manga_interval_expected_update">नयाँ अध्यायहरू लगभग %1$s मा रिलीज हुने भविष्यवाणी गरिएको छ, हरेक %2$s को वरिपरि जाँच गर्दै।</string>
<string name="manga_interval_expected_update_soon">छिटै</string>
<string name="manga_interval_custom_amount">कस्टम अपडेट फ्रिक्वेन्सी:</string>
<string name="exclude_scanlators">स्क्यालेटरहरू समावेश नगर्नुहोस्</string>
<string name="no_scanlators_found">कुनै स्क्यालेटर फेला परेन</string>
<string name="pref_storage_usage">भण्डारण प्रयोग</string>
<string name="no_location_set">कुनै भण्डारण स्थान सेट गरिएको छैन</string>
<string name="pref_storage_location_info">स्वचालित ब्याकअप, अध्याय डाउनलोड, र स्थानीय स्रोतको लागि प्रयोग गरिन्छ।</string>
<string name="action_create">सिर्जना गर्नुहोस्</string>
<string name="invalid_backup_file_error">पूर्ण त्रुटि:</string>
<string name="private_settings">संवेदनशील सेटिङहरू समावेश गर्नुहोस् (जस्तै, ट्र्याकर लगइन टोकनहरू)</string>
</resources>

View File

@ -745,4 +745,61 @@
<string name="app_settings">Ustawienia aplikacji</string>
<string name="action_delete_repo">Usuń repozytorium</string>
<string name="action_add_repo">Dodaj repozytorium</string>
<string name="selected">Zaznaczone</string>
<string name="action_bar_up_description">Przewiń w górę</string>
<string name="onboarding_action_finish">Zaczynajmy</string>
<string name="onboarding_storage_help_action">Przewodnik po pamięci</string>
<string name="onboarding_permission_install_apps">Zainstaluj uprawnienia aplikacji</string>
<string name="onboarding_permission_install_apps_description">Do instalacji rozszerzeń.</string>
<string name="onboarding_permission_action_grant">Zezwól</string>
<string name="onboarding_guides_new_user">Pierwszy raz w %s? Zalecamy zapoznać się z poradnikiem.</string>
<string name="onboarding_guides_returning_user">Ponowna instalacja %s?</string>
<string name="label_extension_repos">Repozytoria rozszerzeń</string>
<string name="label_add_repo_input">Link repozytorium</string>
<string name="pref_storage_usage">Zużycie pamięci</string>
<string name="manga_interval_custom_amount">Niestandardowa częstotliwość aktualizacji:</string>
<string name="no_scanlators_found">Nie znaleziono skanlatorów</string>
<string name="file_null_uri_error">Nie wybrano pliku</string>
<string name="not_selected">Nie zaznaczone</string>
<string name="action_sort_tracker_score">Serwisy śledzące</string>
<string name="label_data_storage">Dane i pamięć</string>
<string name="pref_onboarding_guide">Szybka konfiguracja</string>
<string name="onboarding_permission_ignore_battery_opts_description">Unikaj przerywania długich operacji takich jak pobieranie rozdziałów, aktualizacje bibliotek lub przywracanie kopii zapasowej.</string>
<string name="onboarding_permission_notifications_description">Otrzymuj powiadomienia ze swojej biblioteki i więcej.</string>
<string name="theme_nord">Nord</string>
<string name="pref_relative_format">Użyj dat względnych</string>
<string name="pref_relative_format_summary">\"%1$s\" zamiast \"%2$s\"</string>
<string name="pref_library_update_smart_update">Inteligentna aktualizacja</string>
<string name="onboarding_description">Na początek ustawmy kilka rzeczy. Zawsze możesz je później zmienić w ustawieniach.</string>
<string name="onboarding_storage_help_info">Aktualizujesz ze starszej wersji i nie jesteś pewien co wybrać? Zobacz na przewodnik po pamięci.</string>
<string name="pref_update_only_in_release_period">Przewiduj następną aktualizację</string>
<string name="ext_permission_install_apps_warning">Uprawnienia są wymagane aby zainstalować rozszerzenia. Kliknij tutaj aby je przyznać.</string>
<string name="onboarding_storage_info">Wybierz folder gdzie %1$s będzie zapisywał pobrane rozdziały, kopie zapasowe i inne.
\n
\nZalecany jest dedykowany folder.
\n
\nWybrany folder:%2$s</string>
<string name="ext_revoke_trust">Unieważnij zaufanie nieznanym rozszerzeniom</string>
<string name="information_empty_repos">Nie masz ustawionych repozytoriów.</string>
<string name="action_add_repo_message">Dodaj repozytoria do Mihon. Powinien to być link z końcówką \"index.min.json\".</string>
<string name="error_repo_exists">To repozytorium jest już dodane!</string>
<string name="delete_repo_confirmation">Na pewno chcesz usunąć repozytorium \"%s\"?</string>
<string name="action_open_repo">Repozytorium open source</string>
<string name="pref_flash_page_summ">Redukuje ghosting na wyświetlaczach e-ink</string>
<string name="no_location_set">Brak ustawionej ścieżki pamięci</string>
<string name="pref_storage_location">Miejsce przechowywania danych</string>
<string name="pref_storage_location_info">Używane do automatycznych kopii zapasowych, pobierania rozdziałów i lokalnych źródeł.</string>
<string name="invalid_backup_file_error">Pełny błąd:</string>
<string name="track_activity_name">Login serwisu śledzącego</string>
<string name="action_create">Utwórz</string>
<string name="pref_flash_page">Włącz przerwy między stronami</string>
<string name="private_settings">Dołącz wrażliwe ustawienia (np. tokeny serwisu śledzącego)</string>
<string name="last_auto_backup_info">Ostatnia automatyczna kopia zapasowa: %s</string>
<string name="has_results">Ma wyniki</string>
<string name="manga_display_interval_title">Oszacuj co</string>
<string name="available_disk_space_info">Wolne: %1$s / Ogółem: %2$s</string>
<string name="manga_interval_expected_update_soon">Wkrótce</string>
<string name="licensed_manga_chapters_error">Licencjonowany - Brak rozdziałów</string>
<string name="skipped_reason_not_in_release_period">Pominięto, ponieważ nie spodziewano się dzisiaj żadnej publikacji</string>
<string name="exclude_scanlators">Wyklucz skanlatorów</string>
</resources>

View File

@ -64,4 +64,8 @@
<item quantity="one">Nästa kapitel</item>
<item quantity="other">Nästa %d kapitel</item>
</plurals>
<plurals name="num_repos">
<item quantity="one">%d förråd</item>
<item quantity="other">%d flera förråd</item>
</plurals>
</resources>

View File

@ -445,7 +445,7 @@
<string name="track_started_reading_date">Start datum</string>
<string name="pref_viewer_nav">Tryckzoner</string>
<string name="edge_nav">Kant</string>
<string name="kindlish_nav">Kindle-ish</string>
<string name="kindlish_nav">Kindle-lik</string>
<string name="l_nav">L-formad</string>
<string name="action_filter_tracked">Spåras</string>
<string name="right_and_left_nav">Höger och Vänster</string>
@ -616,7 +616,7 @@
<string name="appwidget_updates_description">Se dina nyligen uppdaterade biblioteket inlägg</string>
<string name="appwidget_unavailable_locked">Widget är inte tillgänglig när applåset är aktiverat</string>
<string name="update_already_running">En uppdatering pågår redan</string>
<string name="multi_lang">Multi</string>
<string name="multi_lang">Flerspråkig</string>
<string name="error_user_agent_string_blank">Strängen för användaragent kan inte vara tom</string>
<string name="are_you_sure">Är du säker\?</string>
<string name="updates_last_update_info">Biblioteket uppdaterades senast: %s</string>
@ -740,7 +740,7 @@
<string name="action_revert_to_default">Återgå till standard</string>
<string name="last_auto_backup_info">Senaste automatiska säkerhetskopieringen: %s</string>
<string name="no_scanlators_found">Inga scanlatorer hittades</string>
<string name="scanlator">Scanlator</string>
<string name="scanlator">Översättare</string>
<string name="pref_flash_page">Blinka vid sidbyte</string>
<string name="pref_storage_usage">Lagringsanvändning</string>
<string name="action_sort_tracker_score">Spårares betyg</string>
@ -784,4 +784,18 @@
<string name="onboarding_storage_help_info">Osäker på vad du ska välja då du uppdaterar från en äldre version? Se lagerhanteringsguiden för mer information.</string>
<string name="pref_library_update_smart_update">Smart uppdatering</string>
<string name="onboarding_storage_help_action">Lagerhanteringsguide</string>
<string name="theme_nord">Nord</string>
<string name="delete_repo_confirmation">Vill du ta bort förråd \"%s\"?</string>
<string name="ext_revoke_trust">Återkalla tillförlitliga okända tillägg</string>
<string name="label_extension_repos">Tilläggsförråd</string>
<string name="information_empty_repos">Du har inga förråd inställda.</string>
<string name="action_add_repo">Lägg till förråd</string>
<string name="label_add_repo_input">Förråd URL</string>
<string name="action_add_repo_message">Lägg till ytterliga förråd till Mihon. Detta ska vara en URL som slutar med \"index.min.json\".</string>
<string name="error_repo_exists">Detta förråd existerar redan!</string>
<string name="action_delete_repo">Ta bort förråd</string>
<string name="invalid_repo_name">Ogiltig förråds URL</string>
<string name="action_open_repo">Öppenkällkods förråd</string>
<string name="manga_interval_expected_update_soon">Snart</string>
<string name="manga_interval_custom_amount">Anpassad uppdateringsfrekvens:</string>
</resources>

View File

@ -1,7 +1,7 @@
<?xml version="1.0" encoding="utf-8"?>
<resources>
<string name="name">Ad</string>
<string name="categories">Ulamlar</string>
<string name="categories">Kategoriler</string>
<string name="manga">Kitaplık girdileri</string>
<string name="chapters">Bölümler</string>
<string name="track">İzleme</string>
@ -798,4 +798,4 @@
<string name="ext_revoke_trust">Güvenilen bilinmeyen uzantıları iptal et</string>
<string name="manga_interval_expected_update_soon">Yakında</string>
<string name="action_open_repo">ık kaynaklı depo</string>
</resources>
</resources>

View File

@ -95,4 +95,10 @@
<item quantity="many">%d днів</item>
<item quantity="other">%d днів</item>
</plurals>
<plurals name="num_repos">
<item quantity="one">%d репозиторій</item>
<item quantity="few">%d репозиторії</item>
<item quantity="many">%d репозиторіїв</item>
<item quantity="other">%d репозиторіїв</item>
</plurals>
</resources>

View File

@ -288,7 +288,7 @@
<string name="action_webview_refresh">刷新</string>
<string name="pref_category_library">书架</string>
<string name="ext_obsolete">废弃</string>
<string name="obsolete_extension_message">此插件已被废弃,可能无法正常运行或导致应用发生故障,建议卸载</string>
<string name="obsolete_extension_message">此插件已被废弃,可能无法正常运行或导致应用发生故障,建议卸载</string>
<string name="pref_date_format">日期格式</string>
<string name="pref_category_library_update">全局更新</string>
<string name="logout_title">要退出 %1$s 吗?</string>
@ -624,12 +624,12 @@
<string name="are_you_sure">你确定吗?</string>
<string name="multi_lang">多语言</string>
<string name="updates_last_update_info">书架更新时间:%s</string>
<string name="remove_manga">即将从书架中删除“%s”</string>
<string name="remove_manga">即将从书架中删除“%s”</string>
<string name="popular">热门</string>
<string name="missing_storage_permission">未授予存储权限</string>
<string name="skipped_reason_not_always_update">已跳过,因为作品无需更新</string>
<string name="action_search_hint">搜索…</string>
<string name="crash_screen_title">哦豁</string>
<string name="crash_screen_title">哦豁</string>
<string name="crash_screen_description">%s 发生了意外错误。建议你反馈时提供崩溃日志。</string>
<string name="crash_screen_restart_application">重启应用</string>
<string name="pref_appearance_summary">主题 • 日期格式</string>
@ -783,7 +783,7 @@
<string name="information_empty_repos">尚未设置仓库</string>
<string name="label_add_repo_input">仓库网址</string>
<string name="action_add_repo_message">在 Mihon 中添加仓库输入的网址结尾应为“index.min.json”。</string>
<string name="onboarding_storage_help_info">如果你是从旧版更新而来,请选择之前使用的“Mihon”目录</string>
<string name="onboarding_storage_help_info">如果你是从旧版更新而来,可以查看存储指南了解详情</string>
<string name="onboarding_storage_help_action">存储指南</string>
<string name="pref_storage_location">存储位置</string>
<string name="onboarding_storage_action_select">选择文件夹</string>

View File

@ -7,7 +7,7 @@
<item quantity="other">%d 個擴充套件可更新</item>
</plurals>
<plurals name="download_queue_summary">
<item quantity="other">剩餘 %1$s </item>
<item quantity="other">剩餘 %1$s </item>
</plurals>
<plurals name="manga_num_chapters">
<item quantity="other">共 %1$s 章</item>

View File

@ -180,7 +180,7 @@
<string name="scale_type_fit_width">符合頁寬</string>
<string name="scale_type_fit_height">符合頁高</string>
<string name="scale_type_original_size">原始大小</string>
<string name="scale_type_smart_fit">智慧填充</string>
<string name="scale_type_smart_fit">智慧填充</string>
<string name="pref_zoom_start">縮放原點</string>
<string name="zoom_start_automatic">自動</string>
<string name="zoom_start_left">左邊</string>
@ -304,7 +304,7 @@
<string name="lock_always">立即</string>
<string name="lock_when_idle">閒置時鎖定</string>
<string name="lock_with_biometrics">上鎖應用程式</string>
<string name="secure_screen_summary">在切換應用程式時隱藏預覽,並禁止擷取螢幕畫面</string>
<string name="secure_screen_summary">在切換應用程式時隱藏預覽,並禁止擷取螢幕畫面</string>
<string name="secure_screen">防窺畫面</string>
<string name="pref_category_security">隱私</string>
<string name="hide_notification_content">隱藏通知內容</string>
@ -790,7 +790,7 @@
<string name="delete_repo_confirmation">確定要刪除「%s」儲存庫嗎</string>
<string name="action_delete_repo">刪除儲存庫</string>
<string name="action_add_repo">新增儲存庫</string>
<string name="information_empty_repos">尚未新增任何儲存庫</string>
<string name="information_empty_repos">尚未新增任何儲存庫</string>
<string name="label_extension_repos">擴充套件儲存庫</string>
<string name="onboarding_storage_help_action">儲存空間指南</string>
<string name="onboarding_storage_help_info">從舊版升級而不確定該如何選擇嗎?請參閱儲存空間指南以取得更多資訊。</string>

View File

@ -11,17 +11,14 @@ import androidx.compose.foundation.gestures.anchoredDraggable
import androidx.compose.foundation.gestures.animateTo
import androidx.compose.foundation.interaction.MutableInteractionSource
import androidx.compose.foundation.layout.Box
import androidx.compose.foundation.layout.WindowInsets
import androidx.compose.foundation.layout.WindowInsetsSides
import androidx.compose.foundation.layout.fillMaxSize
import androidx.compose.foundation.layout.navigationBarsPadding
import androidx.compose.foundation.layout.offset
import androidx.compose.foundation.layout.only
import androidx.compose.foundation.layout.padding
import androidx.compose.foundation.layout.requiredWidthIn
import androidx.compose.foundation.layout.systemBars
import androidx.compose.foundation.layout.statusBarsPadding
import androidx.compose.foundation.layout.systemBarsPadding
import androidx.compose.foundation.layout.widthIn
import androidx.compose.foundation.layout.windowInsetsPadding
import androidx.compose.material3.MaterialTheme
import androidx.compose.material3.Surface
import androidx.compose.runtime.Composable
@ -177,10 +174,8 @@ fun AdaptiveSheet(
orientation = Orientation.Vertical,
enabled = enableSwipeDismiss,
)
.windowInsetsPadding(
WindowInsets.systemBars
.only(WindowInsetsSides.Top + WindowInsetsSides.Horizontal),
),
.navigationBarsPadding()
.statusBarsPadding(),
shape = MaterialTheme.shapes.extraLarge,
tonalElevation = tonalElevation,
content = {