Reduce memory usage
This commit is contained in:
@@ -3,6 +3,7 @@ package org.koitharu.kotatsu.core.db.entity
|
||||
import androidx.room.Embedded
|
||||
import androidx.room.Junction
|
||||
import androidx.room.Relation
|
||||
import org.koitharu.kotatsu.utils.ext.mapToSet
|
||||
|
||||
data class MangaWithTags(
|
||||
@Embedded val manga: MangaEntity,
|
||||
@@ -14,7 +15,7 @@ data class MangaWithTags(
|
||||
val tags: List<TagEntity>
|
||||
) {
|
||||
|
||||
fun toManga() = manga.toManga(tags.map {
|
||||
fun toManga() = manga.toManga(tags.mapToSet {
|
||||
it.toMangaTag()
|
||||
}.toSet())
|
||||
})
|
||||
}
|
||||
@@ -4,6 +4,7 @@ import androidx.room.Embedded
|
||||
import androidx.room.Junction
|
||||
import androidx.room.Relation
|
||||
import org.koitharu.kotatsu.core.model.TrackingLogItem
|
||||
import org.koitharu.kotatsu.utils.ext.mapToSet
|
||||
import java.util.*
|
||||
|
||||
data class TrackLogWithManga(
|
||||
@@ -24,7 +25,7 @@ data class TrackLogWithManga(
|
||||
fun toTrackingLogItem() = TrackingLogItem(
|
||||
id = trackLog.id,
|
||||
chapters = trackLog.chapters.split('\n').filterNot { x -> x.isEmpty() },
|
||||
manga = manga.toManga(tags.map { x -> x.toMangaTag() }.toSet()),
|
||||
manga = manga.toManga(tags.mapToSet { x -> x.toMangaTag() }),
|
||||
createdAt = Date(trackLog.createdAt)
|
||||
)
|
||||
}
|
||||
@@ -1,5 +1,6 @@
|
||||
package org.koitharu.kotatsu.core.parser.site
|
||||
|
||||
import androidx.collection.arraySetOf
|
||||
import org.koitharu.kotatsu.R
|
||||
import org.koitharu.kotatsu.core.exceptions.ParseException
|
||||
import org.koitharu.kotatsu.core.model.*
|
||||
@@ -13,7 +14,11 @@ abstract class ChanRepository(loaderContext: MangaLoaderContext) : RemoteMangaRe
|
||||
|
||||
protected abstract val defaultDomain: String
|
||||
|
||||
override val sortOrders = setOf(SortOrder.NEWEST, SortOrder.POPULARITY, SortOrder.ALPHABETICAL)
|
||||
override val sortOrders = arraySetOf(
|
||||
SortOrder.NEWEST,
|
||||
SortOrder.POPULARITY,
|
||||
SortOrder.ALPHABETICAL
|
||||
)
|
||||
|
||||
override suspend fun getList(
|
||||
offset: Int,
|
||||
@@ -51,13 +56,13 @@ abstract class ChanRepository(loaderContext: MangaLoaderContext) : RemoteMangaRe
|
||||
coverUrl = row.selectFirst("div.manga_images")?.selectFirst("img")
|
||||
?.attr("src")?.withDomain(domain).orEmpty(),
|
||||
tags = safe {
|
||||
row.selectFirst("div.genre")?.select("a")?.map {
|
||||
row.selectFirst("div.genre")?.select("a")?.mapToSet {
|
||||
MangaTag(
|
||||
title = it.text(),
|
||||
key = it.attr("href").substringAfterLast('/').urlEncoded(),
|
||||
source = source
|
||||
)
|
||||
}?.toSet()
|
||||
}
|
||||
}.orEmpty(),
|
||||
source = source
|
||||
)
|
||||
@@ -118,17 +123,17 @@ abstract class ChanRepository(loaderContext: MangaLoaderContext) : RemoteMangaRe
|
||||
val doc = loaderContext.httpGet("https://$domain/catalog").parseHtml()
|
||||
val root = doc.body().selectFirst("div.main_fon").getElementById("side")
|
||||
.select("ul").last()
|
||||
return root.select("li.sidetag").map { li ->
|
||||
return root.select("li.sidetag").mapToSet { li ->
|
||||
val a = li.children().last()
|
||||
MangaTag(
|
||||
title = a.text().capitalize(),
|
||||
key = a.attr("href").substringAfterLast('/'),
|
||||
source = source
|
||||
)
|
||||
}.toSet()
|
||||
}
|
||||
}
|
||||
|
||||
override fun onCreatePreferences() = setOf(R.string.key_parser_domain)
|
||||
override fun onCreatePreferences() = arraySetOf(R.string.key_parser_domain)
|
||||
|
||||
private fun getSortKey(sortOrder: SortOrder?) =
|
||||
when (sortOrder ?: sortOrders.minByOrNull { it.ordinal }) {
|
||||
|
||||
@@ -1,20 +1,18 @@
|
||||
package org.koitharu.kotatsu.core.parser.site
|
||||
|
||||
import androidx.collection.arraySetOf
|
||||
import org.koitharu.kotatsu.R
|
||||
import org.koitharu.kotatsu.core.exceptions.ParseException
|
||||
import org.koitharu.kotatsu.core.model.*
|
||||
import org.koitharu.kotatsu.core.parser.RemoteMangaRepository
|
||||
import org.koitharu.kotatsu.domain.MangaLoaderContext
|
||||
import org.koitharu.kotatsu.utils.ext.map
|
||||
import org.koitharu.kotatsu.utils.ext.mapIndexed
|
||||
import org.koitharu.kotatsu.utils.ext.parseHtml
|
||||
import org.koitharu.kotatsu.utils.ext.parseJson
|
||||
import org.koitharu.kotatsu.utils.ext.*
|
||||
|
||||
class DesuMeRepository(loaderContext: MangaLoaderContext) : RemoteMangaRepository(loaderContext) {
|
||||
|
||||
override val source = MangaSource.DESUME
|
||||
|
||||
override val sortOrders = setOf(
|
||||
override val sortOrders = arraySetOf(
|
||||
SortOrder.UPDATED,
|
||||
SortOrder.POPULARITY,
|
||||
SortOrder.NEWEST,
|
||||
@@ -76,13 +74,13 @@ class DesuMeRepository(loaderContext: MangaLoaderContext) : RemoteMangaRepositor
|
||||
val json = loaderContext.httpGet(url).parseJson().getJSONObject("response")
|
||||
?: throw ParseException("Invalid response")
|
||||
return manga.copy(
|
||||
tags = json.getJSONArray("genres").map {
|
||||
tags = json.getJSONArray("genres").mapToSet {
|
||||
MangaTag(
|
||||
key = it.getString("text"),
|
||||
title = it.getString("russian"),
|
||||
source = manga.source
|
||||
)
|
||||
}.toSet(),
|
||||
},
|
||||
description = json.getString("description"),
|
||||
chapters = json.getJSONObject("chapters").getJSONArray("list").mapIndexed { i, it ->
|
||||
val chid = it.getLong("id")
|
||||
@@ -113,16 +111,16 @@ class DesuMeRepository(loaderContext: MangaLoaderContext) : RemoteMangaRepositor
|
||||
val domain = conf.getDomain(DOMAIN)
|
||||
val doc = loaderContext.httpGet("https://$domain/manga/").parseHtml()
|
||||
val root = doc.body().getElementById("animeFilter").selectFirst(".catalog-genres")
|
||||
return root.select("li").map {
|
||||
return root.select("li").mapToSet {
|
||||
MangaTag(
|
||||
source = source,
|
||||
key = it.selectFirst("input").attr("data-genre"),
|
||||
title = it.selectFirst("label").text()
|
||||
)
|
||||
}.toSet()
|
||||
}
|
||||
}
|
||||
|
||||
override fun onCreatePreferences() = setOf(R.string.key_parser_domain)
|
||||
override fun onCreatePreferences() = arraySetOf(R.string.key_parser_domain)
|
||||
|
||||
private fun getSortKey(sortOrder: SortOrder?) =
|
||||
when (sortOrder) {
|
||||
|
||||
@@ -1,5 +1,6 @@
|
||||
package org.koitharu.kotatsu.core.parser.site
|
||||
|
||||
import androidx.collection.arraySetOf
|
||||
import org.koitharu.kotatsu.R
|
||||
import org.koitharu.kotatsu.core.exceptions.ParseException
|
||||
import org.koitharu.kotatsu.core.model.*
|
||||
@@ -12,7 +13,7 @@ abstract class GroupleRepository(loaderContext: MangaLoaderContext) :
|
||||
|
||||
protected abstract val defaultDomain: String
|
||||
|
||||
override val sortOrders = setOf(
|
||||
override val sortOrders = arraySetOf(
|
||||
SortOrder.UPDATED, SortOrder.POPULARITY,
|
||||
SortOrder.NEWEST, SortOrder.RATING
|
||||
//FIXME SortOrder.ALPHABETICAL
|
||||
@@ -70,13 +71,13 @@ abstract class GroupleRepository(loaderContext: MangaLoaderContext) :
|
||||
author = tileInfo?.selectFirst("a.person-link")?.text(),
|
||||
tags = safe {
|
||||
tileInfo?.select("a.element-link")
|
||||
?.map {
|
||||
?.mapToSet {
|
||||
MangaTag(
|
||||
title = it.text(),
|
||||
key = it.attr("href").substringAfterLast('/'),
|
||||
source = source
|
||||
)
|
||||
}?.toSet()
|
||||
}
|
||||
}.orEmpty(),
|
||||
state = when {
|
||||
node.selectFirst("div.tags")
|
||||
@@ -153,16 +154,16 @@ abstract class GroupleRepository(loaderContext: MangaLoaderContext) :
|
||||
val doc = loaderContext.httpGet("https://$domain/list/genres/sort_name").parseHtml()
|
||||
val root = doc.body().getElementById("mangaBox").selectFirst("div.leftContent")
|
||||
.selectFirst("table.table")
|
||||
return root.select("a.element-link").map { a ->
|
||||
return root.select("a.element-link").mapToSet { a ->
|
||||
MangaTag(
|
||||
title = a.text().capitalize(),
|
||||
key = a.attr("href").substringAfterLast('/'),
|
||||
source = source
|
||||
)
|
||||
}.toSet()
|
||||
}
|
||||
}
|
||||
|
||||
override fun onCreatePreferences() = setOf(R.string.key_parser_domain)
|
||||
override fun onCreatePreferences() = arraySetOf(R.string.key_parser_domain)
|
||||
|
||||
private fun getSortKey(sortOrder: SortOrder?) =
|
||||
when (sortOrder ?: sortOrders.minByOrNull { it.ordinal }) {
|
||||
|
||||
@@ -4,6 +4,7 @@ import org.koitharu.kotatsu.core.exceptions.ParseException
|
||||
import org.koitharu.kotatsu.core.model.*
|
||||
import org.koitharu.kotatsu.domain.MangaLoaderContext
|
||||
import org.koitharu.kotatsu.utils.ext.longHashCode
|
||||
import org.koitharu.kotatsu.utils.ext.mapToSet
|
||||
import org.koitharu.kotatsu.utils.ext.parseHtml
|
||||
import org.koitharu.kotatsu.utils.ext.withDomain
|
||||
|
||||
@@ -37,14 +38,14 @@ class HenChanRepository(loaderContext: MangaLoaderContext) : ChanRepository(load
|
||||
return manga.copy(
|
||||
description = root.getElementById("description")?.html()?.substringBeforeLast("<div"),
|
||||
largeCoverUrl = root.getElementById("cover")?.attr("src")?.withDomain(domain),
|
||||
tags = root.selectFirst("div.sidetags")?.select("li.sidetag")?.map {
|
||||
tags = root.selectFirst("div.sidetags")?.select("li.sidetag")?.mapToSet {
|
||||
val a = it.children().last()
|
||||
MangaTag(
|
||||
title = a.text(),
|
||||
key = a.attr("href").substringAfterLast('/'),
|
||||
source = source
|
||||
)
|
||||
}?.toSet() ?: manga.tags,
|
||||
} ?: manga.tags,
|
||||
chapters = listOf(
|
||||
MangaChapter(
|
||||
id = readLink.longHashCode(),
|
||||
|
||||
@@ -1,5 +1,7 @@
|
||||
package org.koitharu.kotatsu.core.parser.site
|
||||
|
||||
import androidx.collection.ArraySet
|
||||
import androidx.collection.arraySetOf
|
||||
import org.json.JSONArray
|
||||
import org.json.JSONObject
|
||||
import org.koitharu.kotatsu.R
|
||||
@@ -16,7 +18,7 @@ open class MangaLibRepository(loaderContext: MangaLoaderContext) :
|
||||
|
||||
override val source = MangaSource.MANGALIB
|
||||
|
||||
override val sortOrders = setOf(
|
||||
override val sortOrders = arraySetOf(
|
||||
SortOrder.RATING,
|
||||
SortOrder.ALPHABETICAL,
|
||||
SortOrder.POPULARITY,
|
||||
@@ -68,7 +70,7 @@ open class MangaLibRepository(loaderContext: MangaLoaderContext) :
|
||||
}
|
||||
}
|
||||
|
||||
override fun onCreatePreferences() = setOf(R.string.key_parser_domain)
|
||||
override fun onCreatePreferences() = arraySetOf(R.string.key_parser_domain)
|
||||
|
||||
override suspend fun getDetails(manga: Manga): Manga {
|
||||
val doc = loaderContext.httpGet(manga.url + "?section=info").parseHtml()
|
||||
@@ -126,13 +128,13 @@ open class MangaLibRepository(loaderContext: MangaLoaderContext) :
|
||||
author = info.getElementsMatchingOwnText("Автор").firstOrNull()
|
||||
?.nextElementSibling()?.text() ?: manga.author,
|
||||
tags = info.getElementsMatchingOwnText("Жанры")?.firstOrNull()
|
||||
?.nextElementSibling()?.select("a")?.mapNotNull { a ->
|
||||
?.nextElementSibling()?.select("a")?.mapToSet { a ->
|
||||
MangaTag(
|
||||
title = a.text().capitalize(),
|
||||
key = a.attr("href").substringAfterLast('='),
|
||||
source = source
|
||||
)
|
||||
}?.toSet() ?: manga.tags,
|
||||
} ?: manga.tags,
|
||||
description = info.getElementsMatchingOwnText("Описание")?.firstOrNull()
|
||||
?.nextElementSibling()?.html(),
|
||||
chapters = chapters
|
||||
@@ -183,7 +185,7 @@ open class MangaLibRepository(loaderContext: MangaLoaderContext) :
|
||||
if (raw.startsWith("window.__DATA")) {
|
||||
val json = JSONObject(raw.substringAfter('=').substringBeforeLast(';'))
|
||||
val genres = json.getJSONObject("filters").getJSONArray("genres")
|
||||
val result = HashSet<MangaTag>(genres.length())
|
||||
val result = ArraySet<MangaTag>(genres.length())
|
||||
for (x in genres) {
|
||||
result += MangaTag(
|
||||
source = source,
|
||||
|
||||
@@ -1,5 +1,6 @@
|
||||
package org.koitharu.kotatsu.core.parser.site
|
||||
|
||||
import androidx.collection.arraySetOf
|
||||
import org.intellij.lang.annotations.Language
|
||||
import org.koitharu.kotatsu.R
|
||||
import org.koitharu.kotatsu.core.exceptions.ParseException
|
||||
@@ -13,7 +14,7 @@ class MangaTownRepository(loaderContext: MangaLoaderContext) : RemoteMangaReposi
|
||||
|
||||
override val source = MangaSource.MANGATOWN
|
||||
|
||||
override val sortOrders = setOf(
|
||||
override val sortOrders = arraySetOf(
|
||||
SortOrder.ALPHABETICAL,
|
||||
SortOrder.RATING,
|
||||
SortOrder.POPULARITY,
|
||||
@@ -71,13 +72,13 @@ class MangaTownRepository(loaderContext: MangaLoaderContext) : RemoteMangaReposi
|
||||
"completed" -> MangaState.FINISHED
|
||||
else -> null
|
||||
},
|
||||
tags = li.selectFirst("p.keyWord")?.select("a")?.mapNotNull tags@{ x ->
|
||||
tags = li.selectFirst("p.keyWord")?.select("a")?.mapNotNullToSet tags@{ x ->
|
||||
MangaTag(
|
||||
title = x.attr("title"),
|
||||
key = x.attr("href").parseTagKey() ?: return@tags null,
|
||||
source = MangaSource.MANGATOWN
|
||||
)
|
||||
}?.toSet().orEmpty(),
|
||||
}.orEmpty(),
|
||||
url = href
|
||||
)
|
||||
}
|
||||
@@ -150,22 +151,22 @@ class MangaTownRepository(loaderContext: MangaLoaderContext) : RemoteMangaReposi
|
||||
.getElementsContainingOwnText("Genres")
|
||||
.first()
|
||||
.nextElementSibling()
|
||||
return root.select("li").mapNotNull { li ->
|
||||
val a = li.selectFirst("a") ?: return@mapNotNull null
|
||||
return root.select("li").mapNotNullToSet { li ->
|
||||
val a = li.selectFirst("a") ?: return@mapNotNullToSet null
|
||||
val key = a.attr("href").parseTagKey()
|
||||
if (key.isNullOrEmpty()) {
|
||||
return@mapNotNull null
|
||||
return@mapNotNullToSet null
|
||||
}
|
||||
MangaTag(
|
||||
source = MangaSource.MANGATOWN,
|
||||
key = key,
|
||||
title = a.text()
|
||||
)
|
||||
}.toSet()
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
override fun onCreatePreferences() = setOf(R.string.key_parser_domain, R.string.key_parser_ssl)
|
||||
override fun onCreatePreferences() = arraySetOf(R.string.key_parser_domain, R.string.key_parser_ssl)
|
||||
|
||||
private fun String.parseTagKey() = split('/').findLast { TAG_REGEX matches it }
|
||||
|
||||
|
||||
@@ -1,5 +1,6 @@
|
||||
package org.koitharu.kotatsu.core.parser.site
|
||||
|
||||
import androidx.collection.arraySetOf
|
||||
import org.koitharu.kotatsu.R
|
||||
import org.koitharu.kotatsu.core.exceptions.ParseException
|
||||
import org.koitharu.kotatsu.core.model.*
|
||||
@@ -12,7 +13,7 @@ class NudeMoonRepository(loaderContext: MangaLoaderContext) : RemoteMangaReposit
|
||||
|
||||
override val source = MangaSource.NUDEMOON
|
||||
|
||||
override val sortOrders = setOf(SortOrder.NEWEST, SortOrder.POPULARITY, SortOrder.RATING)
|
||||
override val sortOrders = arraySetOf(SortOrder.NEWEST, SortOrder.POPULARITY, SortOrder.RATING)
|
||||
|
||||
init {
|
||||
loaderContext.insertCookies(
|
||||
@@ -133,7 +134,7 @@ class NudeMoonRepository(loaderContext: MangaLoaderContext) : RemoteMangaReposit
|
||||
}
|
||||
}
|
||||
|
||||
override fun onCreatePreferences() = setOf(R.string.key_parser_domain)
|
||||
override fun onCreatePreferences() = arraySetOf(R.string.key_parser_domain)
|
||||
|
||||
private fun getSortKey(sortOrder: SortOrder?) =
|
||||
when (sortOrder ?: sortOrders.minByOrNull { it.ordinal }) {
|
||||
|
||||
@@ -5,6 +5,7 @@ import android.content.SharedPreferences
|
||||
import android.content.res.Resources
|
||||
import android.provider.Settings
|
||||
import androidx.appcompat.app.AppCompatDelegate
|
||||
import androidx.collection.arraySetOf
|
||||
import androidx.core.content.edit
|
||||
import androidx.preference.PreferenceManager
|
||||
import org.koitharu.kotatsu.R
|
||||
@@ -44,7 +45,7 @@ class AppSettings private constructor(resources: Resources, private val prefs: S
|
||||
|
||||
val readerPageSwitch by StringSetPreferenceDelegate(
|
||||
resources.getString(R.string.key_reader_switchers),
|
||||
setOf(PAGE_SWITCH_TAPS)
|
||||
arraySetOf(PAGE_SWITCH_TAPS)
|
||||
)
|
||||
|
||||
var isTrafficWarningEnabled by BoolPreferenceDelegate(
|
||||
@@ -89,7 +90,7 @@ class AppSettings private constructor(resources: Resources, private val prefs: S
|
||||
|
||||
val trackSources by StringSetPreferenceDelegate(
|
||||
resources.getString(R.string.key_track_sources),
|
||||
setOf(TRACK_FAVOURITES, TRACK_HISTORY)
|
||||
arraySetOf(TRACK_FAVOURITES, TRACK_HISTORY)
|
||||
)
|
||||
|
||||
var appPassword by NullableStringPreferenceDelegate(
|
||||
|
||||
@@ -11,27 +11,28 @@ import org.koitharu.kotatsu.core.db.entity.MangaEntity
|
||||
import org.koitharu.kotatsu.core.db.entity.TagEntity
|
||||
import org.koitharu.kotatsu.core.model.FavouriteCategory
|
||||
import org.koitharu.kotatsu.core.model.Manga
|
||||
import org.koitharu.kotatsu.utils.ext.mapToSet
|
||||
|
||||
class FavouritesRepository(private val db: MangaDatabase) {
|
||||
|
||||
suspend fun getAllManga(): List<Manga> {
|
||||
val entities = db.favouritesDao.findAll()
|
||||
return entities.map { it.manga.toManga(it.tags.map(TagEntity::toMangaTag).toSet()) }
|
||||
return entities.map { it.manga.toManga(it.tags.mapToSet(TagEntity::toMangaTag)) }
|
||||
}
|
||||
|
||||
suspend fun getAllManga(offset: Int): List<Manga> {
|
||||
val entities = db.favouritesDao.findAll(offset, 20)
|
||||
return entities.map { it.manga.toManga(it.tags.map(TagEntity::toMangaTag).toSet()) }
|
||||
return entities.map { it.manga.toManga(it.tags.mapToSet(TagEntity::toMangaTag)) }
|
||||
}
|
||||
|
||||
suspend fun getManga(categoryId: Long): List<Manga> {
|
||||
val entities = db.favouritesDao.findAll(categoryId)
|
||||
return entities.map { it.manga.toManga(it.tags.map(TagEntity::toMangaTag).toSet()) }
|
||||
return entities.map { it.manga.toManga(it.tags.mapToSet(TagEntity::toMangaTag)) }
|
||||
}
|
||||
|
||||
suspend fun getManga(categoryId: Long, offset: Int): List<Manga> {
|
||||
val entities = db.favouritesDao.findAll(categoryId, offset, 20)
|
||||
return entities.map { it.manga.toManga(it.tags.map(TagEntity::toMangaTag).toSet()) }
|
||||
return entities.map { it.manga.toManga(it.tags.mapToSet(TagEntity::toMangaTag)) }
|
||||
}
|
||||
|
||||
suspend fun getAllCategories(): List<FavouriteCategory> {
|
||||
|
||||
@@ -13,6 +13,7 @@ import org.koitharu.kotatsu.core.db.entity.TagEntity
|
||||
import org.koitharu.kotatsu.core.model.Manga
|
||||
import org.koitharu.kotatsu.core.model.MangaHistory
|
||||
import org.koitharu.kotatsu.domain.tracking.TrackingRepository
|
||||
import org.koitharu.kotatsu.utils.ext.mapToSet
|
||||
|
||||
class HistoryRepository(private val db: MangaDatabase) : KoinComponent {
|
||||
|
||||
@@ -20,7 +21,7 @@ class HistoryRepository(private val db: MangaDatabase) : KoinComponent {
|
||||
|
||||
suspend fun getList(offset: Int, limit: Int = 20): List<Manga> {
|
||||
val entities = db.historyDao.findAll(offset, limit)
|
||||
return entities.map { it.manga.toManga(it.tags.map(TagEntity::toMangaTag).toSet()) }
|
||||
return entities.map { it.manga.toManga(it.tags.mapToSet(TagEntity::toMangaTag)) }
|
||||
}
|
||||
|
||||
suspend fun addOrUpdate(manga: Manga, chapterId: Long, page: Int, scroll: Int) {
|
||||
|
||||
@@ -8,7 +8,7 @@ import org.koitharu.kotatsu.core.model.MangaChapter
|
||||
import org.koitharu.kotatsu.core.model.MangaSource
|
||||
import org.koitharu.kotatsu.core.model.MangaTag
|
||||
import org.koitharu.kotatsu.utils.ext.getStringOrNull
|
||||
import org.koitharu.kotatsu.utils.ext.map
|
||||
import org.koitharu.kotatsu.utils.ext.mapToSet
|
||||
import org.koitharu.kotatsu.utils.ext.safe
|
||||
|
||||
class MangaIndex(source: String?) {
|
||||
@@ -51,13 +51,13 @@ class MangaIndex(source: String?) {
|
||||
rating = json.getDouble("rating").toFloat(),
|
||||
coverUrl = json.getString("cover"),
|
||||
description = json.getStringOrNull("description"),
|
||||
tags = json.getJSONArray("tags").map { x ->
|
||||
tags = json.getJSONArray("tags").mapToSet { x ->
|
||||
MangaTag(
|
||||
title = x.getString("title"),
|
||||
key = x.getString("key"),
|
||||
source = source
|
||||
)
|
||||
}.toSet(),
|
||||
},
|
||||
chapters = getChapters(json.getJSONObject("chapters"), source)
|
||||
)
|
||||
}
|
||||
|
||||
@@ -56,7 +56,7 @@ class DownloadService : BaseService() {
|
||||
when (intent?.action) {
|
||||
ACTION_DOWNLOAD_START -> {
|
||||
val manga = intent.getParcelableExtra<Manga>(EXTRA_MANGA)
|
||||
val chapters = intent.getLongArrayExtra(EXTRA_CHAPTERS_IDS)?.toSet()
|
||||
val chapters = intent.getLongArrayExtra(EXTRA_CHAPTERS_IDS)?.toArraySet()
|
||||
if (manga != null) {
|
||||
jobs[startId] = downloadManga(manga, chapters, startId)
|
||||
Toast.makeText(this, R.string.manga_downloading_, Toast.LENGTH_SHORT).show()
|
||||
|
||||
@@ -7,6 +7,7 @@ import org.koin.core.component.get
|
||||
import org.koitharu.kotatsu.core.model.Manga
|
||||
import org.koitharu.kotatsu.domain.favourites.FavouritesRepository
|
||||
import org.koitharu.kotatsu.ui.base.BasePresenter
|
||||
import org.koitharu.kotatsu.utils.ext.mapToSet
|
||||
|
||||
@InjectViewState
|
||||
class FavouriteCategoriesPresenter : BasePresenter<FavouriteCategoriesView>() {
|
||||
@@ -29,7 +30,7 @@ class FavouriteCategoriesPresenter : BasePresenter<FavouriteCategoriesView>() {
|
||||
fun loadMangaCategories(manga: Manga) {
|
||||
launchJob {
|
||||
val categories = repository.getCategories(manga.id)
|
||||
viewState.onCheckedCategoriesChanged(categories.map { it.id.toInt() }.toSet())
|
||||
viewState.onCheckedCategoriesChanged(categories.mapToSet { it.id.toInt() })
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -11,6 +11,7 @@ import org.koitharu.kotatsu.core.model.MangaSource
|
||||
import org.koitharu.kotatsu.core.prefs.AppSettings
|
||||
import org.koitharu.kotatsu.domain.MangaProviderFactory
|
||||
import org.koitharu.kotatsu.ui.base.list.OnRecyclerItemClickListener
|
||||
import org.koitharu.kotatsu.utils.ext.mapToSet
|
||||
import org.koitharu.kotatsu.utils.ext.safe
|
||||
|
||||
class SourcesAdapter(private val onItemClickListener: OnRecyclerItemClickListener<MangaSource>) :
|
||||
@@ -44,7 +45,7 @@ class SourcesAdapter(private val onItemClickListener: OnRecyclerItemClickListene
|
||||
} else {
|
||||
hiddenItems.add(holder.requireData())
|
||||
}
|
||||
settings.hiddenSources = hiddenItems.map { x -> x.name }.toSet()
|
||||
settings.hiddenSources = hiddenItems.mapToSet { x -> x.name }
|
||||
}
|
||||
holder.imageView_config.setOnClickListener { v ->
|
||||
onItemClickListener.onItemClick(holder.requireData(), holder.bindingAdapterPosition, v)
|
||||
|
||||
@@ -30,7 +30,28 @@ fun <T> List<T>.medianOrNull(): T? = when {
|
||||
|
||||
inline fun <T, R> Collection<T>.mapToSet(transform: (T) -> R): Set<R> {
|
||||
val destination = ArraySet<R>(size)
|
||||
for (item in this)
|
||||
for (item in this) {
|
||||
destination.add(transform(item))
|
||||
}
|
||||
return destination
|
||||
}
|
||||
|
||||
inline fun <T, R> Collection<T>.mapNotNullToSet(transform: (T) -> R?): Set<R> {
|
||||
val destination = ArraySet<R>(size)
|
||||
for (item in this) {
|
||||
destination.add(transform(item) ?: continue)
|
||||
}
|
||||
return destination
|
||||
}
|
||||
|
||||
fun LongArray.toArraySet(): Set<Long> {
|
||||
return when (size) {
|
||||
0 -> emptySet()
|
||||
1 -> setOf(this[0])
|
||||
else -> ArraySet<Long>(size).also { set ->
|
||||
for (item in this) {
|
||||
set.add(item)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -3,7 +3,7 @@ package org.koitharu.kotatsu.utils.ext
|
||||
import android.os.Bundle
|
||||
import androidx.fragment.app.Fragment
|
||||
|
||||
fun <T : Fragment> T.withArgs(size: Int, block: Bundle.() -> Unit): T {
|
||||
inline fun <T : Fragment> T.withArgs(size: Int, block: Bundle.() -> Unit): T {
|
||||
val b = Bundle(size)
|
||||
b.block()
|
||||
this.arguments = b
|
||||
|
||||
@@ -1,5 +1,6 @@
|
||||
package org.koitharu.kotatsu.utils.ext
|
||||
|
||||
import androidx.collection.ArraySet
|
||||
import org.json.JSONArray
|
||||
import org.json.JSONObject
|
||||
|
||||
@@ -36,4 +37,14 @@ private class JSONIterator(private val array: JSONArray) : Iterator<JSONObject>
|
||||
|
||||
override fun next(): JSONObject = array.getJSONObject(index++)
|
||||
|
||||
}
|
||||
|
||||
fun <T> JSONArray.mapToSet(block: (JSONObject) -> T): Set<T> {
|
||||
val len = length()
|
||||
val result = ArraySet<T>(len)
|
||||
for (i in 0 until len) {
|
||||
val jo = getJSONObject(i)
|
||||
result.add(block(jo))
|
||||
}
|
||||
return result
|
||||
}
|
||||
@@ -1,6 +1,7 @@
|
||||
package org.koitharu.kotatsu.utils.ext
|
||||
|
||||
import android.net.Uri
|
||||
import androidx.collection.arraySetOf
|
||||
import java.math.BigInteger
|
||||
import java.net.URLEncoder
|
||||
import java.security.MessageDigest
|
||||
@@ -71,7 +72,7 @@ fun String.transliterate(skipMissing: Boolean): String {
|
||||
}
|
||||
|
||||
fun String.toFileNameSafe() = this.transliterate(false)
|
||||
.replace(Regex("[^a-z0-9_\\-]", setOf(RegexOption.IGNORE_CASE)), " ")
|
||||
.replace(Regex("[^a-z0-9_\\-]", arraySetOf(RegexOption.IGNORE_CASE)), " ")
|
||||
.replace(Regex("\\s+"), "_")
|
||||
|
||||
fun String.ellipsize(maxLength: Int) = if (this.length > maxLength) {
|
||||
|
||||
@@ -143,7 +143,7 @@ fun View.measureWidth(): Int {
|
||||
} else vw
|
||||
}
|
||||
|
||||
fun ViewPager2.doOnPageChanged(callback: (Int) -> Unit) {
|
||||
inline fun ViewPager2.doOnPageChanged(crossinline callback: (Int) -> Unit) {
|
||||
registerOnPageChangeCallback(object : ViewPager2.OnPageChangeCallback() {
|
||||
|
||||
override fun onPageSelected(position: Int) {
|
||||
@@ -153,7 +153,7 @@ fun ViewPager2.doOnPageChanged(callback: (Int) -> Unit) {
|
||||
})
|
||||
}
|
||||
|
||||
fun RecyclerView.doOnCurrentItemChanged(callback: (Int) -> Unit) {
|
||||
inline fun RecyclerView.doOnCurrentItemChanged(crossinline callback: (Int) -> Unit) {
|
||||
addOnScrollListener(object : RecyclerView.OnScrollListener() {
|
||||
|
||||
private var lastItem = -1
|
||||
|
||||
Reference in New Issue
Block a user