Compare commits

...

5 Commits
v7.1 ... v4.4.9

Author SHA1 Message Date
Koitharu
5436c65b76 Update about settings 2023-04-19 18:26:19 +03:00
Koitharu
c590813a1a Filter GitHub assets by type 2023-04-19 18:24:50 +03:00
Koitharu
1cf36e1b41 Fix domain validator 2023-04-19 18:24:14 +03:00
Koitharu
5895a20af1 Update shikimori domain 2023-04-19 18:24:00 +03:00
Koitharu
fd5fd43b72 Update parsers 2023-04-19 18:23:36 +03:00
11 changed files with 59 additions and 70 deletions

View File

@@ -15,8 +15,8 @@ android {
applicationId 'org.koitharu.kotatsu' applicationId 'org.koitharu.kotatsu'
minSdkVersion 21 minSdkVersion 21
targetSdkVersion 33 targetSdkVersion 33
versionCode 524 versionCode 525
versionName '4.4.8' versionName '4.4.9'
generatedDensities = [] generatedDensities = []
testInstrumentationRunner "androidx.test.runner.AndroidJUnitRunner" testInstrumentationRunner "androidx.test.runner.AndroidJUnitRunner"
@@ -79,7 +79,7 @@ afterEvaluate {
} }
dependencies { dependencies {
//noinspection GradleDependency //noinspection GradleDependency
implementation('com.github.KotatsuApp:kotatsu-parsers:2340100999') { implementation('com.github.KotatsuApp:kotatsu-parsers:1b6d1456f3') {
exclude group: 'org.json', module: 'json' exclude group: 'org.json', module: 'json'
} }

View File

@@ -10,6 +10,8 @@ import kotlinx.coroutines.flow.asStateFlow
import kotlinx.coroutines.withContext import kotlinx.coroutines.withContext
import okhttp3.OkHttpClient import okhttp3.OkHttpClient
import okhttp3.Request import okhttp3.Request
import org.json.JSONArray
import org.json.JSONObject
import org.koitharu.kotatsu.BuildConfig import org.koitharu.kotatsu.BuildConfig
import org.koitharu.kotatsu.core.prefs.AppSettings import org.koitharu.kotatsu.core.prefs.AppSettings
import org.koitharu.kotatsu.parsers.util.await import org.koitharu.kotatsu.parsers.util.await
@@ -28,6 +30,7 @@ import javax.inject.Inject
import javax.inject.Singleton import javax.inject.Singleton
private const val CERT_SHA1 = "2C:19:C7:E8:07:61:2B:8E:94:51:1B:FD:72:67:07:64:5D:C2:58:AE" private const val CERT_SHA1 = "2C:19:C7:E8:07:61:2B:8E:94:51:1B:FD:72:67:07:64:5D:C2:58:AE"
private const val CONTENT_TYPE_APK = "application/vnd.android.package-archive"
@Singleton @Singleton
class AppUpdateRepository @Inject constructor( class AppUpdateRepository @Inject constructor(
@@ -46,7 +49,9 @@ class AppUpdateRepository @Inject constructor(
.url("https://api.github.com/repos/KotatsuApp/Kotatsu/releases?page=1&per_page=10") .url("https://api.github.com/repos/KotatsuApp/Kotatsu/releases?page=1&per_page=10")
val jsonArray = okHttp.newCall(request.build()).await().parseJsonArray() val jsonArray = okHttp.newCall(request.build()).await().parseJsonArray()
return jsonArray.mapJSONNotNull { json -> return jsonArray.mapJSONNotNull { json ->
val asset = json.optJSONArray("assets")?.optJSONObject(0) ?: return@mapJSONNotNull null val asset = json.optJSONArray("assets")?.find { jo ->
jo.optString("content_type") == CONTENT_TYPE_APK
} ?: return@mapJSONNotNull null
AppVersion( AppVersion(
id = json.getLong("id"), id = json.getLong("id"),
url = json.getString("html_url"), url = json.getString("html_url"),
@@ -103,4 +108,15 @@ class AppUpdateRepository @Inject constructor(
}.onFailure { error -> }.onFailure { error ->
error.printStackTraceDebug() error.printStackTraceDebug()
}.getOrNull() }.getOrNull()
private inline fun JSONArray.find(predicate: (JSONObject) -> Boolean): JSONObject? {
val size = length()
for (i in 0 until size) {
val jo = getJSONObject(i)
if (predicate(jo)) {
return jo
}
}
return null
}
} }

View File

@@ -26,7 +26,7 @@ import org.koitharu.kotatsu.scrobbling.common.domain.model.ScrobblerUser
import org.koitharu.kotatsu.utils.ext.toRequestBody import org.koitharu.kotatsu.utils.ext.toRequestBody
private const val REDIRECT_URI = "kotatsu://shikimori-auth" private const val REDIRECT_URI = "kotatsu://shikimori-auth"
private const val BASE_URL = "https://shikimori.one/" private const val BASE_URL = "https://shikimori.me/"
private const val MANGA_PAGE_SIZE = 10 private const val MANGA_PAGE_SIZE = 10
class ShikimoriRepository( class ShikimoriRepository(
@@ -195,15 +195,15 @@ class ShikimoriRepository(
id = json.getLong("id"), id = json.getLong("id"),
name = json.getString("name"), name = json.getString("name"),
altName = json.getStringOrNull("russian"), altName = json.getStringOrNull("russian"),
cover = json.getJSONObject("image").getString("preview").toAbsoluteUrl("shikimori.one"), cover = json.getJSONObject("image").getString("preview").toAbsoluteUrl("shikimori.me"),
url = json.getString("url").toAbsoluteUrl("shikimori.one"), url = json.getString("url").toAbsoluteUrl("shikimori.me"),
) )
private fun ScrobblerMangaInfo(json: JSONObject) = ScrobblerMangaInfo( private fun ScrobblerMangaInfo(json: JSONObject) = ScrobblerMangaInfo(
id = json.getLong("id"), id = json.getLong("id"),
name = json.getString("name"), name = json.getString("name"),
cover = json.getJSONObject("image").getString("preview").toAbsoluteUrl("shikimori.one"), cover = json.getJSONObject("image").getString("preview").toAbsoluteUrl("shikimori.me"),
url = json.getString("url").toAbsoluteUrl("shikimori.one"), url = json.getString("url").toAbsoluteUrl("shikimori.me"),
descriptionHtml = json.getString("description_html"), descriptionHtml = json.getString("description_html"),
) )

View File

@@ -1,11 +1,14 @@
package org.koitharu.kotatsu.settings package org.koitharu.kotatsu.settings
import okhttp3.HttpUrl
import okhttp3.internal.toCanonicalHost import okhttp3.internal.toCanonicalHost
import org.koitharu.kotatsu.R import org.koitharu.kotatsu.R
import org.koitharu.kotatsu.utils.EditTextValidator import org.koitharu.kotatsu.utils.EditTextValidator
class DomainValidator : EditTextValidator() { class DomainValidator : EditTextValidator() {
private val urlBuilder = HttpUrl.Builder()
override fun validate(text: String): ValidationResult { override fun validate(text: String): ValidationResult {
val trimmed = text.trim() val trimmed = text.trim()
if (trimmed.isEmpty()) { if (trimmed.isEmpty()) {
@@ -18,13 +21,7 @@ class DomainValidator : EditTextValidator() {
} }
} }
private fun checkCharacters(value: String): Boolean { private fun checkCharacters(value: String): Boolean = runCatching {
for (i in value.indices) { urlBuilder.host(value)
val c = value[i] }.isSuccess
if (c !in '\u0020'..'\u007e') {
return false
}
}
return true
}
} }

View File

@@ -36,6 +36,7 @@ class AboutSettingsFragment : BasePreferenceFragment(R.string.about) {
} }
findPreference<SwitchPreferenceCompat>(AppSettings.KEY_UPDATES_UNSTABLE)?.run { findPreference<SwitchPreferenceCompat>(AppSettings.KEY_UPDATES_UNSTABLE)?.run {
isEnabled = VersionId(BuildConfig.VERSION_NAME).isStable isEnabled = VersionId(BuildConfig.VERSION_NAME).isStable
if (!isEnabled) isChecked = true
} }
} }

View File

@@ -31,8 +31,7 @@ class AboutLinksPreference @JvmOverloads constructor(
binding.btn4pda, binding.btn4pda,
binding.btnDiscord, binding.btnDiscord,
binding.btnGithub, binding.btnGithub,
binding.btnReddit, binding.btnTelegram,
binding.btnTwitter,
).forEach { button -> ).forEach { button ->
TooltipCompat.setTooltipText(button, button.contentDescription) TooltipCompat.setTooltipText(button, button.contentDescription)
button.setOnClickListener(this) button.setOnClickListener(this)
@@ -43,8 +42,7 @@ class AboutLinksPreference @JvmOverloads constructor(
val urlResId = when (v.id) { val urlResId = when (v.id) {
R.id.btn_4pda -> R.string.url_forpda R.id.btn_4pda -> R.string.url_forpda
R.id.btn_discord -> R.string.url_discord R.id.btn_discord -> R.string.url_discord
R.id.btn_twitter -> R.string.url_twitter R.id.btn_telegram -> R.string.url_telegram
R.id.btn_reddit -> R.string.url_reddit
R.id.btn_github -> R.string.url_github R.id.btn_github -> R.string.url_github
else -> return else -> return
} }
@@ -59,9 +57,9 @@ class AboutLinksPreference @JvmOverloads constructor(
Intent.createChooser(intent, title) Intent.createChooser(intent, title)
} else { } else {
intent intent
} },
) )
} catch (_: ActivityNotFoundException) { } catch (_: ActivityNotFoundException) {
} }
} }
} }

View File

@@ -1,11 +0,0 @@
<vector
xmlns:android="http://schemas.android.com/apk/res/android"
android:width="24dp"
android:height="24dp"
android:tint="?attr/colorControlNormal"
android:viewportWidth="24"
android:viewportHeight="24">
<path
android:fillColor="#FF000000"
android:pathData="M14.5 15.41C14.58 15.5 14.58 15.69 14.5 15.8C13.77 16.5 12.41 16.56 12 16.56C11.61 16.56 10.25 16.5 9.54 15.8C9.44 15.69 9.44 15.5 9.54 15.41C9.65 15.31 9.82 15.31 9.92 15.41C10.38 15.87 11.33 16 12 16C12.69 16 13.66 15.87 14.1 15.41C14.21 15.31 14.38 15.31 14.5 15.41M10.75 13.04C10.75 12.47 10.28 12 9.71 12C9.14 12 8.67 12.47 8.67 13.04C8.67 13.61 9.14 14.09 9.71 14.08C10.28 14.08 10.75 13.61 10.75 13.04M14.29 12C13.72 12 13.25 12.5 13.25 13.05S13.72 14.09 14.29 14.09C14.86 14.09 15.33 13.61 15.33 13.05C15.33 12.5 14.86 12 14.29 12M22 12C22 17.5 17.5 22 12 22S2 17.5 2 12C2 6.5 6.5 2 12 2S22 6.5 22 12M18.67 12C18.67 11.19 18 10.54 17.22 10.54C16.82 10.54 16.46 10.7 16.2 10.95C15.2 10.23 13.83 9.77 12.3 9.71L12.97 6.58L15.14 7.05C15.16 7.6 15.62 8.04 16.18 8.04C16.75 8.04 17.22 7.57 17.22 7C17.22 6.43 16.75 5.96 16.18 5.96C15.77 5.96 15.41 6.2 15.25 6.55L12.82 6.03C12.75 6 12.68 6.03 12.63 6.07C12.57 6.11 12.54 6.17 12.53 6.24L11.79 9.72C10.24 9.77 8.84 10.23 7.82 10.96C7.56 10.71 7.2 10.56 6.81 10.56C6 10.56 5.35 11.21 5.35 12C5.35 12.61 5.71 13.11 6.21 13.34C6.19 13.5 6.18 13.62 6.18 13.78C6.18 16 8.79 17.85 12 17.85C15.23 17.85 17.85 16.03 17.85 13.78C17.85 13.64 17.84 13.5 17.81 13.34C18.31 13.11 18.67 12.6 18.67 12Z" />
</vector>

View File

@@ -0,0 +1,10 @@
<vector xmlns:android="http://schemas.android.com/apk/res/android"
android:width="24dp"
android:height="24dp"
android:viewportWidth="512"
android:viewportHeight="512">
<path
android:pathData="m196.03,328.68 l162,118.8c16.8,10.8 31.2,4.8 36,-16.8l66,-309.6c6,-26.4 -10.8,-38.4 -28.8,-30L46.03,239.88c-25.2,9.6 -25.2,25.2 -4.8,31.2l99.6,31.2 228,-145.2c10.8,-6 20.4,-3.6 13.2,4.8"
android:strokeWidth="1.2"
android:fillColor="#000000"/>
</vector>

View File

@@ -1,11 +0,0 @@
<vector
xmlns:android="http://schemas.android.com/apk/res/android"
android:width="24dp"
android:height="24dp"
android:tint="?attr/colorControlNormal"
android:viewportWidth="24"
android:viewportHeight="24">
<path
android:fillColor="@android:color/white"
android:pathData="M22.46,6C21.69,6.35 20.86,6.58 20,6.69C20.88,6.16 21.56,5.32 21.88,4.31C21.05,4.81 20.13,5.16 19.16,5.36C18.37,4.5 17.26,4 16,4C13.65,4 11.73,5.92 11.73,8.29C11.73,8.63 11.77,8.96 11.84,9.27C8.28,9.09 5.11,7.38 3,4.79C2.63,5.42 2.42,6.16 2.42,6.94C2.42,8.43 3.17,9.75 4.33,10.5C3.62,10.5 2.96,10.3 2.38,10C2.38,10 2.38,10 2.38,10.03C2.38,12.11 3.86,13.85 5.82,14.24C5.46,14.34 5.08,14.39 4.69,14.39C4.42,14.39 4.15,14.36 3.89,14.31C4.43,16 6,17.26 7.89,17.29C6.43,18.45 4.58,19.13 2.56,19.13C2.22,19.13 1.88,19.11 1.54,19.07C3.44,20.29 5.7,21 8.12,21C16,21 20.33,14.46 20.33,8.79C20.33,8.6 20.33,8.42 20.32,8.23C21.16,7.63 21.88,6.87 22.46,6Z" />
</vector>

View File

@@ -1,5 +1,6 @@
<?xml version="1.0" encoding="utf-8"?> <?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" <LinearLayout
xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto" xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools" xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent" android:layout_width="match_parent"
@@ -7,13 +8,13 @@
android:gravity="center"> android:gravity="center">
<ImageButton <ImageButton
android:id="@+id/btn_4pda" android:id="@+id/btn_github"
android:layout_width="wrap_content" android:layout_width="wrap_content"
android:layout_height="wrap_content" android:layout_height="wrap_content"
android:background="?attr/selectableItemBackgroundBorderless" android:background="?attr/selectableItemBackgroundBorderless"
android:contentDescription="4PDA" android:contentDescription="GitHub"
android:padding="16dp" android:padding="16dp"
android:src="@drawable/ic_4pda" android:src="@drawable/ic_github"
app:tint="?attr/colorAccent" app:tint="?attr/colorAccent"
tools:ignore="HardcodedText" /> tools:ignore="HardcodedText" />
@@ -29,36 +30,25 @@
tools:ignore="HardcodedText" /> tools:ignore="HardcodedText" />
<ImageButton <ImageButton
android:id="@+id/btn_twitter" android:id="@+id/btn_telegram"
android:layout_width="wrap_content" android:layout_width="wrap_content"
android:layout_height="wrap_content" android:layout_height="wrap_content"
android:background="?attr/selectableItemBackgroundBorderless" android:background="?attr/selectableItemBackgroundBorderless"
android:contentDescription="Twitter" android:contentDescription="Telegram"
android:padding="16dp" android:padding="16dp"
android:src="@drawable/ic_twitter" android:src="@drawable/ic_telegram"
app:tint="?attr/colorAccent" app:tint="?attr/colorAccent"
tools:ignore="HardcodedText" /> tools:ignore="HardcodedText" />
<ImageButton <ImageButton
android:id="@+id/btn_reddit" android:id="@+id/btn_4pda"
android:layout_width="wrap_content" android:layout_width="wrap_content"
android:layout_height="wrap_content" android:layout_height="wrap_content"
android:background="?attr/selectableItemBackgroundBorderless" android:background="?attr/selectableItemBackgroundBorderless"
android:contentDescription="Reddit" android:contentDescription="4PDA"
android:padding="16dp" android:padding="16dp"
android:src="@drawable/ic_reddit" android:src="@drawable/ic_4pda"
app:tint="?attr/colorAccent" app:tint="?attr/colorAccent"
tools:ignore="HardcodedText" /> tools:ignore="HardcodedText" />
<ImageButton </LinearLayout>
android:id="@+id/btn_github"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:background="?attr/selectableItemBackgroundBorderless"
android:contentDescription="GitHub"
android:padding="16dp"
android:src="@drawable/ic_github"
app:tint="?attr/colorAccent"
tools:ignore="HardcodedText" />
</LinearLayout>

View File

@@ -3,8 +3,7 @@
<string name="url_github" translatable="false">https://github.com/KotatsuApp/Kotatsu</string> <string name="url_github" translatable="false">https://github.com/KotatsuApp/Kotatsu</string>
<string name="url_discord" translatable="false">https://discord.gg/NNJ5RgVBC5</string> <string name="url_discord" translatable="false">https://discord.gg/NNJ5RgVBC5</string>
<string name="url_forpda" translatable="false">https://4pda.to/forum/index.php?showtopic=697669</string> <string name="url_forpda" translatable="false">https://4pda.to/forum/index.php?showtopic=697669</string>
<string name="url_twitter" translatable="false">https://twitter.com/kotatsuapp</string> <string name="url_telegram" translatable="false">https://t.me/kotatsuapp</string>
<string name="url_reddit" translatable="false">https://reddit.com/user/kotatsuapp</string>
<string name="url_weblate" translatable="false">https://hosted.weblate.org/engage/kotatsu</string> <string name="url_weblate" translatable="false">https://hosted.weblate.org/engage/kotatsu</string>
<string name="url_error_report" translatable="false">https://acra.kotatsu.app/report</string> <string name="url_error_report" translatable="false">https://acra.kotatsu.app/report</string>
<string name="account_type_sync" translatable="false">org.kotatsu.sync</string> <string name="account_type_sync" translatable="false">org.kotatsu.sync</string>