Merge branch 'devel' into next

This commit is contained in:
Koitharu
2023-07-18 12:04:41 +03:00
13 changed files with 131 additions and 15 deletions

View File

@@ -81,7 +81,7 @@ afterEvaluate {
}
dependencies {
//noinspection GradleDependency
implementation('com.github.KotatsuApp:kotatsu-parsers:06a043d290') {
implementation('com.github.KotatsuApp:kotatsu-parsers:a1598fd712') {
exclude group: 'org.json', module: 'json'
}
@@ -127,8 +127,8 @@ dependencies {
implementation 'com.hannesdorfmann:adapterdelegates4-kotlin-dsl:4.3.2'
implementation 'com.hannesdorfmann:adapterdelegates4-kotlin-dsl-viewbinding:4.3.2'
implementation 'com.google.dagger:hilt-android:2.46.1'
kapt 'com.google.dagger:hilt-compiler:2.46.1'
implementation 'com.google.dagger:hilt-android:2.47'
kapt 'com.google.dagger:hilt-compiler:2.47'
implementation 'androidx.hilt:hilt-work:1.0.0'
kapt 'androidx.hilt:hilt-compiler:1.0.0'
@@ -157,6 +157,6 @@ dependencies {
androidTestImplementation 'androidx.room:room-testing:2.5.2'
androidTestImplementation 'com.squareup.moshi:moshi-kotlin:1.15.0'
androidTestImplementation 'com.google.dagger:hilt-android-testing:2.46.1'
kaptAndroidTest 'com.google.dagger:hilt-android-compiler:2.46.1'
androidTestImplementation 'com.google.dagger:hilt-android-testing:2.47'
kaptAndroidTest 'com.google.dagger:hilt-android-compiler:2.47'
}

View File

@@ -1,6 +1,7 @@
package org.koitharu.kotatsu.bookmarks.domain
import org.koitharu.kotatsu.list.ui.model.ListModel
import org.koitharu.kotatsu.local.data.ImageFileFilter
import org.koitharu.kotatsu.parsers.model.Manga
import org.koitharu.kotatsu.parsers.model.MangaPage
import java.util.Date
@@ -37,7 +38,8 @@ class Bookmark(
)
private fun isImageUrlDirect(): Boolean {
return imageUrl.substringAfterLast('.').length in 2..4
val extension = imageUrl.substringAfterLast('.')
return extension.isNotEmpty() && ImageFileFilter().isExtensionValid(extension)
}
override fun equals(other: Any?): Boolean {

View File

@@ -5,15 +5,19 @@ import coil.ImageLoader
import com.hannesdorfmann.adapterdelegates4.dsl.adapterDelegateViewBinding
import org.koitharu.kotatsu.R
import org.koitharu.kotatsu.bookmarks.domain.Bookmark
import org.koitharu.kotatsu.core.ui.drawable.TextDrawable
import org.koitharu.kotatsu.core.ui.image.CoverSizeResolver
import org.koitharu.kotatsu.core.ui.list.AdapterDelegateClickListenerAdapter
import org.koitharu.kotatsu.core.ui.list.OnListItemClickListener
import org.koitharu.kotatsu.core.util.ext.decodeRegion
import org.koitharu.kotatsu.core.util.ext.disposeImageRequest
import org.koitharu.kotatsu.core.util.ext.enqueueWith
import org.koitharu.kotatsu.core.util.ext.getThemeResId
import org.koitharu.kotatsu.core.util.ext.newImageRequest
import org.koitharu.kotatsu.core.util.ext.source
import org.koitharu.kotatsu.databinding.ItemBookmarkBinding
import org.koitharu.kotatsu.parsers.util.format
import com.google.android.material.R as materialR
fun bookmarkListAD(
coil: ImageLoader,

View File

@@ -0,0 +1,100 @@
package org.koitharu.kotatsu.core.ui.drawable
import android.annotation.SuppressLint
import android.content.Context
import android.graphics.Canvas
import android.graphics.Color
import android.graphics.ColorFilter
import android.graphics.Paint
import android.graphics.PixelFormat
import android.graphics.Typeface
import android.graphics.drawable.Drawable
import android.os.Build
import android.text.Layout
import android.text.StaticLayout
import android.text.TextPaint
import androidx.annotation.ColorInt
import androidx.annotation.Px
import androidx.annotation.StyleRes
import androidx.core.graphics.withTranslation
import com.google.android.material.resources.TextAppearance
import com.google.android.material.resources.TextAppearanceFontCallback
import org.koitharu.kotatsu.core.util.ext.getThemeColor
class TextDrawable(
val text: CharSequence,
) : Drawable() {
private val paint = TextPaint(Paint.ANTI_ALIAS_FLAG)
private var cachedLayout: StaticLayout? = null
@SuppressLint("RestrictedApi")
constructor(context: Context, text: CharSequence, @StyleRes textAppearanceId: Int) : this(text) {
val ta = TextAppearance(context, textAppearanceId)
paint.color = ta.textColor?.defaultColor ?: context.getThemeColor(android.R.attr.textColorPrimary, Color.BLACK)
paint.typeface = ta.fallbackFont
ta.getFontAsync(
context, paint,
object : TextAppearanceFontCallback() {
override fun onFontRetrieved(typeface: Typeface?, fontResolvedSynchronously: Boolean) = Unit
override fun onFontRetrievalFailed(reason: Int) = Unit
},
)
paint.letterSpacing = ta.letterSpacing
}
var alignment = Layout.Alignment.ALIGN_NORMAL
var lineSpacingMultiplier = 1f
@Px
var lineSpacingExtra = 0f
@get:ColorInt
var textColor: Int
get() = paint.color
set(@ColorInt value) {
paint.color = value
}
override fun draw(canvas: Canvas) {
val b = bounds
if (b.isEmpty) {
return
}
canvas.withTranslation(x = b.left.toFloat(), y = b.top.toFloat()) {
obtainLayout().draw(canvas)
}
}
override fun setAlpha(alpha: Int) {
paint.alpha = alpha
}
override fun setColorFilter(colorFilter: ColorFilter?) {
paint.setColorFilter(colorFilter)
}
@Suppress("DeprecatedCallableAddReplaceWith")
@Deprecated("Deprecated in Java")
override fun getOpacity(): Int = PixelFormat.TRANSLUCENT
private fun obtainLayout(): StaticLayout {
val width = bounds.width()
cachedLayout?.let {
if (it.width == width) {
return it
}
}
return if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) {
StaticLayout.Builder.obtain(text, 0, text.length, paint, width)
.setAlignment(alignment)
.setLineSpacing(lineSpacingExtra, lineSpacingMultiplier)
.setIncludePad(true)
.build()
} else {
@Suppress("DEPRECATION")
StaticLayout(text, paint, width, alignment, lineSpacingMultiplier, lineSpacingExtra, true)
}.also { cachedLayout = it }
}
}

View File

@@ -66,6 +66,13 @@ fun Context.getThemeColorStateList(
it.getColorStateList(0)
}
fun Context.getThemeResId(
@AttrRes resId: Int,
fallback: Int
): Int = obtainStyledAttributes(intArrayOf(resId)).use {
it.getResourceId(0, fallback)
}
fun TypedArray.getDrawableCompat(context: Context, index: Int): Drawable? {
val resId = getResourceId(index, 0)
return if (resId != 0) ContextCompat.getDrawable(context, resId) else null

View File

@@ -23,7 +23,7 @@ class ImageFileFilter : FilenameFilter, FileFilter {
return isExtensionValid(ext)
}
private fun isExtensionValid(ext: String): Boolean {
fun isExtensionValid(ext: String): Boolean {
return ext == "png" || ext == "jpg" || ext == "jpeg" || ext == "webp"
}
}

View File

@@ -13,7 +13,7 @@ enum class ScoreFormat {
POINT_5 -> score / 5f
POINT_3 -> score / 3f
}
}.coerceIn(0f, 1f)
companion object {

View File

@@ -173,7 +173,7 @@ class MALRepository @Inject constructor(
status = json.getString("status"),
chapter = json.getInt("num_chapters_read"),
comment = json.getString("comments"),
rating = json.getDouble("score").toFloat() / 10f,
rating = (json.getDouble("score").toFloat() / 10f).coerceIn(0f, 1f),
)
db.scrobblingDao.upsert(entity)
}

View File

@@ -190,7 +190,7 @@ class ShikimoriRepository @Inject constructor(
status = json.getString("status"),
chapter = json.getInt("chapters"),
comment = json.getString("text"),
rating = json.getDouble("score").toFloat() / 10f,
rating = (json.getDouble("score").toFloat() / 10f).coerceIn(0f, 1f),
)
db.scrobblingDao.upsert(entity)
}

View File

@@ -13,7 +13,6 @@ import kotlinx.coroutines.flow.onStart
import org.koitharu.kotatsu.core.db.MangaDatabase
import org.koitharu.kotatsu.core.model.FavouriteCategory
import org.koitharu.kotatsu.core.prefs.AppSettings
import org.koitharu.kotatsu.core.prefs.observeAsFlow
import org.koitharu.kotatsu.favourites.data.FavouriteCategoryEntity
import org.koitharu.kotatsu.favourites.data.toFavouriteCategory
import org.koitharu.kotatsu.favourites.data.toMangaList
@@ -52,8 +51,8 @@ class ShelfContentObserveUseCase @Inject constructor(
private fun observeLocalManga(sortOrder: SortOrder, limit: Int): Flow<List<Manga>> {
return combine<LocalManga?, String, Any?>(
localStorageChanges,
settings.observe().filter { it == AppSettings.KEY_LOCAL_MANGA_DIRS }
) { _, _ -> Any() }
settings.observe().filter { it == AppSettings.KEY_LOCAL_MANGA_DIRS }.onStart { emit("") }
) { a, b -> a to b }
.onStart { emit(null) }
.mapLatest {
localMangaRepository.getList(0, null, sortOrder).take(limit)

View File

@@ -225,4 +225,8 @@
<string name="various_languages">विभिन्न भाषाहरू</string>
<string name="search_chapters">अध्याय खोज्नुहोस्</string>
<string name="appearance">उपस्थिति</string>
<string name="history_shortcuts">हालैको मंगा सर्टकट देखाउनुहोस्</string>
<string name="reader_control_ltr_summary">दायाँ किनारामा ट्याप गर्नुहोस् वा दायाँ कुञ्जी थिच्दा सधैं अर्को पृष्ठमा स्विच हुन्छ</string>
<string name="reader_control_ltr">Ergonomic पाठक नियन्त्रण</string>
<string name="manga_error_description_pattern">त्रुटि विवरण:&lt;br&gt; &lt;tt&gt;%1$s&lt;/tt&gt;&lt;br&gt;&lt;br&gt; 1. &lt;a href=%2$s&gt;वेब ब्राउजरमा मंगा खोल्ने&lt;/a&gt; प्रयास गर्नुहोस् कि यो यसको स्रोतमा उपलब्ध छ&lt;br&gt; 2. निश्चित गर्नुहोस् कि तपाइँ &lt;a href=kotatsu://about&gt;Kotatsu को नवीनतम संस्करण&lt;/a&gt; प्रयोग गर्दै हुनुहुन्छ&lt;br&gt; 3. यदि यो उपलब्ध छ भने, विकासकर्ताहरूलाई त्रुटि रिपोर्ट पठाउनुहोस्।</string>
</resources>

View File

@@ -389,7 +389,7 @@
<string name="address">Địa chỉ</string>
<string name="invert_colors">Đảo màu</string>
<string name="invalid_port_number">Cổng không hợp lệ</string>
<string name="download_option_manual_selection">Chọn các chương bằng tay</string>
<string name="download_option_manual_selection">Chọn thủ công các chương</string>
<string name="download_option_all_unread">Tất cả các chương chưa đọc</string>
<string name="resume">Tiếp tục</string>
<string name="clear_new_chapters_counters">Xoá thông tin về chương mới</string>

View File

@@ -6,7 +6,7 @@ buildscript {
dependencies {
classpath 'com.android.tools.build:gradle:8.0.2'
classpath 'org.jetbrains.kotlin:kotlin-gradle-plugin:1.8.22'
classpath 'com.google.dagger:hilt-android-gradle-plugin:2.46.1'
classpath 'com.google.dagger:hilt-android-gradle-plugin:2.47'
}
}