diff --git a/app/build.gradle b/app/build.gradle
index 0574ceaac..00a9d4e72 100644
--- a/app/build.gradle
+++ b/app/build.gradle
@@ -6,15 +6,15 @@ plugins {
}
android {
- compileSdkVersion 30
+ compileSdkVersion 31
buildToolsVersion '30.0.3'
defaultConfig {
applicationId 'org.koitharu.kotatsu'
minSdkVersion 21
- targetSdkVersion 30
- versionCode 369
- versionName '2.0-b1'
+ targetSdkVersion 31
+ versionCode 370
+ versionName '2.0-b2'
generatedDensities = []
testInstrumentationRunner "androidx.test.runner.AndroidJUnitRunner"
@@ -82,7 +82,7 @@ dependencies {
implementation 'androidx.recyclerview:recyclerview:1.2.1'
implementation 'androidx.viewpager2:viewpager2:1.1.0-beta01'
implementation 'androidx.preference:preference-ktx:1.1.1'
- implementation 'androidx.work:work-runtime-ktx:2.6.0'
+ implementation 'androidx.work:work-runtime-ktx:2.7.0'
implementation 'com.google.android.material:material:1.4.0'
//noinspection LifecycleAnnotationProcessorWithJava8
kapt 'androidx.lifecycle:lifecycle-compiler:2.3.1'
@@ -93,13 +93,13 @@ dependencies {
implementation 'com.squareup.okhttp3:okhttp:4.9.1'
implementation 'com.squareup.okio:okio:2.10.0'
- implementation 'org.jsoup:jsoup:1.14.2'
+ implementation 'org.jsoup:jsoup:1.14.3'
implementation 'com.hannesdorfmann:adapterdelegates4-kotlin-dsl:4.3.0'
implementation 'com.hannesdorfmann:adapterdelegates4-kotlin-dsl-viewbinding:4.3.0'
implementation 'io.insert-koin:koin-android:3.1.2'
- implementation 'io.coil-kt:coil-base:1.3.2'
+ implementation 'io.coil-kt:coil-base:1.4.0'
implementation 'com.davemorrissey.labs:subsampling-scale-image-view-androidx:3.10.0'
implementation 'com.github.solkin:disk-lru-cache:1.3'
diff --git a/app/src/main/java/org/koitharu/kotatsu/core/parser/site/ChanRepository.kt b/app/src/main/java/org/koitharu/kotatsu/core/parser/site/ChanRepository.kt
index 86c6b884d..7dde9de2e 100644
--- a/app/src/main/java/org/koitharu/kotatsu/core/parser/site/ChanRepository.kt
+++ b/app/src/main/java/org/koitharu/kotatsu/core/parser/site/ChanRepository.kt
@@ -77,6 +77,7 @@ abstract class ChanRepository(loaderContext: MangaLoaderContext) : RemoteMangaRe
val doc = loaderContext.httpGet(manga.url.withDomain()).parseHtml()
val root =
doc.body().getElementById("dle-content") ?: throw ParseException("Cannot find root")
+ val dateFormat = SimpleDateFormat("yyyy-MM-dd", Locale.US)
return manga.copy(
description = root.getElementById("description")?.html()?.substringBeforeLast("
"favdesc"
}
- private fun parseChapterDate(string: String): Long {
- return SimpleDateFormat("yyyy-MM-dd", Locale.US).tryParse(string)
- }
-
}
\ No newline at end of file
diff --git a/app/src/main/java/org/koitharu/kotatsu/core/parser/site/GroupleRepository.kt b/app/src/main/java/org/koitharu/kotatsu/core/parser/site/GroupleRepository.kt
index 6bcce48f6..2f422cdad 100644
--- a/app/src/main/java/org/koitharu/kotatsu/core/parser/site/GroupleRepository.kt
+++ b/app/src/main/java/org/koitharu/kotatsu/core/parser/site/GroupleRepository.kt
@@ -109,6 +109,7 @@ abstract class GroupleRepository(loaderContext: MangaLoaderContext) :
val doc = loaderContext.httpGet(manga.url.withDomain(), HEADER).parseHtml()
val root = doc.body().getElementById("mangaBox")?.selectFirst("div.leftContent")
?: throw ParseException("Cannot find root")
+ val dateFormat = SimpleDateFormat("dd.MM.yy", Locale.US)
return manga.copy(
description = root.selectFirst("div.manga-description")?.html(),
largeCoverUrl = root.selectFirst("div.subject-cower")?.selectFirst("img")?.attr(
@@ -139,7 +140,7 @@ abstract class GroupleRepository(loaderContext: MangaLoaderContext) :
name = tr.selectFirst("a")?.text().orEmpty().removePrefix(manga.title).trim(),
number = i + 1,
url = href,
- uploadDate = parseChapterDate(tr.select("td.d-none").text()),
+ uploadDate = dateFormat.tryParse(tr.selectFirst("td.d-none")?.text()),
scanlator = translators,
source = source
)
@@ -234,10 +235,6 @@ abstract class GroupleRepository(loaderContext: MangaLoaderContext) :
return loaderContext.httpPost(url, payload)
}
- private fun parseChapterDate(string: String): Long {
- return SimpleDateFormat("dd.MM.yy", Locale.US).tryParse(string)
- }
-
private companion object {
private const val PAGE_SIZE = 70
diff --git a/app/src/main/java/org/koitharu/kotatsu/core/parser/site/MangaLibRepository.kt b/app/src/main/java/org/koitharu/kotatsu/core/parser/site/MangaLibRepository.kt
index b74aaabb5..efa574f8c 100644
--- a/app/src/main/java/org/koitharu/kotatsu/core/parser/site/MangaLibRepository.kt
+++ b/app/src/main/java/org/koitharu/kotatsu/core/parser/site/MangaLibRepository.kt
@@ -80,6 +80,7 @@ open class MangaLibRepository(loaderContext: MangaLoaderContext) :
val info = root.selectFirst("div.media-content")
val chaptersDoc = loaderContext.httpGet("$fullUrl?section=chapters").parseHtml()
val scripts = chaptersDoc.select("script")
+ val dateFormat = SimpleDateFormat("yyy-MM-dd", Locale.US)
var chapters: ArrayList? = null
scripts@ for (script in scripts) {
val raw = script.html().lines()
@@ -113,7 +114,9 @@ open class MangaLibRepository(loaderContext: MangaLoaderContext) :
url = url,
source = source,
number = total - i,
- uploadDate = parseChapterDate(item.getString("chapter_created_at").substringBefore(" ")),
+ uploadDate = dateFormat.tryParse(
+ item.getString("chapter_created_at").substringBefore(" ")
+ ),
scanlator = scanlator,
name = if (nameChapter.isNullOrBlank()) fullNameChapter else "$fullNameChapter - $nameChapter"
)
@@ -241,9 +244,4 @@ open class MangaLibRepository(loaderContext: MangaLoaderContext) :
)
}
}
-
- private fun parseChapterDate(string: String): Long {
- return SimpleDateFormat("yyy-MM-dd", Locale.US).tryParse(string)
- }
-
}
\ No newline at end of file
diff --git a/app/src/main/java/org/koitharu/kotatsu/core/parser/site/MangaOwlRepository.kt b/app/src/main/java/org/koitharu/kotatsu/core/parser/site/MangaOwlRepository.kt
index b47712ad8..ade883600 100644
--- a/app/src/main/java/org/koitharu/kotatsu/core/parser/site/MangaOwlRepository.kt
+++ b/app/src/main/java/org/koitharu/kotatsu/core/parser/site/MangaOwlRepository.kt
@@ -74,6 +74,7 @@ class MangaOwlRepository(loaderContext: MangaLoaderContext) : RemoteMangaReposit
val doc = loaderContext.httpGet(manga.publicUrl).parseHtml()
val info = doc.body().selectFirst("div.single_detail") ?: parseFailed("An error occurred while parsing")
val table = doc.body().selectFirst("div.single-grid-right") ?: parseFailed("An error occurred while parsing")
+ val dateFormat = SimpleDateFormat("MM/dd/yyyy", Locale.US)
return manga.copy(
description = info.selectFirst(".description")?.html(),
largeCoverUrl = info.select("img").first()?.let { img ->
@@ -100,7 +101,7 @@ class MangaOwlRepository(loaderContext: MangaLoaderContext) : RemoteMangaReposit
name = a.select("label").text(),
number = i + 1,
url = href,
- uploadDate = parseChapterDate(li.select("small:last-of-type").text()),
+ uploadDate = dateFormat.tryParse(li.selectFirst("small:last-of-type")?.text()),
source = MangaSource.MANGAOWL
)
}
@@ -157,9 +158,4 @@ class MangaOwlRepository(loaderContext: MangaLoaderContext) : RemoteMangaReposit
SortOrder.UPDATED -> "3"
else -> "3"
}
-
- private fun parseChapterDate(string: String): Long {
- return SimpleDateFormat("MM/dd/yyyy", Locale.US).tryParse(string)
- }
-
}
\ No newline at end of file
diff --git a/app/src/main/java/org/koitharu/kotatsu/core/parser/site/MangaTownRepository.kt b/app/src/main/java/org/koitharu/kotatsu/core/parser/site/MangaTownRepository.kt
index d40bdf96f..b23bce7a5 100644
--- a/app/src/main/java/org/koitharu/kotatsu/core/parser/site/MangaTownRepository.kt
+++ b/app/src/main/java/org/koitharu/kotatsu/core/parser/site/MangaTownRepository.kt
@@ -7,6 +7,7 @@ import org.koitharu.kotatsu.core.model.*
import org.koitharu.kotatsu.core.parser.RemoteMangaRepository
import org.koitharu.kotatsu.core.prefs.SourceSettings
import org.koitharu.kotatsu.utils.ext.*
+import java.text.DateFormat
import java.text.SimpleDateFormat
import java.util.*
@@ -97,6 +98,7 @@ class MangaTownRepository(loaderContext: MangaLoaderContext) :
val info = root.selectFirst("div.detail_info")?.selectFirst("ul")
val chaptersList = root.selectFirst("div.chapter_content")
?.selectFirst("ul.chapter_list")?.select("li")?.asReversed()
+ val dateFormat = SimpleDateFormat("MMM dd,yyyy", Locale.US)
return manga.copy(
tags = manga.tags + info?.select("li")?.find { x ->
x.selectFirst("b")?.ownText() == "Genre(s):"
@@ -118,7 +120,10 @@ class MangaTownRepository(loaderContext: MangaLoaderContext) :
url = href,
source = MangaSource.MANGATOWN,
number = i + 1,
- uploadDate = parseChapterDate(li.selectFirst("span.time")?.text().orEmpty()),
+ uploadDate = parseChapterDate(
+ dateFormat,
+ li.selectFirst("span.time")?.text()
+ ),
name = name.ifEmpty { "${manga.title} - ${i + 1}" }
)
}
@@ -169,11 +174,12 @@ class MangaTownRepository(loaderContext: MangaLoaderContext) :
}
}
- private fun parseChapterDate(date: String): Long {
+ private fun parseChapterDate(dateFormat: DateFormat, date: String?): Long {
return when {
+ date.isNullOrEmpty() -> 0L
date.contains("Today") -> Calendar.getInstance().timeInMillis
date.contains("Yesterday") -> Calendar.getInstance().apply { add(Calendar.DAY_OF_MONTH, -1) }.timeInMillis
- else -> SimpleDateFormat("MMM dd,yyyy", Locale.US).tryParse(date)
+ else -> dateFormat.tryParse(date)
}
}
diff --git a/app/src/main/java/org/koitharu/kotatsu/core/parser/site/MangareadRepository.kt b/app/src/main/java/org/koitharu/kotatsu/core/parser/site/MangareadRepository.kt
index 068016887..5cb3a1ef2 100644
--- a/app/src/main/java/org/koitharu/kotatsu/core/parser/site/MangareadRepository.kt
+++ b/app/src/main/java/org/koitharu/kotatsu/core/parser/site/MangareadRepository.kt
@@ -6,6 +6,7 @@ import org.koitharu.kotatsu.core.model.*
import org.koitharu.kotatsu.core.parser.RemoteMangaRepository
import org.koitharu.kotatsu.utils.WordSet
import org.koitharu.kotatsu.utils.ext.*
+import java.text.DateFormat
import java.text.SimpleDateFormat
import java.util.*
@@ -116,6 +117,7 @@ class MangareadRepository(
"manga" to mangaId.toString()
)
).parseHtml()
+ val dateFormat = SimpleDateFormat("MMMM dd, yyyy", Locale.US)
return manga.copy(
tags = root.selectFirst("div.genres-content")?.select("a")
?.mapNotNullToSet { a ->
@@ -140,7 +142,10 @@ class MangareadRepository(
name = a!!.ownText(),
number = i + 1,
url = href,
- uploadDate = parseChapterDate(doc2.selectFirst("span.chapter-release-date i")?.text()),
+ uploadDate = parseChapterDate(
+ dateFormat,
+ doc2.selectFirst("span.chapter-release-date i")?.text()
+ ),
source = MangaSource.MANGAREAD
)
}
@@ -165,7 +170,8 @@ class MangareadRepository(
}
}
- private fun parseChapterDate(date: String?): Long {
+ private fun parseChapterDate(dateFormat: DateFormat, date: String?): Long {
+
date ?: return 0
return when {
date.endsWith(" ago", ignoreCase = true) -> {
@@ -240,9 +246,5 @@ class MangareadRepository(
val pos = it.indexOf('=')
it.substring(0, pos) to it.substring(pos + 1)
}.toMutableMap()
-
- private val dateFormat by lazy {
- SimpleDateFormat("MMMM dd, yyyy", Locale.US)
- }
}
}
diff --git a/app/src/main/java/org/koitharu/kotatsu/core/parser/site/NineMangaRepository.kt b/app/src/main/java/org/koitharu/kotatsu/core/parser/site/NineMangaRepository.kt
index 5c0ad5185..0c00df31a 100644
--- a/app/src/main/java/org/koitharu/kotatsu/core/parser/site/NineMangaRepository.kt
+++ b/app/src/main/java/org/koitharu/kotatsu/core/parser/site/NineMangaRepository.kt
@@ -161,7 +161,7 @@ abstract class NineMangaRepository(
else -> null
}
- fun parseChapterDateByLang(date: String): Long {
+ private fun parseChapterDateByLang(date: String): Long {
val dateWords = date.split(" ")
if (dateWords.size == 3) {
diff --git a/app/src/main/java/org/koitharu/kotatsu/core/parser/site/RemangaRepository.kt b/app/src/main/java/org/koitharu/kotatsu/core/parser/site/RemangaRepository.kt
index 3a817b76b..bc37ead73 100644
--- a/app/src/main/java/org/koitharu/kotatsu/core/parser/site/RemangaRepository.kt
+++ b/app/src/main/java/org/koitharu/kotatsu/core/parser/site/RemangaRepository.kt
@@ -94,6 +94,7 @@ class RemangaRepository(loaderContext: MangaLoaderContext) : RemoteMangaReposito
val chapters = loaderContext.httpGet(
url = "https://api.$domain/api/titles/chapters/?branch_id=$branchId"
).parseJson().getJSONArray("content")
+ val dateFormat = SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ss", Locale.US)
return manga.copy(
description = content.getString("description"),
state = when (content.optJSONObject("status")?.getInt("id")) {
@@ -110,7 +111,7 @@ class RemangaRepository(loaderContext: MangaLoaderContext) : RemoteMangaReposito
},
chapters = chapters.mapIndexed { i, jo ->
val id = jo.getLong("id")
- val name = jo.getString("name").capitalize(Locale.ROOT)
+ val name = jo.getString("name").toTitleCase(Locale.ROOT)
val publishers = jo.getJSONArray("publishers")
MangaChapter(
id = generateUid(id),
@@ -127,7 +128,7 @@ class RemangaRepository(loaderContext: MangaLoaderContext) : RemoteMangaReposito
append(name)
}
},
- uploadDate = parseChapterDate(jo.getString("upload_date")),
+ uploadDate = dateFormat.tryParse(jo.getString("upload_date")),
scanlator = publishers.optJSONObject(0)?.getStringOrNull("name"),
source = MangaSource.REMANGA
)
@@ -178,10 +179,6 @@ class RemangaRepository(loaderContext: MangaLoaderContext) : RemoteMangaReposito
source = source
)
- private fun parseChapterDate(string: String): Long {
- return SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ss", Locale.US).tryParse(string)
- }
-
private companion object {
const val PAGE_SIZE = 30
diff --git a/app/src/main/java/org/koitharu/kotatsu/utils/ext/ParseExt.kt b/app/src/main/java/org/koitharu/kotatsu/utils/ext/ParseExt.kt
index 89e02566f..4da5a2cff 100644
--- a/app/src/main/java/org/koitharu/kotatsu/utils/ext/ParseExt.kt
+++ b/app/src/main/java/org/koitharu/kotatsu/utils/ext/ParseExt.kt
@@ -10,7 +10,7 @@ import org.jsoup.nodes.Document
import org.jsoup.nodes.Element
import org.jsoup.nodes.Node
import org.jsoup.select.Elements
-import java.text.SimpleDateFormat
+import java.text.DateFormat
fun Response.parseHtml(): Document {
try {
@@ -100,6 +100,10 @@ fun Element.css(property: String): String? {
return css.substringAfter(':').removeSuffix(';').trim()
}
-fun SimpleDateFormat.tryParse(str: String): Long = runCatching {
- parse(str)?.time ?: 0L
-}.getOrDefault(0L)
\ No newline at end of file
+fun DateFormat.tryParse(str: String?): Long = if (str.isNullOrEmpty()) {
+ 0L
+} else {
+ runCatching {
+ parse(str)?.time ?: 0L
+ }.getOrDefault(0L)
+}
\ No newline at end of file
diff --git a/app/src/main/java/org/koitharu/kotatsu/utils/ext/StringExt.kt b/app/src/main/java/org/koitharu/kotatsu/utils/ext/StringExt.kt
index 05d310506..7c66bacaf 100644
--- a/app/src/main/java/org/koitharu/kotatsu/utils/ext/StringExt.kt
+++ b/app/src/main/java/org/koitharu/kotatsu/utils/ext/StringExt.kt
@@ -52,6 +52,10 @@ fun String.toTitleCase(): String {
return replaceFirstChar { x -> x.uppercase() }
}
+fun String.toTitleCase(locale: Locale): String {
+ return replaceFirstChar { x -> x.uppercase(locale) }
+}
+
fun String.transliterate(skipMissing: Boolean): String {
val cyr = charArrayOf(
'а', 'б', 'в', 'г', 'д', 'е', 'ж', 'з', 'и', 'й', 'к', 'л', 'м', 'н', 'о', 'п',