Switch to different ktlint plugin

Should be better at incremental builds.
To format, run `./gradlew ktlintFormat`.
This commit is contained in:
arkon 2023-09-01 23:02:18 -04:00
parent 772db51593
commit d29b7c4e57
69 changed files with 628 additions and 291 deletions

View file

@ -3,5 +3,5 @@ indent_size=4
insert_final_newline=true insert_final_newline=true
ij_kotlin_allow_trailing_comma=true ij_kotlin_allow_trailing_comma=true
ij_kotlin_allow_trailing_comma_on_call_site=true ij_kotlin_allow_trailing_comma_on_call_site=true
ij_kotlin_name_count_to_use_star_import = 2147483647 ij_kotlin_name_count_to_use_star_import=2147483647
ij_kotlin_name_count_to_use_star_import_for_members = 2147483647 ij_kotlin_name_count_to_use_star_import_for_members=2147483647

View file

@ -1,5 +1,4 @@
import org.jetbrains.kotlin.gradle.tasks.KotlinCompile import org.jetbrains.kotlin.gradle.tasks.KotlinCompile
import org.jmailen.gradle.kotlinter.tasks.LintTask
plugins { plugins {
id("com.android.application") id("com.android.application")
@ -104,15 +103,17 @@ android {
} }
packaging { packaging {
resources.excludes.addAll(listOf( resources.excludes.addAll(
"META-INF/DEPENDENCIES", listOf(
"LICENSE.txt", "META-INF/DEPENDENCIES",
"META-INF/LICENSE", "LICENSE.txt",
"META-INF/LICENSE.txt", "META-INF/LICENSE",
"META-INF/README.md", "META-INF/LICENSE.txt",
"META-INF/NOTICE", "META-INF/README.md",
"META-INF/*.kotlin_module", "META-INF/NOTICE",
)) "META-INF/*.kotlin_module",
),
)
} }
dependenciesInfo { dependenciesInfo {
@ -264,7 +265,9 @@ androidComponents {
beforeVariants { variantBuilder -> beforeVariants { variantBuilder ->
// Disables standardBenchmark // Disables standardBenchmark
if (variantBuilder.buildType == "benchmark") { if (variantBuilder.buildType == "benchmark") {
variantBuilder.enable = variantBuilder.productFlavors.containsAll(listOf("default" to "dev")) variantBuilder.enable = variantBuilder.productFlavors.containsAll(
listOf("default" to "dev"),
)
} }
} }
onVariants(selector().withFlavor("default" to "standard")) { onVariants(selector().withFlavor("default" to "standard")) {
@ -275,10 +278,6 @@ androidComponents {
} }
tasks { tasks {
withType<LintTask>().configureEach {
exclude { it.file.path.contains("generated[\\\\/]".toRegex()) }
}
// See https://kotlinlang.org/docs/reference/experimental.html#experimental-status-of-experimental-api(-markers) // See https://kotlinlang.org/docs/reference/experimental.html#experimental-status-of-experimental-api(-markers)
withType<KotlinCompile> { withType<KotlinCompile> {
kotlinOptions.freeCompilerArgs += listOf( kotlinOptions.freeCompilerArgs += listOf(
@ -303,12 +302,12 @@ tasks {
kotlinOptions.freeCompilerArgs += listOf( kotlinOptions.freeCompilerArgs += listOf(
"-P", "-P",
"plugin:androidx.compose.compiler.plugins.kotlin:reportsDestination=" + "plugin:androidx.compose.compiler.plugins.kotlin:reportsDestination=" +
project.buildDir.absolutePath + "/compose_metrics" project.buildDir.absolutePath + "/compose_metrics",
) )
kotlinOptions.freeCompilerArgs += listOf( kotlinOptions.freeCompilerArgs += listOf(
"-P", "-P",
"plugin:androidx.compose.compiler.plugins.kotlin:metricsDestination=" + "plugin:androidx.compose.compiler.plugins.kotlin:metricsDestination=" +
project.buildDir.absolutePath + "/compose_metrics" project.buildDir.absolutePath + "/compose_metrics",
) )
} }
} }

View file

@ -162,7 +162,7 @@ fun CategoryDeleteDialog(
TextButton(onClick = { TextButton(onClick = {
onDelete() onDelete()
onDismissRequest() onDismissRequest()
},) { }) {
Text(text = stringResource(R.string.action_ok)) Text(text = stringResource(R.string.action_ok))
} }
}, },
@ -217,7 +217,7 @@ fun ChangeCategoryDialog(
tachiyomi.presentation.core.components.material.TextButton(onClick = { tachiyomi.presentation.core.components.material.TextButton(onClick = {
onDismissRequest() onDismissRequest()
onEditCategories() onEditCategories()
},) { }) {
Text(text = stringResource(R.string.action_edit)) Text(text = stringResource(R.string.action_edit))
} }
Spacer(modifier = Modifier.weight(1f)) Spacer(modifier = Modifier.weight(1f))

View file

@ -61,7 +61,7 @@ fun HistoryDeleteDialog(
TextButton(onClick = { TextButton(onClick = {
onDelete(removeEverything) onDelete(removeEverything)
onDismissRequest() onDismissRequest()
},) { }) {
Text(text = stringResource(R.string.action_remove)) Text(text = stringResource(R.string.action_remove))
} }
}, },
@ -90,7 +90,7 @@ fun HistoryDeleteAllDialog(
TextButton(onClick = { TextButton(onClick = {
onDelete() onDelete()
onDismissRequest() onDismissRequest()
},) { }) {
Text(text = stringResource(R.string.action_ok)) Text(text = stringResource(R.string.action_ok))
} }
}, },

View file

@ -91,7 +91,7 @@ fun SetIntervalDialog(
TextButton(onClick = { TextButton(onClick = {
onValueChanged(selectedInterval) onValueChanged(selectedInterval)
onDismissRequest() onDismissRequest()
},) { }) {
Text(text = stringResource(R.string.action_ok)) Text(text = stringResource(R.string.action_ok))
} }
}, },

View file

@ -108,11 +108,11 @@ fun MoreScreen(
stringResource(R.string.paused) stringResource(R.string.paused)
} else { } else {
"${stringResource(R.string.paused)}${ "${stringResource(R.string.paused)}${
pluralStringResource( pluralStringResource(
id = R.plurals.download_queue_summary, id = R.plurals.download_queue_summary,
count = pending, count = pending,
pending, pending,
) )
}" }"
} }
} }

View file

@ -4,7 +4,6 @@ import androidx.compose.runtime.Composable
import androidx.compose.runtime.remember import androidx.compose.runtime.remember
import androidx.compose.ui.graphics.vector.ImageVector import androidx.compose.ui.graphics.vector.ImageVector
import androidx.compose.ui.res.stringResource import androidx.compose.ui.res.stringResource
import eu.kanade.presentation.more.settings.Preference.PreferenceItem
import eu.kanade.tachiyomi.R import eu.kanade.tachiyomi.R
import eu.kanade.tachiyomi.data.track.TrackService import eu.kanade.tachiyomi.data.track.TrackService
import tachiyomi.core.preference.Preference as PreferenceData import tachiyomi.core.preference.Preference as PreferenceData

View file

@ -21,7 +21,7 @@ fun UpdatesDeleteConfirmationDialog(
TextButton(onClick = { TextButton(onClick = {
onConfirm() onConfirm()
onDismissRequest() onDismissRequest()
},) { }) {
Text(text = stringResource(R.string.action_ok)) Text(text = stringResource(R.string.action_ok))
} }
}, },

View file

@ -64,7 +64,7 @@ fun SourceFilterDialog(
Button(onClick = { Button(onClick = {
onFilter() onFilter()
onDismissRequest() onDismissRequest()
},) { }) {
Text(stringResource(R.string.action_filter)) Text(stringResource(R.string.action_filter))
} }
} }

View file

@ -271,7 +271,10 @@ private data class TrackStatusSelectorScreen(
selection = state.selection, selection = state.selection,
onSelectionChange = sm::setSelection, onSelectionChange = sm::setSelection,
selections = remember { sm.getSelections() }, selections = remember { sm.getSelections() },
onConfirm = { sm.setStatus(); navigator.pop() }, onConfirm = {
sm.setStatus()
navigator.pop()
},
onDismissRequest = navigator::pop, onDismissRequest = navigator::pop,
) )
} }
@ -322,7 +325,10 @@ private data class TrackChapterSelectorScreen(
selection = state.selection, selection = state.selection,
onSelectionChange = sm::setSelection, onSelectionChange = sm::setSelection,
range = remember { sm.getRange() }, range = remember { sm.getRange() },
onConfirm = { sm.setChapter(); navigator.pop() }, onConfirm = {
sm.setChapter()
navigator.pop()
},
onDismissRequest = navigator::pop, onDismissRequest = navigator::pop,
) )
} }
@ -378,7 +384,10 @@ private data class TrackScoreSelectorScreen(
selection = state.selection, selection = state.selection,
onSelectionChange = sm::setSelection, onSelectionChange = sm::setSelection,
selections = remember { sm.getSelections() }, selections = remember { sm.getSelections() },
onConfirm = { sm.setScore(); navigator.pop() }, onConfirm = {
sm.setScore()
navigator.pop()
},
onDismissRequest = navigator::pop, onDismissRequest = navigator::pop,
) )
} }
@ -495,7 +504,10 @@ private data class TrackDateSelectorScreen(
}, },
initialSelectedDateMillis = sm.initialSelection, initialSelectedDateMillis = sm.initialSelection,
selectableDates = selectableDates, selectableDates = selectableDates,
onConfirm = { sm.setDate(it); navigator.pop() }, onConfirm = {
sm.setDate(it)
navigator.pop()
},
onRemove = { sm.confirmRemoveDate(navigator) }.takeIf { canRemove }, onRemove = { sm.confirmRemoveDate(navigator) }.takeIf { canRemove },
onDismissRequest = navigator::pop, onDismissRequest = navigator::pop,
) )
@ -584,7 +596,10 @@ private data class TrackDateRemoverScreen(
Text(text = stringResource(android.R.string.cancel)) Text(text = stringResource(android.R.string.cancel))
} }
FilledTonalButton( FilledTonalButton(
onClick = { sm.removeDate(); navigator.popUntil { it is TrackInfoDialogHomeScreen } }, onClick = {
sm.removeDate()
navigator.popUntil { it is TrackInfoDialogHomeScreen }
},
colors = ButtonDefaults.filledTonalButtonColors( colors = ButtonDefaults.filledTonalButtonColors(
containerColor = MaterialTheme.colorScheme.errorContainer, containerColor = MaterialTheme.colorScheme.errorContainer,
contentColor = MaterialTheme.colorScheme.onErrorContainer, contentColor = MaterialTheme.colorScheme.onErrorContainer,
@ -646,7 +661,10 @@ data class TrackServiceSearchScreen(
queryResult = state.queryResult, queryResult = state.queryResult,
selected = state.selected, selected = state.selected,
onSelectedChange = sm::updateSelection, onSelectedChange = sm::updateSelection,
onConfirmSelection = { sm.registerTracking(state.selected!!); navigator.pop() }, onConfirmSelection = {
sm.registerTracking(state.selected!!)
navigator.pop()
},
onDismissRequest = navigator::pop, onDismissRequest = navigator::pop,
) )
} }

View file

@ -5,7 +5,7 @@ plugins {
dependencies { dependencies {
implementation(androidxLibs.gradle) implementation(androidxLibs.gradle)
implementation(kotlinLibs.gradle) implementation(kotlinLibs.gradle)
implementation(libs.kotlinter) implementation(libs.ktlint)
implementation(gradleApi()) implementation(gradleApi())
} }

View file

@ -1,20 +1,14 @@
import org.jmailen.gradle.kotlinter.KotlinterExtension import org.jlleitschuh.gradle.ktlint.KtlintExtension
import org.jmailen.gradle.kotlinter.KotlinterPlugin import org.jlleitschuh.gradle.ktlint.KtlintPlugin
apply<KotlinterPlugin>() apply<KtlintPlugin>()
extensions.configure<KotlinterExtension>("kotlinter") { extensions.configure<KtlintExtension>("ktlint") {
experimentalRules = true version.set("0.50.0")
android.set(true)
enableExperimentalRules.set(true)
disabledRules = arrayOf( filter {
"experimental:argument-list-wrapping", // Doesn't play well with Android Studio exclude("**/generated/**")
"filename", // Often broken to give a more general name
)
}
tasks {
named<DefaultTask>("preBuild").configure {
if (!System.getenv("CI").toBoolean())
dependsOn("formatKotlin")
} }
} }

View file

@ -11,7 +11,6 @@ android {
testInstrumentationRunner = "androidx.test.runner.AndroidJUnitRunner" testInstrumentationRunner = "androidx.test.runner.AndroidJUnitRunner"
consumerProguardFiles("consumer-rules.pro") consumerProguardFiles("consumer-rules.pro")
} }
} }
dependencies { dependencies {

View file

@ -39,7 +39,9 @@ class NetworkHelper(
builder.addNetworkInterceptor(httpLoggingInterceptor) builder.addNetworkInterceptor(httpLoggingInterceptor)
} }
builder.addInterceptor(CloudflareInterceptor(context, cookieJar, ::defaultUserAgentProvider)) builder.addInterceptor(
CloudflareInterceptor(context, cookieJar, ::defaultUserAgentProvider),
)
when (preferences.dohProvider().get()) { when (preferences.dohProvider().get()) {
PREF_DOH_CLOUDFLARE -> builder.dohCloudflare() PREF_DOH_CLOUDFLARE -> builder.dohCloudflare()

View file

@ -17,6 +17,9 @@ class NetworkPreferences(
} }
fun defaultUserAgent(): Preference<String> { fun defaultUserAgent(): Preference<String> {
return preferenceStore.getString("default_user_agent", "Mozilla/5.0 (Windows NT 10.0; Win64; x64; rv:109.0) Gecko/20100101 Firefox/114.0") return preferenceStore.getString(
"default_user_agent",
"Mozilla/5.0 (Windows NT 10.0; Win64; x64; rv:109.0) Gecko/20100101 Firefox/114.0",
)
} }
} }

View file

@ -9,7 +9,10 @@ import okio.Source
import okio.buffer import okio.buffer
import java.io.IOException import java.io.IOException
class ProgressResponseBody(private val responseBody: ResponseBody, private val progressListener: ProgressListener) : ResponseBody() { class ProgressResponseBody(
private val responseBody: ResponseBody,
private val progressListener: ProgressListener,
) : ResponseBody() {
private val bufferedSource: BufferedSource by lazy { private val bufferedSource: BufferedSource by lazy {
source(responseBody.source()).buffer() source(responseBody.source()).buffer()
@ -36,7 +39,11 @@ class ProgressResponseBody(private val responseBody: ResponseBody, private val p
val bytesRead = super.read(sink, byteCount) val bytesRead = super.read(sink, byteCount)
// read() returns the number of bytes read, or -1 if this source is exhausted. // read() returns the number of bytes read, or -1 if this source is exhausted.
totalBytesRead += if (bytesRead != -1L) bytesRead else 0 totalBytesRead += if (bytesRead != -1L) bytesRead else 0
progressListener.update(totalBytesRead, responseBody.contentLength(), bytesRead == -1L) progressListener.update(
totalBytesRead,
responseBody.contentLength(),
bytesRead == -1L,
)
return bytesRead return bytesRead
} }
} }

View file

@ -31,7 +31,11 @@ class CloudflareInterceptor(
return response.code in ERROR_CODES && response.header("Server") in SERVER_CHECK return response.code in ERROR_CODES && response.header("Server") in SERVER_CHECK
} }
override fun intercept(chain: Interceptor.Chain, request: Request, response: Response): Response { override fun intercept(
chain: Interceptor.Chain,
request: Request,
response: Response,
): Response {
try { try {
response.close() response.close()
cookieManager.remove(request.url, COOKIE_NAMES, 0) cookieManager.remove(request.url, COOKIE_NAMES, 0)

View file

@ -33,7 +33,9 @@ fun OkHttpClient.Builder.rateLimitHost(
permits: Int, permits: Int,
period: Long = 1, period: Long = 1,
unit: TimeUnit = TimeUnit.SECONDS, unit: TimeUnit = TimeUnit.SECONDS,
) = addInterceptor(RateLimitInterceptor(httpUrl.host, permits, period.toDuration(unit.toDurationUnit()))) ) = addInterceptor(
RateLimitInterceptor(httpUrl.host, permits, period.toDuration(unit.toDurationUnit())),
)
/** /**
* An OkHttp interceptor that handles given url host's rate limiting. * An OkHttp interceptor that handles given url host's rate limiting.
@ -69,8 +71,5 @@ fun OkHttpClient.Builder.rateLimitHost(
* @param permits [Int] Number of requests allowed within a period of units. * @param permits [Int] Number of requests allowed within a period of units.
* @param period [Duration] The limiting duration. Defaults to 1.seconds. * @param period [Duration] The limiting duration. Defaults to 1.seconds.
*/ */
fun OkHttpClient.Builder.rateLimitHost( fun OkHttpClient.Builder.rateLimitHost(url: String, permits: Int, period: Duration = 1.seconds) =
url: String, addInterceptor(RateLimitInterceptor(url.toHttpUrlOrNull()?.host, permits, period))
permits: Int,
period: Duration = 1.seconds,
) = addInterceptor(RateLimitInterceptor(url.toHttpUrlOrNull()?.host, permits, period))

View file

@ -10,7 +10,11 @@ import androidx.annotation.StringRes
* @param resource the text resource. * @param resource the text resource.
* @param duration the duration of the toast. Defaults to short. * @param duration the duration of the toast. Defaults to short.
*/ */
fun Context.toast(@StringRes resource: Int, duration: Int = Toast.LENGTH_SHORT, block: (Toast) -> Unit = {}): Toast { fun Context.toast(
@StringRes resource: Int,
duration: Int = Toast.LENGTH_SHORT,
block: (Toast) -> Unit = {},
): Toast {
return toast(getString(resource), duration, block) return toast(getString(resource), duration, block)
} }
@ -20,7 +24,11 @@ fun Context.toast(@StringRes resource: Int, duration: Int = Toast.LENGTH_SHORT,
* @param text the text to display. * @param text the text to display.
* @param duration the duration of the toast. Defaults to short. * @param duration the duration of the toast. Defaults to short.
*/ */
fun Context.toast(text: String?, duration: Int = Toast.LENGTH_SHORT, block: (Toast) -> Unit = {}): Toast { fun Context.toast(
text: String?,
duration: Int = Toast.LENGTH_SHORT,
block: (Toast) -> Unit = {},
): Toast {
return Toast.makeText(applicationContext, text.orEmpty(), duration).also { return Toast.makeText(applicationContext, text.orEmpty(), duration).also {
block(it) block(it)
it.show() it.show()

View file

@ -47,10 +47,7 @@ abstract class WebViewClientCompat : WebViewClient() {
return shouldInterceptRequestCompat(view, request.url.toString()) return shouldInterceptRequestCompat(view, request.url.toString())
} }
final override fun shouldInterceptRequest( final override fun shouldInterceptRequest(view: WebView, url: String): WebResourceResponse? {
view: WebView,
url: String,
): WebResourceResponse? {
return shouldInterceptRequestCompat(view, url) return shouldInterceptRequestCompat(view, url)
} }

View file

@ -68,7 +68,11 @@ sealed class AndroidPreference<T>(
key: String, key: String,
defaultValue: String, defaultValue: String,
) : AndroidPreference<String>(preferences, keyFlow, key, defaultValue) { ) : AndroidPreference<String>(preferences, keyFlow, key, defaultValue) {
override fun read(preferences: SharedPreferences, key: String, defaultValue: String): String { override fun read(
preferences: SharedPreferences,
key: String,
defaultValue: String,
): String {
return preferences.getString(key, defaultValue) ?: defaultValue return preferences.getString(key, defaultValue) ?: defaultValue
} }
@ -128,7 +132,11 @@ sealed class AndroidPreference<T>(
key: String, key: String,
defaultValue: Boolean, defaultValue: Boolean,
) : AndroidPreference<Boolean>(preferences, keyFlow, key, defaultValue) { ) : AndroidPreference<Boolean>(preferences, keyFlow, key, defaultValue) {
override fun read(preferences: SharedPreferences, key: String, defaultValue: Boolean): Boolean { override fun read(
preferences: SharedPreferences,
key: String,
defaultValue: Boolean,
): Boolean {
return preferences.getBoolean(key, defaultValue) return preferences.getBoolean(key, defaultValue)
} }
@ -143,7 +151,11 @@ sealed class AndroidPreference<T>(
key: String, key: String,
defaultValue: Set<String>, defaultValue: Set<String>,
) : AndroidPreference<Set<String>>(preferences, keyFlow, key, defaultValue) { ) : AndroidPreference<Set<String>>(preferences, keyFlow, key, defaultValue) {
override fun read(preferences: SharedPreferences, key: String, defaultValue: Set<String>): Set<String> { override fun read(
preferences: SharedPreferences,
key: String,
defaultValue: Set<String>,
): Set<String> {
return preferences.getStringSet(key, defaultValue) ?: defaultValue return preferences.getStringSet(key, defaultValue) ?: defaultValue
} }

View file

@ -64,7 +64,11 @@ class AndroidPreferenceStore(
private val SharedPreferences.keyFlow private val SharedPreferences.keyFlow
get() = callbackFlow { get() = callbackFlow {
val listener = SharedPreferences.OnSharedPreferenceChangeListener { _, key: String? -> trySend(key) } val listener = SharedPreferences.OnSharedPreferenceChangeListener { _, key: String? ->
trySend(
key,
)
}
registerOnSharedPreferenceChangeListener(listener) registerOnSharedPreferenceChangeListener(listener)
awaitClose { awaitClose {
unregisterOnSharedPreferenceChangeListener(listener) unregisterOnSharedPreferenceChangeListener(listener)

View file

@ -23,7 +23,9 @@ interface Preference<T> {
fun stateIn(scope: CoroutineScope): StateFlow<T> fun stateIn(scope: CoroutineScope): StateFlow<T>
} }
inline fun <reified T, R : T> Preference<T>.getAndSet(crossinline block: (T) -> R) = set(block(get())) inline fun <reified T, R : T> Preference<T>.getAndSet(crossinline block: (T) -> R) = set(
block(get()),
)
operator fun <T> Preference<Set<T>>.plusAssign(item: T) { operator fun <T> Preference<Set<T>>.plusAssign(item: T) {
set(get() + item) set(get() + item)

View file

@ -52,9 +52,15 @@ fun CoroutineScope.launchIO(block: suspend CoroutineScope.() -> Unit): Job =
fun CoroutineScope.launchNonCancellable(block: suspend CoroutineScope.() -> Unit): Job = fun CoroutineScope.launchNonCancellable(block: suspend CoroutineScope.() -> Unit): Job =
launchIO { withContext(NonCancellable, block) } launchIO { withContext(NonCancellable, block) }
suspend fun <T> withUIContext(block: suspend CoroutineScope.() -> T) = withContext(Dispatchers.Main, block) suspend fun <T> withUIContext(block: suspend CoroutineScope.() -> T) = withContext(
Dispatchers.Main,
block,
)
suspend fun <T> withIOContext(block: suspend CoroutineScope.() -> T) = withContext(Dispatchers.IO, block) suspend fun <T> withIOContext(block: suspend CoroutineScope.() -> T) = withContext(
Dispatchers.IO,
block,
)
suspend fun <T> withNonCancellableContext(block: suspend CoroutineScope.() -> T) = suspend fun <T> withNonCancellableContext(block: suspend CoroutineScope.() -> T) =
withContext(NonCancellable, block) withContext(NonCancellable, block)

View file

@ -11,13 +11,14 @@ object DateColumnAdapter : ColumnAdapter<Date, Long> {
private const val LIST_OF_STRINGS_SEPARATOR = ", " private const val LIST_OF_STRINGS_SEPARATOR = ", "
object StringListColumnAdapter : ColumnAdapter<List<String>, String> { object StringListColumnAdapter : ColumnAdapter<List<String>, String> {
override fun decode(databaseValue: String) = override fun decode(databaseValue: String) = if (databaseValue.isEmpty()) {
if (databaseValue.isEmpty()) { emptyList()
emptyList() } else {
} else { databaseValue.split(LIST_OF_STRINGS_SEPARATOR)
databaseValue.split(LIST_OF_STRINGS_SEPARATOR) }
} override fun encode(value: List<String>) = value.joinToString(
override fun encode(value: List<String>) = value.joinToString(separator = LIST_OF_STRINGS_SEPARATOR) separator = LIST_OF_STRINGS_SEPARATOR,
)
} }
object UpdateStrategyColumnAdapter : ColumnAdapter<UpdateStrategy, Long> { object UpdateStrategyColumnAdapter : ColumnAdapter<UpdateStrategy, Long> {

View file

@ -2,7 +2,21 @@ package tachiyomi.data.chapter
import tachiyomi.domain.chapter.model.Chapter import tachiyomi.domain.chapter.model.Chapter
val chapterMapper: (Long, Long, String, String, String?, Boolean, Boolean, Long, Double, Long, Long, Long, Long) -> Chapter = val chapterMapper: (
Long,
Long,
String,
String,
String?,
Boolean,
Boolean,
Long,
Double,
Long,
Long,
Long,
Long,
) -> Chapter =
{ id, mangaId, url, name, scanlator, read, bookmark, lastPageRead, chapterNumber, sourceOrder, dateFetch, dateUpload, lastModifiedAt -> { id, mangaId, url, name, scanlator, read, bookmark, lastPageRead, chapterNumber, sourceOrder, dateFetch, dateUpload, lastModifiedAt ->
Chapter( Chapter(
id = id, id = id,

View file

@ -81,7 +81,12 @@ class ChapterRepositoryImpl(
} }
override suspend fun getBookmarkedChaptersByMangaId(mangaId: Long): List<Chapter> { override suspend fun getBookmarkedChaptersByMangaId(mangaId: Long): List<Chapter> {
return handler.awaitList { chaptersQueries.getBookmarkedChaptersByMangaId(mangaId, chapterMapper) } return handler.awaitList {
chaptersQueries.getBookmarkedChaptersByMangaId(
mangaId,
chapterMapper,
)
}
} }
override suspend fun getChapterById(id: Long): Chapter? { override suspend fun getChapterById(id: Long): Chapter? {
@ -89,10 +94,21 @@ class ChapterRepositoryImpl(
} }
override suspend fun getChapterByMangaIdAsFlow(mangaId: Long): Flow<List<Chapter>> { override suspend fun getChapterByMangaIdAsFlow(mangaId: Long): Flow<List<Chapter>> {
return handler.subscribeToList { chaptersQueries.getChaptersByMangaId(mangaId, chapterMapper) } return handler.subscribeToList {
chaptersQueries.getChaptersByMangaId(
mangaId,
chapterMapper,
)
}
} }
override suspend fun getChapterByUrlAndMangaId(url: String, mangaId: Long): Chapter? { override suspend fun getChapterByUrlAndMangaId(url: String, mangaId: Long): Chapter? {
return handler.awaitOneOrNull { chaptersQueries.getChapterByUrlAndMangaId(url, mangaId, chapterMapper) } return handler.awaitOneOrNull {
chaptersQueries.getChapterByUrlAndMangaId(
url,
mangaId,
chapterMapper,
)
}
} }
} }

View file

@ -14,7 +14,19 @@ val historyMapper: (Long, Long, Date?, Long) -> History = { id, chapterId, readA
) )
} }
val historyWithRelationsMapper: (Long, Long, Long, String, String?, Long, Boolean, Long, Double, Date?, Long) -> HistoryWithRelations = { val historyWithRelationsMapper: (
Long,
Long,
Long,
String,
String?,
Long,
Boolean,
Long,
Double,
Date?,
Long,
) -> HistoryWithRelations = {
historyId, mangaId, chapterId, title, thumbnailUrl, sourceId, isFavorite, coverLastModified, chapterNumber, readAt, readDuration -> historyId, mangaId, chapterId, title, thumbnailUrl, sourceId, isFavorite, coverLastModified, chapterNumber, readAt, readDuration ->
HistoryWithRelations( HistoryWithRelations(
id = historyId, id = historyId,

View file

@ -4,7 +4,30 @@ import eu.kanade.tachiyomi.source.model.UpdateStrategy
import tachiyomi.domain.library.model.LibraryManga import tachiyomi.domain.library.model.LibraryManga
import tachiyomi.domain.manga.model.Manga import tachiyomi.domain.manga.model.Manga
val mangaMapper: (Long, Long, String, String?, String?, String?, List<String>?, String, Long, String?, Boolean, Long?, Long?, Boolean, Long, Long, Long, Long, UpdateStrategy, Long, Long, Long?) -> Manga = val mangaMapper: (
Long,
Long,
String,
String?,
String?,
String?,
List<String>?,
String,
Long,
String?,
Boolean,
Long?,
Long?,
Boolean,
Long,
Long,
Long,
Long,
UpdateStrategy,
Long,
Long,
Long?,
) -> Manga =
{ id, source, url, artist, author, description, genre, title, status, thumbnailUrl, favorite, lastUpdate, nextUpdate, initialized, viewerFlags, chapterFlags, coverLastModified, dateAdded, updateStrategy, calculateInterval, lastModifiedAt, favoriteModifiedAt -> { id, source, url, artist, author, description, genre, title, status, thumbnailUrl, favorite, lastUpdate, nextUpdate, initialized, viewerFlags, chapterFlags, coverLastModified, dateAdded, updateStrategy, calculateInterval, lastModifiedAt, favoriteModifiedAt ->
Manga( Manga(
id = id, id = id,
@ -32,7 +55,37 @@ val mangaMapper: (Long, Long, String, String?, String?, String?, List<String>?,
) )
} }
val libraryManga: (Long, Long, String, String?, String?, String?, List<String>?, String, Long, String?, Boolean, Long?, Long?, Boolean, Long, Long, Long, Long, UpdateStrategy, Long, Long, Long?, Long, Double, Long, Long, Long, Double, Long) -> LibraryManga = val libraryManga: (
Long,
Long,
String,
String?,
String?,
String?,
List<String>?,
String,
Long,
String?,
Boolean,
Long?,
Long?,
Boolean,
Long,
Long,
Long,
Long,
UpdateStrategy,
Long,
Long,
Long?,
Long,
Double,
Long,
Long,
Long,
Double,
Long,
) -> LibraryManga =
{ id, source, url, artist, author, description, genre, title, status, thumbnailUrl, favorite, lastUpdate, nextUpdate, initialized, viewerFlags, chapterFlags, coverLastModified, dateAdded, updateStrategy, calculateInterval, lastModifiedAt, favoriteModifiedAt, totalCount, readCount, latestUpload, chapterFetchedAt, lastRead, bookmarkCount, category -> { id, source, url, artist, author, description, genre, title, status, thumbnailUrl, favorite, lastUpdate, nextUpdate, initialized, viewerFlags, chapterFlags, coverLastModified, dateAdded, updateStrategy, calculateInterval, lastModifiedAt, favoriteModifiedAt, totalCount, readCount, latestUpload, chapterFetchedAt, lastRead, bookmarkCount, category ->
LibraryManga( LibraryManga(
manga = mangaMapper( manga = mangaMapper(

View file

@ -24,11 +24,23 @@ class MangaRepositoryImpl(
} }
override suspend fun getMangaByUrlAndSourceId(url: String, sourceId: Long): Manga? { override suspend fun getMangaByUrlAndSourceId(url: String, sourceId: Long): Manga? {
return handler.awaitOneOrNull(inTransaction = true) { mangasQueries.getMangaByUrlAndSource(url, sourceId, mangaMapper) } return handler.awaitOneOrNull(inTransaction = true) {
mangasQueries.getMangaByUrlAndSource(
url,
sourceId,
mangaMapper,
)
}
} }
override fun getMangaByUrlAndSourceIdAsFlow(url: String, sourceId: Long): Flow<Manga?> { override fun getMangaByUrlAndSourceIdAsFlow(url: String, sourceId: Long): Flow<Manga?> {
return handler.subscribeToOneOrNull { mangasQueries.getMangaByUrlAndSource(url, sourceId, mangaMapper) } return handler.subscribeToOneOrNull {
mangasQueries.getMangaByUrlAndSource(
url,
sourceId,
mangaMapper,
)
}
} }
override suspend fun getFavorites(): List<Manga> { override suspend fun getFavorites(): List<Manga> {

View file

@ -32,7 +32,9 @@ data class GitHubAssets(@SerialName("browser_download_url") val downloadLink: St
* Reference: https://stackoverflow.com/a/30281147 * Reference: https://stackoverflow.com/a/30281147
*/ */
val gitHubUsernameMentionRegex = val gitHubUsernameMentionRegex =
"""\B@([a-z0-9](?:-(?=[a-z0-9])|[a-z0-9]){0,38}(?<=[a-z0-9]))""".toRegex(RegexOption.IGNORE_CASE) """\B@([a-z0-9](?:-(?=[a-z0-9])|[a-z0-9]){0,38}(?<=[a-z0-9]))""".toRegex(
RegexOption.IGNORE_CASE,
)
val releaseMapper: (GithubRelease) -> Release = { val releaseMapper: (GithubRelease) -> Release = {
Release( Release(

View file

@ -9,7 +9,9 @@ import tachiyomi.core.util.lang.awaitSingle
import tachiyomi.core.util.lang.withIOContext import tachiyomi.core.util.lang.withIOContext
import tachiyomi.domain.source.repository.SourcePagingSourceType import tachiyomi.domain.source.repository.SourcePagingSourceType
class SourceSearchPagingSource(source: CatalogueSource, val query: String, val filters: FilterList) : SourcePagingSource(source) { class SourceSearchPagingSource(source: CatalogueSource, val query: String, val filters: FilterList) : SourcePagingSource(
source,
) {
override suspend fun requestNextPage(currentPage: Int): MangasPage { override suspend fun requestNextPage(currentPage: Int): MangasPage {
return source.fetchSearchManga(currentPage, query, filters).awaitSingle() return source.fetchSearchManga(currentPage, query, filters).awaitSingle()
} }

View file

@ -2,7 +2,21 @@ package tachiyomi.data.track
import tachiyomi.domain.track.model.Track import tachiyomi.domain.track.model.Track
val trackMapper: (Long, Long, Long, Long, Long?, String, Double, Long, Long, Double, String, Long, Long) -> Track = val trackMapper: (
Long,
Long,
Long,
Long,
Long?,
String,
Double,
Long,
Long,
Double,
String,
Long,
Long,
) -> Track =
{ id, mangaId, syncId, remoteId, libraryId, title, lastChapterRead, totalChapters, status, score, remoteUrl, startDate, finishDate -> { id, mangaId, syncId, remoteId, libraryId, title, lastChapterRead, totalChapters, status, score, remoteUrl, startDate, finishDate ->
Track( Track(
id = id, id = id,

View file

@ -3,7 +3,22 @@ package tachiyomi.data.updates
import tachiyomi.domain.manga.model.MangaCover import tachiyomi.domain.manga.model.MangaCover
import tachiyomi.domain.updates.model.UpdatesWithRelations import tachiyomi.domain.updates.model.UpdatesWithRelations
val updateWithRelationMapper: (Long, String, Long, String, String?, Boolean, Boolean, Long, Long, Boolean, String?, Long, Long, Long) -> UpdatesWithRelations = { val updateWithRelationMapper: (
Long,
String,
Long,
String,
String?,
Boolean,
Boolean,
Long,
Long,
Boolean,
String?,
Long,
Long,
Long,
) -> UpdatesWithRelations = {
mangaId, mangaTitle, chapterId, chapterName, scanlator, read, bookmark, lastPageRead, sourceId, favorite, thumbnailUrl, coverLastModified, _, dateFetch -> mangaId, mangaTitle, chapterId, chapterName, scanlator, read, bookmark, lastPageRead, sourceId, favorite, thumbnailUrl, coverLastModified, _, dateFetch ->
UpdatesWithRelations( UpdatesWithRelations(
mangaId = mangaId, mangaId = mangaId,

View file

@ -9,7 +9,11 @@ class UpdatesRepositoryImpl(
private val databaseHandler: DatabaseHandler, private val databaseHandler: DatabaseHandler,
) : UpdatesRepository { ) : UpdatesRepository {
override suspend fun awaitWithRead(read: Boolean, after: Long, limit: Long): List<UpdatesWithRelations> { override suspend fun awaitWithRead(
read: Boolean,
after: Long,
limit: Long,
): List<UpdatesWithRelations> {
return databaseHandler.awaitList { return databaseHandler.awaitList {
updatesViewQueries.getUpdatesByReadStatus( updatesViewQueries.getUpdatesByReadStatus(
read = read, read = read,
@ -26,7 +30,11 @@ class UpdatesRepositoryImpl(
} }
} }
override fun subscribeWithRead(read: Boolean, after: Long, limit: Long): Flow<List<UpdatesWithRelations>> { override fun subscribeWithRead(
read: Boolean,
after: Long,
limit: Long,
): Flow<List<UpdatesWithRelations>> {
return databaseHandler.subscribeToList { return databaseHandler.subscribeToList {
updatesViewQueries.getUpdatesByReadStatus( updatesViewQueries.getUpdatesByReadStatus(
read = read, read = read,

View file

@ -16,11 +16,9 @@ class ReorderCategory(
private val mutex = Mutex() private val mutex = Mutex()
suspend fun moveUp(category: Category): Result = suspend fun moveUp(category: Category): Result = await(category, MoveTo.UP)
await(category, MoveTo.UP)
suspend fun moveDown(category: Category): Result = suspend fun moveDown(category: Category): Result = await(category, MoveTo.DOWN)
await(category, MoveTo.DOWN)
private suspend fun await(category: Category, moveTo: MoveTo) = withNonCancellableContext { private suspend fun await(category: Category, moveTo: MoveTo) = withNonCancellableContext {
mutex.withLock { mutex.withLock {

View file

@ -28,7 +28,11 @@ class SetSortModeForCategory(
} }
} }
suspend fun await(category: Category?, type: LibrarySort.Type, direction: LibrarySort.Direction) { suspend fun await(
category: Category?,
type: LibrarySort.Type,
direction: LibrarySort.Direction,
) {
await(category?.id, type, direction) await(category?.id, type, direction)
} }
} }

View file

@ -30,7 +30,11 @@ object ChapterRecognition {
*/ */
private val unwantedWhiteSpace = Regex("""\s(?=extra|special|omake)""") private val unwantedWhiteSpace = Regex("""\s(?=extra|special|omake)""")
fun parseChapterNumber(mangaTitle: String, chapterName: String, chapterNumber: Double? = null): Double { fun parseChapterNumber(
mangaTitle: String,
chapterName: String,
chapterNumber: Double? = null,
): Double {
// If chapter number is known return. // If chapter number is known return.
if (chapterNumber != null && (chapterNumber == -2.0 || chapterNumber > -1.0)) { if (chapterNumber != null && (chapterNumber == -2.0 || chapterNumber > -1.0)) {
return chapterNumber return chapterNumber

View file

@ -3,7 +3,13 @@ package tachiyomi.domain.chapter.service
import tachiyomi.domain.chapter.model.Chapter import tachiyomi.domain.chapter.model.Chapter
import tachiyomi.domain.manga.model.Manga import tachiyomi.domain.manga.model.Manga
fun getChapterSort(manga: Manga, sortDescending: Boolean = manga.sortDescending()): (Chapter, Chapter) -> Int { fun getChapterSort(
manga: Manga,
sortDescending: Boolean = manga.sortDescending(),
): (
Chapter,
Chapter,
) -> Int {
return when (manga.sorting) { return when (manga.sorting) {
Manga.CHAPTER_SORTING_SOURCE -> when (sortDescending) { Manga.CHAPTER_SORTING_SOURCE -> when (sortDescending) {
true -> { c1, c2 -> c1.sourceOrder.compareTo(c2.sourceOrder) } true -> { c1, c2 -> c1.sourceOrder.compareTo(c2.sourceOrder) }

View file

@ -8,9 +8,15 @@ class DownloadPreferences(
private val preferenceStore: PreferenceStore, private val preferenceStore: PreferenceStore,
) { ) {
fun downloadsDirectory() = preferenceStore.getString("download_directory", folderProvider.path()) fun downloadsDirectory() = preferenceStore.getString(
"download_directory",
folderProvider.path(),
)
fun downloadOnlyOverWifi() = preferenceStore.getBoolean("pref_download_only_over_wifi_key", true) fun downloadOnlyOverWifi() = preferenceStore.getBoolean(
"pref_download_only_over_wifi_key",
true,
)
fun saveChaptersAsCBZ() = preferenceStore.getBoolean("save_chapter_as_cbz", true) fun saveChaptersAsCBZ() = preferenceStore.getBoolean("save_chapter_as_cbz", true)
@ -20,15 +26,27 @@ class DownloadPreferences(
fun removeAfterReadSlots() = preferenceStore.getInt("remove_after_read_slots", -1) fun removeAfterReadSlots() = preferenceStore.getInt("remove_after_read_slots", -1)
fun removeAfterMarkedAsRead() = preferenceStore.getBoolean("pref_remove_after_marked_as_read_key", false) fun removeAfterMarkedAsRead() = preferenceStore.getBoolean(
"pref_remove_after_marked_as_read_key",
false,
)
fun removeBookmarkedChapters() = preferenceStore.getBoolean("pref_remove_bookmarked", false) fun removeBookmarkedChapters() = preferenceStore.getBoolean("pref_remove_bookmarked", false)
fun removeExcludeCategories() = preferenceStore.getStringSet("remove_exclude_categories", emptySet()) fun removeExcludeCategories() = preferenceStore.getStringSet(
"remove_exclude_categories",
emptySet(),
)
fun downloadNewChapters() = preferenceStore.getBoolean("download_new", false) fun downloadNewChapters() = preferenceStore.getBoolean("download_new", false)
fun downloadNewChapterCategories() = preferenceStore.getStringSet("download_new_categories", emptySet()) fun downloadNewChapterCategories() = preferenceStore.getStringSet(
"download_new_categories",
emptySet(),
)
fun downloadNewChapterCategoriesExclude() = preferenceStore.getStringSet("download_new_categories_exclude", emptySet()) fun downloadNewChapterCategoriesExclude() = preferenceStore.getStringSet(
"download_new_categories_exclude",
emptySet(),
)
} }

View file

@ -30,7 +30,11 @@ class GetNextChapters(
} }
} }
suspend fun await(mangaId: Long, fromChapterId: Long, onlyUnread: Boolean = true): List<Chapter> { suspend fun await(
mangaId: Long,
fromChapterId: Long,
onlyUnread: Boolean = true,
): List<Chapter> {
val chapters = await(mangaId, onlyUnread) val chapters = await(mangaId, onlyUnread)
val currChapterIndex = chapters.indexOfFirst { it.id == fromChapterId } val currChapterIndex = chapters.indexOfFirst { it.id == fromChapterId }
val nextChapters = chapters.subList(max(0, currChapterIndex), chapters.size) val nextChapters = chapters.subList(max(0, currChapterIndex), chapters.size)

View file

@ -65,7 +65,18 @@ data class LibrarySort(
} }
companion object { companion object {
val types by lazy { setOf(Type.Alphabetical, Type.LastRead, Type.LastUpdate, Type.UnreadCount, Type.TotalChapters, Type.LatestChapter, Type.ChapterFetchDate, Type.DateAdded) } val types by lazy {
setOf(
Type.Alphabetical,
Type.LastRead,
Type.LastUpdate,
Type.UnreadCount,
Type.TotalChapters,
Type.LatestChapter,
Type.ChapterFetchDate,
Type.DateAdded,
)
}
val directions by lazy { setOf(Direction.Ascending, Direction.Descending) } val directions by lazy { setOf(Direction.Ascending, Direction.Descending) }
val default = LibrarySort(Type.Alphabetical, Direction.Ascending) val default = LibrarySort(Type.Alphabetical, Direction.Ascending)

View file

@ -11,9 +11,19 @@ class LibraryPreferences(
private val preferenceStore: PreferenceStore, private val preferenceStore: PreferenceStore,
) { ) {
fun displayMode() = preferenceStore.getObject("pref_display_mode_library", LibraryDisplayMode.default, LibraryDisplayMode.Serializer::serialize, LibraryDisplayMode.Serializer::deserialize) fun displayMode() = preferenceStore.getObject(
"pref_display_mode_library",
LibraryDisplayMode.default,
LibraryDisplayMode.Serializer::serialize,
LibraryDisplayMode.Serializer::deserialize,
)
fun sortingMode() = preferenceStore.getObject("library_sorting_mode", LibrarySort.default, LibrarySort.Serializer::serialize, LibrarySort.Serializer::deserialize) fun sortingMode() = preferenceStore.getObject(
"library_sorting_mode",
LibrarySort.default,
LibrarySort.Serializer::serialize,
LibrarySort.Serializer::deserialize,
)
fun portraitColumns() = preferenceStore.getInt("pref_library_columns_portrait_key", 0) fun portraitColumns() = preferenceStore.getInt("pref_library_columns_portrait_key", 0)
@ -42,31 +52,64 @@ class LibraryPreferences(
fun autoUpdateTrackers() = preferenceStore.getBoolean("auto_update_trackers", false) fun autoUpdateTrackers() = preferenceStore.getBoolean("auto_update_trackers", false)
fun showContinueReadingButton() = preferenceStore.getBoolean("display_continue_reading_button", false) fun showContinueReadingButton() = preferenceStore.getBoolean(
"display_continue_reading_button",
false,
)
// region Filter // region Filter
fun filterDownloaded() = preferenceStore.getEnum("pref_filter_library_downloaded_v2", TriState.DISABLED) fun filterDownloaded() = preferenceStore.getEnum(
"pref_filter_library_downloaded_v2",
TriState.DISABLED,
)
fun filterUnread() = preferenceStore.getEnum("pref_filter_library_unread_v2", TriState.DISABLED) fun filterUnread() = preferenceStore.getEnum("pref_filter_library_unread_v2", TriState.DISABLED)
fun filterStarted() = preferenceStore.getEnum("pref_filter_library_started_v2", TriState.DISABLED) fun filterStarted() = preferenceStore.getEnum(
"pref_filter_library_started_v2",
TriState.DISABLED,
)
fun filterBookmarked() = preferenceStore.getEnum("pref_filter_library_bookmarked_v2", TriState.DISABLED) fun filterBookmarked() = preferenceStore.getEnum(
"pref_filter_library_bookmarked_v2",
TriState.DISABLED,
)
fun filterCompleted() = preferenceStore.getEnum("pref_filter_library_completed_v2", TriState.DISABLED) fun filterCompleted() = preferenceStore.getEnum(
"pref_filter_library_completed_v2",
TriState.DISABLED,
)
fun filterIntervalCustom() = preferenceStore.getEnum("pref_filter_library_interval_custom", TriState.DISABLED) fun filterIntervalCustom() = preferenceStore.getEnum(
"pref_filter_library_interval_custom",
TriState.DISABLED,
)
fun filterIntervalLong() = preferenceStore.getEnum("pref_filter_library_interval_long", TriState.DISABLED) fun filterIntervalLong() = preferenceStore.getEnum(
"pref_filter_library_interval_long",
TriState.DISABLED,
)
fun filterIntervalLate() = preferenceStore.getEnum("pref_filter_library_interval_late", TriState.DISABLED) fun filterIntervalLate() = preferenceStore.getEnum(
"pref_filter_library_interval_late",
TriState.DISABLED,
)
fun filterIntervalDropped() = preferenceStore.getEnum("pref_filter_library_interval_dropped", TriState.DISABLED) fun filterIntervalDropped() = preferenceStore.getEnum(
"pref_filter_library_interval_dropped",
TriState.DISABLED,
)
fun filterIntervalPassed() = preferenceStore.getEnum("pref_filter_library_interval_passed", TriState.DISABLED) fun filterIntervalPassed() = preferenceStore.getEnum(
"pref_filter_library_interval_passed",
TriState.DISABLED,
)
fun filterTracking(id: Int) = preferenceStore.getEnum("pref_filter_library_tracked_${id}_v2", TriState.DISABLED) fun filterTracking(id: Int) = preferenceStore.getEnum(
"pref_filter_library_tracked_${id}_v2",
TriState.DISABLED,
)
// endregion // endregion
@ -97,24 +140,45 @@ class LibraryPreferences(
fun updateCategories() = preferenceStore.getStringSet("library_update_categories", emptySet()) fun updateCategories() = preferenceStore.getStringSet("library_update_categories", emptySet())
fun updateCategoriesExclude() = preferenceStore.getStringSet("library_update_categories_exclude", emptySet()) fun updateCategoriesExclude() = preferenceStore.getStringSet(
"library_update_categories_exclude",
emptySet(),
)
// endregion // endregion
// region Chapter // region Chapter
fun filterChapterByRead() = preferenceStore.getLong("default_chapter_filter_by_read", Manga.SHOW_ALL) fun filterChapterByRead() = preferenceStore.getLong(
"default_chapter_filter_by_read",
Manga.SHOW_ALL,
)
fun filterChapterByDownloaded() = preferenceStore.getLong("default_chapter_filter_by_downloaded", Manga.SHOW_ALL) fun filterChapterByDownloaded() = preferenceStore.getLong(
"default_chapter_filter_by_downloaded",
Manga.SHOW_ALL,
)
fun filterChapterByBookmarked() = preferenceStore.getLong("default_chapter_filter_by_bookmarked", Manga.SHOW_ALL) fun filterChapterByBookmarked() = preferenceStore.getLong(
"default_chapter_filter_by_bookmarked",
Manga.SHOW_ALL,
)
// and upload date // and upload date
fun sortChapterBySourceOrNumber() = preferenceStore.getLong("default_chapter_sort_by_source_or_number", Manga.CHAPTER_SORTING_SOURCE) fun sortChapterBySourceOrNumber() = preferenceStore.getLong(
"default_chapter_sort_by_source_or_number",
Manga.CHAPTER_SORTING_SOURCE,
)
fun displayChapterByNameOrNumber() = preferenceStore.getLong("default_chapter_display_by_name_or_number", Manga.CHAPTER_DISPLAY_NAME) fun displayChapterByNameOrNumber() = preferenceStore.getLong(
"default_chapter_display_by_name_or_number",
Manga.CHAPTER_DISPLAY_NAME,
)
fun sortChapterByAscendingOrDescending() = preferenceStore.getLong("default_chapter_sort_by_ascending_or_descending", Manga.CHAPTER_SORT_DESC) fun sortChapterByAscendingOrDescending() = preferenceStore.getLong(
"default_chapter_sort_by_ascending_or_descending",
Manga.CHAPTER_SORT_DESC,
)
fun setChapterSettingsDefault(manga: Manga) { fun setChapterSettingsDefault(manga: Manga) {
filterChapterByRead().set(manga.unreadFilterRaw) filterChapterByRead().set(manga.unreadFilterRaw)
@ -122,7 +186,9 @@ class LibraryPreferences(
filterChapterByBookmarked().set(manga.bookmarkedFilterRaw) filterChapterByBookmarked().set(manga.bookmarkedFilterRaw)
sortChapterBySourceOrNumber().set(manga.sorting) sortChapterBySourceOrNumber().set(manga.sorting)
displayChapterByNameOrNumber().set(manga.displayMode) displayChapterByNameOrNumber().set(manga.displayMode)
sortChapterByAscendingOrDescending().set(if (manga.sortDescending()) Manga.CHAPTER_SORT_DESC else Manga.CHAPTER_SORT_ASC) sortChapterByAscendingOrDescending().set(
if (manga.sortDescending()) Manga.CHAPTER_SORT_DESC else Manga.CHAPTER_SORT_ASC,
)
} }
fun autoClearChapterCache() = preferenceStore.getBoolean("auto_clear_chapter_cache", false) fun autoClearChapterCache() = preferenceStore.getBoolean("auto_clear_chapter_cache", false)
@ -131,9 +197,15 @@ class LibraryPreferences(
// region Swipe Actions // region Swipe Actions
fun swipeToStartAction() = preferenceStore.getEnum("pref_chapter_swipe_end_action", ChapterSwipeAction.ToggleBookmark) fun swipeToStartAction() = preferenceStore.getEnum(
"pref_chapter_swipe_end_action",
ChapterSwipeAction.ToggleBookmark,
)
fun swipeToEndAction() = preferenceStore.getEnum("pref_chapter_swipe_start_action", ChapterSwipeAction.ToggleRead) fun swipeToEndAction() = preferenceStore.getEnum(
"pref_chapter_swipe_start_action",
ChapterSwipeAction.ToggleRead,
)
// endregion // endregion

View file

@ -27,7 +27,10 @@ class SetFetchInterval(
window window
} }
val chapters = getChapterByMangaId.await(manga.id) val chapters = getChapterByMangaId.await(manga.id)
val interval = manga.fetchInterval.takeIf { it < 0 } ?: calculateInterval(chapters, dateTime) val interval = manga.fetchInterval.takeIf { it < 0 } ?: calculateInterval(
chapters,
dateTime,
)
val nextUpdate = calculateNextUpdate(manga, interval, dateTime, currentWindow) val nextUpdate = calculateNextUpdate(manga, interval, dateTime, currentWindow)
return if (manga.nextUpdate == nextUpdate && manga.fetchInterval == interval) { return if (manga.nextUpdate == nextUpdate && manga.fetchInterval == interval) {
@ -46,7 +49,9 @@ class SetFetchInterval(
internal fun calculateInterval(chapters: List<Chapter>, zonedDateTime: ZonedDateTime): Int { internal fun calculateInterval(chapters: List<Chapter>, zonedDateTime: ZonedDateTime): Int {
val sortedChapters = chapters val sortedChapters = chapters
.sortedWith(compareByDescending<Chapter> { it.dateUpload }.thenByDescending { it.dateFetch }) .sortedWith(
compareByDescending<Chapter> { it.dateUpload }.thenByDescending { it.dateFetch },
)
.take(50) .take(50)
val uploadDates = sortedChapters val uploadDates = sortedChapters
@ -95,7 +100,10 @@ class SetFetchInterval(
manga.nextUpdate !in window.first.rangeTo(window.second + 1) || manga.nextUpdate !in window.first.rangeTo(window.second + 1) ||
manga.fetchInterval == 0 manga.fetchInterval == 0
) { ) {
val latestDate = ZonedDateTime.ofInstant(Instant.ofEpochMilli(manga.lastUpdate), dateTime.zone) val latestDate = ZonedDateTime.ofInstant(
Instant.ofEpochMilli(manga.lastUpdate),
dateTime.zone,
)
.toLocalDate() .toLocalDate()
.atStartOfDay() .atStartOfDay()
val timeSinceLatest = ChronoUnit.DAYS.between(latestDate, dateTime).toInt() val timeSinceLatest = ChronoUnit.DAYS.between(latestDate, dateTime).toInt()

View file

@ -20,7 +20,10 @@ class GetApplicationRelease(
val now = Instant.now() val now = Instant.now()
// Limit checks to once every 3 days at most // Limit checks to once every 3 days at most
if (arguments.forceCheck.not() && now.isBefore(Instant.ofEpochMilli(lastChecked.get()).plus(3, ChronoUnit.DAYS))) { if (arguments.forceCheck.not() && now.isBefore(
Instant.ofEpochMilli(lastChecked.get()).plus(3, ChronoUnit.DAYS),
)
) {
return Result.NoNewUpdate return Result.NoNewUpdate
} }
@ -29,7 +32,12 @@ class GetApplicationRelease(
lastChecked.set(now.toEpochMilli()) lastChecked.set(now.toEpochMilli())
// Check if latest version is different from current version // Check if latest version is different from current version
val isNewVersion = isNewVersion(arguments.isPreview, arguments.commitCount, arguments.versionName, release.version) val isNewVersion = isNewVersion(
arguments.isPreview,
arguments.commitCount,
arguments.versionName,
release.version,
)
return when { return when {
isNewVersion && arguments.isThirdParty -> Result.ThirdPartyInstallation isNewVersion && arguments.isThirdParty -> Result.ThirdPartyInstallation
isNewVersion -> Result.NewUpdate(release) isNewVersion -> Result.NewUpdate(release)
@ -37,7 +45,12 @@ class GetApplicationRelease(
} }
} }
private fun isNewVersion(isPreview: Boolean, commitCount: Int, versionName: String, versionTag: String): Boolean { private fun isNewVersion(
isPreview: Boolean,
commitCount: Int,
versionName: String,
versionTag: String,
): Boolean {
// Removes prefixes like "r" or "v" // Removes prefixes like "r" or "v"
val newVersion = versionTag.replace("[^\\d.]".toRegex(), "") val newVersion = versionTag.replace("[^\\d.]".toRegex(), "")
return if (isPreview) { return if (isPreview) {

View file

@ -34,7 +34,10 @@ class LibraryFlagsTest {
@Test @Test
fun `Test Flag plus operator with old flag as base`() { fun `Test Flag plus operator with old flag as base`() {
val currentSort = LibrarySort(LibrarySort.Type.UnreadCount, LibrarySort.Direction.Descending) val currentSort = LibrarySort(
LibrarySort.Type.UnreadCount,
LibrarySort.Direction.Descending,
)
currentSort.flag shouldBe 0b00001100 currentSort.flag shouldBe 0b00001100
val sort = LibrarySort(LibrarySort.Type.DateAdded, LibrarySort.Direction.Ascending) val sort = LibrarySort(LibrarySort.Type.DateAdded, LibrarySort.Direction.Ascending)

View file

@ -79,7 +79,9 @@ class GetApplicationReleaseTest {
), ),
) )
(result as GetApplicationRelease.Result.NewUpdate).release shouldBe GetApplicationRelease.Result.NewUpdate(release).release (result as GetApplicationRelease.Result.NewUpdate).release shouldBe GetApplicationRelease.Result.NewUpdate(
release,
).release
} }
@Test @Test
@ -106,7 +108,9 @@ class GetApplicationReleaseTest {
), ),
) )
(result as GetApplicationRelease.Result.NewUpdate).release shouldBe GetApplicationRelease.Result.NewUpdate(release).release (result as GetApplicationRelease.Result.NewUpdate).release shouldBe GetApplicationRelease.Result.NewUpdate(
release,
).release
} }
@Test @Test

View file

@ -90,7 +90,7 @@ voyager-navigator = { module = "cafe.adriel.voyager:voyager-navigator", version.
voyager-tab-navigator = { module = "cafe.adriel.voyager:voyager-tab-navigator", version.ref = "voyager" } voyager-tab-navigator = { module = "cafe.adriel.voyager:voyager-tab-navigator", version.ref = "voyager" }
voyager-transitions = { module = "cafe.adriel.voyager:voyager-transitions", version.ref = "voyager" } voyager-transitions = { module = "cafe.adriel.voyager:voyager-transitions", version.ref = "voyager" }
kotlinter = "org.jmailen.gradle:kotlinter-gradle:3.13.0" ktlint = "org.jlleitschuh.gradle:ktlint-gradle:11.5.1"
[bundles] [bundles]
okhttp = ["okhttp-core", "okhttp-logging", "okhttp-dnsoverhttps"] okhttp = ["okhttp-core", "okhttp-logging", "okhttp-dnsoverhttps"]

View file

@ -60,11 +60,16 @@ abstract class AbstractStartupBenchmark(private val startupMode: StartupMode) {
@Test @Test
fun startupBaselineProfileDisabled() = startup( fun startupBaselineProfileDisabled() = startup(
CompilationMode.Partial(baselineProfileMode = BaselineProfileMode.Disable, warmupIterations = 1), CompilationMode.Partial(
baselineProfileMode = BaselineProfileMode.Disable,
warmupIterations = 1,
),
) )
@Test @Test
fun startupBaselineProfile() = startup(CompilationMode.Partial(baselineProfileMode = BaselineProfileMode.Require)) fun startupBaselineProfile() = startup(
CompilationMode.Partial(baselineProfileMode = BaselineProfileMode.Require),
)
@Test @Test
fun startupFullCompilation() = startup(CompilationMode.Full()) fun startupFullCompilation() = startup(CompilationMode.Full())

View file

@ -182,7 +182,10 @@ fun AdaptiveSheet(
shape = MaterialTheme.shapes.extraLarge, shape = MaterialTheme.shapes.extraLarge,
tonalElevation = tonalElevation, tonalElevation = tonalElevation,
content = { content = {
BackHandler(enabled = anchoredDraggableState.targetValue == 0, onBack = internalOnDismissRequest) BackHandler(
enabled = anchoredDraggableState.targetValue == 0,
onBack = internalOnDismissRequest,
)
content() content()
}, },
) )
@ -200,49 +203,50 @@ fun AdaptiveSheet(
} }
} }
private fun <T> AnchoredDraggableState<T>.preUpPostDownNestedScrollConnection() = object : NestedScrollConnection { private fun <T> AnchoredDraggableState<T>.preUpPostDownNestedScrollConnection() =
override fun onPreScroll(available: Offset, source: NestedScrollSource): Offset { object : NestedScrollConnection {
val delta = available.toFloat() override fun onPreScroll(available: Offset, source: NestedScrollSource): Offset {
return if (delta < 0 && source == NestedScrollSource.Drag) { val delta = available.toFloat()
dispatchRawDelta(delta).toOffset() return if (delta < 0 && source == NestedScrollSource.Drag) {
} else { dispatchRawDelta(delta).toOffset()
Offset.Zero } else {
Offset.Zero
}
} }
}
override fun onPostScroll( override fun onPostScroll(
consumed: Offset, consumed: Offset,
available: Offset, available: Offset,
source: NestedScrollSource, source: NestedScrollSource,
): Offset { ): Offset {
return if (source == NestedScrollSource.Drag) { return if (source == NestedScrollSource.Drag) {
dispatchRawDelta(available.toFloat()).toOffset() dispatchRawDelta(available.toFloat()).toOffset()
} else { } else {
Offset.Zero Offset.Zero
}
} }
}
override suspend fun onPreFling(available: Velocity): Velocity { override suspend fun onPreFling(available: Velocity): Velocity {
val toFling = available.toFloat() val toFling = available.toFloat()
return if (toFling < 0 && offset > anchors.minAnchor()) { return if (toFling < 0 && offset > anchors.minAnchor()) {
settle(toFling) settle(toFling)
// since we go to the anchor with tween settling, consume all for the best UX // since we go to the anchor with tween settling, consume all for the best UX
available available
} else { } else {
Velocity.Zero Velocity.Zero
}
} }
override suspend fun onPostFling(consumed: Velocity, available: Velocity): Velocity {
settle(velocity = available.toFloat())
return available
}
private fun Float.toOffset(): Offset = Offset(0f, this)
@JvmName("velocityToFloat")
private fun Velocity.toFloat() = this.y
@JvmName("offsetToFloat")
private fun Offset.toFloat(): Float = this.y
} }
override suspend fun onPostFling(consumed: Velocity, available: Velocity): Velocity {
settle(velocity = available.toFloat())
return available
}
private fun Float.toOffset(): Offset = Offset(0f, this)
@JvmName("velocityToFloat")
private fun Velocity.toFloat() = this.y
@JvmName("offsetToFloat")
private fun Offset.toFloat(): Float = this.y
}

View file

@ -37,9 +37,7 @@ import androidx.compose.ui.tooling.preview.Preview
* By always rotating we give the feedback to the user that the application isn't 'stuck'. * By always rotating we give the feedback to the user that the application isn't 'stuck'.
*/ */
@Composable @Composable
fun CombinedCircularProgressIndicator( fun CombinedCircularProgressIndicator(progress: Float) {
progress: Float,
) {
val animatedProgress by animateFloatAsState( val animatedProgress by animateFloatAsState(
targetValue = progress, targetValue = progress,
animationSpec = ProgressIndicatorDefaults.ProgressAnimationSpec, animationSpec = ProgressIndicatorDefaults.ProgressAnimationSpec,

View file

@ -23,10 +23,7 @@ import androidx.compose.ui.unit.dp
import tachiyomi.presentation.core.theme.header import tachiyomi.presentation.core.theme.header
@Composable @Composable
fun CollapsibleBox( fun CollapsibleBox(heading: String, content: @Composable () -> Unit) {
heading: String,
content: @Composable () -> Unit,
) {
var expanded by remember { mutableStateOf(false) } var expanded by remember { mutableStateOf(false) }
Column { Column {

View file

@ -11,12 +11,7 @@ import androidx.compose.ui.platform.LocalUriHandler
import androidx.compose.ui.unit.dp import androidx.compose.ui.unit.dp
@Composable @Composable
fun LinkIcon( fun LinkIcon(modifier: Modifier = Modifier, label: String, icon: ImageVector, url: String) {
modifier: Modifier = Modifier,
label: String,
icon: ImageVector,
url: String,
) {
val uriHandler = LocalUriHandler.current val uriHandler = LocalUriHandler.current
IconButton( IconButton(
modifier = modifier.padding(4.dp), modifier = modifier.padding(4.dp),

View file

@ -9,10 +9,7 @@ import androidx.compose.ui.text.font.FontWeight
import tachiyomi.presentation.core.components.material.padding import tachiyomi.presentation.core.components.material.padding
@Composable @Composable
fun ListGroupHeader( fun ListGroupHeader(modifier: Modifier = Modifier, text: String) {
modifier: Modifier = Modifier,
text: String,
) {
Text( Text(
text = text, text = text,
modifier = modifier modifier = modifier

View file

@ -51,16 +51,12 @@ object SettingsItemsPaddings {
} }
@Composable @Composable
fun HeadingItem( fun HeadingItem(@StringRes labelRes: Int) {
@StringRes labelRes: Int,
) {
HeadingItem(stringResource(labelRes)) HeadingItem(stringResource(labelRes))
} }
@Composable @Composable
fun HeadingItem( fun HeadingItem(text: String) {
text: String,
) {
Text( Text(
text = text, text = text,
style = MaterialTheme.typography.header, style = MaterialTheme.typography.header,
@ -74,11 +70,7 @@ fun HeadingItem(
} }
@Composable @Composable
fun IconItem( fun IconItem(label: String, icon: ImageVector, onClick: () -> Unit) {
label: String,
icon: ImageVector,
onClick: () -> Unit,
) {
BaseSettingsItem( BaseSettingsItem(
label = label, label = label,
widget = { widget = {
@ -93,11 +85,7 @@ fun IconItem(
} }
@Composable @Composable
fun SortItem( fun SortItem(label: String, sortDescending: Boolean?, onClick: () -> Unit) {
label: String,
sortDescending: Boolean?,
onClick: () -> Unit,
) {
val arrowIcon = when (sortDescending) { val arrowIcon = when (sortDescending) {
true -> Icons.Default.ArrowDownward true -> Icons.Default.ArrowDownward
false -> Icons.Default.ArrowUpward false -> Icons.Default.ArrowUpward
@ -122,10 +110,7 @@ fun SortItem(
} }
@Composable @Composable
fun CheckboxItem( fun CheckboxItem(label: String, pref: Preference<Boolean>) {
label: String,
pref: Preference<Boolean>,
) {
val checked by pref.collectAsState() val checked by pref.collectAsState()
CheckboxItem( CheckboxItem(
label = label, label = label,
@ -135,11 +120,7 @@ fun CheckboxItem(
} }
@Composable @Composable
fun CheckboxItem( fun CheckboxItem(label: String, checked: Boolean, onClick: () -> Unit) {
label: String,
checked: Boolean,
onClick: () -> Unit,
) {
BaseSettingsItem( BaseSettingsItem(
label = label, label = label,
widget = { widget = {
@ -153,11 +134,7 @@ fun CheckboxItem(
} }
@Composable @Composable
fun RadioItem( fun RadioItem(label: String, selected: Boolean, onClick: () -> Unit) {
label: String,
selected: Boolean,
onClick: () -> Unit,
) {
BaseSettingsItem( BaseSettingsItem(
label = label, label = label,
widget = { widget = {
@ -314,11 +291,7 @@ fun TriStateItem(
} }
@Composable @Composable
fun TextItem( fun TextItem(label: String, value: String, onChange: (String) -> Unit) {
label: String,
value: String,
onChange: (String) -> Unit,
) {
OutlinedTextField( OutlinedTextField(
modifier = Modifier modifier = Modifier
.fillMaxWidth() .fillMaxWidth()
@ -331,10 +304,7 @@ fun TextItem(
} }
@Composable @Composable
fun SettingsChipRow( fun SettingsChipRow(@StringRes labelRes: Int, content: @Composable FlowRowScope.() -> Unit) {
@StringRes labelRes: Int,
content: @Composable FlowRowScope.() -> Unit,
) {
Column { Column {
HeadingItem(labelRes) HeadingItem(labelRes)
FlowRow( FlowRow(

View file

@ -197,7 +197,8 @@ private fun rememberColumnWidthSums(
horizontalArrangement, horizontalArrangement,
contentPadding, contentPadding,
) { ) {
{ constraints -> {
constraints ->
require(constraints.maxWidth != Constraints.Infinity) { require(constraints.maxWidth != Constraints.Infinity) {
"LazyVerticalGrid's width should be bound by parent" "LazyVerticalGrid's width should be bound by parent"
} }

View file

@ -30,7 +30,9 @@ fun AlertDialogContent(
title = title, title = title,
content = { content = {
Column { Column {
CompositionLocalProvider(LocalContentColor provides MaterialTheme.colorScheme.onSurfaceVariant) { CompositionLocalProvider(
LocalContentColor provides MaterialTheme.colorScheme.onSurfaceVariant,
) {
val textStyle = MaterialTheme.typography.bodyMedium val textStyle = MaterialTheme.typography.bodyMedium
ProvideTextStyle(textStyle) { ProvideTextStyle(textStyle) {
Box( Box(
@ -54,7 +56,9 @@ fun AlertDialogContent(
) )
.align(Alignment.End), .align(Alignment.End),
) { ) {
CompositionLocalProvider(LocalContentColor provides MaterialTheme.colorScheme.primary) { CompositionLocalProvider(
LocalContentColor provides MaterialTheme.colorScheme.primary,
) {
val textStyle = MaterialTheme.typography.labelLarge val textStyle = MaterialTheme.typography.labelLarge
ProvideTextStyle(value = textStyle, content = buttons) ProvideTextStyle(value = textStyle, content = buttons)
} }
@ -86,7 +90,9 @@ fun AlertDialogContent(
.fillMaxWidth(), .fillMaxWidth(),
) { ) {
icon?.let { icon?.let {
CompositionLocalProvider(LocalContentColor provides MaterialTheme.colorScheme.secondary) { CompositionLocalProvider(
LocalContentColor provides MaterialTheme.colorScheme.secondary,
) {
Box( Box(
Modifier Modifier
.padding(IconPadding) .padding(IconPadding)
@ -97,7 +103,9 @@ fun AlertDialogContent(
} }
} }
title?.let { title?.let {
CompositionLocalProvider(LocalContentColor provides MaterialTheme.colorScheme.onSurface) { CompositionLocalProvider(
LocalContentColor provides MaterialTheme.colorScheme.onSurface,
) {
val textStyle = MaterialTheme.typography.headlineSmall val textStyle = MaterialTheme.typography.headlineSmall
ProvideTextStyle(textStyle) { ProvideTextStyle(textStyle) {
Box( Box(

View file

@ -64,20 +64,19 @@ fun TextButton(
), ),
contentPadding: PaddingValues = M3ButtonDefaults.TextButtonContentPadding, contentPadding: PaddingValues = M3ButtonDefaults.TextButtonContentPadding,
content: @Composable RowScope.() -> Unit, content: @Composable RowScope.() -> Unit,
) = ) = Button(
Button( onClick = onClick,
onClick = onClick, modifier = modifier,
modifier = modifier, onLongClick = onLongClick,
onLongClick = onLongClick, enabled = enabled,
enabled = enabled, interactionSource = interactionSource,
interactionSource = interactionSource, elevation = elevation,
elevation = elevation, shape = shape,
shape = shape, border = border,
border = border, colors = colors,
colors = colors, contentPadding = contentPadding,
contentPadding = contentPadding, content = content,
content = content, )
)
/** /**
* Button with additional onLongClick functionality. * Button with additional onLongClick functionality.

View file

@ -48,7 +48,10 @@ fun NavigationRail(
.padding(vertical = MaterialTheme.padding.tiny) .padding(vertical = MaterialTheme.padding.tiny)
.selectableGroup(), .selectableGroup(),
horizontalAlignment = Alignment.CenterHorizontally, horizontalAlignment = Alignment.CenterHorizontally,
verticalArrangement = Arrangement.spacedBy(MaterialTheme.padding.tiny, alignment = Alignment.CenterVertically), verticalArrangement = Arrangement.spacedBy(
MaterialTheme.padding.tiny,
alignment = Alignment.CenterVertically,
),
) { ) {
if (header != null) { if (header != null) {
header() header()

View file

@ -99,7 +99,9 @@ import kotlin.math.max
@Composable @Composable
fun Scaffold( fun Scaffold(
modifier: Modifier = Modifier, modifier: Modifier = Modifier,
topBarScrollBehavior: TopAppBarScrollBehavior = TopAppBarDefaults.pinnedScrollBehavior(rememberTopAppBarState()), topBarScrollBehavior: TopAppBarScrollBehavior = TopAppBarDefaults.pinnedScrollBehavior(
rememberTopAppBarState(),
),
topBar: @Composable (TopAppBarScrollBehavior) -> Unit = {}, topBar: @Composable (TopAppBarScrollBehavior) -> Unit = {},
bottomBar: @Composable () -> Unit = {}, bottomBar: @Composable () -> Unit = {},
startBar: @Composable () -> Unit = {}, startBar: @Composable () -> Unit = {},
@ -116,7 +118,11 @@ fun Scaffold(
androidx.compose.material3.Surface( androidx.compose.material3.Surface(
modifier = Modifier modifier = Modifier
.nestedScroll(topBarScrollBehavior.nestedScrollConnection) .nestedScroll(topBarScrollBehavior.nestedScrollConnection)
.onConsumedWindowInsetsChanged { remainingWindowInsets.insets = contentWindowInsets.exclude(it) } .onConsumedWindowInsetsChanged {
remainingWindowInsets.insets = contentWindowInsets.exclude(
it,
)
}
.then(modifier), .then(modifier),
color = containerColor, color = containerColor,
contentColor = contentColor, contentColor = contentColor,
@ -271,7 +277,10 @@ private fun ScaffoldLayout(
} else { } else {
max(bottomBarHeightPx.toDp(), fabOffsetDp) max(bottomBarHeightPx.toDp(), fabOffsetDp)
}, },
start = max(insets.calculateStartPadding((this@SubcomposeLayout).layoutDirection), startBarWidth.toDp()), start = max(
insets.calculateStartPadding((this@SubcomposeLayout).layoutDirection),
startBarWidth.toDp(),
),
end = insets.calculateEndPadding((this@SubcomposeLayout).layoutDirection), end = insets.calculateEndPadding((this@SubcomposeLayout).layoutDirection),
) )
content(innerPadding) content(innerPadding)

View file

@ -104,9 +104,7 @@ private fun surfaceColorAtElevation(color: Color, elevation: Dp): Color {
} }
} }
private fun ColorScheme.surfaceColorAtElevation( private fun ColorScheme.surfaceColorAtElevation(elevation: Dp): Color {
elevation: Dp,
): Color {
if (elevation == 0.dp) return surface if (elevation == 0.dp) return surface
val alpha = ((4.5f * ln(elevation.value + 1)) + 2f) / 100f val alpha = ((4.5f * ln(elevation.value + 1)) + 2f) / 100f
return surfaceTint.copy(alpha = alpha).compositeOver(surface) return surfaceTint.copy(alpha = alpha).compositeOver(surface)

View file

@ -46,10 +46,7 @@ private fun Modifier.tabIndicatorOffset(
} }
@Composable @Composable
fun TabIndicator( fun TabIndicator(currentTabPosition: TabPosition, currentPageOffsetFraction: Float) {
currentTabPosition: TabPosition,
currentPageOffsetFraction: Float,
) {
SecondaryIndicator( SecondaryIndicator(
modifier = Modifier modifier = Modifier
.tabIndicatorOffset(currentTabPosition, currentPageOffsetFraction) .tabIndicatorOffset(currentTabPosition, currentPageOffsetFraction)
@ -59,10 +56,7 @@ fun TabIndicator(
} }
@Composable @Composable
fun TabText( fun TabText(text: String, badgeCount: Int? = null) {
text: String,
badgeCount: Int? = null,
) {
val pillAlpha = if (isSystemInDarkTheme()) 0.12f else 0.08f val pillAlpha = if (isSystemInDarkTheme()) 0.12f else 0.08f
Row( Row(

View file

@ -17,10 +17,7 @@ val CoverWidth = 58.dp
val CoverHeight = 87.dp val CoverHeight = 87.dp
@Composable @Composable
fun UpdatesMangaCover( fun UpdatesMangaCover(modifier: GlanceModifier = GlanceModifier, cover: Bitmap?) {
modifier: GlanceModifier = GlanceModifier,
cover: Bitmap?,
) {
Box( Box(
modifier = modifier modifier = modifier
.size(width = CoverWidth, height = CoverHeight) .size(width = CoverWidth, height = CoverHeight)

View file

@ -64,7 +64,9 @@ interface Source {
"Use the non-RxJava API instead", "Use the non-RxJava API instead",
ReplaceWith("getMangaDetails"), ReplaceWith("getMangaDetails"),
) )
fun fetchMangaDetails(manga: SManga): Observable<SManga> = throw IllegalStateException("Not used") fun fetchMangaDetails(manga: SManga): Observable<SManga> = throw IllegalStateException(
"Not used",
)
/** /**
* Returns an observable with all the available chapters for a manga. * Returns an observable with all the available chapters for a manga.
@ -75,7 +77,9 @@ interface Source {
"Use the non-RxJava API instead", "Use the non-RxJava API instead",
ReplaceWith("getChapterList"), ReplaceWith("getChapterList"),
) )
fun fetchChapterList(manga: SManga): Observable<List<SChapter>> = throw IllegalStateException("Not used") fun fetchChapterList(manga: SManga): Observable<List<SChapter>> = throw IllegalStateException(
"Not used",
)
/** /**
* Returns an observable with the list of pages a chapter has. Pages should be returned * Returns an observable with the list of pages a chapter has. Pages should be returned

View file

@ -3,7 +3,10 @@ package eu.kanade.tachiyomi.source.model
sealed class Filter<T>(val name: String, var state: T) { sealed class Filter<T>(val name: String, var state: T) {
open class Header(name: String) : Filter<Any>(name, 0) open class Header(name: String) : Filter<Any>(name, 0)
open class Separator(name: String = "") : Filter<Any>(name, 0) open class Separator(name: String = "") : Filter<Any>(name, 0)
abstract class Select<V>(name: String, val values: Array<V>, state: Int = 0) : Filter<Int>(name, state) abstract class Select<V>(name: String, val values: Array<V>, state: Int = 0) : Filter<Int>(
name,
state,
)
abstract class Text(name: String, state: String = "") : Filter<String>(name, state) abstract class Text(name: String, state: String = "") : Filter<String>(name, state)
abstract class CheckBox(name: String, state: Boolean = false) : Filter<Boolean>(name, state) abstract class CheckBox(name: String, state: Boolean = false) : Filter<Boolean>(name, state)
abstract class TriState(name: String, state: Int = STATE_IGNORE) : Filter<Int>(name, state) { abstract class TriState(name: String, state: Int = STATE_IGNORE) : Filter<Int>(name, state) {

View file

@ -135,7 +135,11 @@ abstract class HttpSource : CatalogueSource {
* @param query the search query. * @param query the search query.
* @param filters the list of filters to apply. * @param filters the list of filters to apply.
*/ */
override fun fetchSearchManga(page: Int, query: String, filters: FilterList): Observable<MangasPage> { override fun fetchSearchManga(
page: Int,
query: String,
filters: FilterList,
): Observable<MangasPage> {
return Observable.defer { return Observable.defer {
try { try {
client.newCall(searchMangaRequest(page, query, filters)).asObservableSuccess() client.newCall(searchMangaRequest(page, query, filters)).asObservableSuccess()
@ -157,7 +161,11 @@ abstract class HttpSource : CatalogueSource {
* @param query the search query. * @param query the search query.
* @param filters the list of filters to apply. * @param filters the list of filters to apply.
*/ */
protected abstract fun searchMangaRequest(page: Int, query: String, filters: FilterList): Request protected abstract fun searchMangaRequest(
page: Int,
query: String,
filters: FilterList,
): Request
/** /**
* Parses the response from the site and returns a [MangasPage] object. * Parses the response from the site and returns a [MangasPage] object.