Address spotless lint errors (mihonapp/mihon#1138)
* Add spotless (with ktlint) * Run spotlessApply * screaming case screaming case screaming case * Update PagerViewerAdapter.kt * Update ReaderTransitionView.kt (cherry picked from commit d6252ab7703d52ecf9f43de3ee36fd63e665a31f)
This commit is contained in:
parent
62507fc3cd
commit
e7ca892f65
267 changed files with 605 additions and 505 deletions
|
|
@ -23,7 +23,7 @@ if (gradle.startParameter.taskRequests.toString().contains("Standard")) {
|
|||
|
||||
// shortcutHelper.setFilePath("./shortcuts.xml")
|
||||
|
||||
val SUPPORTED_ABIS = setOf("armeabi-v7a", "arm64-v8a", "x86", "x86_64")
|
||||
val supportedAbis = setOf("armeabi-v7a", "arm64-v8a", "x86", "x86_64")
|
||||
|
||||
android {
|
||||
namespace = "eu.kanade.tachiyomi"
|
||||
|
|
@ -41,7 +41,7 @@ android {
|
|||
buildConfigField("boolean", "PREVIEW", "false")
|
||||
|
||||
ndk {
|
||||
abiFilters += SUPPORTED_ABIS
|
||||
abiFilters += supportedAbis
|
||||
}
|
||||
testInstrumentationRunner = "androidx.test.runner.AndroidJUnitRunner"
|
||||
}
|
||||
|
|
@ -50,7 +50,7 @@ android {
|
|||
abi {
|
||||
isEnable = true
|
||||
reset()
|
||||
include(*SUPPORTED_ABIS.toTypedArray())
|
||||
include(*supportedAbis.toTypedArray())
|
||||
isUniversalApk = true
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -117,7 +117,10 @@ class SyncChaptersWithSource(
|
|||
downloadManager.isChapterDownloaded(
|
||||
dbChapter.name,
|
||||
dbChapter.scanlator,
|
||||
/* SY --> */ manga.ogTitle /* SY <-- */,
|
||||
// SY -->
|
||||
// manga.title,
|
||||
manga.ogTitle,
|
||||
// SY <--
|
||||
manga.source,
|
||||
)
|
||||
|
||||
|
|
|
|||
|
|
@ -20,7 +20,11 @@ class UiPreferences(
|
|||
|
||||
fun appTheme() = preferenceStore.getEnum(
|
||||
"pref_app_theme",
|
||||
if (DeviceUtil.isDynamicColorAvailable) { AppTheme.MONET } else { AppTheme.DEFAULT },
|
||||
if (DeviceUtil.isDynamicColorAvailable) {
|
||||
AppTheme.MONET
|
||||
} else {
|
||||
AppTheme.DEFAULT
|
||||
},
|
||||
)
|
||||
|
||||
fun themeDarkAmoled() = preferenceStore.getBoolean("pref_theme_dark_amoled_key", false)
|
||||
|
|
|
|||
|
|
@ -266,7 +266,7 @@ private fun DetailsHeader(
|
|||
Extension name: ${extension.name} (lang: ${extension.lang}; package: ${extension.pkgName})
|
||||
Extension version: ${extension.versionName} (lib: ${extension.libVersion}; version code: ${extension.versionCode})
|
||||
NSFW: ${extension.isNsfw}
|
||||
""".trimIndent()
|
||||
""".trimIndent(),
|
||||
)
|
||||
|
||||
if (extension is Extension.Installed) {
|
||||
|
|
@ -276,8 +276,8 @@ private fun DetailsHeader(
|
|||
Update available: ${extension.hasUpdate}
|
||||
Obsolete: ${extension.isObsolete}
|
||||
Shared: ${extension.isShared}
|
||||
Repository: ${extension.repoUrl}
|
||||
""".trimIndent()
|
||||
Repository: ${extension.repoUrl}
|
||||
""".trimIndent(),
|
||||
)
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -231,7 +231,9 @@ private fun ExtensionContent(
|
|||
when (it) {
|
||||
is Extension.Available -> onInstallExtension(it)
|
||||
is Extension.Installed -> onOpenExtension(it)
|
||||
is Extension.Untrusted -> { trustState = it }
|
||||
is Extension.Untrusted -> {
|
||||
trustState = it
|
||||
}
|
||||
}
|
||||
},
|
||||
onLongClickItem = onLongClickItem,
|
||||
|
|
@ -253,7 +255,9 @@ private fun ExtensionContent(
|
|||
onOpenExtension(it)
|
||||
}
|
||||
}
|
||||
is Extension.Untrusted -> { trustState = it }
|
||||
is Extension.Untrusted -> {
|
||||
trustState = it
|
||||
}
|
||||
}
|
||||
},
|
||||
)
|
||||
|
|
|
|||
|
|
@ -69,7 +69,7 @@ import tachiyomi.i18n.kmk.KMR
|
|||
import tachiyomi.i18n.sy.SYMR
|
||||
import tachiyomi.presentation.core.components.FastScrollLazyColumn
|
||||
import tachiyomi.presentation.core.components.LabeledCheckbox
|
||||
import tachiyomi.presentation.core.components.material.SecondaryItemAlpha
|
||||
import tachiyomi.presentation.core.components.material.SECONDARY_ALPHA
|
||||
import tachiyomi.presentation.core.components.material.padding
|
||||
import tachiyomi.presentation.core.i18n.stringResource
|
||||
import tachiyomi.presentation.core.screens.EmptyScreen
|
||||
|
|
@ -399,7 +399,7 @@ private fun SourcePinButton(
|
|||
MaterialTheme.colorScheme.primary
|
||||
} else {
|
||||
MaterialTheme.colorScheme.onBackground.copy(
|
||||
alpha = SecondaryItemAlpha,
|
||||
alpha = SECONDARY_ALPHA,
|
||||
)
|
||||
}
|
||||
val description = if (isPinned) MR.strings.action_unpin else MR.strings.action_pin
|
||||
|
|
|
|||
|
|
@ -34,7 +34,7 @@ import com.gowtham.ratingbar.RatingBar
|
|||
import com.gowtham.ratingbar.RatingBarStyle
|
||||
import dev.icerock.moko.resources.StringResource
|
||||
import eu.kanade.presentation.library.components.CommonMangaItemDefaults
|
||||
import eu.kanade.presentation.library.components.GridSelectedCoverAlpha
|
||||
import eu.kanade.presentation.library.components.GRID_SELECTED_COVER_ALPHA
|
||||
import eu.kanade.presentation.manga.components.MangaCover
|
||||
import eu.kanade.presentation.manga.components.MangaCoverHide
|
||||
import exh.debug.DebugToggles
|
||||
|
|
@ -205,7 +205,7 @@ fun BrowseSourceEHentaiListItem(
|
|||
modifier = Modifier
|
||||
.fillMaxHeight(),
|
||||
// KMK -->
|
||||
alpha = if (isSelected) GridSelectedCoverAlpha else coverAlpha,
|
||||
alpha = if (isSelected) GRID_SELECTED_COVER_ALPHA else coverAlpha,
|
||||
bgColor = bgColor ?: (MaterialTheme.colorScheme.surface.takeIf { isSelected }),
|
||||
tint = onBgColor,
|
||||
// KMK <--
|
||||
|
|
|
|||
|
|
@ -79,7 +79,7 @@ fun TabbedDialog(
|
|||
modifier = Modifier.animateContentSize(),
|
||||
state = pagerState,
|
||||
verticalAlignment = Alignment.Top,
|
||||
pageContent = { page -> content(page) }
|
||||
pageContent = { page -> content(page) },
|
||||
)
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -63,7 +63,7 @@ private val ContinueReadingButtonIconSizeLarge = 20.dp
|
|||
private val ContinueReadingButtonGridPadding = 6.dp
|
||||
private val ContinueReadingButtonListSpacing = 8.dp
|
||||
|
||||
internal const val GridSelectedCoverAlpha = 0.76f
|
||||
internal const val GRID_SELECTED_COVER_ALPHA = 0.76f
|
||||
|
||||
/**
|
||||
* Layout of grid list item with title overlaying the cover.
|
||||
|
|
@ -113,7 +113,7 @@ fun MangaCompactGridItem(
|
|||
.fillMaxWidth(),
|
||||
data = coverData,
|
||||
// KMK -->
|
||||
alpha = if (isSelected) GridSelectedCoverAlpha else coverAlpha,
|
||||
alpha = if (isSelected) GRID_SELECTED_COVER_ALPHA else coverAlpha,
|
||||
bgColor = bgColor ?: (MaterialTheme.colorScheme.surface.takeIf { isSelected }),
|
||||
tint = onBgColor,
|
||||
// KMK <--
|
||||
|
|
@ -245,7 +245,7 @@ fun MangaComfortableGridItem(
|
|||
.fillMaxWidth(),
|
||||
data = coverData,
|
||||
// KMK -->
|
||||
alpha = if (isSelected) GridSelectedCoverAlpha else coverAlpha,
|
||||
alpha = if (isSelected) GRID_SELECTED_COVER_ALPHA else coverAlpha,
|
||||
bgColor = bgColor ?: (MaterialTheme.colorScheme.surface.takeIf { isSelected }),
|
||||
tint = onBgColor,
|
||||
// KMK <--
|
||||
|
|
@ -448,7 +448,7 @@ fun MangaListItem(
|
|||
size = ContinueReadingButtonSizeSmall,
|
||||
iconSize = ContinueReadingButtonIconSizeSmall,
|
||||
onClick = onClickContinueReading,
|
||||
modifier = Modifier.padding(start = ContinueReadingButtonListSpacing)
|
||||
modifier = Modifier.padding(start = ContinueReadingButtonListSpacing),
|
||||
)
|
||||
}
|
||||
}
|
||||
|
|
@ -469,7 +469,7 @@ private fun ContinueReadingButton(
|
|||
containerColor = MaterialTheme.colorScheme.primaryContainer.copy(alpha = 0.9f),
|
||||
contentColor = contentColorFor(MaterialTheme.colorScheme.primaryContainer),
|
||||
),
|
||||
modifier = Modifier.size(size)
|
||||
modifier = Modifier.size(size),
|
||||
) {
|
||||
Icon(
|
||||
imageVector = Icons.Filled.PlayArrow,
|
||||
|
|
|
|||
|
|
@ -14,7 +14,7 @@ import androidx.compose.ui.Modifier
|
|||
import androidx.compose.ui.text.style.TextOverflow
|
||||
import androidx.compose.ui.unit.dp
|
||||
import tachiyomi.i18n.MR
|
||||
import tachiyomi.presentation.core.components.material.SecondaryItemAlpha
|
||||
import tachiyomi.presentation.core.components.material.SECONDARY_ALPHA
|
||||
import tachiyomi.presentation.core.components.material.padding
|
||||
import tachiyomi.presentation.core.i18n.pluralStringResource
|
||||
import tachiyomi.presentation.core.i18n.stringResource
|
||||
|
|
@ -70,6 +70,6 @@ private fun MissingChaptersWarning(count: Int) {
|
|||
maxLines = 1,
|
||||
overflow = TextOverflow.Ellipsis,
|
||||
style = MaterialTheme.typography.bodySmall,
|
||||
color = MaterialTheme.colorScheme.error.copy(alpha = SecondaryItemAlpha),
|
||||
color = MaterialTheme.colorScheme.error.copy(alpha = SECONDARY_ALPHA),
|
||||
)
|
||||
}
|
||||
|
|
|
|||
|
|
@ -40,8 +40,8 @@ import eu.kanade.tachiyomi.data.download.model.Download
|
|||
import me.saket.swipe.SwipeableActionsBox
|
||||
import tachiyomi.domain.library.service.LibraryPreferences
|
||||
import tachiyomi.i18n.MR
|
||||
import tachiyomi.presentation.core.components.material.ReadItemAlpha
|
||||
import tachiyomi.presentation.core.components.material.SecondaryItemAlpha
|
||||
import tachiyomi.presentation.core.components.material.DISABLED_ALPHA
|
||||
import tachiyomi.presentation.core.components.material.SECONDARY_ALPHA
|
||||
import tachiyomi.presentation.core.i18n.stringResource
|
||||
import tachiyomi.presentation.core.util.selectedBackground
|
||||
|
||||
|
|
@ -135,7 +135,7 @@ fun MangaChapterListItem(
|
|||
maxLines = 1,
|
||||
overflow = TextOverflow.Ellipsis,
|
||||
onTextLayout = { textHeight = it.size.height },
|
||||
color = LocalContentColor.current.copy(alpha = if (read) ReadItemAlpha else 1f),
|
||||
color = LocalContentColor.current.copy(alpha = if (read) DISABLED_ALPHA else 1f),
|
||||
)
|
||||
}
|
||||
|
||||
|
|
@ -143,7 +143,7 @@ fun MangaChapterListItem(
|
|||
val subtitleStyle = MaterialTheme.typography.bodySmall
|
||||
.merge(
|
||||
color = LocalContentColor.current
|
||||
.copy(alpha = if (read) ReadItemAlpha else SecondaryItemAlpha)
|
||||
.copy(alpha = if (read) DISABLED_ALPHA else SECONDARY_ALPHA),
|
||||
)
|
||||
ProvideTextStyle(value = subtitleStyle) {
|
||||
if (date != null) {
|
||||
|
|
@ -159,7 +159,7 @@ fun MangaChapterListItem(
|
|||
text = readProgress,
|
||||
maxLines = 1,
|
||||
overflow = TextOverflow.Ellipsis,
|
||||
color = LocalContentColor.current.copy(alpha = ReadItemAlpha),
|
||||
color = LocalContentColor.current.copy(alpha = DISABLED_ALPHA),
|
||||
)
|
||||
if (scanlator != null/* SY --> */ || sourceName != null/* SY <-- */) DotSeparatorText()
|
||||
}
|
||||
|
|
|
|||
|
|
@ -83,6 +83,7 @@ import tachiyomi.domain.manga.model.Manga
|
|||
import tachiyomi.i18n.MR
|
||||
import tachiyomi.i18n.kmk.KMR
|
||||
import tachiyomi.i18n.sy.SYMR
|
||||
import tachiyomi.presentation.core.components.material.DISABLED_ALPHA
|
||||
import tachiyomi.presentation.core.components.material.TextButton
|
||||
import tachiyomi.presentation.core.components.material.padding
|
||||
import tachiyomi.presentation.core.i18n.pluralStringResource
|
||||
|
|
@ -209,7 +210,7 @@ fun MangaActionRow(
|
|||
// SY <--
|
||||
modifier: Modifier = Modifier,
|
||||
) {
|
||||
val defaultActionButtonColor = MaterialTheme.colorScheme.onSurface.copy(alpha = .38f)
|
||||
val defaultActionButtonColor = MaterialTheme.colorScheme.onSurface.copy(alpha = DISABLED_ALPHA)
|
||||
|
||||
// TODO: show something better when using custom interval
|
||||
val nextUpdateDays = remember(nextUpdate) {
|
||||
|
|
|
|||
|
|
@ -76,7 +76,7 @@ private fun NewUpdateScreenPreview() {
|
|||
changelogInfo = """
|
||||
## Yay
|
||||
Foobar
|
||||
|
||||
|
||||
### More info
|
||||
- Hello
|
||||
- World
|
||||
|
|
|
|||
|
|
@ -397,7 +397,7 @@ object SettingsAdvancedScreen : SearchableSettings {
|
|||
chooseColorProfile.launch(arrayOf("*/*"))
|
||||
},
|
||||
),
|
||||
)
|
||||
),
|
||||
)
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -37,7 +37,7 @@ class OpenSourceLicensesScreen : Screen() {
|
|||
name = it.name,
|
||||
website = it.website,
|
||||
license = it.licenses.firstOrNull()?.htmlReadyLicenseContent.orEmpty(),
|
||||
)
|
||||
),
|
||||
)
|
||||
},
|
||||
)
|
||||
|
|
|
|||
|
|
@ -28,7 +28,7 @@ import tachiyomi.presentation.core.i18n.stringResource
|
|||
class BackupSchemaScreen : Screen() {
|
||||
|
||||
companion object {
|
||||
const val title = "Backup file schema"
|
||||
const val TITLE = "Backup file schema"
|
||||
}
|
||||
|
||||
@Composable
|
||||
|
|
@ -41,7 +41,7 @@ class BackupSchemaScreen : Screen() {
|
|||
Scaffold(
|
||||
topBar = {
|
||||
AppBar(
|
||||
title = title,
|
||||
title = TITLE,
|
||||
navigateUp = navigator::pop,
|
||||
actions = {
|
||||
AppBarActions(
|
||||
|
|
@ -50,7 +50,7 @@ class BackupSchemaScreen : Screen() {
|
|||
title = stringResource(MR.strings.action_copy_to_clipboard),
|
||||
icon = Icons.Default.ContentCopy,
|
||||
onClick = {
|
||||
context.copyToClipboard(title, schema)
|
||||
context.copyToClipboard(TITLE, schema)
|
||||
},
|
||||
),
|
||||
),
|
||||
|
|
|
|||
|
|
@ -31,11 +31,11 @@ class DebugInfoScreen : Screen() {
|
|||
itemsProvider = {
|
||||
listOf(
|
||||
Preference.PreferenceItem.TextPreference(
|
||||
title = WorkerInfoScreen.title,
|
||||
title = WorkerInfoScreen.TITLE,
|
||||
onClick = { navigator.push(WorkerInfoScreen()) },
|
||||
),
|
||||
Preference.PreferenceItem.TextPreference(
|
||||
title = BackupSchemaScreen.title,
|
||||
title = BackupSchemaScreen.TITLE,
|
||||
onClick = { navigator.push(BackupSchemaScreen()) },
|
||||
),
|
||||
getAppInfoGroup(),
|
||||
|
|
|
|||
|
|
@ -49,7 +49,7 @@ import java.time.ZoneId
|
|||
class WorkerInfoScreen : Screen() {
|
||||
|
||||
companion object {
|
||||
const val title = "Worker info"
|
||||
const val TITLE = "Worker info"
|
||||
}
|
||||
|
||||
@Composable
|
||||
|
|
@ -65,7 +65,7 @@ class WorkerInfoScreen : Screen() {
|
|||
Scaffold(
|
||||
topBar = {
|
||||
AppBar(
|
||||
title = title,
|
||||
title = TITLE,
|
||||
navigateUp = navigator::pop,
|
||||
actions = {
|
||||
AppBarActions(
|
||||
|
|
@ -74,7 +74,7 @@ class WorkerInfoScreen : Screen() {
|
|||
title = stringResource(MR.strings.action_copy_to_clipboard),
|
||||
icon = Icons.Default.ContentCopy,
|
||||
onClick = {
|
||||
context.copyToClipboard(title, enqueued + finished + running)
|
||||
context.copyToClipboard(TITLE, enqueued + finished + running)
|
||||
},
|
||||
),
|
||||
),
|
||||
|
|
@ -159,7 +159,7 @@ class WorkerInfoScreen : Screen() {
|
|||
Injekt.get<UiPreferences>().dateFormat().get(),
|
||||
),
|
||||
)
|
||||
appendLine("Next scheduled run: $timestamp",)
|
||||
appendLine("Next scheduled run: $timestamp")
|
||||
appendLine("Attempt #${workInfo.runAttemptCount + 1}")
|
||||
}
|
||||
appendLine()
|
||||
|
|
|
|||
|
|
@ -32,7 +32,9 @@ import tachiyomi.i18n.MR
|
|||
import tachiyomi.presentation.core.i18n.stringResource
|
||||
|
||||
private enum class State {
|
||||
CHECKED, INVERSED, UNCHECKED
|
||||
CHECKED,
|
||||
INVERSED,
|
||||
UNCHECKED,
|
||||
}
|
||||
|
||||
@Composable
|
||||
|
|
|
|||
|
|
@ -15,7 +15,7 @@ import androidx.compose.ui.graphics.vector.ImageVector
|
|||
import androidx.compose.ui.text.TextStyle
|
||||
import androidx.compose.ui.text.font.FontWeight
|
||||
import androidx.compose.ui.text.style.TextAlign
|
||||
import tachiyomi.presentation.core.components.material.SecondaryItemAlpha
|
||||
import tachiyomi.presentation.core.components.material.SECONDARY_ALPHA
|
||||
import tachiyomi.presentation.core.components.material.padding
|
||||
|
||||
@Composable
|
||||
|
|
@ -73,7 +73,7 @@ private fun RowScope.BaseStatsItem(
|
|||
style = subtitleStyle
|
||||
.copy(
|
||||
color = MaterialTheme.colorScheme.onSurface
|
||||
.copy(alpha = SecondaryItemAlpha),
|
||||
.copy(alpha = SECONDARY_ALPHA),
|
||||
),
|
||||
textAlign = TextAlign.Center,
|
||||
)
|
||||
|
|
|
|||
|
|
@ -226,7 +226,7 @@ private fun ChapterText(
|
|||
Text(
|
||||
text = buildAnnotatedString {
|
||||
if (downloaded) {
|
||||
appendInlineContent(DownloadedIconContentId)
|
||||
appendInlineContent(DOWNLOADED_ICON_ID)
|
||||
append(' ')
|
||||
}
|
||||
append(name)
|
||||
|
|
@ -236,7 +236,7 @@ private fun ChapterText(
|
|||
overflow = TextOverflow.Ellipsis,
|
||||
style = MaterialTheme.typography.titleLarge,
|
||||
inlineContent = persistentMapOf(
|
||||
DownloadedIconContentId to InlineTextContent(
|
||||
DOWNLOADED_ICON_ID to InlineTextContent(
|
||||
Placeholder(
|
||||
width = 22.sp,
|
||||
height = 22.sp,
|
||||
|
|
@ -273,7 +273,7 @@ private val CardColor: CardColors
|
|||
)
|
||||
|
||||
private val VerticalSpacerSize = 24.dp
|
||||
private const val DownloadedIconContentId = "downloaded"
|
||||
private const val DOWNLOADED_ICON_ID = "downloaded"
|
||||
|
||||
private fun previewChapter(name: String, scanlator: String, chapterNumber: Double) = Chapter.create().copy(
|
||||
id = 0L,
|
||||
|
|
|
|||
|
|
@ -38,7 +38,6 @@ import androidx.compose.runtime.remember
|
|||
import androidx.compose.runtime.setValue
|
||||
import androidx.compose.ui.Alignment
|
||||
import androidx.compose.ui.Modifier
|
||||
import androidx.compose.ui.draw.alpha
|
||||
import androidx.compose.ui.draw.clip
|
||||
import androidx.compose.ui.platform.LocalContext
|
||||
import androidx.compose.ui.text.style.TextAlign
|
||||
|
|
@ -58,8 +57,6 @@ import tachiyomi.i18n.MR
|
|||
import tachiyomi.presentation.core.i18n.stringResource
|
||||
import java.time.format.DateTimeFormatter
|
||||
|
||||
private const val UnsetStatusTextAlpha = 0.5F
|
||||
|
||||
@Composable
|
||||
fun TrackInfoDialogHome(
|
||||
trackItems: List<TrackItem>,
|
||||
|
|
@ -211,10 +208,9 @@ private fun TrackInfoItem(
|
|||
if (onScoreClick != null) {
|
||||
VerticalDivider()
|
||||
TrackDetailsItem(
|
||||
modifier = Modifier
|
||||
.weight(1f)
|
||||
.alpha(if (score == null) UnsetStatusTextAlpha else 1f),
|
||||
text = score ?: stringResource(MR.strings.score),
|
||||
modifier = Modifier.weight(1f),
|
||||
text = score,
|
||||
placeholder = stringResource(MR.strings.score),
|
||||
onClick = onScoreClick,
|
||||
)
|
||||
}
|
||||
|
|
@ -243,6 +239,8 @@ private fun TrackInfoItem(
|
|||
}
|
||||
}
|
||||
|
||||
private const val UNSET_TEXT_ALPHA = 0.5F
|
||||
|
||||
@Composable
|
||||
private fun TrackDetailsItem(
|
||||
text: String?,
|
||||
|
|
@ -263,7 +261,7 @@ private fun TrackDetailsItem(
|
|||
overflow = TextOverflow.Ellipsis,
|
||||
style = MaterialTheme.typography.bodyMedium,
|
||||
textAlign = TextAlign.Center,
|
||||
color = MaterialTheme.colorScheme.onSurface.copy(alpha = if (text == null) UnsetStatusTextAlpha else 1f),
|
||||
color = MaterialTheme.colorScheme.onSurface.copy(alpha = if (text == null) UNSET_TEXT_ALPHA else 1f),
|
||||
)
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -45,7 +45,7 @@ import eu.kanade.tachiyomi.ui.updates.UpdatesItem
|
|||
import tachiyomi.domain.updates.model.UpdatesWithRelations
|
||||
import tachiyomi.i18n.MR
|
||||
import tachiyomi.presentation.core.components.ListGroupHeader
|
||||
import tachiyomi.presentation.core.components.material.ReadItemAlpha
|
||||
import tachiyomi.presentation.core.components.material.DISABLED_ALPHA
|
||||
import tachiyomi.presentation.core.components.material.padding
|
||||
import tachiyomi.presentation.core.i18n.stringResource
|
||||
import tachiyomi.presentation.core.util.selectedBackground
|
||||
|
|
@ -154,7 +154,7 @@ private fun UpdatesUiItem(
|
|||
modifier: Modifier = Modifier,
|
||||
) {
|
||||
val haptic = LocalHapticFeedback.current
|
||||
val textAlpha = if (update.read) ReadItemAlpha else 1f
|
||||
val textAlpha = if (update.read) DISABLED_ALPHA else 1f
|
||||
|
||||
Row(
|
||||
modifier = modifier
|
||||
|
|
@ -238,7 +238,7 @@ private fun UpdatesUiItem(
|
|||
Text(
|
||||
text = readProgress,
|
||||
maxLines = 1,
|
||||
color = LocalContentColor.current.copy(alpha = ReadItemAlpha),
|
||||
color = LocalContentColor.current.copy(alpha = DISABLED_ALPHA),
|
||||
overflow = TextOverflow.Ellipsis,
|
||||
)
|
||||
}
|
||||
|
|
|
|||
|
|
@ -218,7 +218,7 @@ class BackupRestorer(
|
|||
}
|
||||
|
||||
private fun CoroutineScope.restoreExtensionRepos(
|
||||
backupExtensionRepo: List<BackupExtensionRepos>
|
||||
backupExtensionRepo: List<BackupExtensionRepos>,
|
||||
) = launch {
|
||||
backupExtensionRepo
|
||||
.forEach {
|
||||
|
|
|
|||
|
|
@ -8,7 +8,7 @@ import uy.kohesive.injekt.api.get
|
|||
|
||||
class ExtensionRepoRestorer(
|
||||
private val handler: DatabaseHandler = Injekt.get(),
|
||||
private val getExtensionRepos: GetExtensionRepo = Injekt.get()
|
||||
private val getExtensionRepos: GetExtensionRepo = Injekt.get(),
|
||||
) {
|
||||
|
||||
suspend operator fun invoke(
|
||||
|
|
@ -32,7 +32,7 @@ class ExtensionRepoRestorer(
|
|||
backupRepo.name,
|
||||
backupRepo.shortName,
|
||||
backupRepo.website,
|
||||
backupRepo.signingKeyFingerprint
|
||||
backupRepo.signingKeyFingerprint,
|
||||
)
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -110,7 +110,7 @@ class MangaCoverFetcher(
|
|||
source = ImageSource(
|
||||
file = file.toOkioPath(),
|
||||
fileSystem = FileSystem.SYSTEM,
|
||||
diskCacheKey = diskCacheKey
|
||||
diskCacheKey = diskCacheKey,
|
||||
),
|
||||
mimeType = "image/*",
|
||||
dataSource = DataSource.DISK,
|
||||
|
|
|
|||
|
|
@ -1,3 +1,5 @@
|
|||
@file:Suppress("PropertyName", "ktlint:standard:property-naming")
|
||||
|
||||
package eu.kanade.tachiyomi.data.database.models
|
||||
|
||||
import eu.kanade.tachiyomi.source.model.SChapter
|
||||
|
|
|
|||
|
|
@ -1,3 +1,5 @@
|
|||
@file:Suppress("PropertyName", "ktlint:standard:property-naming")
|
||||
|
||||
package eu.kanade.tachiyomi.data.database.models
|
||||
|
||||
class ChapterImpl : Chapter {
|
||||
|
|
|
|||
|
|
@ -1,3 +1,5 @@
|
|||
@file:Suppress("PropertyName", "ktlint:standard:property-naming")
|
||||
|
||||
package eu.kanade.tachiyomi.data.database.models
|
||||
|
||||
import java.io.Serializable
|
||||
|
|
|
|||
|
|
@ -1,3 +1,5 @@
|
|||
@file:Suppress("PropertyName", "ktlint:standard:property-naming")
|
||||
|
||||
package eu.kanade.tachiyomi.data.database.models
|
||||
|
||||
class TrackImpl : Track {
|
||||
|
|
|
|||
|
|
@ -190,7 +190,7 @@ class Downloader(
|
|||
fun clearQueue() {
|
||||
cancelDownloaderJob()
|
||||
|
||||
_clearQueue()
|
||||
internalClearQueue()
|
||||
notifier.dismissProgress()
|
||||
}
|
||||
|
||||
|
|
@ -204,9 +204,12 @@ class Downloader(
|
|||
val activeDownloadsFlow = queueState.transformLatest { queue ->
|
||||
while (true) {
|
||||
val activeDownloads = queue.asSequence()
|
||||
.filter { it.status.value <= Download.State.DOWNLOADING.value } // Ignore completed downloads, leave them in the queue
|
||||
// Ignore completed downloads, leave them in the queue
|
||||
.filter { it.status.value <= Download.State.DOWNLOADING.value }
|
||||
.groupBy { it.source }
|
||||
.toList().take(5) // Concurrently download from 5 different sources
|
||||
.toList()
|
||||
// Concurrently download from 5 different sources
|
||||
.take(5)
|
||||
.map { (_, downloads) -> downloads.first() }
|
||||
emit(activeDownloads)
|
||||
|
||||
|
|
@ -650,7 +653,7 @@ class Downloader(
|
|||
chapter,
|
||||
urls,
|
||||
categories,
|
||||
source.name
|
||||
source.name,
|
||||
)
|
||||
|
||||
// Remove the old file
|
||||
|
|
@ -710,7 +713,7 @@ class Downloader(
|
|||
removeFromQueueIf { it.manga.id == manga.id }
|
||||
}
|
||||
|
||||
private fun _clearQueue() {
|
||||
private fun internalClearQueue() {
|
||||
_queueState.update {
|
||||
it.forEach { download ->
|
||||
if (download.status == Download.State.DOWNLOADING || download.status == Download.State.QUEUE) {
|
||||
|
|
@ -732,7 +735,7 @@ class Downloader(
|
|||
}
|
||||
|
||||
pause()
|
||||
_clearQueue()
|
||||
internalClearQueue()
|
||||
addAllToQueue(downloads)
|
||||
|
||||
if (wasRunning) {
|
||||
|
|
|
|||
|
|
@ -778,7 +778,9 @@ class LibraryUpdateJob(private val context: Context, workerParams: WorkerParamet
|
|||
val constraints = Constraints(
|
||||
requiredNetworkType = if (DEVICE_NETWORK_NOT_METERED in restrictions) {
|
||||
NetworkType.UNMETERED
|
||||
} else { NetworkType.CONNECTED },
|
||||
} else {
|
||||
NetworkType.CONNECTED
|
||||
},
|
||||
requiresCharging = DEVICE_CHARGING in restrictions,
|
||||
requiresBatteryNotLow = true,
|
||||
)
|
||||
|
|
|
|||
|
|
@ -47,10 +47,10 @@ class AnilistApi(val client: OkHttpClient, interceptor: AnilistInterceptor) {
|
|||
return withIOContext {
|
||||
val query = """
|
||||
|mutation AddManga(${'$'}mangaId: Int, ${'$'}progress: Int, ${'$'}status: MediaListStatus) {
|
||||
|SaveMediaListEntry (mediaId: ${'$'}mangaId, progress: ${'$'}progress, status: ${'$'}status) {
|
||||
| id
|
||||
| status
|
||||
|}
|
||||
|SaveMediaListEntry (mediaId: ${'$'}mangaId, progress: ${'$'}progress, status: ${'$'}status) {
|
||||
| id
|
||||
| status
|
||||
|}
|
||||
|}
|
||||
|
|
||||
""".trimMargin()
|
||||
|
|
@ -65,7 +65,7 @@ class AnilistApi(val client: OkHttpClient, interceptor: AnilistInterceptor) {
|
|||
with(json) {
|
||||
authClient.newCall(
|
||||
POST(
|
||||
apiUrl,
|
||||
API_URL,
|
||||
body = payload.toString().toRequestBody(jsonMime),
|
||||
),
|
||||
)
|
||||
|
|
@ -109,7 +109,7 @@ class AnilistApi(val client: OkHttpClient, interceptor: AnilistInterceptor) {
|
|||
put("completedAt", createDate(track.finished_reading_date))
|
||||
}
|
||||
}
|
||||
authClient.newCall(POST(apiUrl, body = payload.toString().toRequestBody(jsonMime)))
|
||||
authClient.newCall(POST(API_URL, body = payload.toString().toRequestBody(jsonMime)))
|
||||
.awaitSuccess()
|
||||
track
|
||||
}
|
||||
|
|
@ -119,9 +119,9 @@ class AnilistApi(val client: OkHttpClient, interceptor: AnilistInterceptor) {
|
|||
withIOContext {
|
||||
val query = """
|
||||
|mutation DeleteManga(${'$'}listId: Int) {
|
||||
|DeleteMediaListEntry(id: ${'$'}listId) {
|
||||
|DeleteMediaListEntry(id: ${'$'}listId) {
|
||||
|deleted
|
||||
|}
|
||||
|}
|
||||
|}
|
||||
|
|
||||
""".trimMargin()
|
||||
|
|
@ -131,7 +131,7 @@ class AnilistApi(val client: OkHttpClient, interceptor: AnilistInterceptor) {
|
|||
put("listId", track.libraryId)
|
||||
}
|
||||
}
|
||||
authClient.newCall(POST(apiUrl, body = payload.toString().toRequestBody(jsonMime)))
|
||||
authClient.newCall(POST(API_URL, body = payload.toString().toRequestBody(jsonMime)))
|
||||
.awaitSuccess()
|
||||
}
|
||||
}
|
||||
|
|
@ -172,7 +172,7 @@ class AnilistApi(val client: OkHttpClient, interceptor: AnilistInterceptor) {
|
|||
with(json) {
|
||||
authClient.newCall(
|
||||
POST(
|
||||
apiUrl,
|
||||
API_URL,
|
||||
body = payload.toString().toRequestBody(jsonMime),
|
||||
),
|
||||
)
|
||||
|
|
@ -242,7 +242,7 @@ class AnilistApi(val client: OkHttpClient, interceptor: AnilistInterceptor) {
|
|||
with(json) {
|
||||
authClient.newCall(
|
||||
POST(
|
||||
apiUrl,
|
||||
API_URL,
|
||||
body = payload.toString().toRequestBody(jsonMime),
|
||||
),
|
||||
)
|
||||
|
|
@ -286,7 +286,7 @@ class AnilistApi(val client: OkHttpClient, interceptor: AnilistInterceptor) {
|
|||
with(json) {
|
||||
authClient.newCall(
|
||||
POST(
|
||||
apiUrl,
|
||||
API_URL,
|
||||
body = payload.toString().toRequestBody(jsonMime),
|
||||
),
|
||||
)
|
||||
|
|
@ -365,17 +365,17 @@ class AnilistApi(val client: OkHttpClient, interceptor: AnilistInterceptor) {
|
|||
|
||||
companion object {
|
||||
// Registered under KMK's MAL account
|
||||
private const val clientId = "16801"
|
||||
private const val apiUrl = "https://graphql.anilist.co/"
|
||||
private const val baseUrl = "https://anilist.co/api/v2/"
|
||||
private const val baseMangaUrl = "https://anilist.co/manga/"
|
||||
private const val CLIENT_ID = "16801"
|
||||
private const val API_URL = "https://graphql.anilist.co/"
|
||||
private const val BASE_URL = "https://anilist.co/api/v2/"
|
||||
private const val BASE_MANGA_URL = "https://anilist.co/manga/"
|
||||
|
||||
fun mangaUrl(mediaId: Long): String {
|
||||
return baseMangaUrl + mediaId
|
||||
return BASE_MANGA_URL + mediaId
|
||||
}
|
||||
|
||||
fun authUrl(): Uri = "${baseUrl}oauth/authorize".toUri().buildUpon()
|
||||
.appendQueryParameter("client_id", clientId)
|
||||
fun authUrl(): Uri = "${BASE_URL}oauth/authorize".toUri().buildUpon()
|
||||
.appendQueryParameter("client_id", CLIENT_ID)
|
||||
.appendQueryParameter("response_type", "token")
|
||||
.build()
|
||||
}
|
||||
|
|
|
|||
|
|
@ -42,7 +42,7 @@ class BangumiApi(
|
|||
.add("rating", track.score.toInt().toString())
|
||||
.add("status", track.toBangumiStatus())
|
||||
.build()
|
||||
authClient.newCall(POST("$apiUrl/collection/${track.remote_id}/update", body = body))
|
||||
authClient.newCall(POST("$API_URL/collection/${track.remote_id}/update", body = body))
|
||||
.awaitSuccess()
|
||||
track
|
||||
}
|
||||
|
|
@ -55,7 +55,7 @@ class BangumiApi(
|
|||
.add("rating", track.score.toInt().toString())
|
||||
.add("status", track.toBangumiStatus())
|
||||
.build()
|
||||
authClient.newCall(POST("$apiUrl/collection/${track.remote_id}/update", body = sbody))
|
||||
authClient.newCall(POST("$API_URL/collection/${track.remote_id}/update", body = sbody))
|
||||
.awaitSuccess()
|
||||
|
||||
// chapter update
|
||||
|
|
@ -64,7 +64,7 @@ class BangumiApi(
|
|||
.build()
|
||||
authClient.newCall(
|
||||
POST(
|
||||
"$apiUrl/subject/${track.remote_id}/update/watched_eps",
|
||||
"$API_URL/subject/${track.remote_id}/update/watched_eps",
|
||||
body = body,
|
||||
),
|
||||
).awaitSuccess()
|
||||
|
|
@ -75,7 +75,7 @@ class BangumiApi(
|
|||
|
||||
suspend fun search(search: String): List<TrackSearch> {
|
||||
return withIOContext {
|
||||
val url = "$apiUrl/search/subject/${URLEncoder.encode(search, StandardCharsets.UTF_8.name())}"
|
||||
val url = "$API_URL/search/subject/${URLEncoder.encode(search, StandardCharsets.UTF_8.name())}"
|
||||
.toUri()
|
||||
.buildUpon()
|
||||
.appendQueryParameter("max_results", "20")
|
||||
|
|
@ -124,7 +124,7 @@ class BangumiApi(
|
|||
suspend fun findLibManga(track: Track): Track? {
|
||||
return withIOContext {
|
||||
with(json) {
|
||||
authClient.newCall(GET("$apiUrl/subject/${track.remote_id}"))
|
||||
authClient.newCall(GET("$API_URL/subject/${track.remote_id}"))
|
||||
.awaitSuccess()
|
||||
.parseAs<JsonObject>()
|
||||
.let { jsonToSearch(it) }
|
||||
|
|
@ -134,7 +134,7 @@ class BangumiApi(
|
|||
|
||||
suspend fun statusLibManga(track: Track): Track? {
|
||||
return withIOContext {
|
||||
val urlUserRead = "$apiUrl/collection/${track.remote_id}"
|
||||
val urlUserRead = "$API_URL/collection/${track.remote_id}"
|
||||
val requestUserRead = Request.Builder()
|
||||
.url(urlUserRead)
|
||||
.cacheControl(CacheControl.FORCE_NETWORK)
|
||||
|
|
@ -171,41 +171,41 @@ class BangumiApi(
|
|||
}
|
||||
|
||||
private fun accessTokenRequest(code: String) = POST(
|
||||
oauthUrl,
|
||||
OAUTH_URL,
|
||||
body = FormBody.Builder()
|
||||
.add("grant_type", "authorization_code")
|
||||
.add("client_id", clientId)
|
||||
.add("client_secret", clientSecret)
|
||||
.add("client_id", CLIENT_ID)
|
||||
.add("client_secret", CLIENT_SECRET)
|
||||
.add("code", code)
|
||||
.add("redirect_uri", redirectUrl)
|
||||
.add("redirect_uri", REDIRECT_URL)
|
||||
.build(),
|
||||
)
|
||||
|
||||
companion object {
|
||||
private const val clientId = "bgm31586666817a5d03b"
|
||||
private const val clientSecret = "3dad27cf8edcac6f55361d7971d219e1"
|
||||
private const val CLIENT_ID = "bgm31586666817a5d03b"
|
||||
private const val CLIENT_SECRET = "3dad27cf8edcac6f55361d7971d219e1"
|
||||
|
||||
private const val apiUrl = "https://api.bgm.tv"
|
||||
private const val oauthUrl = "https://bgm.tv/oauth/access_token"
|
||||
private const val loginUrl = "https://bgm.tv/oauth/authorize"
|
||||
private const val API_URL = "https://api.bgm.tv"
|
||||
private const val OAUTH_URL = "https://bgm.tv/oauth/access_token"
|
||||
private const val LOGIN_URL = "https://bgm.tv/oauth/authorize"
|
||||
|
||||
private const val redirectUrl = "komikku://bangumi-auth"
|
||||
private const val REDIRECT_URL = "komikku://bangumi-auth"
|
||||
|
||||
fun authUrl(): Uri =
|
||||
loginUrl.toUri().buildUpon()
|
||||
.appendQueryParameter("client_id", clientId)
|
||||
LOGIN_URL.toUri().buildUpon()
|
||||
.appendQueryParameter("client_id", CLIENT_ID)
|
||||
.appendQueryParameter("response_type", "code")
|
||||
.appendQueryParameter("redirect_uri", redirectUrl)
|
||||
.appendQueryParameter("redirect_uri", REDIRECT_URL)
|
||||
.build()
|
||||
|
||||
fun refreshTokenRequest(token: String) = POST(
|
||||
oauthUrl,
|
||||
OAUTH_URL,
|
||||
body = FormBody.Builder()
|
||||
.add("grant_type", "refresh_token")
|
||||
.add("client_id", clientId)
|
||||
.add("client_secret", clientSecret)
|
||||
.add("client_id", CLIENT_ID)
|
||||
.add("client_secret", CLIENT_SECRET)
|
||||
.add("refresh_token", token)
|
||||
.add("redirect_uri", redirectUrl)
|
||||
.add("redirect_uri", REDIRECT_URL)
|
||||
.build(),
|
||||
)
|
||||
}
|
||||
|
|
|
|||
|
|
@ -66,7 +66,7 @@ class KitsuApi(private val client: OkHttpClient, interceptor: KitsuInterceptor)
|
|||
with(json) {
|
||||
authClient.newCall(
|
||||
POST(
|
||||
"${baseUrl}library-entries",
|
||||
"${BASE_URL}library-entries",
|
||||
headers = headersOf(
|
||||
"Content-Type",
|
||||
"application/vnd.api+json",
|
||||
|
|
@ -104,7 +104,7 @@ class KitsuApi(private val client: OkHttpClient, interceptor: KitsuInterceptor)
|
|||
with(json) {
|
||||
authClient.newCall(
|
||||
Request.Builder()
|
||||
.url("${baseUrl}library-entries/${track.remote_id}")
|
||||
.url("${BASE_URL}library-entries/${track.remote_id}")
|
||||
.headers(
|
||||
headersOf(
|
||||
"Content-Type",
|
||||
|
|
@ -130,7 +130,7 @@ class KitsuApi(private val client: OkHttpClient, interceptor: KitsuInterceptor)
|
|||
authClient
|
||||
.newCall(
|
||||
DELETE(
|
||||
"${baseUrl}library-entries/${track.remoteId}",
|
||||
"${BASE_URL}library-entries/${track.remoteId}",
|
||||
headers = headersOf(
|
||||
"Content-Type",
|
||||
"application/vnd.api+json",
|
||||
|
|
@ -143,7 +143,7 @@ class KitsuApi(private val client: OkHttpClient, interceptor: KitsuInterceptor)
|
|||
suspend fun search(query: String): List<TrackSearch> {
|
||||
return withIOContext {
|
||||
with(json) {
|
||||
authClient.newCall(GET(algoliaKeyUrl))
|
||||
authClient.newCall(GET(ALGOLIA_KEY_URL))
|
||||
.awaitSuccess()
|
||||
.parseAs<JsonObject>()
|
||||
.let {
|
||||
|
|
@ -157,16 +157,16 @@ class KitsuApi(private val client: OkHttpClient, interceptor: KitsuInterceptor)
|
|||
private suspend fun algoliaSearch(key: String, query: String): List<TrackSearch> {
|
||||
return withIOContext {
|
||||
val jsonObject = buildJsonObject {
|
||||
put("params", "query=${URLEncoder.encode(query, StandardCharsets.UTF_8.name())}$algoliaFilter")
|
||||
put("params", "query=${URLEncoder.encode(query, StandardCharsets.UTF_8.name())}$ALGOLIA_FILTER")
|
||||
}
|
||||
|
||||
with(json) {
|
||||
client.newCall(
|
||||
POST(
|
||||
algoliaUrl,
|
||||
ALGOLIA_URL,
|
||||
headers = headersOf(
|
||||
"X-Algolia-Application-Id",
|
||||
algoliaAppId,
|
||||
ALGOLIA_APP_ID,
|
||||
"X-Algolia-API-Key",
|
||||
key,
|
||||
),
|
||||
|
|
@ -187,7 +187,7 @@ class KitsuApi(private val client: OkHttpClient, interceptor: KitsuInterceptor)
|
|||
|
||||
suspend fun findLibManga(track: Track, userId: String): Track? {
|
||||
return withIOContext {
|
||||
val url = "${baseUrl}library-entries".toUri().buildUpon()
|
||||
val url = "${BASE_URL}library-entries".toUri().buildUpon()
|
||||
.encodedQuery("filter[manga_id]=${track.remote_id}&filter[user_id]=$userId")
|
||||
.appendQueryParameter("include", "manga")
|
||||
.build()
|
||||
|
|
@ -210,7 +210,7 @@ class KitsuApi(private val client: OkHttpClient, interceptor: KitsuInterceptor)
|
|||
|
||||
suspend fun getLibManga(track: Track): Track {
|
||||
return withIOContext {
|
||||
val url = "${baseUrl}library-entries".toUri().buildUpon()
|
||||
val url = "${BASE_URL}library-entries".toUri().buildUpon()
|
||||
.encodedQuery("filter[id]=${track.remote_id}")
|
||||
.appendQueryParameter("include", "manga")
|
||||
.build()
|
||||
|
|
@ -237,11 +237,11 @@ class KitsuApi(private val client: OkHttpClient, interceptor: KitsuInterceptor)
|
|||
.add("username", username)
|
||||
.add("password", password)
|
||||
.add("grant_type", "password")
|
||||
.add("client_id", clientId)
|
||||
.add("client_secret", clientSecret)
|
||||
.add("client_id", CLIENT_ID)
|
||||
.add("client_secret", CLIENT_SECRET)
|
||||
.build()
|
||||
with(json) {
|
||||
client.newCall(POST(loginUrl, body = formBody))
|
||||
client.newCall(POST(LOGIN_URL, body = formBody))
|
||||
.awaitSuccess()
|
||||
.parseAs()
|
||||
}
|
||||
|
|
@ -250,7 +250,7 @@ class KitsuApi(private val client: OkHttpClient, interceptor: KitsuInterceptor)
|
|||
|
||||
suspend fun getCurrentUser(): String {
|
||||
return withIOContext {
|
||||
val url = "${baseUrl}users".toUri().buildUpon()
|
||||
val url = "${BASE_URL}users".toUri().buildUpon()
|
||||
.encodedQuery("filter[self]=true")
|
||||
.build()
|
||||
with(json) {
|
||||
|
|
@ -265,35 +265,31 @@ class KitsuApi(private val client: OkHttpClient, interceptor: KitsuInterceptor)
|
|||
}
|
||||
|
||||
companion object {
|
||||
private const val clientId =
|
||||
"dd031b32d2f56c990b1425efe6c42ad847e7fe3ab46bf1299f05ecd856bdb7dd"
|
||||
private const val clientSecret =
|
||||
"54d7307928f63414defd96399fc31ba847961ceaecef3a5fd93144e960c0e151"
|
||||
private const val CLIENT_ID = "dd031b32d2f56c990b1425efe6c42ad847e7fe3ab46bf1299f05ecd856bdb7dd"
|
||||
private const val CLIENT_SECRET = "54d7307928f63414defd96399fc31ba847961ceaecef3a5fd93144e960c0e151"
|
||||
|
||||
private const val baseUrl = "https://kitsu.app/api/edge/"
|
||||
private const val loginUrl = "https://kitsu.app/api/oauth/token"
|
||||
private const val baseMangaUrl = "https://kitsu.app/manga/"
|
||||
private const val algoliaKeyUrl = "https://kitsu.app/api/edge/algolia-keys/media/"
|
||||
private const val BASE_URL = "https://kitsu.app/api/edge/"
|
||||
private const val LOGIN_URL = "https://kitsu.app/api/oauth/token"
|
||||
private const val BASE_MANGA_URL = "https://kitsu.app/manga/"
|
||||
private const val ALGOLIA_KEY_URL = "https://kitsu.app/api/edge/algolia-keys/media/"
|
||||
|
||||
private const val algoliaUrl =
|
||||
"https://AWQO5J657S-dsn.algolia.net/1/indexes/production_media/query/"
|
||||
private const val algoliaAppId = "AWQO5J657S"
|
||||
private const val algoliaFilter =
|
||||
"&facetFilters=%5B%22kind%3Amanga%22%5D&attributesToRetrieve=" +
|
||||
"%5B%22synopsis%22%2C%22averageRating%22%2C%22canonicalTitle%22%2C%22chapterCount%22%2C%22" +
|
||||
"posterImage%22%2C%22startDate%22%2C%22subtype%22%2C%22endDate%22%2C%20%22id%22%5D"
|
||||
private const val ALGOLIA_APP_ID = "AWQO5J657S"
|
||||
private const val ALGOLIA_URL = "https://$ALGOLIA_APP_ID-dsn.algolia.net/1/indexes/production_media/query/"
|
||||
private const val ALGOLIA_FILTER = "&facetFilters=%5B%22kind%3Amanga%22%5D&attributesToRetrieve=" +
|
||||
"%5B%22synopsis%22%2C%22averageRating%22%2C%22canonicalTitle%22%2C%22chapterCount%22%2C%22" +
|
||||
"posterImage%22%2C%22startDate%22%2C%22subtype%22%2C%22endDate%22%2C%20%22id%22%5D"
|
||||
|
||||
fun mangaUrl(remoteId: Long): String {
|
||||
return baseMangaUrl + remoteId
|
||||
return BASE_MANGA_URL + remoteId
|
||||
}
|
||||
|
||||
fun refreshTokenRequest(token: String) = POST(
|
||||
loginUrl,
|
||||
LOGIN_URL,
|
||||
body = FormBody.Builder()
|
||||
.add("grant_type", "refresh_token")
|
||||
.add("refresh_token", token)
|
||||
.add("client_id", clientId)
|
||||
.add("client_secret", clientSecret)
|
||||
.add("client_id", CLIENT_ID)
|
||||
.add("client_secret", CLIENT_SECRET)
|
||||
.build(),
|
||||
)
|
||||
}
|
||||
|
|
|
|||
|
|
@ -6,8 +6,8 @@ import java.util.Locale
|
|||
|
||||
object KitsuDateHelper {
|
||||
|
||||
private const val pattern = "yyyy-MM-dd'T'HH:mm:ss.SSS'Z'"
|
||||
private val formatter = SimpleDateFormat(pattern, Locale.ENGLISH)
|
||||
private const val PATTERN = "yyyy-MM-dd'T'HH:mm:ss.SSS'Z'"
|
||||
private val formatter = SimpleDateFormat(PATTERN, Locale.ENGLISH)
|
||||
|
||||
fun convert(dateValue: Long): String? {
|
||||
if (dateValue == 0L) return null
|
||||
|
|
|
|||
|
|
@ -1,3 +1,5 @@
|
|||
@file:Suppress("PropertyName", "ktlint:standard:property-naming")
|
||||
|
||||
package eu.kanade.tachiyomi.data.track.model
|
||||
|
||||
import eu.kanade.tachiyomi.data.database.models.Track
|
||||
|
|
|
|||
|
|
@ -54,7 +54,7 @@ class ShikimoriApi(
|
|||
}
|
||||
authClient.newCall(
|
||||
POST(
|
||||
"$apiUrl/v2/user_rates",
|
||||
"$API_URL/v2/user_rates",
|
||||
body = payload.toString().toRequestBody(jsonMime),
|
||||
),
|
||||
).awaitSuccess()
|
||||
|
|
@ -72,14 +72,14 @@ class ShikimoriApi(
|
|||
suspend fun deleteLibManga(track: DomainTrack) {
|
||||
withIOContext {
|
||||
authClient
|
||||
.newCall(DELETE("$apiUrl/v2/user_rates/${track.libraryId}"))
|
||||
.newCall(DELETE("$API_URL/v2/user_rates/${track.libraryId}"))
|
||||
.awaitSuccess()
|
||||
}
|
||||
}
|
||||
|
||||
suspend fun search(search: String): List<TrackSearch> {
|
||||
return withIOContext {
|
||||
val url = "$apiUrl/mangas".toUri().buildUpon()
|
||||
val url = "$API_URL/mangas".toUri().buildUpon()
|
||||
.appendQueryParameter("order", "popularity")
|
||||
.appendQueryParameter("search", search)
|
||||
.appendQueryParameter("limit", "20")
|
||||
|
|
@ -102,10 +102,10 @@ class ShikimoriApi(
|
|||
remote_id = obj["id"]!!.jsonPrimitive.long
|
||||
title = obj["name"]!!.jsonPrimitive.content
|
||||
total_chapters = obj["chapters"]!!.jsonPrimitive.long
|
||||
cover_url = baseUrl + obj["image"]!!.jsonObject["preview"]!!.jsonPrimitive.content
|
||||
cover_url = BASE_URL + obj["image"]!!.jsonObject["preview"]!!.jsonPrimitive.content
|
||||
summary = ""
|
||||
score = obj["score"]!!.jsonPrimitive.double
|
||||
tracking_url = baseUrl + obj["url"]!!.jsonPrimitive.content
|
||||
tracking_url = BASE_URL + obj["url"]!!.jsonPrimitive.content
|
||||
publishing_status = obj["status"]!!.jsonPrimitive.content
|
||||
publishing_type = obj["kind"]!!.jsonPrimitive.content
|
||||
start_date = obj["aired_on"]!!.jsonPrimitive.contentOrNull ?: ""
|
||||
|
|
@ -121,13 +121,13 @@ class ShikimoriApi(
|
|||
last_chapter_read = obj["chapters"]!!.jsonPrimitive.double
|
||||
score = obj["score"]!!.jsonPrimitive.int.toDouble()
|
||||
status = toTrackStatus(obj["status"]!!.jsonPrimitive.content)
|
||||
tracking_url = baseUrl + mangas["url"]!!.jsonPrimitive.content
|
||||
tracking_url = BASE_URL + mangas["url"]!!.jsonPrimitive.content
|
||||
}
|
||||
}
|
||||
|
||||
suspend fun findLibManga(track: Track, userId: String): Track? {
|
||||
return withIOContext {
|
||||
val urlMangas = "$apiUrl/mangas".toUri().buildUpon()
|
||||
val urlMangas = "$API_URL/mangas".toUri().buildUpon()
|
||||
.appendPath(track.remote_id.toString())
|
||||
.build()
|
||||
val mangas = with(json) {
|
||||
|
|
@ -136,7 +136,7 @@ class ShikimoriApi(
|
|||
.parseAs<JsonObject>()
|
||||
}
|
||||
|
||||
val url = "$apiUrl/v2/user_rates".toUri().buildUpon()
|
||||
val url = "$API_URL/v2/user_rates".toUri().buildUpon()
|
||||
.appendQueryParameter("user_id", userId)
|
||||
.appendQueryParameter("target_id", track.remote_id.toString())
|
||||
.appendQueryParameter("target_type", "Manga")
|
||||
|
|
@ -160,7 +160,7 @@ class ShikimoriApi(
|
|||
|
||||
suspend fun getCurrentUser(): Int {
|
||||
return with(json) {
|
||||
authClient.newCall(GET("$apiUrl/users/whoami"))
|
||||
authClient.newCall(GET("$API_URL/users/whoami"))
|
||||
.awaitSuccess()
|
||||
.parseAs<JsonObject>()
|
||||
.let {
|
||||
|
|
@ -180,39 +180,39 @@ class ShikimoriApi(
|
|||
}
|
||||
|
||||
private fun accessTokenRequest(code: String) = POST(
|
||||
oauthUrl,
|
||||
OAUTH_URL,
|
||||
body = FormBody.Builder()
|
||||
.add("grant_type", "authorization_code")
|
||||
.add("client_id", clientId)
|
||||
.add("client_secret", clientSecret)
|
||||
.add("client_id", CLIENT_ID)
|
||||
.add("client_secret", CLIENT_SECRET)
|
||||
.add("code", code)
|
||||
.add("redirect_uri", redirectUrl)
|
||||
.add("redirect_uri", REDIRECT_URL)
|
||||
.build(),
|
||||
)
|
||||
|
||||
companion object {
|
||||
private const val clientId = "hst3O_VlZ0HrrXcnZAd6m-SCIc1_mv5cQV-3nQCdJ0E"
|
||||
private const val clientSecret = "n1Pn9AIKvUhDzjehfPt_5nk7xbr4wSnas6djggw_AjE"
|
||||
private const val CLIENT_ID = "hst3O_VlZ0HrrXcnZAd6m-SCIc1_mv5cQV-3nQCdJ0E"
|
||||
private const val CLIENT_SECRET = "n1Pn9AIKvUhDzjehfPt_5nk7xbr4wSnas6djggw_AjE"
|
||||
|
||||
private const val baseUrl = "https://shikimori.one"
|
||||
private const val apiUrl = "$baseUrl/api"
|
||||
private const val oauthUrl = "$baseUrl/oauth/token"
|
||||
private const val loginUrl = "$baseUrl/oauth/authorize"
|
||||
private const val BASE_URL = "https://shikimori.one"
|
||||
private const val API_URL = "$BASE_URL/api"
|
||||
private const val OAUTH_URL = "$BASE_URL/oauth/token"
|
||||
private const val LOGIN_URL = "$BASE_URL/oauth/authorize"
|
||||
|
||||
private const val redirectUrl = "komikku://shikimori-auth"
|
||||
private const val REDIRECT_URL = "komikku://shikimori-auth"
|
||||
|
||||
fun authUrl(): Uri = loginUrl.toUri().buildUpon()
|
||||
.appendQueryParameter("client_id", clientId)
|
||||
.appendQueryParameter("redirect_uri", redirectUrl)
|
||||
fun authUrl(): Uri = LOGIN_URL.toUri().buildUpon()
|
||||
.appendQueryParameter("client_id", CLIENT_ID)
|
||||
.appendQueryParameter("redirect_uri", REDIRECT_URL)
|
||||
.appendQueryParameter("response_type", "code")
|
||||
.build()
|
||||
|
||||
fun refreshTokenRequest(token: String) = POST(
|
||||
oauthUrl,
|
||||
OAUTH_URL,
|
||||
body = FormBody.Builder()
|
||||
.add("grant_type", "refresh_token")
|
||||
.add("client_id", clientId)
|
||||
.add("client_secret", clientSecret)
|
||||
.add("client_id", CLIENT_ID)
|
||||
.add("client_secret", CLIENT_SECRET)
|
||||
.add("refresh_token", token)
|
||||
.build(),
|
||||
)
|
||||
|
|
|
|||
|
|
@ -69,17 +69,17 @@ class ExtensionManager(
|
|||
|
||||
private val iconMap = mutableMapOf<String, Drawable>()
|
||||
|
||||
private val _installedExtensionsMapFlow = MutableStateFlow(emptyMap<String, Extension.Installed>())
|
||||
val installedExtensionsFlow = _installedExtensionsMapFlow.mapExtensions(scope)
|
||||
private val installedExtensionMapFlow = MutableStateFlow(emptyMap<String, Extension.Installed>())
|
||||
val installedExtensionsFlow = installedExtensionMapFlow.mapExtensions(scope)
|
||||
|
||||
private val _availableExtensionsMapFlow = MutableStateFlow(emptyMap<String, Extension.Available>())
|
||||
private val availableExtensionMapFlow = MutableStateFlow(emptyMap<String, Extension.Available>())
|
||||
// SY -->
|
||||
val availableExtensionsFlow = _availableExtensionsMapFlow.map { it.filterNotBlacklisted().values.toList() }
|
||||
.stateIn(scope, SharingStarted.Lazily, _availableExtensionsMapFlow.value.values.toList())
|
||||
val availableExtensionsFlow = availableExtensionMapFlow.map { it.filterNotBlacklisted().values.toList() }
|
||||
.stateIn(scope, SharingStarted.Lazily, availableExtensionMapFlow.value.values.toList())
|
||||
// SY <--
|
||||
|
||||
private val _untrustedExtensionsMapFlow = MutableStateFlow(emptyMap<String, Extension.Untrusted>())
|
||||
val untrustedExtensionsFlow = _untrustedExtensionsMapFlow.mapExtensions(scope)
|
||||
private val untrustedExtensionMapFlow = MutableStateFlow(emptyMap<String, Extension.Untrusted>())
|
||||
val untrustedExtensionsFlow = untrustedExtensionMapFlow.mapExtensions(scope)
|
||||
|
||||
init {
|
||||
initExtensions()
|
||||
|
|
@ -89,7 +89,7 @@ class ExtensionManager(
|
|||
private var subLanguagesEnabledOnFirstRun = preferences.enabledLanguages().isSet()
|
||||
|
||||
fun getAppIconForSource(sourceId: Long): Drawable? {
|
||||
val pkgName = _installedExtensionsMapFlow.value.values
|
||||
val pkgName = installedExtensionMapFlow.value.values
|
||||
.find { ext ->
|
||||
ext.sources.any { it.id == sourceId }
|
||||
}
|
||||
|
|
@ -128,11 +128,11 @@ class ExtensionManager(
|
|||
private fun initExtensions() {
|
||||
val extensions = ExtensionLoader.loadExtensions(context)
|
||||
|
||||
_installedExtensionsMapFlow.value = extensions
|
||||
installedExtensionMapFlow.value = extensions
|
||||
.filterIsInstance<LoadResult.Success>()
|
||||
.associate { it.extension.pkgName to it.extension }
|
||||
|
||||
_untrustedExtensionsMapFlow.value = extensions
|
||||
untrustedExtensionMapFlow.value = extensions
|
||||
.filterIsInstance<LoadResult.Untrusted>()
|
||||
.associate { it.extension.pkgName to it.extension }
|
||||
// SY -->
|
||||
|
|
@ -159,7 +159,7 @@ class ExtensionManager(
|
|||
// EXH <--
|
||||
|
||||
/**
|
||||
* Finds the available extensions in the [api] and updates [_availableExtensionsMapFlow].
|
||||
* Finds the available extensions in the [api] and updates [availableExtensionMapFlow].
|
||||
*/
|
||||
suspend fun findAvailableExtensions() {
|
||||
val extensions: List<Extension.Available> = try {
|
||||
|
|
@ -172,7 +172,7 @@ class ExtensionManager(
|
|||
|
||||
enableAdditionalSubLanguages(extensions)
|
||||
|
||||
_availableExtensionsMapFlow.value = extensions.associateBy { it.pkgName }
|
||||
availableExtensionMapFlow.value = extensions.associateBy { it.pkgName }
|
||||
updatedInstalledExtensionsStatuses(extensions)
|
||||
setupAvailableExtensionsSourcesDataMap(extensions)
|
||||
}
|
||||
|
|
@ -218,7 +218,7 @@ class ExtensionManager(
|
|||
return
|
||||
}
|
||||
|
||||
val installedExtensionsMap = _installedExtensionsMapFlow.value.toMutableMap()
|
||||
val installedExtensionsMap = installedExtensionMapFlow.value.toMutableMap()
|
||||
var changed = false
|
||||
for ((pkgName, extension) in installedExtensionsMap) {
|
||||
val availableExt = availableExtensions.find { it.pkgName == pkgName }
|
||||
|
|
@ -247,7 +247,7 @@ class ExtensionManager(
|
|||
}
|
||||
}
|
||||
if (changed) {
|
||||
_installedExtensionsMapFlow.value = installedExtensionsMap
|
||||
installedExtensionMapFlow.value = installedExtensionsMap
|
||||
}
|
||||
updatePendingUpdatesCount()
|
||||
}
|
||||
|
|
@ -271,7 +271,7 @@ class ExtensionManager(
|
|||
* @param extension The extension to be updated.
|
||||
*/
|
||||
fun updateExtension(extension: Extension.Installed): Flow<InstallStep> {
|
||||
val availableExt = _availableExtensionsMapFlow.value[extension.pkgName] ?: return emptyFlow()
|
||||
val availableExt = availableExtensionMapFlow.value[extension.pkgName] ?: return emptyFlow()
|
||||
return installExtension(availableExt)
|
||||
}
|
||||
|
||||
|
|
@ -308,11 +308,11 @@ class ExtensionManager(
|
|||
* @param extension the extension to trust
|
||||
*/
|
||||
suspend fun trust(extension: Extension.Untrusted) {
|
||||
_untrustedExtensionsMapFlow.value[extension.pkgName] ?: return
|
||||
untrustedExtensionMapFlow.value[extension.pkgName] ?: return
|
||||
|
||||
trustExtension.trust(extension.pkgName, extension.versionCode, extension.signatureHash)
|
||||
|
||||
_untrustedExtensionsMapFlow.value -= extension.pkgName
|
||||
untrustedExtensionMapFlow.value -= extension.pkgName
|
||||
|
||||
ExtensionLoader.loadExtensionFromPkgName(context, extension.pkgName)
|
||||
.let { it as? LoadResult.Success }
|
||||
|
|
@ -332,7 +332,7 @@ class ExtensionManager(
|
|||
}
|
||||
// SY <--
|
||||
|
||||
_installedExtensionsMapFlow.value += extension
|
||||
installedExtensionMapFlow.value += extension
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
@ -349,7 +349,7 @@ class ExtensionManager(
|
|||
}
|
||||
// SY <--
|
||||
|
||||
_installedExtensionsMapFlow.value += extension
|
||||
installedExtensionMapFlow.value += extension
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
@ -359,8 +359,8 @@ class ExtensionManager(
|
|||
* @param pkgName The package name of the uninstalled application.
|
||||
*/
|
||||
private fun unregisterExtension(pkgName: String) {
|
||||
_installedExtensionsMapFlow.value -= pkgName
|
||||
_untrustedExtensionsMapFlow.value -= pkgName
|
||||
installedExtensionMapFlow.value -= pkgName
|
||||
untrustedExtensionMapFlow.value -= pkgName
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
@ -379,8 +379,8 @@ class ExtensionManager(
|
|||
}
|
||||
|
||||
override fun onExtensionUntrusted(extension: Extension.Untrusted) {
|
||||
_installedExtensionsMapFlow.value -= extension.pkgName
|
||||
_untrustedExtensionsMapFlow.value += extension
|
||||
installedExtensionMapFlow.value -= extension.pkgName
|
||||
untrustedExtensionMapFlow.value += extension
|
||||
updatePendingUpdatesCount()
|
||||
}
|
||||
|
||||
|
|
@ -404,14 +404,14 @@ class ExtensionManager(
|
|||
|
||||
private fun Extension.Installed.updateExists(availableExtension: Extension.Available? = null): Boolean {
|
||||
val availableExt = availableExtension
|
||||
?: _availableExtensionsMapFlow.value[pkgName]
|
||||
?: availableExtensionMapFlow.value[pkgName]
|
||||
?: return false
|
||||
|
||||
return (availableExt.versionCode > versionCode || availableExt.libVersion > libVersion)
|
||||
}
|
||||
|
||||
private fun updatePendingUpdatesCount() {
|
||||
val pendingUpdateCount = _installedExtensionsMapFlow.value.values.count { it.hasUpdate }
|
||||
val pendingUpdateCount = installedExtensionMapFlow.value.values.count { it.hasUpdate }
|
||||
preferences.extensionUpdatesCount().set(pendingUpdateCount)
|
||||
if (pendingUpdateCount == 0) {
|
||||
ExtensionUpdateNotifier(context).dismiss()
|
||||
|
|
|
|||
|
|
@ -1,7 +1,13 @@
|
|||
package eu.kanade.tachiyomi.extension.model
|
||||
|
||||
enum class InstallStep {
|
||||
Idle, Pending, Downloading, Installing, Installed, Error;
|
||||
Idle,
|
||||
Pending,
|
||||
Downloading,
|
||||
Installing,
|
||||
Installed,
|
||||
Error,
|
||||
;
|
||||
|
||||
fun isCompleted(): Boolean {
|
||||
return this == Installed || this == Error || this == Idle
|
||||
|
|
|
|||
|
|
@ -140,7 +140,7 @@ class SecureActivityDelegateImpl : SecureActivityDelegate, DefaultLifecycleObser
|
|||
val incognitoModeFlow = preferences.incognitoMode().changes()
|
||||
combine(secureScreenFlow, incognitoModeFlow) { secureScreen, incognitoMode ->
|
||||
secureScreen == SecurityPreferences.SecureScreenMode.ALWAYS ||
|
||||
secureScreen == SecurityPreferences.SecureScreenMode.INCOGNITO && incognitoMode
|
||||
(secureScreen == SecurityPreferences.SecureScreenMode.INCOGNITO && incognitoMode)
|
||||
}
|
||||
.onEach(activity.window::setSecureScreen)
|
||||
.launchIn(activity.lifecycleScope)
|
||||
|
|
|
|||
|
|
@ -41,7 +41,7 @@ class ExtensionsScreenModel(
|
|||
private val getExtensions: GetExtensionsByType = Injekt.get(),
|
||||
) : StateScreenModel<ExtensionsScreenModel.State>(State()) {
|
||||
|
||||
private var _currentDownloads = MutableStateFlow<Map<String, InstallStep>>(hashMapOf())
|
||||
private val currentDownloads = MutableStateFlow<Map<String, InstallStep>>(hashMapOf())
|
||||
|
||||
init {
|
||||
val context = Injekt.get<Application>()
|
||||
|
|
@ -62,14 +62,20 @@ class ExtensionsScreenModel(
|
|||
it.name.contains(input, ignoreCase = true) ||
|
||||
it.baseUrl.contains(input, ignoreCase = true) ||
|
||||
it.id == input.toLongOrNull()
|
||||
} || extension.name.contains(input, ignoreCase = true)
|
||||
} ||
|
||||
extension.name.contains(input, ignoreCase = true)
|
||||
}
|
||||
is Extension.Installed -> {
|
||||
extension.sources.any {
|
||||
it.name.contains(input, ignoreCase = true) ||
|
||||
it.id == input.toLongOrNull() ||
|
||||
if (it is HttpSource) { it.baseUrl.contains(input, ignoreCase = true) } else false
|
||||
} || extension.name.contains(input, ignoreCase = true)
|
||||
if (it is HttpSource) {
|
||||
it.baseUrl.contains(input, ignoreCase = true)
|
||||
} else {
|
||||
false
|
||||
}
|
||||
} ||
|
||||
extension.name.contains(input, ignoreCase = true)
|
||||
}
|
||||
is Extension.Untrusted -> extension.name.contains(input, ignoreCase = true)
|
||||
}
|
||||
|
|
@ -83,7 +89,7 @@ class ExtensionsScreenModel(
|
|||
// KMK -->
|
||||
state.map { it.nsfwOnly }.distinctUntilChanged().debounce(SEARCH_DEBOUNCE_MILLIS),
|
||||
// KMK <--
|
||||
_currentDownloads,
|
||||
currentDownloads,
|
||||
getExtensions.subscribe(),
|
||||
) { query, nsfwOnly, downloads, (_updates, _installed, _available, _untrusted) ->
|
||||
val searchQuery = query ?: ""
|
||||
|
|
@ -181,11 +187,11 @@ class ExtensionsScreenModel(
|
|||
}
|
||||
|
||||
private fun addDownloadState(extension: Extension, installStep: InstallStep) {
|
||||
_currentDownloads.update { it + Pair(extension.pkgName, installStep) }
|
||||
currentDownloads.update { it + Pair(extension.pkgName, installStep) }
|
||||
}
|
||||
|
||||
private fun removeDownloadState(extension: Extension) {
|
||||
_currentDownloads.update { it - extension.pkgName }
|
||||
currentDownloads.update { it - extension.pkgName }
|
||||
}
|
||||
|
||||
private suspend fun Flow<InstallStep>.collectToInstallUpdate(extension: Extension) =
|
||||
|
|
|
|||
|
|
@ -71,8 +71,8 @@ object HomeScreen : Screen() {
|
|||
private val openTabEvent = Channel<Tab>()
|
||||
private val showBottomNavEvent = Channel<Boolean>()
|
||||
|
||||
private const val TabFadeDuration = 200
|
||||
private const val TabNavigatorKey = "HomeTabs"
|
||||
private const val TAB_FADE_DURATION = 200
|
||||
private const val TAB_NAVIGATOR_KEY = "HomeTabs"
|
||||
|
||||
private val tabs = listOf(
|
||||
LibraryTab,
|
||||
|
|
@ -95,7 +95,7 @@ object HomeScreen : Screen() {
|
|||
|
||||
TabNavigator(
|
||||
tab = LibraryTab,
|
||||
key = TabNavigatorKey,
|
||||
key = TAB_NAVIGATOR_KEY,
|
||||
) { tabNavigator ->
|
||||
// Provide usable navigator to content screen
|
||||
CompositionLocalProvider(LocalNavigator provides navigator) {
|
||||
|
|
@ -145,8 +145,11 @@ object HomeScreen : Screen() {
|
|||
AnimatedContent(
|
||||
targetState = tabNavigator.current,
|
||||
transitionSpec = {
|
||||
materialFadeThroughIn(initialScale = 1f, durationMillis = TabFadeDuration) togetherWith
|
||||
materialFadeThroughOut(durationMillis = TabFadeDuration)
|
||||
materialFadeThroughIn(
|
||||
initialScale = 1f,
|
||||
durationMillis = TAB_FADE_DURATION,
|
||||
) togetherWith
|
||||
materialFadeThroughOut(durationMillis = TAB_FADE_DURATION)
|
||||
},
|
||||
label = "tabContent",
|
||||
contentKey = { it.key }
|
||||
|
|
|
|||
|
|
@ -384,8 +384,9 @@ class LibraryScreenModel(
|
|||
// Map<MangaId, List<Track>>
|
||||
trackMap: Map<Long, List<Track>>,
|
||||
loggedInTrackerIds: Set<Long>,
|
||||
/* SY --> */
|
||||
groupSort: LibrarySort? = null, /* SY <-- */
|
||||
// SY -->
|
||||
groupSort: LibrarySort? = null,
|
||||
// SY <--
|
||||
): LibraryMap {
|
||||
// SY -->
|
||||
val listOfTags by lazy {
|
||||
|
|
|
|||
|
|
@ -34,7 +34,7 @@ class LibrarySettingsScreenModel(
|
|||
.stateIn(
|
||||
scope = screenModelScope,
|
||||
started = SharingStarted.WhileSubscribed(5.seconds.inWholeMilliseconds),
|
||||
initialValue = trackerManager.loggedInTrackers()
|
||||
initialValue = trackerManager.loggedInTrackers(),
|
||||
)
|
||||
|
||||
// SY -->
|
||||
|
|
|
|||
|
|
@ -109,8 +109,8 @@ private class MoreScreenModel(
|
|||
val showNavHistory by uiPreferences.showNavHistory().asState(screenModelScope)
|
||||
// SY <--
|
||||
|
||||
private var _state: MutableStateFlow<DownloadQueueState> = MutableStateFlow(DownloadQueueState.Stopped)
|
||||
val downloadQueueState: StateFlow<DownloadQueueState> = _state.asStateFlow()
|
||||
private var _downloadQueueState: MutableStateFlow<DownloadQueueState> = MutableStateFlow(DownloadQueueState.Stopped)
|
||||
val downloadQueueState: StateFlow<DownloadQueueState> = _downloadQueueState.asStateFlow()
|
||||
|
||||
init {
|
||||
// Handle running/paused status change and queue progress updating
|
||||
|
|
@ -121,7 +121,7 @@ private class MoreScreenModel(
|
|||
) { isRunning, downloadQueue -> Pair(isRunning, downloadQueue.size) }
|
||||
.collectLatest { (isDownloading, downloadQueueSize) ->
|
||||
val pendingDownloadExists = downloadQueueSize != 0
|
||||
_state.value = when {
|
||||
_downloadQueueState.value = when {
|
||||
!pendingDownloadExists -> DownloadQueueState.Stopped
|
||||
!isDownloading -> DownloadQueueState.Paused(downloadQueueSize)
|
||||
else -> DownloadQueueState.Downloading(downloadQueueSize)
|
||||
|
|
|
|||
|
|
@ -191,7 +191,7 @@ class ReaderPreferences(
|
|||
enum class FlashColor {
|
||||
BLACK,
|
||||
WHITE,
|
||||
WHITE_BLACK
|
||||
WHITE_BLACK,
|
||||
}
|
||||
|
||||
enum class TappingInvertMode(
|
||||
|
|
|
|||
|
|
@ -398,7 +398,9 @@ open class ReaderPageImageView @JvmOverloads constructor(
|
|||
)
|
||||
|
||||
enum class ZoomStartPosition {
|
||||
LEFT, CENTER, RIGHT
|
||||
LEFT,
|
||||
CENTER,
|
||||
RIGHT,
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -43,15 +43,16 @@ class ReaderTransitionView @JvmOverloads constructor(
|
|||
Data(
|
||||
transition = transition,
|
||||
currChapterDownloaded = transition.from.pageLoader?.isLocal == true,
|
||||
goingToChapterDownloaded = manga.isLocal() || transition.to?.chapter?.let { goingToChapter ->
|
||||
downloadManager.isChapterDownloaded(
|
||||
chapterName = goingToChapter.name,
|
||||
chapterScanlator = goingToChapter.scanlator,
|
||||
mangaTitle = /* SY --> */ manga.ogTitle, /* SY <-- */
|
||||
sourceId = manga.source,
|
||||
skipCache = true,
|
||||
)
|
||||
} ?: false,
|
||||
goingToChapterDownloaded = manga.isLocal() ||
|
||||
transition.to?.chapter?.let { goingToChapter ->
|
||||
downloadManager.isChapterDownloaded(
|
||||
chapterName = goingToChapter.name,
|
||||
chapterScanlator = goingToChapter.scanlator,
|
||||
mangaTitle = /* SY --> */ manga.ogTitle, /* SY <-- */
|
||||
sourceId = manga.source,
|
||||
skipCache = true,
|
||||
)
|
||||
} ?: false,
|
||||
)
|
||||
} else {
|
||||
null
|
||||
|
|
|
|||
|
|
@ -115,7 +115,9 @@ class PagerViewerAdapter(
|
|||
// Add next chapter transition and pages.
|
||||
nextTransition = ChapterTransition.Next(chapters.currChapter, chapters.nextChapter)
|
||||
.also {
|
||||
if (nextHasMissingChapters || forceTransition ||
|
||||
if (
|
||||
nextHasMissingChapters ||
|
||||
forceTransition ||
|
||||
chapters.nextChapter?.state !is ReaderChapter.State.Loaded
|
||||
) {
|
||||
newItems.add(it)
|
||||
|
|
|
|||
|
|
@ -89,7 +89,7 @@ class WebtoonConfig(
|
|||
readerPreferences.webtoonDisableZoomOut()
|
||||
.register(
|
||||
{ zoomOutDisabled = it },
|
||||
{ zoomPropertyChangedListener?.invoke(it) }
|
||||
{ zoomPropertyChangedListener?.invoke(it) },
|
||||
)
|
||||
|
||||
readerPreferences.webtoonDoubleTapZoomEnabled()
|
||||
|
|
|
|||
|
|
@ -182,7 +182,11 @@ class WebtoonRecyclerView @JvmOverloads constructor(
|
|||
|
||||
setScaleRate(currentScale)
|
||||
|
||||
layoutParams.height = if (currentScale < 1) { (originalHeight / currentScale).toInt() } else { originalHeight }
|
||||
layoutParams.height = if (currentScale < 1) {
|
||||
(originalHeight / currentScale).toInt()
|
||||
} else {
|
||||
originalHeight
|
||||
}
|
||||
halfHeight = layoutParams.height / 2
|
||||
|
||||
if (currentScale != DEFAULT_RATE) {
|
||||
|
|
|
|||
|
|
@ -95,7 +95,7 @@ class WebtoonViewer(
|
|||
.threshold
|
||||
|
||||
init {
|
||||
recycler.setItemViewCacheSize(RecyclerViewCacheSize)
|
||||
recycler.setItemViewCacheSize(RECYCLER_VIEW_CACHE_SIZE)
|
||||
recycler.isVisible = false // Don't let the recycler layout yet
|
||||
recycler.layoutParams = ViewGroup.LayoutParams(MATCH_PARENT, MATCH_PARENT)
|
||||
recycler.isFocusable = false
|
||||
|
|
@ -412,4 +412,4 @@ class WebtoonViewer(
|
|||
}
|
||||
|
||||
// Double the cache size to reduce rebinds/recycles incurred by the extra layout space on scroll direction changes
|
||||
private const val RecyclerViewCacheSize = 4
|
||||
private const val RECYCLER_VIEW_CACHE_SIZE = 4
|
||||
|
|
|
|||
|
|
@ -15,7 +15,7 @@ import java.util.Enumeration
|
|||
class ChildFirstPathClassLoader(
|
||||
dexPath: String,
|
||||
librarySearchPath: String?,
|
||||
parent: ClassLoader
|
||||
parent: ClassLoader,
|
||||
) : PathClassLoader(dexPath, librarySearchPath, parent) {
|
||||
|
||||
private val systemClassLoader: ClassLoader? = getSystemClassLoader()
|
||||
|
|
|
|||
|
|
@ -9,20 +9,24 @@ import tachiyomi.core.common.util.system.logcat
|
|||
|
||||
class MigrationJobFactory(
|
||||
private val migrationContext: MigrationContext,
|
||||
private val scope: CoroutineScope
|
||||
private val scope: CoroutineScope,
|
||||
) {
|
||||
|
||||
fun create(migrations: List<Migration>): Deferred<Boolean> = with(scope) {
|
||||
return migrations.sortedBy { it.version }
|
||||
.fold(CompletableDeferred(true)) { acc: Deferred<Boolean>, migration: Migration ->
|
||||
if (!migrationContext.dryrun) {
|
||||
logcat { "Running migration: { name = ${migration::class.simpleName}, version = ${migration.version} }" }
|
||||
logcat {
|
||||
"Running migration: { name = ${migration::class.simpleName}, version = ${migration.version} }"
|
||||
}
|
||||
async(start = CoroutineStart.UNDISPATCHED) {
|
||||
val prev = acc.await()
|
||||
migration(migrationContext) || prev
|
||||
}
|
||||
} else {
|
||||
logcat { "(Dry-run) Running migration: { name = ${migration::class.simpleName}, version = ${migration.version} }" }
|
||||
logcat {
|
||||
"(Dry-run) Running migration: { name = ${migration::class.simpleName}, version = ${migration.version} }"
|
||||
}
|
||||
CompletableDeferred(true)
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -12,7 +12,7 @@ interface MigrationStrategy {
|
|||
class DefaultMigrationStrategy(
|
||||
private val migrationJobFactory: MigrationJobFactory,
|
||||
private val migrationCompletedListener: MigrationCompletedListener,
|
||||
private val scope: CoroutineScope
|
||||
private val scope: CoroutineScope,
|
||||
) : MigrationStrategy {
|
||||
|
||||
override operator fun invoke(migrations: List<Migration>): Deferred<Boolean> = with(scope) {
|
||||
|
|
@ -46,7 +46,7 @@ class NoopMigrationStrategy(val state: Boolean) : MigrationStrategy {
|
|||
|
||||
class VersionRangeMigrationStrategy(
|
||||
private val versions: IntRange,
|
||||
private val strategy: DefaultMigrationStrategy
|
||||
private val strategy: DefaultMigrationStrategy,
|
||||
) : MigrationStrategy {
|
||||
|
||||
override operator fun invoke(migrations: List<Migration>): Deferred<Boolean> {
|
||||
|
|
|
|||
|
|
@ -17,7 +17,7 @@ object Migrator {
|
|||
new: Int,
|
||||
migrations: List<Migration>,
|
||||
dryrun: Boolean = false,
|
||||
onMigrationComplete: () -> Unit
|
||||
onMigrationComplete: () -> Unit,
|
||||
) {
|
||||
val migrationContext = MigrationContext(dryrun)
|
||||
val migrationJobFactory = MigrationJobFactory(migrationContext, scope)
|
||||
|
|
|
|||
|
|
@ -32,7 +32,7 @@ import java.time.temporal.WeekFields
|
|||
import java.util.Locale
|
||||
|
||||
private val FontSize = 16.sp
|
||||
private const val DaysOfWeek = 7
|
||||
private const val DAYS_OF_WEEK = 7
|
||||
|
||||
@Composable
|
||||
fun Calendar(
|
||||
|
|
@ -54,7 +54,7 @@ fun Calendar(
|
|||
modifier = Modifier
|
||||
.fillMaxWidth()
|
||||
.padding(vertical = MaterialTheme.padding.small)
|
||||
.padding(start = MaterialTheme.padding.medium)
|
||||
.padding(start = MaterialTheme.padding.medium),
|
||||
)
|
||||
CalendarGrid(
|
||||
selectedYearMonth = selectedYearMonth,
|
||||
|
|
@ -72,8 +72,8 @@ private fun CalendarGrid(
|
|||
) {
|
||||
val localeFirstDayOfWeek = WeekFields.of(Locale.getDefault()).firstDayOfWeek.value
|
||||
val weekDays = remember {
|
||||
(0 until DaysOfWeek)
|
||||
.map { DayOfWeek.of((localeFirstDayOfWeek - 1 + it) % DaysOfWeek + 1) }
|
||||
(0 until DAYS_OF_WEEK)
|
||||
.map { DayOfWeek.of((localeFirstDayOfWeek - 1 + it) % DAYS_OF_WEEK + 1) }
|
||||
.toImmutableList()
|
||||
}
|
||||
|
||||
|
|
@ -81,12 +81,12 @@ private fun CalendarGrid(
|
|||
val daysInMonth = selectedYearMonth.lengthOfMonth()
|
||||
|
||||
VerticalGrid(
|
||||
columns = SimpleGridCells.Fixed(DaysOfWeek),
|
||||
columns = SimpleGridCells.Fixed(DAYS_OF_WEEK),
|
||||
modifier = if (isMediumWidthWindow() && !isExpandedWidthWindow()) {
|
||||
Modifier.widthIn(max = 360.dp)
|
||||
} else {
|
||||
Modifier
|
||||
}
|
||||
},
|
||||
) {
|
||||
weekDays.fastForEach { item ->
|
||||
Text(
|
||||
|
|
|
|||
|
|
@ -19,9 +19,10 @@ import androidx.compose.ui.text.font.FontWeight
|
|||
import androidx.compose.ui.text.style.TextAlign
|
||||
import androidx.compose.ui.unit.dp
|
||||
import androidx.compose.ui.unit.sp
|
||||
import tachiyomi.presentation.core.components.material.DISABLED_ALPHA
|
||||
import java.time.LocalDate
|
||||
|
||||
private const val MaxEvents = 3
|
||||
private const val MAX_EVENTS = 3
|
||||
|
||||
@Composable
|
||||
fun CalendarDay(
|
||||
|
|
@ -39,7 +40,7 @@ fun CalendarDay(
|
|||
Modifier.border(
|
||||
border = BorderStroke(
|
||||
width = 1.dp,
|
||||
color = MaterialTheme.colorScheme.onBackground
|
||||
color = MaterialTheme.colorScheme.onBackground,
|
||||
),
|
||||
shape = CircleShape,
|
||||
)
|
||||
|
|
@ -57,14 +58,14 @@ fun CalendarDay(
|
|||
textAlign = TextAlign.Center,
|
||||
fontSize = 16.sp,
|
||||
color = if (date.isBefore(today)) {
|
||||
MaterialTheme.colorScheme.onBackground.copy(alpha = 0.38f)
|
||||
MaterialTheme.colorScheme.onBackground.copy(alpha = DISABLED_ALPHA)
|
||||
} else {
|
||||
MaterialTheme.colorScheme.onBackground
|
||||
},
|
||||
fontWeight = FontWeight.SemiBold,
|
||||
)
|
||||
Row(Modifier.offset(y = 12.dp)) {
|
||||
val size = events.coerceAtMost(MaxEvents)
|
||||
val size = events.coerceAtMost(MAX_EVENTS)
|
||||
for (index in 0 until size) {
|
||||
CalendarIndicator(
|
||||
index = index,
|
||||
|
|
|
|||
|
|
@ -63,20 +63,20 @@ fun CalenderHeader(
|
|||
}
|
||||
}
|
||||
|
||||
private const val MonthYearChangeAnimationDuration = 200
|
||||
private const val MONTH_YEAR_CHANGE_ANIMATION_DURATION = 200
|
||||
|
||||
private fun AnimatedContentTransitionScope<YearMonth>.getAnimation(): ContentTransform {
|
||||
val movingForward = targetState > initialState
|
||||
|
||||
val enterTransition = slideInVertically(
|
||||
animationSpec = tween(durationMillis = MonthYearChangeAnimationDuration),
|
||||
animationSpec = tween(durationMillis = MONTH_YEAR_CHANGE_ANIMATION_DURATION),
|
||||
) { height -> if (movingForward) height else -height } + fadeIn(
|
||||
animationSpec = tween(durationMillis = MonthYearChangeAnimationDuration),
|
||||
animationSpec = tween(durationMillis = MONTH_YEAR_CHANGE_ANIMATION_DURATION),
|
||||
)
|
||||
val exitTransition = slideOutVertically(
|
||||
animationSpec = tween(durationMillis = MonthYearChangeAnimationDuration),
|
||||
animationSpec = tween(durationMillis = MONTH_YEAR_CHANGE_ANIMATION_DURATION),
|
||||
) { height -> if (movingForward) -height else height } + fadeOut(
|
||||
animationSpec = tween(durationMillis = MonthYearChangeAnimationDuration),
|
||||
animationSpec = tween(durationMillis = MONTH_YEAR_CHANGE_ANIMATION_DURATION),
|
||||
)
|
||||
return (enterTransition togetherWith exitTransition)
|
||||
.using(SizeTransform(clip = false))
|
||||
|
|
|
|||
|
|
@ -12,8 +12,8 @@ import androidx.compose.ui.graphics.Color
|
|||
import androidx.compose.ui.unit.Dp
|
||||
import androidx.compose.ui.unit.dp
|
||||
|
||||
private const val IndicatorScale = 12
|
||||
private const val IndicatorAlphaMultiplier = 0.3f
|
||||
private const val INDICATOR_SCALE = 12
|
||||
private const val INDICATOR_ALPHA_MULTIPLIER = 0.3f
|
||||
|
||||
@Composable
|
||||
fun CalendarIndicator(
|
||||
|
|
@ -26,7 +26,7 @@ fun CalendarIndicator(
|
|||
modifier = modifier
|
||||
.padding(horizontal = 1.dp)
|
||||
.clip(shape = CircleShape)
|
||||
.background(color = color.copy(alpha = (index + 1) * IndicatorAlphaMultiplier))
|
||||
.size(size = size.div(IndicatorScale)),
|
||||
.background(color = color.copy(alpha = (index + 1) * INDICATOR_ALPHA_MULTIPLIER))
|
||||
.size(size = size.div(INDICATOR_SCALE)),
|
||||
)
|
||||
}
|
||||
|
|
|
|||
|
|
@ -6,4 +6,4 @@
|
|||
android:viewportHeight="24"
|
||||
android:tint="@android:color/black">
|
||||
<path android:fillColor="#000" android:pathData="M17.5 14.33C18.29 14.33 19.13 14.41 20 14.57V16.07C19.38 15.91 18.54 15.83 17.5 15.83C15.6 15.83 14.11 16.16 13 16.82V15.13C14.17 14.6 15.67 14.33 17.5 14.33M13 12.46C14.29 11.93 15.79 11.67 17.5 11.67C18.29 11.67 19.13 11.74 20 11.9V13.4C19.38 13.24 18.54 13.16 17.5 13.16C15.6 13.16 14.11 13.5 13 14.15M17.5 10.5C15.6 10.5 14.11 10.82 13 11.5V9.84C14.23 9.28 15.73 9 17.5 9C18.29 9 19.13 9.08 20 9.23V10.78C19.26 10.59 18.41 10.5 17.5 10.5M21 18.5V7C19.96 6.67 18.79 6.5 17.5 6.5C15.45 6.5 13.62 7 12 8V19.5C13.62 18.5 15.45 18 17.5 18C18.69 18 19.86 18.16 21 18.5M17.5 4.5C19.85 4.5 21.69 5 23 6V20.56C23 20.68 22.95 20.8 22.84 20.91C22.73 21 22.61 21.08 22.5 21.08C22.39 21.08 22.31 21.06 22.25 21.03C20.97 20.34 19.38 20 17.5 20C15.45 20 13.62 20.5 12 21.5C10.66 20.5 8.83 20 6.5 20C4.84 20 3.25 20.36 1.75 21.07C1.72 21.08 1.68 21.08 1.63 21.1C1.59 21.11 1.55 21.12 1.5 21.12C1.39 21.12 1.27 21.08 1.16 21C1.05 20.89 1 20.78 1 20.65V6C2.34 5 4.18 4.5 6.5 4.5C8.83 4.5 10.66 5 12 6C13.34 5 15.17 4.5 17.5 4.5Z" />
|
||||
</vector>
|
||||
</vector>
|
||||
|
|
|
|||
|
|
@ -6,4 +6,4 @@
|
|||
android:viewportWidth="24"
|
||||
android:viewportHeight="24">
|
||||
<path android:fillColor="#000" android:pathData="M22,3H5A2,2 0 0,0 3,5V9H5V5H22V19H5V15H3V19A2,2 0 0,0 5,21H22A2,2 0 0,0 24,19V5A2,2 0 0,0 22,3M7,15V13H0V11H7V9L11,12L7,15M20,13H13V11H20V13M20,9H13V7H20V9M17,17H13V15H17V17Z" />
|
||||
</vector>
|
||||
</vector>
|
||||
|
|
|
|||
|
|
@ -7,4 +7,4 @@ android:viewportHeight="24">
|
|||
<path
|
||||
android:fillColor="@color/cover_placeholder"
|
||||
android:pathData="M21,5v6.59l-2.29,-2.3c-0.39,-0.39 -1.03,-0.39 -1.42,0L14,12.59 10.71,9.3c-0.39,-0.39 -1.02,-0.39 -1.41,0L6,12.59 3,9.58L3,5c0,-1.1 0.9,-2 2,-2h14c1.1,0 2,0.9 2,2zM18,11.42l3,3.01L21,19c0,1.1 -0.9,2 -2,2L5,21c-1.1,0 -2,-0.9 -2,-2v-6.58l2.29,2.29c0.39,0.39 1.02,0.39 1.41,0l3.3,-3.3 3.29,3.29c0.39,0.39 1.02,0.39 1.41,0l3.3,-3.28z"/>
|
||||
</vector>
|
||||
</vector>
|
||||
|
|
|
|||
|
|
@ -6,4 +6,4 @@
|
|||
<path
|
||||
android:fillColor="#FFF"
|
||||
android:pathData="M3,10C2.76,10 2.55,10.09 2.41,10.25C2.27,10.4 2.21,10.62 2.24,10.86L2.74,13.85C2.82,14.5 3.4,15 4,15H7C7.64,15 8.36,14.44 8.5,13.82L9.56,10.63C9.6,10.5 9.57,10.31 9.5,10.19C9.39,10.07 9.22,10 9,10H3M7,17H4C2.38,17 0.96,15.74 0.76,14.14L0.26,11.15C0.15,10.3 0.39,9.5 0.91,8.92C1.43,8.34 2.19,8 3,8H9C9.83,8 10.58,8.35 11.06,8.96C11.17,9.11 11.27,9.27 11.35,9.45C11.78,9.36 12.22,9.36 12.64,9.45C12.72,9.27 12.82,9.11 12.94,8.96C13.41,8.35 14.16,8 15,8H21C21.81,8 22.57,8.34 23.09,8.92C23.6,9.5 23.84,10.3 23.74,11.11L23.23,14.18C23.04,15.74 21.61,17 20,17H17C15.44,17 13.92,15.81 13.54,14.3L12.64,11.59C12.26,11.31 11.73,11.31 11.35,11.59L10.43,14.37C10.07,15.82 8.56,17 7,17M15,10C14.78,10 14.61,10.07 14.5,10.19C14.42,10.31 14.4,10.5 14.45,10.7L15.46,13.75C15.64,14.44 16.36,15 17,15H20C20.59,15 21.18,14.5 21.25,13.89L21.76,10.82C21.79,10.62 21.73,10.4 21.59,10.25C21.45,10.09 21.24,10 21,10H15Z" />
|
||||
</vector>
|
||||
</vector>
|
||||
|
|
|
|||
|
|
@ -7,4 +7,4 @@
|
|||
<path
|
||||
android:fillColor="#000"
|
||||
android:pathData="M13,2.03V2.05L13,4.05C17.39,4.59 20.5,8.58 19.96,12.97C19.5,16.61 16.64,19.5 13,19.93V21.93C18.5,21.38 22.5,16.5 21.95,11C21.5,6.25 17.73,2.5 13,2.03M11,2.06C9.05,2.25 7.19,3 5.67,4.26L7.1,5.74C8.22,4.84 9.57,4.26 11,4.06V2.06M4.26,5.67C3,7.19 2.25,9.04 2.05,11H4.05C4.24,9.58 4.8,8.23 5.69,7.1L4.26,5.67M2.06,13C2.26,14.96 3.03,16.81 4.27,18.33L5.69,16.9C4.81,15.77 4.24,14.42 4.06,13H2.06M7.1,18.37L5.67,19.74C7.18,21 9.04,21.79 11,22V20C9.58,19.82 8.23,19.25 7.1,18.37M12.5,7V12.25L17,14.92L16.25,16.15L11,13V7H12.5Z" />
|
||||
</vector>
|
||||
</vector>
|
||||
|
|
|
|||
|
|
@ -5,4 +5,4 @@
|
|||
android:viewportWidth="24"
|
||||
android:viewportHeight="24">
|
||||
<path android:fillColor="#000" android:pathData="M2,2H6V3H13V2H17V6H16V9H18V8H22V12H21V18H22V22H18V21H12V22H8V18H9V16H6V17H2V13H3V6H2V2M18,12V11H16V13H17V17H13V16H11V18H12V19H18V18H19V12H18M13,6V5H6V6H5V13H6V14H9V12H8V8H12V9H14V6H13M12,12H11V14H13V13H14V11H12V12Z" />
|
||||
</vector>
|
||||
</vector>
|
||||
|
|
|
|||
|
|
@ -12,4 +12,4 @@
|
|||
<corners android:radius="@dimen/m3_alert_dialog_corner_size" />
|
||||
</shape>
|
||||
</item>
|
||||
</layer-list>
|
||||
</layer-list>
|
||||
|
|
|
|||
|
|
@ -36,4 +36,4 @@
|
|||
|
||||
</androidx.constraintlayout.widget.ConstraintLayout>
|
||||
|
||||
</LinearLayout>
|
||||
</LinearLayout>
|
||||
|
|
|
|||
|
|
@ -157,4 +157,4 @@
|
|||
|
||||
|
||||
|
||||
</LinearLayout>
|
||||
</LinearLayout>
|
||||
|
|
|
|||
|
|
@ -27,4 +27,4 @@
|
|||
app:layout_constraintEnd_toEndOf="parent"
|
||||
app:layout_constraintTop_toTopOf="parent" />
|
||||
|
||||
</androidx.constraintlayout.widget.ConstraintLayout>
|
||||
</androidx.constraintlayout.widget.ConstraintLayout>
|
||||
|
|
|
|||
|
|
@ -45,4 +45,4 @@
|
|||
app:layout_constraintEnd_toEndOf="parent"
|
||||
app:layout_constraintTop_toTopOf="parent" />
|
||||
|
||||
</androidx.constraintlayout.widget.ConstraintLayout>
|
||||
</androidx.constraintlayout.widget.ConstraintLayout>
|
||||
|
|
|
|||
|
|
@ -95,4 +95,4 @@
|
|||
app:layout_constraintTop_toTopOf="parent" />
|
||||
</androidx.constraintlayout.widget.ConstraintLayout>
|
||||
|
||||
</LinearLayout>
|
||||
</LinearLayout>
|
||||
|
|
|
|||
|
|
@ -115,4 +115,4 @@
|
|||
</androidx.constraintlayout.widget.ConstraintLayout>
|
||||
|
||||
|
||||
</LinearLayout>
|
||||
</LinearLayout>
|
||||
|
|
|
|||
|
|
@ -124,4 +124,4 @@
|
|||
|
||||
</androidx.constraintlayout.widget.ConstraintLayout>
|
||||
|
||||
</LinearLayout>
|
||||
</LinearLayout>
|
||||
|
|
|
|||
|
|
@ -14,4 +14,4 @@
|
|||
android:layout_height="1dp"
|
||||
android:background="?android:attr/divider"/>
|
||||
|
||||
</LinearLayout>
|
||||
</LinearLayout>
|
||||
|
|
|
|||
|
|
@ -4,4 +4,4 @@
|
|||
android:layout_width="match_parent"
|
||||
android:layout_height="match_parent"
|
||||
android:clipToPadding="false"
|
||||
tools:listitem="@layout/migration_source_item" />
|
||||
tools:listitem="@layout/migration_source_item" />
|
||||
|
|
|
|||
|
|
@ -17,4 +17,4 @@
|
|||
<item name="android:clickable">true</item>
|
||||
<item name="android:focusable">true</item>
|
||||
</style>
|
||||
</resources>
|
||||
</resources>
|
||||
|
|
|
|||
|
|
@ -660,7 +660,7 @@
|
|||
<item name="colorSurfaceContainerLow">@color/nord_surfaceContainerLow</item>
|
||||
<item name="colorSurfaceContainerLowest">@color/nord_surfaceContainerLowest</item>
|
||||
</style>
|
||||
|
||||
|
||||
<!--== AMOLED Mode Overlay ==-->
|
||||
<style name="ThemeOverlay.Tachiyomi.Amoled" parent="" />
|
||||
|
||||
|
|
|
|||
|
|
@ -57,4 +57,4 @@
|
|||
name="gesture"
|
||||
value="swipe_left" />
|
||||
</action>
|
||||
</remote-actions>
|
||||
</remote-actions>
|
||||
|
|
|
|||
|
|
@ -133,8 +133,8 @@ class MigratorTest {
|
|||
listOf(
|
||||
Migration.of(Migration.ALWAYS) { true },
|
||||
Migration.of(2f) { true },
|
||||
Migration.of(3f) { false }
|
||||
)
|
||||
Migration.of(3f) { false },
|
||||
),
|
||||
)
|
||||
|
||||
execute.await()
|
||||
|
|
|
|||
|
|
@ -1,2 +1,2 @@
|
|||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<manifest />
|
||||
<manifest />
|
||||
|
|
|
|||
|
|
@ -1,2 +1,2 @@
|
|||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<manifest />
|
||||
<manifest />
|
||||
|
|
|
|||
|
|
@ -1,3 +1,5 @@
|
|||
@file:Suppress("FunctionName", "ktlint:standard:function-naming")
|
||||
|
||||
package eu.kanade.tachiyomi.network
|
||||
|
||||
import okhttp3.CacheControl
|
||||
|
|
|
|||
|
|
@ -546,16 +546,20 @@ object ImageUtil {
|
|||
darkBG -> {
|
||||
return ColorDrawable(blackColor)
|
||||
}
|
||||
topIsBlackStreak || (
|
||||
topCornersIsDark && topOffsetCornersIsDark &&
|
||||
(topMidIsDark || overallBlackPixels > 9)
|
||||
) -> {
|
||||
topIsBlackStreak ||
|
||||
(
|
||||
topCornersIsDark &&
|
||||
topOffsetCornersIsDark &&
|
||||
(topMidIsDark || overallBlackPixels > 9)
|
||||
) -> {
|
||||
intArrayOf(blackColor, blackColor, whiteColor, whiteColor)
|
||||
}
|
||||
bottomIsBlackStreak || (
|
||||
botCornersIsDark && botOffsetCornersIsDark &&
|
||||
(bottomCenterPixel.isDark() || overallBlackPixels > 9)
|
||||
) -> {
|
||||
bottomIsBlackStreak ||
|
||||
(
|
||||
botCornersIsDark &&
|
||||
botOffsetCornersIsDark &&
|
||||
(bottomCenterPixel.isDark() || overallBlackPixels > 9)
|
||||
) -> {
|
||||
intArrayOf(whiteColor, whiteColor, blackColor, blackColor)
|
||||
}
|
||||
else -> {
|
||||
|
|
|
|||
|
|
@ -1,2 +1,2 @@
|
|||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<manifest />
|
||||
<manifest />
|
||||
|
|
|
|||
|
|
@ -42,8 +42,8 @@ class QueryPagingSource<RowType : Any>(
|
|||
}
|
||||
|
||||
val (prevKey, nextKey) = when (params) {
|
||||
is LoadParams.Append -> { offset - loadSize to offset + loadSize }
|
||||
else -> { offset to offset + loadSize }
|
||||
is LoadParams.Append -> (offset - loadSize to offset + loadSize)
|
||||
else -> (offset to offset + loadSize)
|
||||
}
|
||||
|
||||
return LoadResult.Page(
|
||||
|
|
|
|||
|
|
@ -1,2 +1,2 @@
|
|||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<manifest />
|
||||
<manifest />
|
||||
|
|
|
|||
|
|
@ -5,7 +5,8 @@ import tachiyomi.domain.chapter.model.Chapter
|
|||
class ShouldUpdateDbChapter {
|
||||
|
||||
fun await(dbChapter: Chapter, sourceChapter: Chapter): Boolean {
|
||||
return dbChapter.scanlator != sourceChapter.scanlator || dbChapter.name != sourceChapter.name ||
|
||||
return dbChapter.scanlator != sourceChapter.scanlator ||
|
||||
dbChapter.name != sourceChapter.name ||
|
||||
dbChapter.dateUpload != sourceChapter.dateUpload ||
|
||||
dbChapter.chapterNumber != sourceChapter.chapterNumber ||
|
||||
dbChapter.sourceOrder != sourceChapter.sourceOrder
|
||||
|
|
|
|||
|
|
@ -20,10 +20,8 @@ class GetApplicationRelease(
|
|||
val now = Instant.now()
|
||||
|
||||
// Limit checks to once every 3 days at most
|
||||
if (!arguments.forceCheck && now.isBefore(
|
||||
Instant.ofEpochMilli(lastChecked.get()).plus(3, ChronoUnit.DAYS),
|
||||
)
|
||||
) {
|
||||
val nextCheckTime = Instant.ofEpochMilli(lastChecked.get()).plus(3, ChronoUnit.DAYS)
|
||||
if (!arguments.forceCheck && now.isBefore(nextCheckTime)) {
|
||||
return Result.NoNewUpdate
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -293,7 +293,7 @@ object FlagKit {
|
|||
"yt",
|
||||
"za",
|
||||
"zm",
|
||||
"zw"
|
||||
"zw",
|
||||
)
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,3 +1,3 @@
|
|||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<resources>
|
||||
</resources>
|
||||
</resources>
|
||||
|
|
|
|||
|
|
@ -80,4 +80,4 @@
|
|||
<item quantity="many">منذُ %1$d دقيقة</item>
|
||||
<item quantity="other">منذُ %1$d دقيقة</item>
|
||||
</plurals>
|
||||
</resources>
|
||||
</resources>
|
||||
|
|
|
|||
|
|
@ -451,4 +451,4 @@
|
|||
<string name="action_copy_combined_page">نسخ الصفحة المجمعة</string>
|
||||
<string name="only_show_updated_entries">إظهار الإدخالات التي تحتوي على فصول جديدة فقط</string>
|
||||
<string name="pref_crop_borders_pager">قص اطراف الصفحات</string>
|
||||
</resources>
|
||||
</resources>
|
||||
|
|
|
|||
|
|
@ -1,2 +1,2 @@
|
|||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<resources></resources>
|
||||
<resources></resources>
|
||||
|
|
|
|||
|
|
@ -1,2 +1,2 @@
|
|||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<resources></resources>
|
||||
<resources></resources>
|
||||
|
|
|
|||
|
|
@ -1,2 +1,2 @@
|
|||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<resources></resources>
|
||||
<resources></resources>
|
||||
|
|
|
|||
|
|
@ -533,4 +533,4 @@
|
|||
<string name="group">Grupo</string>
|
||||
<string name="uploader_capital">Naka-capitalize ang Uploader</string>
|
||||
<string name="deduplication_entry_info">Impo ng entry:</string>
|
||||
</resources>
|
||||
</resources>
|
||||
|
|
|
|||
|
|
@ -67,4 +67,4 @@
|
|||
<item quantity="one">%1$d seconde auparavant</item>
|
||||
<item quantity="other">%1$d seconde auparavant</item>
|
||||
</plurals>
|
||||
</resources>
|
||||
</resources>
|
||||
|
|
|
|||
|
|
@ -72,4 +72,4 @@
|
|||
<item quantity="one">%1$d detik yang lalu</item>
|
||||
<item quantity="other">%1$d detik yang lalu</item>
|
||||
</plurals>
|
||||
</resources>
|
||||
</resources>
|
||||
|
|
|
|||
Some files were not shown because too many files have changed in this diff Show more
Loading…
Reference in a new issue