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")
|
// 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 {
|
android {
|
||||||
namespace = "eu.kanade.tachiyomi"
|
namespace = "eu.kanade.tachiyomi"
|
||||||
|
|
@ -41,7 +41,7 @@ android {
|
||||||
buildConfigField("boolean", "PREVIEW", "false")
|
buildConfigField("boolean", "PREVIEW", "false")
|
||||||
|
|
||||||
ndk {
|
ndk {
|
||||||
abiFilters += SUPPORTED_ABIS
|
abiFilters += supportedAbis
|
||||||
}
|
}
|
||||||
testInstrumentationRunner = "androidx.test.runner.AndroidJUnitRunner"
|
testInstrumentationRunner = "androidx.test.runner.AndroidJUnitRunner"
|
||||||
}
|
}
|
||||||
|
|
@ -50,7 +50,7 @@ android {
|
||||||
abi {
|
abi {
|
||||||
isEnable = true
|
isEnable = true
|
||||||
reset()
|
reset()
|
||||||
include(*SUPPORTED_ABIS.toTypedArray())
|
include(*supportedAbis.toTypedArray())
|
||||||
isUniversalApk = true
|
isUniversalApk = true
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -117,7 +117,10 @@ class SyncChaptersWithSource(
|
||||||
downloadManager.isChapterDownloaded(
|
downloadManager.isChapterDownloaded(
|
||||||
dbChapter.name,
|
dbChapter.name,
|
||||||
dbChapter.scanlator,
|
dbChapter.scanlator,
|
||||||
/* SY --> */ manga.ogTitle /* SY <-- */,
|
// SY -->
|
||||||
|
// manga.title,
|
||||||
|
manga.ogTitle,
|
||||||
|
// SY <--
|
||||||
manga.source,
|
manga.source,
|
||||||
)
|
)
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -20,7 +20,11 @@ class UiPreferences(
|
||||||
|
|
||||||
fun appTheme() = preferenceStore.getEnum(
|
fun appTheme() = preferenceStore.getEnum(
|
||||||
"pref_app_theme",
|
"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)
|
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 name: ${extension.name} (lang: ${extension.lang}; package: ${extension.pkgName})
|
||||||
Extension version: ${extension.versionName} (lib: ${extension.libVersion}; version code: ${extension.versionCode})
|
Extension version: ${extension.versionName} (lib: ${extension.libVersion}; version code: ${extension.versionCode})
|
||||||
NSFW: ${extension.isNsfw}
|
NSFW: ${extension.isNsfw}
|
||||||
""".trimIndent()
|
""".trimIndent(),
|
||||||
)
|
)
|
||||||
|
|
||||||
if (extension is Extension.Installed) {
|
if (extension is Extension.Installed) {
|
||||||
|
|
@ -276,8 +276,8 @@ private fun DetailsHeader(
|
||||||
Update available: ${extension.hasUpdate}
|
Update available: ${extension.hasUpdate}
|
||||||
Obsolete: ${extension.isObsolete}
|
Obsolete: ${extension.isObsolete}
|
||||||
Shared: ${extension.isShared}
|
Shared: ${extension.isShared}
|
||||||
Repository: ${extension.repoUrl}
|
Repository: ${extension.repoUrl}
|
||||||
""".trimIndent()
|
""".trimIndent(),
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -231,7 +231,9 @@ private fun ExtensionContent(
|
||||||
when (it) {
|
when (it) {
|
||||||
is Extension.Available -> onInstallExtension(it)
|
is Extension.Available -> onInstallExtension(it)
|
||||||
is Extension.Installed -> onOpenExtension(it)
|
is Extension.Installed -> onOpenExtension(it)
|
||||||
is Extension.Untrusted -> { trustState = it }
|
is Extension.Untrusted -> {
|
||||||
|
trustState = it
|
||||||
|
}
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
onLongClickItem = onLongClickItem,
|
onLongClickItem = onLongClickItem,
|
||||||
|
|
@ -253,7 +255,9 @@ private fun ExtensionContent(
|
||||||
onOpenExtension(it)
|
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.i18n.sy.SYMR
|
||||||
import tachiyomi.presentation.core.components.FastScrollLazyColumn
|
import tachiyomi.presentation.core.components.FastScrollLazyColumn
|
||||||
import tachiyomi.presentation.core.components.LabeledCheckbox
|
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.components.material.padding
|
||||||
import tachiyomi.presentation.core.i18n.stringResource
|
import tachiyomi.presentation.core.i18n.stringResource
|
||||||
import tachiyomi.presentation.core.screens.EmptyScreen
|
import tachiyomi.presentation.core.screens.EmptyScreen
|
||||||
|
|
@ -399,7 +399,7 @@ private fun SourcePinButton(
|
||||||
MaterialTheme.colorScheme.primary
|
MaterialTheme.colorScheme.primary
|
||||||
} else {
|
} else {
|
||||||
MaterialTheme.colorScheme.onBackground.copy(
|
MaterialTheme.colorScheme.onBackground.copy(
|
||||||
alpha = SecondaryItemAlpha,
|
alpha = SECONDARY_ALPHA,
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
val description = if (isPinned) MR.strings.action_unpin else MR.strings.action_pin
|
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 com.gowtham.ratingbar.RatingBarStyle
|
||||||
import dev.icerock.moko.resources.StringResource
|
import dev.icerock.moko.resources.StringResource
|
||||||
import eu.kanade.presentation.library.components.CommonMangaItemDefaults
|
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.MangaCover
|
||||||
import eu.kanade.presentation.manga.components.MangaCoverHide
|
import eu.kanade.presentation.manga.components.MangaCoverHide
|
||||||
import exh.debug.DebugToggles
|
import exh.debug.DebugToggles
|
||||||
|
|
@ -205,7 +205,7 @@ fun BrowseSourceEHentaiListItem(
|
||||||
modifier = Modifier
|
modifier = Modifier
|
||||||
.fillMaxHeight(),
|
.fillMaxHeight(),
|
||||||
// KMK -->
|
// KMK -->
|
||||||
alpha = if (isSelected) GridSelectedCoverAlpha else coverAlpha,
|
alpha = if (isSelected) GRID_SELECTED_COVER_ALPHA else coverAlpha,
|
||||||
bgColor = bgColor ?: (MaterialTheme.colorScheme.surface.takeIf { isSelected }),
|
bgColor = bgColor ?: (MaterialTheme.colorScheme.surface.takeIf { isSelected }),
|
||||||
tint = onBgColor,
|
tint = onBgColor,
|
||||||
// KMK <--
|
// KMK <--
|
||||||
|
|
|
||||||
|
|
@ -79,7 +79,7 @@ fun TabbedDialog(
|
||||||
modifier = Modifier.animateContentSize(),
|
modifier = Modifier.animateContentSize(),
|
||||||
state = pagerState,
|
state = pagerState,
|
||||||
verticalAlignment = Alignment.Top,
|
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 ContinueReadingButtonGridPadding = 6.dp
|
||||||
private val ContinueReadingButtonListSpacing = 8.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.
|
* Layout of grid list item with title overlaying the cover.
|
||||||
|
|
@ -113,7 +113,7 @@ fun MangaCompactGridItem(
|
||||||
.fillMaxWidth(),
|
.fillMaxWidth(),
|
||||||
data = coverData,
|
data = coverData,
|
||||||
// KMK -->
|
// KMK -->
|
||||||
alpha = if (isSelected) GridSelectedCoverAlpha else coverAlpha,
|
alpha = if (isSelected) GRID_SELECTED_COVER_ALPHA else coverAlpha,
|
||||||
bgColor = bgColor ?: (MaterialTheme.colorScheme.surface.takeIf { isSelected }),
|
bgColor = bgColor ?: (MaterialTheme.colorScheme.surface.takeIf { isSelected }),
|
||||||
tint = onBgColor,
|
tint = onBgColor,
|
||||||
// KMK <--
|
// KMK <--
|
||||||
|
|
@ -245,7 +245,7 @@ fun MangaComfortableGridItem(
|
||||||
.fillMaxWidth(),
|
.fillMaxWidth(),
|
||||||
data = coverData,
|
data = coverData,
|
||||||
// KMK -->
|
// KMK -->
|
||||||
alpha = if (isSelected) GridSelectedCoverAlpha else coverAlpha,
|
alpha = if (isSelected) GRID_SELECTED_COVER_ALPHA else coverAlpha,
|
||||||
bgColor = bgColor ?: (MaterialTheme.colorScheme.surface.takeIf { isSelected }),
|
bgColor = bgColor ?: (MaterialTheme.colorScheme.surface.takeIf { isSelected }),
|
||||||
tint = onBgColor,
|
tint = onBgColor,
|
||||||
// KMK <--
|
// KMK <--
|
||||||
|
|
@ -448,7 +448,7 @@ fun MangaListItem(
|
||||||
size = ContinueReadingButtonSizeSmall,
|
size = ContinueReadingButtonSizeSmall,
|
||||||
iconSize = ContinueReadingButtonIconSizeSmall,
|
iconSize = ContinueReadingButtonIconSizeSmall,
|
||||||
onClick = onClickContinueReading,
|
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),
|
containerColor = MaterialTheme.colorScheme.primaryContainer.copy(alpha = 0.9f),
|
||||||
contentColor = contentColorFor(MaterialTheme.colorScheme.primaryContainer),
|
contentColor = contentColorFor(MaterialTheme.colorScheme.primaryContainer),
|
||||||
),
|
),
|
||||||
modifier = Modifier.size(size)
|
modifier = Modifier.size(size),
|
||||||
) {
|
) {
|
||||||
Icon(
|
Icon(
|
||||||
imageVector = Icons.Filled.PlayArrow,
|
imageVector = Icons.Filled.PlayArrow,
|
||||||
|
|
|
||||||
|
|
@ -14,7 +14,7 @@ import androidx.compose.ui.Modifier
|
||||||
import androidx.compose.ui.text.style.TextOverflow
|
import androidx.compose.ui.text.style.TextOverflow
|
||||||
import androidx.compose.ui.unit.dp
|
import androidx.compose.ui.unit.dp
|
||||||
import tachiyomi.i18n.MR
|
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.components.material.padding
|
||||||
import tachiyomi.presentation.core.i18n.pluralStringResource
|
import tachiyomi.presentation.core.i18n.pluralStringResource
|
||||||
import tachiyomi.presentation.core.i18n.stringResource
|
import tachiyomi.presentation.core.i18n.stringResource
|
||||||
|
|
@ -70,6 +70,6 @@ private fun MissingChaptersWarning(count: Int) {
|
||||||
maxLines = 1,
|
maxLines = 1,
|
||||||
overflow = TextOverflow.Ellipsis,
|
overflow = TextOverflow.Ellipsis,
|
||||||
style = MaterialTheme.typography.bodySmall,
|
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 me.saket.swipe.SwipeableActionsBox
|
||||||
import tachiyomi.domain.library.service.LibraryPreferences
|
import tachiyomi.domain.library.service.LibraryPreferences
|
||||||
import tachiyomi.i18n.MR
|
import tachiyomi.i18n.MR
|
||||||
import tachiyomi.presentation.core.components.material.ReadItemAlpha
|
import tachiyomi.presentation.core.components.material.DISABLED_ALPHA
|
||||||
import tachiyomi.presentation.core.components.material.SecondaryItemAlpha
|
import tachiyomi.presentation.core.components.material.SECONDARY_ALPHA
|
||||||
import tachiyomi.presentation.core.i18n.stringResource
|
import tachiyomi.presentation.core.i18n.stringResource
|
||||||
import tachiyomi.presentation.core.util.selectedBackground
|
import tachiyomi.presentation.core.util.selectedBackground
|
||||||
|
|
||||||
|
|
@ -135,7 +135,7 @@ fun MangaChapterListItem(
|
||||||
maxLines = 1,
|
maxLines = 1,
|
||||||
overflow = TextOverflow.Ellipsis,
|
overflow = TextOverflow.Ellipsis,
|
||||||
onTextLayout = { textHeight = it.size.height },
|
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
|
val subtitleStyle = MaterialTheme.typography.bodySmall
|
||||||
.merge(
|
.merge(
|
||||||
color = LocalContentColor.current
|
color = LocalContentColor.current
|
||||||
.copy(alpha = if (read) ReadItemAlpha else SecondaryItemAlpha)
|
.copy(alpha = if (read) DISABLED_ALPHA else SECONDARY_ALPHA),
|
||||||
)
|
)
|
||||||
ProvideTextStyle(value = subtitleStyle) {
|
ProvideTextStyle(value = subtitleStyle) {
|
||||||
if (date != null) {
|
if (date != null) {
|
||||||
|
|
@ -159,7 +159,7 @@ fun MangaChapterListItem(
|
||||||
text = readProgress,
|
text = readProgress,
|
||||||
maxLines = 1,
|
maxLines = 1,
|
||||||
overflow = TextOverflow.Ellipsis,
|
overflow = TextOverflow.Ellipsis,
|
||||||
color = LocalContentColor.current.copy(alpha = ReadItemAlpha),
|
color = LocalContentColor.current.copy(alpha = DISABLED_ALPHA),
|
||||||
)
|
)
|
||||||
if (scanlator != null/* SY --> */ || sourceName != null/* SY <-- */) DotSeparatorText()
|
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.MR
|
||||||
import tachiyomi.i18n.kmk.KMR
|
import tachiyomi.i18n.kmk.KMR
|
||||||
import tachiyomi.i18n.sy.SYMR
|
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.TextButton
|
||||||
import tachiyomi.presentation.core.components.material.padding
|
import tachiyomi.presentation.core.components.material.padding
|
||||||
import tachiyomi.presentation.core.i18n.pluralStringResource
|
import tachiyomi.presentation.core.i18n.pluralStringResource
|
||||||
|
|
@ -209,7 +210,7 @@ fun MangaActionRow(
|
||||||
// SY <--
|
// SY <--
|
||||||
modifier: Modifier = Modifier,
|
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
|
// TODO: show something better when using custom interval
|
||||||
val nextUpdateDays = remember(nextUpdate) {
|
val nextUpdateDays = remember(nextUpdate) {
|
||||||
|
|
|
||||||
|
|
@ -76,7 +76,7 @@ private fun NewUpdateScreenPreview() {
|
||||||
changelogInfo = """
|
changelogInfo = """
|
||||||
## Yay
|
## Yay
|
||||||
Foobar
|
Foobar
|
||||||
|
|
||||||
### More info
|
### More info
|
||||||
- Hello
|
- Hello
|
||||||
- World
|
- World
|
||||||
|
|
|
||||||
|
|
@ -397,7 +397,7 @@ object SettingsAdvancedScreen : SearchableSettings {
|
||||||
chooseColorProfile.launch(arrayOf("*/*"))
|
chooseColorProfile.launch(arrayOf("*/*"))
|
||||||
},
|
},
|
||||||
),
|
),
|
||||||
)
|
),
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -37,7 +37,7 @@ class OpenSourceLicensesScreen : Screen() {
|
||||||
name = it.name,
|
name = it.name,
|
||||||
website = it.website,
|
website = it.website,
|
||||||
license = it.licenses.firstOrNull()?.htmlReadyLicenseContent.orEmpty(),
|
license = it.licenses.firstOrNull()?.htmlReadyLicenseContent.orEmpty(),
|
||||||
)
|
),
|
||||||
)
|
)
|
||||||
},
|
},
|
||||||
)
|
)
|
||||||
|
|
|
||||||
|
|
@ -28,7 +28,7 @@ import tachiyomi.presentation.core.i18n.stringResource
|
||||||
class BackupSchemaScreen : Screen() {
|
class BackupSchemaScreen : Screen() {
|
||||||
|
|
||||||
companion object {
|
companion object {
|
||||||
const val title = "Backup file schema"
|
const val TITLE = "Backup file schema"
|
||||||
}
|
}
|
||||||
|
|
||||||
@Composable
|
@Composable
|
||||||
|
|
@ -41,7 +41,7 @@ class BackupSchemaScreen : Screen() {
|
||||||
Scaffold(
|
Scaffold(
|
||||||
topBar = {
|
topBar = {
|
||||||
AppBar(
|
AppBar(
|
||||||
title = title,
|
title = TITLE,
|
||||||
navigateUp = navigator::pop,
|
navigateUp = navigator::pop,
|
||||||
actions = {
|
actions = {
|
||||||
AppBarActions(
|
AppBarActions(
|
||||||
|
|
@ -50,7 +50,7 @@ class BackupSchemaScreen : Screen() {
|
||||||
title = stringResource(MR.strings.action_copy_to_clipboard),
|
title = stringResource(MR.strings.action_copy_to_clipboard),
|
||||||
icon = Icons.Default.ContentCopy,
|
icon = Icons.Default.ContentCopy,
|
||||||
onClick = {
|
onClick = {
|
||||||
context.copyToClipboard(title, schema)
|
context.copyToClipboard(TITLE, schema)
|
||||||
},
|
},
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
|
|
|
||||||
|
|
@ -31,11 +31,11 @@ class DebugInfoScreen : Screen() {
|
||||||
itemsProvider = {
|
itemsProvider = {
|
||||||
listOf(
|
listOf(
|
||||||
Preference.PreferenceItem.TextPreference(
|
Preference.PreferenceItem.TextPreference(
|
||||||
title = WorkerInfoScreen.title,
|
title = WorkerInfoScreen.TITLE,
|
||||||
onClick = { navigator.push(WorkerInfoScreen()) },
|
onClick = { navigator.push(WorkerInfoScreen()) },
|
||||||
),
|
),
|
||||||
Preference.PreferenceItem.TextPreference(
|
Preference.PreferenceItem.TextPreference(
|
||||||
title = BackupSchemaScreen.title,
|
title = BackupSchemaScreen.TITLE,
|
||||||
onClick = { navigator.push(BackupSchemaScreen()) },
|
onClick = { navigator.push(BackupSchemaScreen()) },
|
||||||
),
|
),
|
||||||
getAppInfoGroup(),
|
getAppInfoGroup(),
|
||||||
|
|
|
||||||
|
|
@ -49,7 +49,7 @@ import java.time.ZoneId
|
||||||
class WorkerInfoScreen : Screen() {
|
class WorkerInfoScreen : Screen() {
|
||||||
|
|
||||||
companion object {
|
companion object {
|
||||||
const val title = "Worker info"
|
const val TITLE = "Worker info"
|
||||||
}
|
}
|
||||||
|
|
||||||
@Composable
|
@Composable
|
||||||
|
|
@ -65,7 +65,7 @@ class WorkerInfoScreen : Screen() {
|
||||||
Scaffold(
|
Scaffold(
|
||||||
topBar = {
|
topBar = {
|
||||||
AppBar(
|
AppBar(
|
||||||
title = title,
|
title = TITLE,
|
||||||
navigateUp = navigator::pop,
|
navigateUp = navigator::pop,
|
||||||
actions = {
|
actions = {
|
||||||
AppBarActions(
|
AppBarActions(
|
||||||
|
|
@ -74,7 +74,7 @@ class WorkerInfoScreen : Screen() {
|
||||||
title = stringResource(MR.strings.action_copy_to_clipboard),
|
title = stringResource(MR.strings.action_copy_to_clipboard),
|
||||||
icon = Icons.Default.ContentCopy,
|
icon = Icons.Default.ContentCopy,
|
||||||
onClick = {
|
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(),
|
Injekt.get<UiPreferences>().dateFormat().get(),
|
||||||
),
|
),
|
||||||
)
|
)
|
||||||
appendLine("Next scheduled run: $timestamp",)
|
appendLine("Next scheduled run: $timestamp")
|
||||||
appendLine("Attempt #${workInfo.runAttemptCount + 1}")
|
appendLine("Attempt #${workInfo.runAttemptCount + 1}")
|
||||||
}
|
}
|
||||||
appendLine()
|
appendLine()
|
||||||
|
|
|
||||||
|
|
@ -32,7 +32,9 @@ import tachiyomi.i18n.MR
|
||||||
import tachiyomi.presentation.core.i18n.stringResource
|
import tachiyomi.presentation.core.i18n.stringResource
|
||||||
|
|
||||||
private enum class State {
|
private enum class State {
|
||||||
CHECKED, INVERSED, UNCHECKED
|
CHECKED,
|
||||||
|
INVERSED,
|
||||||
|
UNCHECKED,
|
||||||
}
|
}
|
||||||
|
|
||||||
@Composable
|
@Composable
|
||||||
|
|
|
||||||
|
|
@ -15,7 +15,7 @@ import androidx.compose.ui.graphics.vector.ImageVector
|
||||||
import androidx.compose.ui.text.TextStyle
|
import androidx.compose.ui.text.TextStyle
|
||||||
import androidx.compose.ui.text.font.FontWeight
|
import androidx.compose.ui.text.font.FontWeight
|
||||||
import androidx.compose.ui.text.style.TextAlign
|
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
|
import tachiyomi.presentation.core.components.material.padding
|
||||||
|
|
||||||
@Composable
|
@Composable
|
||||||
|
|
@ -73,7 +73,7 @@ private fun RowScope.BaseStatsItem(
|
||||||
style = subtitleStyle
|
style = subtitleStyle
|
||||||
.copy(
|
.copy(
|
||||||
color = MaterialTheme.colorScheme.onSurface
|
color = MaterialTheme.colorScheme.onSurface
|
||||||
.copy(alpha = SecondaryItemAlpha),
|
.copy(alpha = SECONDARY_ALPHA),
|
||||||
),
|
),
|
||||||
textAlign = TextAlign.Center,
|
textAlign = TextAlign.Center,
|
||||||
)
|
)
|
||||||
|
|
|
||||||
|
|
@ -226,7 +226,7 @@ private fun ChapterText(
|
||||||
Text(
|
Text(
|
||||||
text = buildAnnotatedString {
|
text = buildAnnotatedString {
|
||||||
if (downloaded) {
|
if (downloaded) {
|
||||||
appendInlineContent(DownloadedIconContentId)
|
appendInlineContent(DOWNLOADED_ICON_ID)
|
||||||
append(' ')
|
append(' ')
|
||||||
}
|
}
|
||||||
append(name)
|
append(name)
|
||||||
|
|
@ -236,7 +236,7 @@ private fun ChapterText(
|
||||||
overflow = TextOverflow.Ellipsis,
|
overflow = TextOverflow.Ellipsis,
|
||||||
style = MaterialTheme.typography.titleLarge,
|
style = MaterialTheme.typography.titleLarge,
|
||||||
inlineContent = persistentMapOf(
|
inlineContent = persistentMapOf(
|
||||||
DownloadedIconContentId to InlineTextContent(
|
DOWNLOADED_ICON_ID to InlineTextContent(
|
||||||
Placeholder(
|
Placeholder(
|
||||||
width = 22.sp,
|
width = 22.sp,
|
||||||
height = 22.sp,
|
height = 22.sp,
|
||||||
|
|
@ -273,7 +273,7 @@ private val CardColor: CardColors
|
||||||
)
|
)
|
||||||
|
|
||||||
private val VerticalSpacerSize = 24.dp
|
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(
|
private fun previewChapter(name: String, scanlator: String, chapterNumber: Double) = Chapter.create().copy(
|
||||||
id = 0L,
|
id = 0L,
|
||||||
|
|
|
||||||
|
|
@ -38,7 +38,6 @@ import androidx.compose.runtime.remember
|
||||||
import androidx.compose.runtime.setValue
|
import androidx.compose.runtime.setValue
|
||||||
import androidx.compose.ui.Alignment
|
import androidx.compose.ui.Alignment
|
||||||
import androidx.compose.ui.Modifier
|
import androidx.compose.ui.Modifier
|
||||||
import androidx.compose.ui.draw.alpha
|
|
||||||
import androidx.compose.ui.draw.clip
|
import androidx.compose.ui.draw.clip
|
||||||
import androidx.compose.ui.platform.LocalContext
|
import androidx.compose.ui.platform.LocalContext
|
||||||
import androidx.compose.ui.text.style.TextAlign
|
import androidx.compose.ui.text.style.TextAlign
|
||||||
|
|
@ -58,8 +57,6 @@ import tachiyomi.i18n.MR
|
||||||
import tachiyomi.presentation.core.i18n.stringResource
|
import tachiyomi.presentation.core.i18n.stringResource
|
||||||
import java.time.format.DateTimeFormatter
|
import java.time.format.DateTimeFormatter
|
||||||
|
|
||||||
private const val UnsetStatusTextAlpha = 0.5F
|
|
||||||
|
|
||||||
@Composable
|
@Composable
|
||||||
fun TrackInfoDialogHome(
|
fun TrackInfoDialogHome(
|
||||||
trackItems: List<TrackItem>,
|
trackItems: List<TrackItem>,
|
||||||
|
|
@ -211,10 +208,9 @@ private fun TrackInfoItem(
|
||||||
if (onScoreClick != null) {
|
if (onScoreClick != null) {
|
||||||
VerticalDivider()
|
VerticalDivider()
|
||||||
TrackDetailsItem(
|
TrackDetailsItem(
|
||||||
modifier = Modifier
|
modifier = Modifier.weight(1f),
|
||||||
.weight(1f)
|
text = score,
|
||||||
.alpha(if (score == null) UnsetStatusTextAlpha else 1f),
|
placeholder = stringResource(MR.strings.score),
|
||||||
text = score ?: stringResource(MR.strings.score),
|
|
||||||
onClick = onScoreClick,
|
onClick = onScoreClick,
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
@ -243,6 +239,8 @@ private fun TrackInfoItem(
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private const val UNSET_TEXT_ALPHA = 0.5F
|
||||||
|
|
||||||
@Composable
|
@Composable
|
||||||
private fun TrackDetailsItem(
|
private fun TrackDetailsItem(
|
||||||
text: String?,
|
text: String?,
|
||||||
|
|
@ -263,7 +261,7 @@ private fun TrackDetailsItem(
|
||||||
overflow = TextOverflow.Ellipsis,
|
overflow = TextOverflow.Ellipsis,
|
||||||
style = MaterialTheme.typography.bodyMedium,
|
style = MaterialTheme.typography.bodyMedium,
|
||||||
textAlign = TextAlign.Center,
|
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.domain.updates.model.UpdatesWithRelations
|
||||||
import tachiyomi.i18n.MR
|
import tachiyomi.i18n.MR
|
||||||
import tachiyomi.presentation.core.components.ListGroupHeader
|
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.components.material.padding
|
||||||
import tachiyomi.presentation.core.i18n.stringResource
|
import tachiyomi.presentation.core.i18n.stringResource
|
||||||
import tachiyomi.presentation.core.util.selectedBackground
|
import tachiyomi.presentation.core.util.selectedBackground
|
||||||
|
|
@ -154,7 +154,7 @@ private fun UpdatesUiItem(
|
||||||
modifier: Modifier = Modifier,
|
modifier: Modifier = Modifier,
|
||||||
) {
|
) {
|
||||||
val haptic = LocalHapticFeedback.current
|
val haptic = LocalHapticFeedback.current
|
||||||
val textAlpha = if (update.read) ReadItemAlpha else 1f
|
val textAlpha = if (update.read) DISABLED_ALPHA else 1f
|
||||||
|
|
||||||
Row(
|
Row(
|
||||||
modifier = modifier
|
modifier = modifier
|
||||||
|
|
@ -238,7 +238,7 @@ private fun UpdatesUiItem(
|
||||||
Text(
|
Text(
|
||||||
text = readProgress,
|
text = readProgress,
|
||||||
maxLines = 1,
|
maxLines = 1,
|
||||||
color = LocalContentColor.current.copy(alpha = ReadItemAlpha),
|
color = LocalContentColor.current.copy(alpha = DISABLED_ALPHA),
|
||||||
overflow = TextOverflow.Ellipsis,
|
overflow = TextOverflow.Ellipsis,
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -218,7 +218,7 @@ class BackupRestorer(
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun CoroutineScope.restoreExtensionRepos(
|
private fun CoroutineScope.restoreExtensionRepos(
|
||||||
backupExtensionRepo: List<BackupExtensionRepos>
|
backupExtensionRepo: List<BackupExtensionRepos>,
|
||||||
) = launch {
|
) = launch {
|
||||||
backupExtensionRepo
|
backupExtensionRepo
|
||||||
.forEach {
|
.forEach {
|
||||||
|
|
|
||||||
|
|
@ -8,7 +8,7 @@ import uy.kohesive.injekt.api.get
|
||||||
|
|
||||||
class ExtensionRepoRestorer(
|
class ExtensionRepoRestorer(
|
||||||
private val handler: DatabaseHandler = Injekt.get(),
|
private val handler: DatabaseHandler = Injekt.get(),
|
||||||
private val getExtensionRepos: GetExtensionRepo = Injekt.get()
|
private val getExtensionRepos: GetExtensionRepo = Injekt.get(),
|
||||||
) {
|
) {
|
||||||
|
|
||||||
suspend operator fun invoke(
|
suspend operator fun invoke(
|
||||||
|
|
@ -32,7 +32,7 @@ class ExtensionRepoRestorer(
|
||||||
backupRepo.name,
|
backupRepo.name,
|
||||||
backupRepo.shortName,
|
backupRepo.shortName,
|
||||||
backupRepo.website,
|
backupRepo.website,
|
||||||
backupRepo.signingKeyFingerprint
|
backupRepo.signingKeyFingerprint,
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -110,7 +110,7 @@ class MangaCoverFetcher(
|
||||||
source = ImageSource(
|
source = ImageSource(
|
||||||
file = file.toOkioPath(),
|
file = file.toOkioPath(),
|
||||||
fileSystem = FileSystem.SYSTEM,
|
fileSystem = FileSystem.SYSTEM,
|
||||||
diskCacheKey = diskCacheKey
|
diskCacheKey = diskCacheKey,
|
||||||
),
|
),
|
||||||
mimeType = "image/*",
|
mimeType = "image/*",
|
||||||
dataSource = DataSource.DISK,
|
dataSource = DataSource.DISK,
|
||||||
|
|
|
||||||
|
|
@ -1,3 +1,5 @@
|
||||||
|
@file:Suppress("PropertyName", "ktlint:standard:property-naming")
|
||||||
|
|
||||||
package eu.kanade.tachiyomi.data.database.models
|
package eu.kanade.tachiyomi.data.database.models
|
||||||
|
|
||||||
import eu.kanade.tachiyomi.source.model.SChapter
|
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
|
package eu.kanade.tachiyomi.data.database.models
|
||||||
|
|
||||||
class ChapterImpl : Chapter {
|
class ChapterImpl : Chapter {
|
||||||
|
|
|
||||||
|
|
@ -1,3 +1,5 @@
|
||||||
|
@file:Suppress("PropertyName", "ktlint:standard:property-naming")
|
||||||
|
|
||||||
package eu.kanade.tachiyomi.data.database.models
|
package eu.kanade.tachiyomi.data.database.models
|
||||||
|
|
||||||
import java.io.Serializable
|
import java.io.Serializable
|
||||||
|
|
|
||||||
|
|
@ -1,3 +1,5 @@
|
||||||
|
@file:Suppress("PropertyName", "ktlint:standard:property-naming")
|
||||||
|
|
||||||
package eu.kanade.tachiyomi.data.database.models
|
package eu.kanade.tachiyomi.data.database.models
|
||||||
|
|
||||||
class TrackImpl : Track {
|
class TrackImpl : Track {
|
||||||
|
|
|
||||||
|
|
@ -190,7 +190,7 @@ class Downloader(
|
||||||
fun clearQueue() {
|
fun clearQueue() {
|
||||||
cancelDownloaderJob()
|
cancelDownloaderJob()
|
||||||
|
|
||||||
_clearQueue()
|
internalClearQueue()
|
||||||
notifier.dismissProgress()
|
notifier.dismissProgress()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -204,9 +204,12 @@ class Downloader(
|
||||||
val activeDownloadsFlow = queueState.transformLatest { queue ->
|
val activeDownloadsFlow = queueState.transformLatest { queue ->
|
||||||
while (true) {
|
while (true) {
|
||||||
val activeDownloads = queue.asSequence()
|
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 }
|
.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() }
|
.map { (_, downloads) -> downloads.first() }
|
||||||
emit(activeDownloads)
|
emit(activeDownloads)
|
||||||
|
|
||||||
|
|
@ -650,7 +653,7 @@ class Downloader(
|
||||||
chapter,
|
chapter,
|
||||||
urls,
|
urls,
|
||||||
categories,
|
categories,
|
||||||
source.name
|
source.name,
|
||||||
)
|
)
|
||||||
|
|
||||||
// Remove the old file
|
// Remove the old file
|
||||||
|
|
@ -710,7 +713,7 @@ class Downloader(
|
||||||
removeFromQueueIf { it.manga.id == manga.id }
|
removeFromQueueIf { it.manga.id == manga.id }
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun _clearQueue() {
|
private fun internalClearQueue() {
|
||||||
_queueState.update {
|
_queueState.update {
|
||||||
it.forEach { download ->
|
it.forEach { download ->
|
||||||
if (download.status == Download.State.DOWNLOADING || download.status == Download.State.QUEUE) {
|
if (download.status == Download.State.DOWNLOADING || download.status == Download.State.QUEUE) {
|
||||||
|
|
@ -732,7 +735,7 @@ class Downloader(
|
||||||
}
|
}
|
||||||
|
|
||||||
pause()
|
pause()
|
||||||
_clearQueue()
|
internalClearQueue()
|
||||||
addAllToQueue(downloads)
|
addAllToQueue(downloads)
|
||||||
|
|
||||||
if (wasRunning) {
|
if (wasRunning) {
|
||||||
|
|
|
||||||
|
|
@ -778,7 +778,9 @@ class LibraryUpdateJob(private val context: Context, workerParams: WorkerParamet
|
||||||
val constraints = Constraints(
|
val constraints = Constraints(
|
||||||
requiredNetworkType = if (DEVICE_NETWORK_NOT_METERED in restrictions) {
|
requiredNetworkType = if (DEVICE_NETWORK_NOT_METERED in restrictions) {
|
||||||
NetworkType.UNMETERED
|
NetworkType.UNMETERED
|
||||||
} else { NetworkType.CONNECTED },
|
} else {
|
||||||
|
NetworkType.CONNECTED
|
||||||
|
},
|
||||||
requiresCharging = DEVICE_CHARGING in restrictions,
|
requiresCharging = DEVICE_CHARGING in restrictions,
|
||||||
requiresBatteryNotLow = true,
|
requiresBatteryNotLow = true,
|
||||||
)
|
)
|
||||||
|
|
|
||||||
|
|
@ -47,10 +47,10 @@ class AnilistApi(val client: OkHttpClient, interceptor: AnilistInterceptor) {
|
||||||
return withIOContext {
|
return withIOContext {
|
||||||
val query = """
|
val query = """
|
||||||
|mutation AddManga(${'$'}mangaId: Int, ${'$'}progress: Int, ${'$'}status: MediaListStatus) {
|
|mutation AddManga(${'$'}mangaId: Int, ${'$'}progress: Int, ${'$'}status: MediaListStatus) {
|
||||||
|SaveMediaListEntry (mediaId: ${'$'}mangaId, progress: ${'$'}progress, status: ${'$'}status) {
|
|SaveMediaListEntry (mediaId: ${'$'}mangaId, progress: ${'$'}progress, status: ${'$'}status) {
|
||||||
| id
|
| id
|
||||||
| status
|
| status
|
||||||
|}
|
|}
|
||||||
|}
|
|}
|
||||||
|
|
|
|
||||||
""".trimMargin()
|
""".trimMargin()
|
||||||
|
|
@ -65,7 +65,7 @@ class AnilistApi(val client: OkHttpClient, interceptor: AnilistInterceptor) {
|
||||||
with(json) {
|
with(json) {
|
||||||
authClient.newCall(
|
authClient.newCall(
|
||||||
POST(
|
POST(
|
||||||
apiUrl,
|
API_URL,
|
||||||
body = payload.toString().toRequestBody(jsonMime),
|
body = payload.toString().toRequestBody(jsonMime),
|
||||||
),
|
),
|
||||||
)
|
)
|
||||||
|
|
@ -109,7 +109,7 @@ class AnilistApi(val client: OkHttpClient, interceptor: AnilistInterceptor) {
|
||||||
put("completedAt", createDate(track.finished_reading_date))
|
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()
|
.awaitSuccess()
|
||||||
track
|
track
|
||||||
}
|
}
|
||||||
|
|
@ -119,9 +119,9 @@ class AnilistApi(val client: OkHttpClient, interceptor: AnilistInterceptor) {
|
||||||
withIOContext {
|
withIOContext {
|
||||||
val query = """
|
val query = """
|
||||||
|mutation DeleteManga(${'$'}listId: Int) {
|
|mutation DeleteManga(${'$'}listId: Int) {
|
||||||
|DeleteMediaListEntry(id: ${'$'}listId) {
|
|DeleteMediaListEntry(id: ${'$'}listId) {
|
||||||
|deleted
|
|deleted
|
||||||
|}
|
|}
|
||||||
|}
|
|}
|
||||||
|
|
|
|
||||||
""".trimMargin()
|
""".trimMargin()
|
||||||
|
|
@ -131,7 +131,7 @@ class AnilistApi(val client: OkHttpClient, interceptor: AnilistInterceptor) {
|
||||||
put("listId", track.libraryId)
|
put("listId", track.libraryId)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
authClient.newCall(POST(apiUrl, body = payload.toString().toRequestBody(jsonMime)))
|
authClient.newCall(POST(API_URL, body = payload.toString().toRequestBody(jsonMime)))
|
||||||
.awaitSuccess()
|
.awaitSuccess()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -172,7 +172,7 @@ class AnilistApi(val client: OkHttpClient, interceptor: AnilistInterceptor) {
|
||||||
with(json) {
|
with(json) {
|
||||||
authClient.newCall(
|
authClient.newCall(
|
||||||
POST(
|
POST(
|
||||||
apiUrl,
|
API_URL,
|
||||||
body = payload.toString().toRequestBody(jsonMime),
|
body = payload.toString().toRequestBody(jsonMime),
|
||||||
),
|
),
|
||||||
)
|
)
|
||||||
|
|
@ -242,7 +242,7 @@ class AnilistApi(val client: OkHttpClient, interceptor: AnilistInterceptor) {
|
||||||
with(json) {
|
with(json) {
|
||||||
authClient.newCall(
|
authClient.newCall(
|
||||||
POST(
|
POST(
|
||||||
apiUrl,
|
API_URL,
|
||||||
body = payload.toString().toRequestBody(jsonMime),
|
body = payload.toString().toRequestBody(jsonMime),
|
||||||
),
|
),
|
||||||
)
|
)
|
||||||
|
|
@ -286,7 +286,7 @@ class AnilistApi(val client: OkHttpClient, interceptor: AnilistInterceptor) {
|
||||||
with(json) {
|
with(json) {
|
||||||
authClient.newCall(
|
authClient.newCall(
|
||||||
POST(
|
POST(
|
||||||
apiUrl,
|
API_URL,
|
||||||
body = payload.toString().toRequestBody(jsonMime),
|
body = payload.toString().toRequestBody(jsonMime),
|
||||||
),
|
),
|
||||||
)
|
)
|
||||||
|
|
@ -365,17 +365,17 @@ class AnilistApi(val client: OkHttpClient, interceptor: AnilistInterceptor) {
|
||||||
|
|
||||||
companion object {
|
companion object {
|
||||||
// Registered under KMK's MAL account
|
// Registered under KMK's MAL account
|
||||||
private const val clientId = "16801"
|
private const val CLIENT_ID = "16801"
|
||||||
private const val apiUrl = "https://graphql.anilist.co/"
|
private const val API_URL = "https://graphql.anilist.co/"
|
||||||
private const val baseUrl = "https://anilist.co/api/v2/"
|
private const val BASE_URL = "https://anilist.co/api/v2/"
|
||||||
private const val baseMangaUrl = "https://anilist.co/manga/"
|
private const val BASE_MANGA_URL = "https://anilist.co/manga/"
|
||||||
|
|
||||||
fun mangaUrl(mediaId: Long): String {
|
fun mangaUrl(mediaId: Long): String {
|
||||||
return baseMangaUrl + mediaId
|
return BASE_MANGA_URL + mediaId
|
||||||
}
|
}
|
||||||
|
|
||||||
fun authUrl(): Uri = "${baseUrl}oauth/authorize".toUri().buildUpon()
|
fun authUrl(): Uri = "${BASE_URL}oauth/authorize".toUri().buildUpon()
|
||||||
.appendQueryParameter("client_id", clientId)
|
.appendQueryParameter("client_id", CLIENT_ID)
|
||||||
.appendQueryParameter("response_type", "token")
|
.appendQueryParameter("response_type", "token")
|
||||||
.build()
|
.build()
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -42,7 +42,7 @@ class BangumiApi(
|
||||||
.add("rating", track.score.toInt().toString())
|
.add("rating", track.score.toInt().toString())
|
||||||
.add("status", track.toBangumiStatus())
|
.add("status", track.toBangumiStatus())
|
||||||
.build()
|
.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()
|
.awaitSuccess()
|
||||||
track
|
track
|
||||||
}
|
}
|
||||||
|
|
@ -55,7 +55,7 @@ class BangumiApi(
|
||||||
.add("rating", track.score.toInt().toString())
|
.add("rating", track.score.toInt().toString())
|
||||||
.add("status", track.toBangumiStatus())
|
.add("status", track.toBangumiStatus())
|
||||||
.build()
|
.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()
|
.awaitSuccess()
|
||||||
|
|
||||||
// chapter update
|
// chapter update
|
||||||
|
|
@ -64,7 +64,7 @@ class BangumiApi(
|
||||||
.build()
|
.build()
|
||||||
authClient.newCall(
|
authClient.newCall(
|
||||||
POST(
|
POST(
|
||||||
"$apiUrl/subject/${track.remote_id}/update/watched_eps",
|
"$API_URL/subject/${track.remote_id}/update/watched_eps",
|
||||||
body = body,
|
body = body,
|
||||||
),
|
),
|
||||||
).awaitSuccess()
|
).awaitSuccess()
|
||||||
|
|
@ -75,7 +75,7 @@ class BangumiApi(
|
||||||
|
|
||||||
suspend fun search(search: String): List<TrackSearch> {
|
suspend fun search(search: String): List<TrackSearch> {
|
||||||
return withIOContext {
|
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()
|
.toUri()
|
||||||
.buildUpon()
|
.buildUpon()
|
||||||
.appendQueryParameter("max_results", "20")
|
.appendQueryParameter("max_results", "20")
|
||||||
|
|
@ -124,7 +124,7 @@ class BangumiApi(
|
||||||
suspend fun findLibManga(track: Track): Track? {
|
suspend fun findLibManga(track: Track): Track? {
|
||||||
return withIOContext {
|
return withIOContext {
|
||||||
with(json) {
|
with(json) {
|
||||||
authClient.newCall(GET("$apiUrl/subject/${track.remote_id}"))
|
authClient.newCall(GET("$API_URL/subject/${track.remote_id}"))
|
||||||
.awaitSuccess()
|
.awaitSuccess()
|
||||||
.parseAs<JsonObject>()
|
.parseAs<JsonObject>()
|
||||||
.let { jsonToSearch(it) }
|
.let { jsonToSearch(it) }
|
||||||
|
|
@ -134,7 +134,7 @@ class BangumiApi(
|
||||||
|
|
||||||
suspend fun statusLibManga(track: Track): Track? {
|
suspend fun statusLibManga(track: Track): Track? {
|
||||||
return withIOContext {
|
return withIOContext {
|
||||||
val urlUserRead = "$apiUrl/collection/${track.remote_id}"
|
val urlUserRead = "$API_URL/collection/${track.remote_id}"
|
||||||
val requestUserRead = Request.Builder()
|
val requestUserRead = Request.Builder()
|
||||||
.url(urlUserRead)
|
.url(urlUserRead)
|
||||||
.cacheControl(CacheControl.FORCE_NETWORK)
|
.cacheControl(CacheControl.FORCE_NETWORK)
|
||||||
|
|
@ -171,41 +171,41 @@ class BangumiApi(
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun accessTokenRequest(code: String) = POST(
|
private fun accessTokenRequest(code: String) = POST(
|
||||||
oauthUrl,
|
OAUTH_URL,
|
||||||
body = FormBody.Builder()
|
body = FormBody.Builder()
|
||||||
.add("grant_type", "authorization_code")
|
.add("grant_type", "authorization_code")
|
||||||
.add("client_id", clientId)
|
.add("client_id", CLIENT_ID)
|
||||||
.add("client_secret", clientSecret)
|
.add("client_secret", CLIENT_SECRET)
|
||||||
.add("code", code)
|
.add("code", code)
|
||||||
.add("redirect_uri", redirectUrl)
|
.add("redirect_uri", REDIRECT_URL)
|
||||||
.build(),
|
.build(),
|
||||||
)
|
)
|
||||||
|
|
||||||
companion object {
|
companion object {
|
||||||
private const val clientId = "bgm31586666817a5d03b"
|
private const val CLIENT_ID = "bgm31586666817a5d03b"
|
||||||
private const val clientSecret = "3dad27cf8edcac6f55361d7971d219e1"
|
private const val CLIENT_SECRET = "3dad27cf8edcac6f55361d7971d219e1"
|
||||||
|
|
||||||
private const val apiUrl = "https://api.bgm.tv"
|
private const val API_URL = "https://api.bgm.tv"
|
||||||
private const val oauthUrl = "https://bgm.tv/oauth/access_token"
|
private const val OAUTH_URL = "https://bgm.tv/oauth/access_token"
|
||||||
private const val loginUrl = "https://bgm.tv/oauth/authorize"
|
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 =
|
fun authUrl(): Uri =
|
||||||
loginUrl.toUri().buildUpon()
|
LOGIN_URL.toUri().buildUpon()
|
||||||
.appendQueryParameter("client_id", clientId)
|
.appendQueryParameter("client_id", CLIENT_ID)
|
||||||
.appendQueryParameter("response_type", "code")
|
.appendQueryParameter("response_type", "code")
|
||||||
.appendQueryParameter("redirect_uri", redirectUrl)
|
.appendQueryParameter("redirect_uri", REDIRECT_URL)
|
||||||
.build()
|
.build()
|
||||||
|
|
||||||
fun refreshTokenRequest(token: String) = POST(
|
fun refreshTokenRequest(token: String) = POST(
|
||||||
oauthUrl,
|
OAUTH_URL,
|
||||||
body = FormBody.Builder()
|
body = FormBody.Builder()
|
||||||
.add("grant_type", "refresh_token")
|
.add("grant_type", "refresh_token")
|
||||||
.add("client_id", clientId)
|
.add("client_id", CLIENT_ID)
|
||||||
.add("client_secret", clientSecret)
|
.add("client_secret", CLIENT_SECRET)
|
||||||
.add("refresh_token", token)
|
.add("refresh_token", token)
|
||||||
.add("redirect_uri", redirectUrl)
|
.add("redirect_uri", REDIRECT_URL)
|
||||||
.build(),
|
.build(),
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -66,7 +66,7 @@ class KitsuApi(private val client: OkHttpClient, interceptor: KitsuInterceptor)
|
||||||
with(json) {
|
with(json) {
|
||||||
authClient.newCall(
|
authClient.newCall(
|
||||||
POST(
|
POST(
|
||||||
"${baseUrl}library-entries",
|
"${BASE_URL}library-entries",
|
||||||
headers = headersOf(
|
headers = headersOf(
|
||||||
"Content-Type",
|
"Content-Type",
|
||||||
"application/vnd.api+json",
|
"application/vnd.api+json",
|
||||||
|
|
@ -104,7 +104,7 @@ class KitsuApi(private val client: OkHttpClient, interceptor: KitsuInterceptor)
|
||||||
with(json) {
|
with(json) {
|
||||||
authClient.newCall(
|
authClient.newCall(
|
||||||
Request.Builder()
|
Request.Builder()
|
||||||
.url("${baseUrl}library-entries/${track.remote_id}")
|
.url("${BASE_URL}library-entries/${track.remote_id}")
|
||||||
.headers(
|
.headers(
|
||||||
headersOf(
|
headersOf(
|
||||||
"Content-Type",
|
"Content-Type",
|
||||||
|
|
@ -130,7 +130,7 @@ class KitsuApi(private val client: OkHttpClient, interceptor: KitsuInterceptor)
|
||||||
authClient
|
authClient
|
||||||
.newCall(
|
.newCall(
|
||||||
DELETE(
|
DELETE(
|
||||||
"${baseUrl}library-entries/${track.remoteId}",
|
"${BASE_URL}library-entries/${track.remoteId}",
|
||||||
headers = headersOf(
|
headers = headersOf(
|
||||||
"Content-Type",
|
"Content-Type",
|
||||||
"application/vnd.api+json",
|
"application/vnd.api+json",
|
||||||
|
|
@ -143,7 +143,7 @@ class KitsuApi(private val client: OkHttpClient, interceptor: KitsuInterceptor)
|
||||||
suspend fun search(query: String): List<TrackSearch> {
|
suspend fun search(query: String): List<TrackSearch> {
|
||||||
return withIOContext {
|
return withIOContext {
|
||||||
with(json) {
|
with(json) {
|
||||||
authClient.newCall(GET(algoliaKeyUrl))
|
authClient.newCall(GET(ALGOLIA_KEY_URL))
|
||||||
.awaitSuccess()
|
.awaitSuccess()
|
||||||
.parseAs<JsonObject>()
|
.parseAs<JsonObject>()
|
||||||
.let {
|
.let {
|
||||||
|
|
@ -157,16 +157,16 @@ class KitsuApi(private val client: OkHttpClient, interceptor: KitsuInterceptor)
|
||||||
private suspend fun algoliaSearch(key: String, query: String): List<TrackSearch> {
|
private suspend fun algoliaSearch(key: String, query: String): List<TrackSearch> {
|
||||||
return withIOContext {
|
return withIOContext {
|
||||||
val jsonObject = buildJsonObject {
|
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) {
|
with(json) {
|
||||||
client.newCall(
|
client.newCall(
|
||||||
POST(
|
POST(
|
||||||
algoliaUrl,
|
ALGOLIA_URL,
|
||||||
headers = headersOf(
|
headers = headersOf(
|
||||||
"X-Algolia-Application-Id",
|
"X-Algolia-Application-Id",
|
||||||
algoliaAppId,
|
ALGOLIA_APP_ID,
|
||||||
"X-Algolia-API-Key",
|
"X-Algolia-API-Key",
|
||||||
key,
|
key,
|
||||||
),
|
),
|
||||||
|
|
@ -187,7 +187,7 @@ class KitsuApi(private val client: OkHttpClient, interceptor: KitsuInterceptor)
|
||||||
|
|
||||||
suspend fun findLibManga(track: Track, userId: String): Track? {
|
suspend fun findLibManga(track: Track, userId: String): Track? {
|
||||||
return withIOContext {
|
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")
|
.encodedQuery("filter[manga_id]=${track.remote_id}&filter[user_id]=$userId")
|
||||||
.appendQueryParameter("include", "manga")
|
.appendQueryParameter("include", "manga")
|
||||||
.build()
|
.build()
|
||||||
|
|
@ -210,7 +210,7 @@ class KitsuApi(private val client: OkHttpClient, interceptor: KitsuInterceptor)
|
||||||
|
|
||||||
suspend fun getLibManga(track: Track): Track {
|
suspend fun getLibManga(track: Track): Track {
|
||||||
return withIOContext {
|
return withIOContext {
|
||||||
val url = "${baseUrl}library-entries".toUri().buildUpon()
|
val url = "${BASE_URL}library-entries".toUri().buildUpon()
|
||||||
.encodedQuery("filter[id]=${track.remote_id}")
|
.encodedQuery("filter[id]=${track.remote_id}")
|
||||||
.appendQueryParameter("include", "manga")
|
.appendQueryParameter("include", "manga")
|
||||||
.build()
|
.build()
|
||||||
|
|
@ -237,11 +237,11 @@ class KitsuApi(private val client: OkHttpClient, interceptor: KitsuInterceptor)
|
||||||
.add("username", username)
|
.add("username", username)
|
||||||
.add("password", password)
|
.add("password", password)
|
||||||
.add("grant_type", "password")
|
.add("grant_type", "password")
|
||||||
.add("client_id", clientId)
|
.add("client_id", CLIENT_ID)
|
||||||
.add("client_secret", clientSecret)
|
.add("client_secret", CLIENT_SECRET)
|
||||||
.build()
|
.build()
|
||||||
with(json) {
|
with(json) {
|
||||||
client.newCall(POST(loginUrl, body = formBody))
|
client.newCall(POST(LOGIN_URL, body = formBody))
|
||||||
.awaitSuccess()
|
.awaitSuccess()
|
||||||
.parseAs()
|
.parseAs()
|
||||||
}
|
}
|
||||||
|
|
@ -250,7 +250,7 @@ class KitsuApi(private val client: OkHttpClient, interceptor: KitsuInterceptor)
|
||||||
|
|
||||||
suspend fun getCurrentUser(): String {
|
suspend fun getCurrentUser(): String {
|
||||||
return withIOContext {
|
return withIOContext {
|
||||||
val url = "${baseUrl}users".toUri().buildUpon()
|
val url = "${BASE_URL}users".toUri().buildUpon()
|
||||||
.encodedQuery("filter[self]=true")
|
.encodedQuery("filter[self]=true")
|
||||||
.build()
|
.build()
|
||||||
with(json) {
|
with(json) {
|
||||||
|
|
@ -265,35 +265,31 @@ class KitsuApi(private val client: OkHttpClient, interceptor: KitsuInterceptor)
|
||||||
}
|
}
|
||||||
|
|
||||||
companion object {
|
companion object {
|
||||||
private const val clientId =
|
private const val CLIENT_ID = "dd031b32d2f56c990b1425efe6c42ad847e7fe3ab46bf1299f05ecd856bdb7dd"
|
||||||
"dd031b32d2f56c990b1425efe6c42ad847e7fe3ab46bf1299f05ecd856bdb7dd"
|
private const val CLIENT_SECRET = "54d7307928f63414defd96399fc31ba847961ceaecef3a5fd93144e960c0e151"
|
||||||
private const val clientSecret =
|
|
||||||
"54d7307928f63414defd96399fc31ba847961ceaecef3a5fd93144e960c0e151"
|
|
||||||
|
|
||||||
private const val baseUrl = "https://kitsu.app/api/edge/"
|
private const val BASE_URL = "https://kitsu.app/api/edge/"
|
||||||
private const val loginUrl = "https://kitsu.app/api/oauth/token"
|
private const val LOGIN_URL = "https://kitsu.app/api/oauth/token"
|
||||||
private const val baseMangaUrl = "https://kitsu.app/manga/"
|
private const val BASE_MANGA_URL = "https://kitsu.app/manga/"
|
||||||
private const val algoliaKeyUrl = "https://kitsu.app/api/edge/algolia-keys/media/"
|
private const val ALGOLIA_KEY_URL = "https://kitsu.app/api/edge/algolia-keys/media/"
|
||||||
|
|
||||||
private const val algoliaUrl =
|
private const val ALGOLIA_APP_ID = "AWQO5J657S"
|
||||||
"https://AWQO5J657S-dsn.algolia.net/1/indexes/production_media/query/"
|
private const val ALGOLIA_URL = "https://$ALGOLIA_APP_ID-dsn.algolia.net/1/indexes/production_media/query/"
|
||||||
private const val algoliaAppId = "AWQO5J657S"
|
private const val ALGOLIA_FILTER = "&facetFilters=%5B%22kind%3Amanga%22%5D&attributesToRetrieve=" +
|
||||||
private const val algoliaFilter =
|
"%5B%22synopsis%22%2C%22averageRating%22%2C%22canonicalTitle%22%2C%22chapterCount%22%2C%22" +
|
||||||
"&facetFilters=%5B%22kind%3Amanga%22%5D&attributesToRetrieve=" +
|
"posterImage%22%2C%22startDate%22%2C%22subtype%22%2C%22endDate%22%2C%20%22id%22%5D"
|
||||||
"%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 {
|
fun mangaUrl(remoteId: Long): String {
|
||||||
return baseMangaUrl + remoteId
|
return BASE_MANGA_URL + remoteId
|
||||||
}
|
}
|
||||||
|
|
||||||
fun refreshTokenRequest(token: String) = POST(
|
fun refreshTokenRequest(token: String) = POST(
|
||||||
loginUrl,
|
LOGIN_URL,
|
||||||
body = FormBody.Builder()
|
body = FormBody.Builder()
|
||||||
.add("grant_type", "refresh_token")
|
.add("grant_type", "refresh_token")
|
||||||
.add("refresh_token", token)
|
.add("refresh_token", token)
|
||||||
.add("client_id", clientId)
|
.add("client_id", CLIENT_ID)
|
||||||
.add("client_secret", clientSecret)
|
.add("client_secret", CLIENT_SECRET)
|
||||||
.build(),
|
.build(),
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -6,8 +6,8 @@ import java.util.Locale
|
||||||
|
|
||||||
object KitsuDateHelper {
|
object KitsuDateHelper {
|
||||||
|
|
||||||
private const val pattern = "yyyy-MM-dd'T'HH:mm:ss.SSS'Z'"
|
private const val PATTERN = "yyyy-MM-dd'T'HH:mm:ss.SSS'Z'"
|
||||||
private val formatter = SimpleDateFormat(pattern, Locale.ENGLISH)
|
private val formatter = SimpleDateFormat(PATTERN, Locale.ENGLISH)
|
||||||
|
|
||||||
fun convert(dateValue: Long): String? {
|
fun convert(dateValue: Long): String? {
|
||||||
if (dateValue == 0L) return null
|
if (dateValue == 0L) return null
|
||||||
|
|
|
||||||
|
|
@ -1,3 +1,5 @@
|
||||||
|
@file:Suppress("PropertyName", "ktlint:standard:property-naming")
|
||||||
|
|
||||||
package eu.kanade.tachiyomi.data.track.model
|
package eu.kanade.tachiyomi.data.track.model
|
||||||
|
|
||||||
import eu.kanade.tachiyomi.data.database.models.Track
|
import eu.kanade.tachiyomi.data.database.models.Track
|
||||||
|
|
|
||||||
|
|
@ -54,7 +54,7 @@ class ShikimoriApi(
|
||||||
}
|
}
|
||||||
authClient.newCall(
|
authClient.newCall(
|
||||||
POST(
|
POST(
|
||||||
"$apiUrl/v2/user_rates",
|
"$API_URL/v2/user_rates",
|
||||||
body = payload.toString().toRequestBody(jsonMime),
|
body = payload.toString().toRequestBody(jsonMime),
|
||||||
),
|
),
|
||||||
).awaitSuccess()
|
).awaitSuccess()
|
||||||
|
|
@ -72,14 +72,14 @@ class ShikimoriApi(
|
||||||
suspend fun deleteLibManga(track: DomainTrack) {
|
suspend fun deleteLibManga(track: DomainTrack) {
|
||||||
withIOContext {
|
withIOContext {
|
||||||
authClient
|
authClient
|
||||||
.newCall(DELETE("$apiUrl/v2/user_rates/${track.libraryId}"))
|
.newCall(DELETE("$API_URL/v2/user_rates/${track.libraryId}"))
|
||||||
.awaitSuccess()
|
.awaitSuccess()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
suspend fun search(search: String): List<TrackSearch> {
|
suspend fun search(search: String): List<TrackSearch> {
|
||||||
return withIOContext {
|
return withIOContext {
|
||||||
val url = "$apiUrl/mangas".toUri().buildUpon()
|
val url = "$API_URL/mangas".toUri().buildUpon()
|
||||||
.appendQueryParameter("order", "popularity")
|
.appendQueryParameter("order", "popularity")
|
||||||
.appendQueryParameter("search", search)
|
.appendQueryParameter("search", search)
|
||||||
.appendQueryParameter("limit", "20")
|
.appendQueryParameter("limit", "20")
|
||||||
|
|
@ -102,10 +102,10 @@ class ShikimoriApi(
|
||||||
remote_id = obj["id"]!!.jsonPrimitive.long
|
remote_id = obj["id"]!!.jsonPrimitive.long
|
||||||
title = obj["name"]!!.jsonPrimitive.content
|
title = obj["name"]!!.jsonPrimitive.content
|
||||||
total_chapters = obj["chapters"]!!.jsonPrimitive.long
|
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 = ""
|
summary = ""
|
||||||
score = obj["score"]!!.jsonPrimitive.double
|
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_status = obj["status"]!!.jsonPrimitive.content
|
||||||
publishing_type = obj["kind"]!!.jsonPrimitive.content
|
publishing_type = obj["kind"]!!.jsonPrimitive.content
|
||||||
start_date = obj["aired_on"]!!.jsonPrimitive.contentOrNull ?: ""
|
start_date = obj["aired_on"]!!.jsonPrimitive.contentOrNull ?: ""
|
||||||
|
|
@ -121,13 +121,13 @@ class ShikimoriApi(
|
||||||
last_chapter_read = obj["chapters"]!!.jsonPrimitive.double
|
last_chapter_read = obj["chapters"]!!.jsonPrimitive.double
|
||||||
score = obj["score"]!!.jsonPrimitive.int.toDouble()
|
score = obj["score"]!!.jsonPrimitive.int.toDouble()
|
||||||
status = toTrackStatus(obj["status"]!!.jsonPrimitive.content)
|
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? {
|
suspend fun findLibManga(track: Track, userId: String): Track? {
|
||||||
return withIOContext {
|
return withIOContext {
|
||||||
val urlMangas = "$apiUrl/mangas".toUri().buildUpon()
|
val urlMangas = "$API_URL/mangas".toUri().buildUpon()
|
||||||
.appendPath(track.remote_id.toString())
|
.appendPath(track.remote_id.toString())
|
||||||
.build()
|
.build()
|
||||||
val mangas = with(json) {
|
val mangas = with(json) {
|
||||||
|
|
@ -136,7 +136,7 @@ class ShikimoriApi(
|
||||||
.parseAs<JsonObject>()
|
.parseAs<JsonObject>()
|
||||||
}
|
}
|
||||||
|
|
||||||
val url = "$apiUrl/v2/user_rates".toUri().buildUpon()
|
val url = "$API_URL/v2/user_rates".toUri().buildUpon()
|
||||||
.appendQueryParameter("user_id", userId)
|
.appendQueryParameter("user_id", userId)
|
||||||
.appendQueryParameter("target_id", track.remote_id.toString())
|
.appendQueryParameter("target_id", track.remote_id.toString())
|
||||||
.appendQueryParameter("target_type", "Manga")
|
.appendQueryParameter("target_type", "Manga")
|
||||||
|
|
@ -160,7 +160,7 @@ class ShikimoriApi(
|
||||||
|
|
||||||
suspend fun getCurrentUser(): Int {
|
suspend fun getCurrentUser(): Int {
|
||||||
return with(json) {
|
return with(json) {
|
||||||
authClient.newCall(GET("$apiUrl/users/whoami"))
|
authClient.newCall(GET("$API_URL/users/whoami"))
|
||||||
.awaitSuccess()
|
.awaitSuccess()
|
||||||
.parseAs<JsonObject>()
|
.parseAs<JsonObject>()
|
||||||
.let {
|
.let {
|
||||||
|
|
@ -180,39 +180,39 @@ class ShikimoriApi(
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun accessTokenRequest(code: String) = POST(
|
private fun accessTokenRequest(code: String) = POST(
|
||||||
oauthUrl,
|
OAUTH_URL,
|
||||||
body = FormBody.Builder()
|
body = FormBody.Builder()
|
||||||
.add("grant_type", "authorization_code")
|
.add("grant_type", "authorization_code")
|
||||||
.add("client_id", clientId)
|
.add("client_id", CLIENT_ID)
|
||||||
.add("client_secret", clientSecret)
|
.add("client_secret", CLIENT_SECRET)
|
||||||
.add("code", code)
|
.add("code", code)
|
||||||
.add("redirect_uri", redirectUrl)
|
.add("redirect_uri", REDIRECT_URL)
|
||||||
.build(),
|
.build(),
|
||||||
)
|
)
|
||||||
|
|
||||||
companion object {
|
companion object {
|
||||||
private const val clientId = "hst3O_VlZ0HrrXcnZAd6m-SCIc1_mv5cQV-3nQCdJ0E"
|
private const val CLIENT_ID = "hst3O_VlZ0HrrXcnZAd6m-SCIc1_mv5cQV-3nQCdJ0E"
|
||||||
private const val clientSecret = "n1Pn9AIKvUhDzjehfPt_5nk7xbr4wSnas6djggw_AjE"
|
private const val CLIENT_SECRET = "n1Pn9AIKvUhDzjehfPt_5nk7xbr4wSnas6djggw_AjE"
|
||||||
|
|
||||||
private const val baseUrl = "https://shikimori.one"
|
private const val BASE_URL = "https://shikimori.one"
|
||||||
private const val apiUrl = "$baseUrl/api"
|
private const val API_URL = "$BASE_URL/api"
|
||||||
private const val oauthUrl = "$baseUrl/oauth/token"
|
private const val OAUTH_URL = "$BASE_URL/oauth/token"
|
||||||
private const val loginUrl = "$baseUrl/oauth/authorize"
|
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()
|
fun authUrl(): Uri = LOGIN_URL.toUri().buildUpon()
|
||||||
.appendQueryParameter("client_id", clientId)
|
.appendQueryParameter("client_id", CLIENT_ID)
|
||||||
.appendQueryParameter("redirect_uri", redirectUrl)
|
.appendQueryParameter("redirect_uri", REDIRECT_URL)
|
||||||
.appendQueryParameter("response_type", "code")
|
.appendQueryParameter("response_type", "code")
|
||||||
.build()
|
.build()
|
||||||
|
|
||||||
fun refreshTokenRequest(token: String) = POST(
|
fun refreshTokenRequest(token: String) = POST(
|
||||||
oauthUrl,
|
OAUTH_URL,
|
||||||
body = FormBody.Builder()
|
body = FormBody.Builder()
|
||||||
.add("grant_type", "refresh_token")
|
.add("grant_type", "refresh_token")
|
||||||
.add("client_id", clientId)
|
.add("client_id", CLIENT_ID)
|
||||||
.add("client_secret", clientSecret)
|
.add("client_secret", CLIENT_SECRET)
|
||||||
.add("refresh_token", token)
|
.add("refresh_token", token)
|
||||||
.build(),
|
.build(),
|
||||||
)
|
)
|
||||||
|
|
|
||||||
|
|
@ -69,17 +69,17 @@ class ExtensionManager(
|
||||||
|
|
||||||
private val iconMap = mutableMapOf<String, Drawable>()
|
private val iconMap = mutableMapOf<String, Drawable>()
|
||||||
|
|
||||||
private val _installedExtensionsMapFlow = MutableStateFlow(emptyMap<String, Extension.Installed>())
|
private val installedExtensionMapFlow = MutableStateFlow(emptyMap<String, Extension.Installed>())
|
||||||
val installedExtensionsFlow = _installedExtensionsMapFlow.mapExtensions(scope)
|
val installedExtensionsFlow = installedExtensionMapFlow.mapExtensions(scope)
|
||||||
|
|
||||||
private val _availableExtensionsMapFlow = MutableStateFlow(emptyMap<String, Extension.Available>())
|
private val availableExtensionMapFlow = MutableStateFlow(emptyMap<String, Extension.Available>())
|
||||||
// SY -->
|
// SY -->
|
||||||
val availableExtensionsFlow = _availableExtensionsMapFlow.map { it.filterNotBlacklisted().values.toList() }
|
val availableExtensionsFlow = availableExtensionMapFlow.map { it.filterNotBlacklisted().values.toList() }
|
||||||
.stateIn(scope, SharingStarted.Lazily, _availableExtensionsMapFlow.value.values.toList())
|
.stateIn(scope, SharingStarted.Lazily, availableExtensionMapFlow.value.values.toList())
|
||||||
// SY <--
|
// SY <--
|
||||||
|
|
||||||
private val _untrustedExtensionsMapFlow = MutableStateFlow(emptyMap<String, Extension.Untrusted>())
|
private val untrustedExtensionMapFlow = MutableStateFlow(emptyMap<String, Extension.Untrusted>())
|
||||||
val untrustedExtensionsFlow = _untrustedExtensionsMapFlow.mapExtensions(scope)
|
val untrustedExtensionsFlow = untrustedExtensionMapFlow.mapExtensions(scope)
|
||||||
|
|
||||||
init {
|
init {
|
||||||
initExtensions()
|
initExtensions()
|
||||||
|
|
@ -89,7 +89,7 @@ class ExtensionManager(
|
||||||
private var subLanguagesEnabledOnFirstRun = preferences.enabledLanguages().isSet()
|
private var subLanguagesEnabledOnFirstRun = preferences.enabledLanguages().isSet()
|
||||||
|
|
||||||
fun getAppIconForSource(sourceId: Long): Drawable? {
|
fun getAppIconForSource(sourceId: Long): Drawable? {
|
||||||
val pkgName = _installedExtensionsMapFlow.value.values
|
val pkgName = installedExtensionMapFlow.value.values
|
||||||
.find { ext ->
|
.find { ext ->
|
||||||
ext.sources.any { it.id == sourceId }
|
ext.sources.any { it.id == sourceId }
|
||||||
}
|
}
|
||||||
|
|
@ -128,11 +128,11 @@ class ExtensionManager(
|
||||||
private fun initExtensions() {
|
private fun initExtensions() {
|
||||||
val extensions = ExtensionLoader.loadExtensions(context)
|
val extensions = ExtensionLoader.loadExtensions(context)
|
||||||
|
|
||||||
_installedExtensionsMapFlow.value = extensions
|
installedExtensionMapFlow.value = extensions
|
||||||
.filterIsInstance<LoadResult.Success>()
|
.filterIsInstance<LoadResult.Success>()
|
||||||
.associate { it.extension.pkgName to it.extension }
|
.associate { it.extension.pkgName to it.extension }
|
||||||
|
|
||||||
_untrustedExtensionsMapFlow.value = extensions
|
untrustedExtensionMapFlow.value = extensions
|
||||||
.filterIsInstance<LoadResult.Untrusted>()
|
.filterIsInstance<LoadResult.Untrusted>()
|
||||||
.associate { it.extension.pkgName to it.extension }
|
.associate { it.extension.pkgName to it.extension }
|
||||||
// SY -->
|
// SY -->
|
||||||
|
|
@ -159,7 +159,7 @@ class ExtensionManager(
|
||||||
// EXH <--
|
// EXH <--
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Finds the available extensions in the [api] and updates [_availableExtensionsMapFlow].
|
* Finds the available extensions in the [api] and updates [availableExtensionMapFlow].
|
||||||
*/
|
*/
|
||||||
suspend fun findAvailableExtensions() {
|
suspend fun findAvailableExtensions() {
|
||||||
val extensions: List<Extension.Available> = try {
|
val extensions: List<Extension.Available> = try {
|
||||||
|
|
@ -172,7 +172,7 @@ class ExtensionManager(
|
||||||
|
|
||||||
enableAdditionalSubLanguages(extensions)
|
enableAdditionalSubLanguages(extensions)
|
||||||
|
|
||||||
_availableExtensionsMapFlow.value = extensions.associateBy { it.pkgName }
|
availableExtensionMapFlow.value = extensions.associateBy { it.pkgName }
|
||||||
updatedInstalledExtensionsStatuses(extensions)
|
updatedInstalledExtensionsStatuses(extensions)
|
||||||
setupAvailableExtensionsSourcesDataMap(extensions)
|
setupAvailableExtensionsSourcesDataMap(extensions)
|
||||||
}
|
}
|
||||||
|
|
@ -218,7 +218,7 @@ class ExtensionManager(
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
val installedExtensionsMap = _installedExtensionsMapFlow.value.toMutableMap()
|
val installedExtensionsMap = installedExtensionMapFlow.value.toMutableMap()
|
||||||
var changed = false
|
var changed = false
|
||||||
for ((pkgName, extension) in installedExtensionsMap) {
|
for ((pkgName, extension) in installedExtensionsMap) {
|
||||||
val availableExt = availableExtensions.find { it.pkgName == pkgName }
|
val availableExt = availableExtensions.find { it.pkgName == pkgName }
|
||||||
|
|
@ -247,7 +247,7 @@ class ExtensionManager(
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (changed) {
|
if (changed) {
|
||||||
_installedExtensionsMapFlow.value = installedExtensionsMap
|
installedExtensionMapFlow.value = installedExtensionsMap
|
||||||
}
|
}
|
||||||
updatePendingUpdatesCount()
|
updatePendingUpdatesCount()
|
||||||
}
|
}
|
||||||
|
|
@ -271,7 +271,7 @@ class ExtensionManager(
|
||||||
* @param extension The extension to be updated.
|
* @param extension The extension to be updated.
|
||||||
*/
|
*/
|
||||||
fun updateExtension(extension: Extension.Installed): Flow<InstallStep> {
|
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)
|
return installExtension(availableExt)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -308,11 +308,11 @@ class ExtensionManager(
|
||||||
* @param extension the extension to trust
|
* @param extension the extension to trust
|
||||||
*/
|
*/
|
||||||
suspend fun trust(extension: Extension.Untrusted) {
|
suspend fun trust(extension: Extension.Untrusted) {
|
||||||
_untrustedExtensionsMapFlow.value[extension.pkgName] ?: return
|
untrustedExtensionMapFlow.value[extension.pkgName] ?: return
|
||||||
|
|
||||||
trustExtension.trust(extension.pkgName, extension.versionCode, extension.signatureHash)
|
trustExtension.trust(extension.pkgName, extension.versionCode, extension.signatureHash)
|
||||||
|
|
||||||
_untrustedExtensionsMapFlow.value -= extension.pkgName
|
untrustedExtensionMapFlow.value -= extension.pkgName
|
||||||
|
|
||||||
ExtensionLoader.loadExtensionFromPkgName(context, extension.pkgName)
|
ExtensionLoader.loadExtensionFromPkgName(context, extension.pkgName)
|
||||||
.let { it as? LoadResult.Success }
|
.let { it as? LoadResult.Success }
|
||||||
|
|
@ -332,7 +332,7 @@ class ExtensionManager(
|
||||||
}
|
}
|
||||||
// SY <--
|
// SY <--
|
||||||
|
|
||||||
_installedExtensionsMapFlow.value += extension
|
installedExtensionMapFlow.value += extension
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|
@ -349,7 +349,7 @@ class ExtensionManager(
|
||||||
}
|
}
|
||||||
// SY <--
|
// SY <--
|
||||||
|
|
||||||
_installedExtensionsMapFlow.value += extension
|
installedExtensionMapFlow.value += extension
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|
@ -359,8 +359,8 @@ class ExtensionManager(
|
||||||
* @param pkgName The package name of the uninstalled application.
|
* @param pkgName The package name of the uninstalled application.
|
||||||
*/
|
*/
|
||||||
private fun unregisterExtension(pkgName: String) {
|
private fun unregisterExtension(pkgName: String) {
|
||||||
_installedExtensionsMapFlow.value -= pkgName
|
installedExtensionMapFlow.value -= pkgName
|
||||||
_untrustedExtensionsMapFlow.value -= pkgName
|
untrustedExtensionMapFlow.value -= pkgName
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|
@ -379,8 +379,8 @@ class ExtensionManager(
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun onExtensionUntrusted(extension: Extension.Untrusted) {
|
override fun onExtensionUntrusted(extension: Extension.Untrusted) {
|
||||||
_installedExtensionsMapFlow.value -= extension.pkgName
|
installedExtensionMapFlow.value -= extension.pkgName
|
||||||
_untrustedExtensionsMapFlow.value += extension
|
untrustedExtensionMapFlow.value += extension
|
||||||
updatePendingUpdatesCount()
|
updatePendingUpdatesCount()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -404,14 +404,14 @@ class ExtensionManager(
|
||||||
|
|
||||||
private fun Extension.Installed.updateExists(availableExtension: Extension.Available? = null): Boolean {
|
private fun Extension.Installed.updateExists(availableExtension: Extension.Available? = null): Boolean {
|
||||||
val availableExt = availableExtension
|
val availableExt = availableExtension
|
||||||
?: _availableExtensionsMapFlow.value[pkgName]
|
?: availableExtensionMapFlow.value[pkgName]
|
||||||
?: return false
|
?: return false
|
||||||
|
|
||||||
return (availableExt.versionCode > versionCode || availableExt.libVersion > libVersion)
|
return (availableExt.versionCode > versionCode || availableExt.libVersion > libVersion)
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun updatePendingUpdatesCount() {
|
private fun updatePendingUpdatesCount() {
|
||||||
val pendingUpdateCount = _installedExtensionsMapFlow.value.values.count { it.hasUpdate }
|
val pendingUpdateCount = installedExtensionMapFlow.value.values.count { it.hasUpdate }
|
||||||
preferences.extensionUpdatesCount().set(pendingUpdateCount)
|
preferences.extensionUpdatesCount().set(pendingUpdateCount)
|
||||||
if (pendingUpdateCount == 0) {
|
if (pendingUpdateCount == 0) {
|
||||||
ExtensionUpdateNotifier(context).dismiss()
|
ExtensionUpdateNotifier(context).dismiss()
|
||||||
|
|
|
||||||
|
|
@ -1,7 +1,13 @@
|
||||||
package eu.kanade.tachiyomi.extension.model
|
package eu.kanade.tachiyomi.extension.model
|
||||||
|
|
||||||
enum class InstallStep {
|
enum class InstallStep {
|
||||||
Idle, Pending, Downloading, Installing, Installed, Error;
|
Idle,
|
||||||
|
Pending,
|
||||||
|
Downloading,
|
||||||
|
Installing,
|
||||||
|
Installed,
|
||||||
|
Error,
|
||||||
|
;
|
||||||
|
|
||||||
fun isCompleted(): Boolean {
|
fun isCompleted(): Boolean {
|
||||||
return this == Installed || this == Error || this == Idle
|
return this == Installed || this == Error || this == Idle
|
||||||
|
|
|
||||||
|
|
@ -140,7 +140,7 @@ class SecureActivityDelegateImpl : SecureActivityDelegate, DefaultLifecycleObser
|
||||||
val incognitoModeFlow = preferences.incognitoMode().changes()
|
val incognitoModeFlow = preferences.incognitoMode().changes()
|
||||||
combine(secureScreenFlow, incognitoModeFlow) { secureScreen, incognitoMode ->
|
combine(secureScreenFlow, incognitoModeFlow) { secureScreen, incognitoMode ->
|
||||||
secureScreen == SecurityPreferences.SecureScreenMode.ALWAYS ||
|
secureScreen == SecurityPreferences.SecureScreenMode.ALWAYS ||
|
||||||
secureScreen == SecurityPreferences.SecureScreenMode.INCOGNITO && incognitoMode
|
(secureScreen == SecurityPreferences.SecureScreenMode.INCOGNITO && incognitoMode)
|
||||||
}
|
}
|
||||||
.onEach(activity.window::setSecureScreen)
|
.onEach(activity.window::setSecureScreen)
|
||||||
.launchIn(activity.lifecycleScope)
|
.launchIn(activity.lifecycleScope)
|
||||||
|
|
|
||||||
|
|
@ -41,7 +41,7 @@ class ExtensionsScreenModel(
|
||||||
private val getExtensions: GetExtensionsByType = Injekt.get(),
|
private val getExtensions: GetExtensionsByType = Injekt.get(),
|
||||||
) : StateScreenModel<ExtensionsScreenModel.State>(State()) {
|
) : StateScreenModel<ExtensionsScreenModel.State>(State()) {
|
||||||
|
|
||||||
private var _currentDownloads = MutableStateFlow<Map<String, InstallStep>>(hashMapOf())
|
private val currentDownloads = MutableStateFlow<Map<String, InstallStep>>(hashMapOf())
|
||||||
|
|
||||||
init {
|
init {
|
||||||
val context = Injekt.get<Application>()
|
val context = Injekt.get<Application>()
|
||||||
|
|
@ -62,14 +62,20 @@ class ExtensionsScreenModel(
|
||||||
it.name.contains(input, ignoreCase = true) ||
|
it.name.contains(input, ignoreCase = true) ||
|
||||||
it.baseUrl.contains(input, ignoreCase = true) ||
|
it.baseUrl.contains(input, ignoreCase = true) ||
|
||||||
it.id == input.toLongOrNull()
|
it.id == input.toLongOrNull()
|
||||||
} || extension.name.contains(input, ignoreCase = true)
|
} ||
|
||||||
|
extension.name.contains(input, ignoreCase = true)
|
||||||
}
|
}
|
||||||
is Extension.Installed -> {
|
is Extension.Installed -> {
|
||||||
extension.sources.any {
|
extension.sources.any {
|
||||||
it.name.contains(input, ignoreCase = true) ||
|
it.name.contains(input, ignoreCase = true) ||
|
||||||
it.id == input.toLongOrNull() ||
|
it.id == input.toLongOrNull() ||
|
||||||
if (it is HttpSource) { it.baseUrl.contains(input, ignoreCase = true) } else false
|
if (it is HttpSource) {
|
||||||
} || extension.name.contains(input, ignoreCase = true)
|
it.baseUrl.contains(input, ignoreCase = true)
|
||||||
|
} else {
|
||||||
|
false
|
||||||
|
}
|
||||||
|
} ||
|
||||||
|
extension.name.contains(input, ignoreCase = true)
|
||||||
}
|
}
|
||||||
is Extension.Untrusted -> extension.name.contains(input, ignoreCase = true)
|
is Extension.Untrusted -> extension.name.contains(input, ignoreCase = true)
|
||||||
}
|
}
|
||||||
|
|
@ -83,7 +89,7 @@ class ExtensionsScreenModel(
|
||||||
// KMK -->
|
// KMK -->
|
||||||
state.map { it.nsfwOnly }.distinctUntilChanged().debounce(SEARCH_DEBOUNCE_MILLIS),
|
state.map { it.nsfwOnly }.distinctUntilChanged().debounce(SEARCH_DEBOUNCE_MILLIS),
|
||||||
// KMK <--
|
// KMK <--
|
||||||
_currentDownloads,
|
currentDownloads,
|
||||||
getExtensions.subscribe(),
|
getExtensions.subscribe(),
|
||||||
) { query, nsfwOnly, downloads, (_updates, _installed, _available, _untrusted) ->
|
) { query, nsfwOnly, downloads, (_updates, _installed, _available, _untrusted) ->
|
||||||
val searchQuery = query ?: ""
|
val searchQuery = query ?: ""
|
||||||
|
|
@ -181,11 +187,11 @@ class ExtensionsScreenModel(
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun addDownloadState(extension: Extension, installStep: InstallStep) {
|
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) {
|
private fun removeDownloadState(extension: Extension) {
|
||||||
_currentDownloads.update { it - extension.pkgName }
|
currentDownloads.update { it - extension.pkgName }
|
||||||
}
|
}
|
||||||
|
|
||||||
private suspend fun Flow<InstallStep>.collectToInstallUpdate(extension: Extension) =
|
private suspend fun Flow<InstallStep>.collectToInstallUpdate(extension: Extension) =
|
||||||
|
|
|
||||||
|
|
@ -71,8 +71,8 @@ object HomeScreen : Screen() {
|
||||||
private val openTabEvent = Channel<Tab>()
|
private val openTabEvent = Channel<Tab>()
|
||||||
private val showBottomNavEvent = Channel<Boolean>()
|
private val showBottomNavEvent = Channel<Boolean>()
|
||||||
|
|
||||||
private const val TabFadeDuration = 200
|
private const val TAB_FADE_DURATION = 200
|
||||||
private const val TabNavigatorKey = "HomeTabs"
|
private const val TAB_NAVIGATOR_KEY = "HomeTabs"
|
||||||
|
|
||||||
private val tabs = listOf(
|
private val tabs = listOf(
|
||||||
LibraryTab,
|
LibraryTab,
|
||||||
|
|
@ -95,7 +95,7 @@ object HomeScreen : Screen() {
|
||||||
|
|
||||||
TabNavigator(
|
TabNavigator(
|
||||||
tab = LibraryTab,
|
tab = LibraryTab,
|
||||||
key = TabNavigatorKey,
|
key = TAB_NAVIGATOR_KEY,
|
||||||
) { tabNavigator ->
|
) { tabNavigator ->
|
||||||
// Provide usable navigator to content screen
|
// Provide usable navigator to content screen
|
||||||
CompositionLocalProvider(LocalNavigator provides navigator) {
|
CompositionLocalProvider(LocalNavigator provides navigator) {
|
||||||
|
|
@ -145,8 +145,11 @@ object HomeScreen : Screen() {
|
||||||
AnimatedContent(
|
AnimatedContent(
|
||||||
targetState = tabNavigator.current,
|
targetState = tabNavigator.current,
|
||||||
transitionSpec = {
|
transitionSpec = {
|
||||||
materialFadeThroughIn(initialScale = 1f, durationMillis = TabFadeDuration) togetherWith
|
materialFadeThroughIn(
|
||||||
materialFadeThroughOut(durationMillis = TabFadeDuration)
|
initialScale = 1f,
|
||||||
|
durationMillis = TAB_FADE_DURATION,
|
||||||
|
) togetherWith
|
||||||
|
materialFadeThroughOut(durationMillis = TAB_FADE_DURATION)
|
||||||
},
|
},
|
||||||
label = "tabContent",
|
label = "tabContent",
|
||||||
contentKey = { it.key }
|
contentKey = { it.key }
|
||||||
|
|
|
||||||
|
|
@ -384,8 +384,9 @@ class LibraryScreenModel(
|
||||||
// Map<MangaId, List<Track>>
|
// Map<MangaId, List<Track>>
|
||||||
trackMap: Map<Long, List<Track>>,
|
trackMap: Map<Long, List<Track>>,
|
||||||
loggedInTrackerIds: Set<Long>,
|
loggedInTrackerIds: Set<Long>,
|
||||||
/* SY --> */
|
// SY -->
|
||||||
groupSort: LibrarySort? = null, /* SY <-- */
|
groupSort: LibrarySort? = null,
|
||||||
|
// SY <--
|
||||||
): LibraryMap {
|
): LibraryMap {
|
||||||
// SY -->
|
// SY -->
|
||||||
val listOfTags by lazy {
|
val listOfTags by lazy {
|
||||||
|
|
|
||||||
|
|
@ -34,7 +34,7 @@ class LibrarySettingsScreenModel(
|
||||||
.stateIn(
|
.stateIn(
|
||||||
scope = screenModelScope,
|
scope = screenModelScope,
|
||||||
started = SharingStarted.WhileSubscribed(5.seconds.inWholeMilliseconds),
|
started = SharingStarted.WhileSubscribed(5.seconds.inWholeMilliseconds),
|
||||||
initialValue = trackerManager.loggedInTrackers()
|
initialValue = trackerManager.loggedInTrackers(),
|
||||||
)
|
)
|
||||||
|
|
||||||
// SY -->
|
// SY -->
|
||||||
|
|
|
||||||
|
|
@ -109,8 +109,8 @@ private class MoreScreenModel(
|
||||||
val showNavHistory by uiPreferences.showNavHistory().asState(screenModelScope)
|
val showNavHistory by uiPreferences.showNavHistory().asState(screenModelScope)
|
||||||
// SY <--
|
// SY <--
|
||||||
|
|
||||||
private var _state: MutableStateFlow<DownloadQueueState> = MutableStateFlow(DownloadQueueState.Stopped)
|
private var _downloadQueueState: MutableStateFlow<DownloadQueueState> = MutableStateFlow(DownloadQueueState.Stopped)
|
||||||
val downloadQueueState: StateFlow<DownloadQueueState> = _state.asStateFlow()
|
val downloadQueueState: StateFlow<DownloadQueueState> = _downloadQueueState.asStateFlow()
|
||||||
|
|
||||||
init {
|
init {
|
||||||
// Handle running/paused status change and queue progress updating
|
// Handle running/paused status change and queue progress updating
|
||||||
|
|
@ -121,7 +121,7 @@ private class MoreScreenModel(
|
||||||
) { isRunning, downloadQueue -> Pair(isRunning, downloadQueue.size) }
|
) { isRunning, downloadQueue -> Pair(isRunning, downloadQueue.size) }
|
||||||
.collectLatest { (isDownloading, downloadQueueSize) ->
|
.collectLatest { (isDownloading, downloadQueueSize) ->
|
||||||
val pendingDownloadExists = downloadQueueSize != 0
|
val pendingDownloadExists = downloadQueueSize != 0
|
||||||
_state.value = when {
|
_downloadQueueState.value = when {
|
||||||
!pendingDownloadExists -> DownloadQueueState.Stopped
|
!pendingDownloadExists -> DownloadQueueState.Stopped
|
||||||
!isDownloading -> DownloadQueueState.Paused(downloadQueueSize)
|
!isDownloading -> DownloadQueueState.Paused(downloadQueueSize)
|
||||||
else -> DownloadQueueState.Downloading(downloadQueueSize)
|
else -> DownloadQueueState.Downloading(downloadQueueSize)
|
||||||
|
|
|
||||||
|
|
@ -191,7 +191,7 @@ class ReaderPreferences(
|
||||||
enum class FlashColor {
|
enum class FlashColor {
|
||||||
BLACK,
|
BLACK,
|
||||||
WHITE,
|
WHITE,
|
||||||
WHITE_BLACK
|
WHITE_BLACK,
|
||||||
}
|
}
|
||||||
|
|
||||||
enum class TappingInvertMode(
|
enum class TappingInvertMode(
|
||||||
|
|
|
||||||
|
|
@ -398,7 +398,9 @@ open class ReaderPageImageView @JvmOverloads constructor(
|
||||||
)
|
)
|
||||||
|
|
||||||
enum class ZoomStartPosition {
|
enum class ZoomStartPosition {
|
||||||
LEFT, CENTER, RIGHT
|
LEFT,
|
||||||
|
CENTER,
|
||||||
|
RIGHT,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -43,15 +43,16 @@ class ReaderTransitionView @JvmOverloads constructor(
|
||||||
Data(
|
Data(
|
||||||
transition = transition,
|
transition = transition,
|
||||||
currChapterDownloaded = transition.from.pageLoader?.isLocal == true,
|
currChapterDownloaded = transition.from.pageLoader?.isLocal == true,
|
||||||
goingToChapterDownloaded = manga.isLocal() || transition.to?.chapter?.let { goingToChapter ->
|
goingToChapterDownloaded = manga.isLocal() ||
|
||||||
downloadManager.isChapterDownloaded(
|
transition.to?.chapter?.let { goingToChapter ->
|
||||||
chapterName = goingToChapter.name,
|
downloadManager.isChapterDownloaded(
|
||||||
chapterScanlator = goingToChapter.scanlator,
|
chapterName = goingToChapter.name,
|
||||||
mangaTitle = /* SY --> */ manga.ogTitle, /* SY <-- */
|
chapterScanlator = goingToChapter.scanlator,
|
||||||
sourceId = manga.source,
|
mangaTitle = /* SY --> */ manga.ogTitle, /* SY <-- */
|
||||||
skipCache = true,
|
sourceId = manga.source,
|
||||||
)
|
skipCache = true,
|
||||||
} ?: false,
|
)
|
||||||
|
} ?: false,
|
||||||
)
|
)
|
||||||
} else {
|
} else {
|
||||||
null
|
null
|
||||||
|
|
|
||||||
|
|
@ -115,7 +115,9 @@ class PagerViewerAdapter(
|
||||||
// Add next chapter transition and pages.
|
// Add next chapter transition and pages.
|
||||||
nextTransition = ChapterTransition.Next(chapters.currChapter, chapters.nextChapter)
|
nextTransition = ChapterTransition.Next(chapters.currChapter, chapters.nextChapter)
|
||||||
.also {
|
.also {
|
||||||
if (nextHasMissingChapters || forceTransition ||
|
if (
|
||||||
|
nextHasMissingChapters ||
|
||||||
|
forceTransition ||
|
||||||
chapters.nextChapter?.state !is ReaderChapter.State.Loaded
|
chapters.nextChapter?.state !is ReaderChapter.State.Loaded
|
||||||
) {
|
) {
|
||||||
newItems.add(it)
|
newItems.add(it)
|
||||||
|
|
|
||||||
|
|
@ -89,7 +89,7 @@ class WebtoonConfig(
|
||||||
readerPreferences.webtoonDisableZoomOut()
|
readerPreferences.webtoonDisableZoomOut()
|
||||||
.register(
|
.register(
|
||||||
{ zoomOutDisabled = it },
|
{ zoomOutDisabled = it },
|
||||||
{ zoomPropertyChangedListener?.invoke(it) }
|
{ zoomPropertyChangedListener?.invoke(it) },
|
||||||
)
|
)
|
||||||
|
|
||||||
readerPreferences.webtoonDoubleTapZoomEnabled()
|
readerPreferences.webtoonDoubleTapZoomEnabled()
|
||||||
|
|
|
||||||
|
|
@ -182,7 +182,11 @@ class WebtoonRecyclerView @JvmOverloads constructor(
|
||||||
|
|
||||||
setScaleRate(currentScale)
|
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
|
halfHeight = layoutParams.height / 2
|
||||||
|
|
||||||
if (currentScale != DEFAULT_RATE) {
|
if (currentScale != DEFAULT_RATE) {
|
||||||
|
|
|
||||||
|
|
@ -95,7 +95,7 @@ class WebtoonViewer(
|
||||||
.threshold
|
.threshold
|
||||||
|
|
||||||
init {
|
init {
|
||||||
recycler.setItemViewCacheSize(RecyclerViewCacheSize)
|
recycler.setItemViewCacheSize(RECYCLER_VIEW_CACHE_SIZE)
|
||||||
recycler.isVisible = false // Don't let the recycler layout yet
|
recycler.isVisible = false // Don't let the recycler layout yet
|
||||||
recycler.layoutParams = ViewGroup.LayoutParams(MATCH_PARENT, MATCH_PARENT)
|
recycler.layoutParams = ViewGroup.LayoutParams(MATCH_PARENT, MATCH_PARENT)
|
||||||
recycler.isFocusable = false
|
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
|
// 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(
|
class ChildFirstPathClassLoader(
|
||||||
dexPath: String,
|
dexPath: String,
|
||||||
librarySearchPath: String?,
|
librarySearchPath: String?,
|
||||||
parent: ClassLoader
|
parent: ClassLoader,
|
||||||
) : PathClassLoader(dexPath, librarySearchPath, parent) {
|
) : PathClassLoader(dexPath, librarySearchPath, parent) {
|
||||||
|
|
||||||
private val systemClassLoader: ClassLoader? = getSystemClassLoader()
|
private val systemClassLoader: ClassLoader? = getSystemClassLoader()
|
||||||
|
|
|
||||||
|
|
@ -9,20 +9,24 @@ import tachiyomi.core.common.util.system.logcat
|
||||||
|
|
||||||
class MigrationJobFactory(
|
class MigrationJobFactory(
|
||||||
private val migrationContext: MigrationContext,
|
private val migrationContext: MigrationContext,
|
||||||
private val scope: CoroutineScope
|
private val scope: CoroutineScope,
|
||||||
) {
|
) {
|
||||||
|
|
||||||
fun create(migrations: List<Migration>): Deferred<Boolean> = with(scope) {
|
fun create(migrations: List<Migration>): Deferred<Boolean> = with(scope) {
|
||||||
return migrations.sortedBy { it.version }
|
return migrations.sortedBy { it.version }
|
||||||
.fold(CompletableDeferred(true)) { acc: Deferred<Boolean>, migration: Migration ->
|
.fold(CompletableDeferred(true)) { acc: Deferred<Boolean>, migration: Migration ->
|
||||||
if (!migrationContext.dryrun) {
|
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) {
|
async(start = CoroutineStart.UNDISPATCHED) {
|
||||||
val prev = acc.await()
|
val prev = acc.await()
|
||||||
migration(migrationContext) || prev
|
migration(migrationContext) || prev
|
||||||
}
|
}
|
||||||
} else {
|
} 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)
|
CompletableDeferred(true)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -12,7 +12,7 @@ interface MigrationStrategy {
|
||||||
class DefaultMigrationStrategy(
|
class DefaultMigrationStrategy(
|
||||||
private val migrationJobFactory: MigrationJobFactory,
|
private val migrationJobFactory: MigrationJobFactory,
|
||||||
private val migrationCompletedListener: MigrationCompletedListener,
|
private val migrationCompletedListener: MigrationCompletedListener,
|
||||||
private val scope: CoroutineScope
|
private val scope: CoroutineScope,
|
||||||
) : MigrationStrategy {
|
) : MigrationStrategy {
|
||||||
|
|
||||||
override operator fun invoke(migrations: List<Migration>): Deferred<Boolean> = with(scope) {
|
override operator fun invoke(migrations: List<Migration>): Deferred<Boolean> = with(scope) {
|
||||||
|
|
@ -46,7 +46,7 @@ class NoopMigrationStrategy(val state: Boolean) : MigrationStrategy {
|
||||||
|
|
||||||
class VersionRangeMigrationStrategy(
|
class VersionRangeMigrationStrategy(
|
||||||
private val versions: IntRange,
|
private val versions: IntRange,
|
||||||
private val strategy: DefaultMigrationStrategy
|
private val strategy: DefaultMigrationStrategy,
|
||||||
) : MigrationStrategy {
|
) : MigrationStrategy {
|
||||||
|
|
||||||
override operator fun invoke(migrations: List<Migration>): Deferred<Boolean> {
|
override operator fun invoke(migrations: List<Migration>): Deferred<Boolean> {
|
||||||
|
|
|
||||||
|
|
@ -17,7 +17,7 @@ object Migrator {
|
||||||
new: Int,
|
new: Int,
|
||||||
migrations: List<Migration>,
|
migrations: List<Migration>,
|
||||||
dryrun: Boolean = false,
|
dryrun: Boolean = false,
|
||||||
onMigrationComplete: () -> Unit
|
onMigrationComplete: () -> Unit,
|
||||||
) {
|
) {
|
||||||
val migrationContext = MigrationContext(dryrun)
|
val migrationContext = MigrationContext(dryrun)
|
||||||
val migrationJobFactory = MigrationJobFactory(migrationContext, scope)
|
val migrationJobFactory = MigrationJobFactory(migrationContext, scope)
|
||||||
|
|
|
||||||
|
|
@ -32,7 +32,7 @@ import java.time.temporal.WeekFields
|
||||||
import java.util.Locale
|
import java.util.Locale
|
||||||
|
|
||||||
private val FontSize = 16.sp
|
private val FontSize = 16.sp
|
||||||
private const val DaysOfWeek = 7
|
private const val DAYS_OF_WEEK = 7
|
||||||
|
|
||||||
@Composable
|
@Composable
|
||||||
fun Calendar(
|
fun Calendar(
|
||||||
|
|
@ -54,7 +54,7 @@ fun Calendar(
|
||||||
modifier = Modifier
|
modifier = Modifier
|
||||||
.fillMaxWidth()
|
.fillMaxWidth()
|
||||||
.padding(vertical = MaterialTheme.padding.small)
|
.padding(vertical = MaterialTheme.padding.small)
|
||||||
.padding(start = MaterialTheme.padding.medium)
|
.padding(start = MaterialTheme.padding.medium),
|
||||||
)
|
)
|
||||||
CalendarGrid(
|
CalendarGrid(
|
||||||
selectedYearMonth = selectedYearMonth,
|
selectedYearMonth = selectedYearMonth,
|
||||||
|
|
@ -72,8 +72,8 @@ private fun CalendarGrid(
|
||||||
) {
|
) {
|
||||||
val localeFirstDayOfWeek = WeekFields.of(Locale.getDefault()).firstDayOfWeek.value
|
val localeFirstDayOfWeek = WeekFields.of(Locale.getDefault()).firstDayOfWeek.value
|
||||||
val weekDays = remember {
|
val weekDays = remember {
|
||||||
(0 until DaysOfWeek)
|
(0 until DAYS_OF_WEEK)
|
||||||
.map { DayOfWeek.of((localeFirstDayOfWeek - 1 + it) % DaysOfWeek + 1) }
|
.map { DayOfWeek.of((localeFirstDayOfWeek - 1 + it) % DAYS_OF_WEEK + 1) }
|
||||||
.toImmutableList()
|
.toImmutableList()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -81,12 +81,12 @@ private fun CalendarGrid(
|
||||||
val daysInMonth = selectedYearMonth.lengthOfMonth()
|
val daysInMonth = selectedYearMonth.lengthOfMonth()
|
||||||
|
|
||||||
VerticalGrid(
|
VerticalGrid(
|
||||||
columns = SimpleGridCells.Fixed(DaysOfWeek),
|
columns = SimpleGridCells.Fixed(DAYS_OF_WEEK),
|
||||||
modifier = if (isMediumWidthWindow() && !isExpandedWidthWindow()) {
|
modifier = if (isMediumWidthWindow() && !isExpandedWidthWindow()) {
|
||||||
Modifier.widthIn(max = 360.dp)
|
Modifier.widthIn(max = 360.dp)
|
||||||
} else {
|
} else {
|
||||||
Modifier
|
Modifier
|
||||||
}
|
},
|
||||||
) {
|
) {
|
||||||
weekDays.fastForEach { item ->
|
weekDays.fastForEach { item ->
|
||||||
Text(
|
Text(
|
||||||
|
|
|
||||||
|
|
@ -19,9 +19,10 @@ import androidx.compose.ui.text.font.FontWeight
|
||||||
import androidx.compose.ui.text.style.TextAlign
|
import androidx.compose.ui.text.style.TextAlign
|
||||||
import androidx.compose.ui.unit.dp
|
import androidx.compose.ui.unit.dp
|
||||||
import androidx.compose.ui.unit.sp
|
import androidx.compose.ui.unit.sp
|
||||||
|
import tachiyomi.presentation.core.components.material.DISABLED_ALPHA
|
||||||
import java.time.LocalDate
|
import java.time.LocalDate
|
||||||
|
|
||||||
private const val MaxEvents = 3
|
private const val MAX_EVENTS = 3
|
||||||
|
|
||||||
@Composable
|
@Composable
|
||||||
fun CalendarDay(
|
fun CalendarDay(
|
||||||
|
|
@ -39,7 +40,7 @@ fun CalendarDay(
|
||||||
Modifier.border(
|
Modifier.border(
|
||||||
border = BorderStroke(
|
border = BorderStroke(
|
||||||
width = 1.dp,
|
width = 1.dp,
|
||||||
color = MaterialTheme.colorScheme.onBackground
|
color = MaterialTheme.colorScheme.onBackground,
|
||||||
),
|
),
|
||||||
shape = CircleShape,
|
shape = CircleShape,
|
||||||
)
|
)
|
||||||
|
|
@ -57,14 +58,14 @@ fun CalendarDay(
|
||||||
textAlign = TextAlign.Center,
|
textAlign = TextAlign.Center,
|
||||||
fontSize = 16.sp,
|
fontSize = 16.sp,
|
||||||
color = if (date.isBefore(today)) {
|
color = if (date.isBefore(today)) {
|
||||||
MaterialTheme.colorScheme.onBackground.copy(alpha = 0.38f)
|
MaterialTheme.colorScheme.onBackground.copy(alpha = DISABLED_ALPHA)
|
||||||
} else {
|
} else {
|
||||||
MaterialTheme.colorScheme.onBackground
|
MaterialTheme.colorScheme.onBackground
|
||||||
},
|
},
|
||||||
fontWeight = FontWeight.SemiBold,
|
fontWeight = FontWeight.SemiBold,
|
||||||
)
|
)
|
||||||
Row(Modifier.offset(y = 12.dp)) {
|
Row(Modifier.offset(y = 12.dp)) {
|
||||||
val size = events.coerceAtMost(MaxEvents)
|
val size = events.coerceAtMost(MAX_EVENTS)
|
||||||
for (index in 0 until size) {
|
for (index in 0 until size) {
|
||||||
CalendarIndicator(
|
CalendarIndicator(
|
||||||
index = index,
|
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 {
|
private fun AnimatedContentTransitionScope<YearMonth>.getAnimation(): ContentTransform {
|
||||||
val movingForward = targetState > initialState
|
val movingForward = targetState > initialState
|
||||||
|
|
||||||
val enterTransition = slideInVertically(
|
val enterTransition = slideInVertically(
|
||||||
animationSpec = tween(durationMillis = MonthYearChangeAnimationDuration),
|
animationSpec = tween(durationMillis = MONTH_YEAR_CHANGE_ANIMATION_DURATION),
|
||||||
) { height -> if (movingForward) height else -height } + fadeIn(
|
) { height -> if (movingForward) height else -height } + fadeIn(
|
||||||
animationSpec = tween(durationMillis = MonthYearChangeAnimationDuration),
|
animationSpec = tween(durationMillis = MONTH_YEAR_CHANGE_ANIMATION_DURATION),
|
||||||
)
|
)
|
||||||
val exitTransition = slideOutVertically(
|
val exitTransition = slideOutVertically(
|
||||||
animationSpec = tween(durationMillis = MonthYearChangeAnimationDuration),
|
animationSpec = tween(durationMillis = MONTH_YEAR_CHANGE_ANIMATION_DURATION),
|
||||||
) { height -> if (movingForward) -height else height } + fadeOut(
|
) { height -> if (movingForward) -height else height } + fadeOut(
|
||||||
animationSpec = tween(durationMillis = MonthYearChangeAnimationDuration),
|
animationSpec = tween(durationMillis = MONTH_YEAR_CHANGE_ANIMATION_DURATION),
|
||||||
)
|
)
|
||||||
return (enterTransition togetherWith exitTransition)
|
return (enterTransition togetherWith exitTransition)
|
||||||
.using(SizeTransform(clip = false))
|
.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
|
||||||
import androidx.compose.ui.unit.dp
|
import androidx.compose.ui.unit.dp
|
||||||
|
|
||||||
private const val IndicatorScale = 12
|
private const val INDICATOR_SCALE = 12
|
||||||
private const val IndicatorAlphaMultiplier = 0.3f
|
private const val INDICATOR_ALPHA_MULTIPLIER = 0.3f
|
||||||
|
|
||||||
@Composable
|
@Composable
|
||||||
fun CalendarIndicator(
|
fun CalendarIndicator(
|
||||||
|
|
@ -26,7 +26,7 @@ fun CalendarIndicator(
|
||||||
modifier = modifier
|
modifier = modifier
|
||||||
.padding(horizontal = 1.dp)
|
.padding(horizontal = 1.dp)
|
||||||
.clip(shape = CircleShape)
|
.clip(shape = CircleShape)
|
||||||
.background(color = color.copy(alpha = (index + 1) * IndicatorAlphaMultiplier))
|
.background(color = color.copy(alpha = (index + 1) * INDICATOR_ALPHA_MULTIPLIER))
|
||||||
.size(size = size.div(IndicatorScale)),
|
.size(size = size.div(INDICATOR_SCALE)),
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -6,4 +6,4 @@
|
||||||
android:viewportHeight="24"
|
android:viewportHeight="24"
|
||||||
android:tint="@android:color/black">
|
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" />
|
<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:viewportWidth="24"
|
||||||
android:viewportHeight="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" />
|
<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
|
<path
|
||||||
android:fillColor="@color/cover_placeholder"
|
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"/>
|
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
|
<path
|
||||||
android:fillColor="#FFF"
|
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" />
|
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
|
<path
|
||||||
android:fillColor="#000"
|
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" />
|
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:viewportWidth="24"
|
||||||
android:viewportHeight="24">
|
android:viewportHeight="24">
|
||||||
<path android:fillColor="#000" android:pathData="M2,2H6V3H13V2H17V6H16V9H18V8H22V12H21V18H22V22H18V21H12V22H8V18H9V16H6V17H2V13H3V6H2V2M18,12V11H16V13H17V17H13V16H11V18H12V19H18V18H19V12H18M13,6V5H6V6H5V13H6V14H9V12H8V8H12V9H14V6H13M12,12H11V14H13V13H14V11H12V12Z" />
|
<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" />
|
<corners android:radius="@dimen/m3_alert_dialog_corner_size" />
|
||||||
</shape>
|
</shape>
|
||||||
</item>
|
</item>
|
||||||
</layer-list>
|
</layer-list>
|
||||||
|
|
|
||||||
|
|
@ -36,4 +36,4 @@
|
||||||
|
|
||||||
</androidx.constraintlayout.widget.ConstraintLayout>
|
</androidx.constraintlayout.widget.ConstraintLayout>
|
||||||
|
|
||||||
</LinearLayout>
|
</LinearLayout>
|
||||||
|
|
|
||||||
|
|
@ -157,4 +157,4 @@
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
</LinearLayout>
|
</LinearLayout>
|
||||||
|
|
|
||||||
|
|
@ -27,4 +27,4 @@
|
||||||
app:layout_constraintEnd_toEndOf="parent"
|
app:layout_constraintEnd_toEndOf="parent"
|
||||||
app:layout_constraintTop_toTopOf="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_constraintEnd_toEndOf="parent"
|
||||||
app:layout_constraintTop_toTopOf="parent" />
|
app:layout_constraintTop_toTopOf="parent" />
|
||||||
|
|
||||||
</androidx.constraintlayout.widget.ConstraintLayout>
|
</androidx.constraintlayout.widget.ConstraintLayout>
|
||||||
|
|
|
||||||
|
|
@ -95,4 +95,4 @@
|
||||||
app:layout_constraintTop_toTopOf="parent" />
|
app:layout_constraintTop_toTopOf="parent" />
|
||||||
</androidx.constraintlayout.widget.ConstraintLayout>
|
</androidx.constraintlayout.widget.ConstraintLayout>
|
||||||
|
|
||||||
</LinearLayout>
|
</LinearLayout>
|
||||||
|
|
|
||||||
|
|
@ -115,4 +115,4 @@
|
||||||
</androidx.constraintlayout.widget.ConstraintLayout>
|
</androidx.constraintlayout.widget.ConstraintLayout>
|
||||||
|
|
||||||
|
|
||||||
</LinearLayout>
|
</LinearLayout>
|
||||||
|
|
|
||||||
|
|
@ -124,4 +124,4 @@
|
||||||
|
|
||||||
</androidx.constraintlayout.widget.ConstraintLayout>
|
</androidx.constraintlayout.widget.ConstraintLayout>
|
||||||
|
|
||||||
</LinearLayout>
|
</LinearLayout>
|
||||||
|
|
|
||||||
|
|
@ -14,4 +14,4 @@
|
||||||
android:layout_height="1dp"
|
android:layout_height="1dp"
|
||||||
android:background="?android:attr/divider"/>
|
android:background="?android:attr/divider"/>
|
||||||
|
|
||||||
</LinearLayout>
|
</LinearLayout>
|
||||||
|
|
|
||||||
|
|
@ -4,4 +4,4 @@
|
||||||
android:layout_width="match_parent"
|
android:layout_width="match_parent"
|
||||||
android:layout_height="match_parent"
|
android:layout_height="match_parent"
|
||||||
android:clipToPadding="false"
|
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:clickable">true</item>
|
||||||
<item name="android:focusable">true</item>
|
<item name="android:focusable">true</item>
|
||||||
</style>
|
</style>
|
||||||
</resources>
|
</resources>
|
||||||
|
|
|
||||||
|
|
@ -660,7 +660,7 @@
|
||||||
<item name="colorSurfaceContainerLow">@color/nord_surfaceContainerLow</item>
|
<item name="colorSurfaceContainerLow">@color/nord_surfaceContainerLow</item>
|
||||||
<item name="colorSurfaceContainerLowest">@color/nord_surfaceContainerLowest</item>
|
<item name="colorSurfaceContainerLowest">@color/nord_surfaceContainerLowest</item>
|
||||||
</style>
|
</style>
|
||||||
|
|
||||||
<!--== AMOLED Mode Overlay ==-->
|
<!--== AMOLED Mode Overlay ==-->
|
||||||
<style name="ThemeOverlay.Tachiyomi.Amoled" parent="" />
|
<style name="ThemeOverlay.Tachiyomi.Amoled" parent="" />
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -57,4 +57,4 @@
|
||||||
name="gesture"
|
name="gesture"
|
||||||
value="swipe_left" />
|
value="swipe_left" />
|
||||||
</action>
|
</action>
|
||||||
</remote-actions>
|
</remote-actions>
|
||||||
|
|
|
||||||
|
|
@ -133,8 +133,8 @@ class MigratorTest {
|
||||||
listOf(
|
listOf(
|
||||||
Migration.of(Migration.ALWAYS) { true },
|
Migration.of(Migration.ALWAYS) { true },
|
||||||
Migration.of(2f) { true },
|
Migration.of(2f) { true },
|
||||||
Migration.of(3f) { false }
|
Migration.of(3f) { false },
|
||||||
)
|
),
|
||||||
)
|
)
|
||||||
|
|
||||||
execute.await()
|
execute.await()
|
||||||
|
|
|
||||||
|
|
@ -1,2 +1,2 @@
|
||||||
<?xml version="1.0" encoding="utf-8"?>
|
<?xml version="1.0" encoding="utf-8"?>
|
||||||
<manifest />
|
<manifest />
|
||||||
|
|
|
||||||
|
|
@ -1,2 +1,2 @@
|
||||||
<?xml version="1.0" encoding="utf-8"?>
|
<?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
|
package eu.kanade.tachiyomi.network
|
||||||
|
|
||||||
import okhttp3.CacheControl
|
import okhttp3.CacheControl
|
||||||
|
|
|
||||||
|
|
@ -546,16 +546,20 @@ object ImageUtil {
|
||||||
darkBG -> {
|
darkBG -> {
|
||||||
return ColorDrawable(blackColor)
|
return ColorDrawable(blackColor)
|
||||||
}
|
}
|
||||||
topIsBlackStreak || (
|
topIsBlackStreak ||
|
||||||
topCornersIsDark && topOffsetCornersIsDark &&
|
(
|
||||||
(topMidIsDark || overallBlackPixels > 9)
|
topCornersIsDark &&
|
||||||
) -> {
|
topOffsetCornersIsDark &&
|
||||||
|
(topMidIsDark || overallBlackPixels > 9)
|
||||||
|
) -> {
|
||||||
intArrayOf(blackColor, blackColor, whiteColor, whiteColor)
|
intArrayOf(blackColor, blackColor, whiteColor, whiteColor)
|
||||||
}
|
}
|
||||||
bottomIsBlackStreak || (
|
bottomIsBlackStreak ||
|
||||||
botCornersIsDark && botOffsetCornersIsDark &&
|
(
|
||||||
(bottomCenterPixel.isDark() || overallBlackPixels > 9)
|
botCornersIsDark &&
|
||||||
) -> {
|
botOffsetCornersIsDark &&
|
||||||
|
(bottomCenterPixel.isDark() || overallBlackPixels > 9)
|
||||||
|
) -> {
|
||||||
intArrayOf(whiteColor, whiteColor, blackColor, blackColor)
|
intArrayOf(whiteColor, whiteColor, blackColor, blackColor)
|
||||||
}
|
}
|
||||||
else -> {
|
else -> {
|
||||||
|
|
|
||||||
|
|
@ -1,2 +1,2 @@
|
||||||
<?xml version="1.0" encoding="utf-8"?>
|
<?xml version="1.0" encoding="utf-8"?>
|
||||||
<manifest />
|
<manifest />
|
||||||
|
|
|
||||||
|
|
@ -42,8 +42,8 @@ class QueryPagingSource<RowType : Any>(
|
||||||
}
|
}
|
||||||
|
|
||||||
val (prevKey, nextKey) = when (params) {
|
val (prevKey, nextKey) = when (params) {
|
||||||
is LoadParams.Append -> { offset - loadSize to offset + loadSize }
|
is LoadParams.Append -> (offset - loadSize to offset + loadSize)
|
||||||
else -> { offset to offset + loadSize }
|
else -> (offset to offset + loadSize)
|
||||||
}
|
}
|
||||||
|
|
||||||
return LoadResult.Page(
|
return LoadResult.Page(
|
||||||
|
|
|
||||||
|
|
@ -1,2 +1,2 @@
|
||||||
<?xml version="1.0" encoding="utf-8"?>
|
<?xml version="1.0" encoding="utf-8"?>
|
||||||
<manifest />
|
<manifest />
|
||||||
|
|
|
||||||
|
|
@ -5,7 +5,8 @@ import tachiyomi.domain.chapter.model.Chapter
|
||||||
class ShouldUpdateDbChapter {
|
class ShouldUpdateDbChapter {
|
||||||
|
|
||||||
fun await(dbChapter: Chapter, sourceChapter: Chapter): Boolean {
|
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.dateUpload != sourceChapter.dateUpload ||
|
||||||
dbChapter.chapterNumber != sourceChapter.chapterNumber ||
|
dbChapter.chapterNumber != sourceChapter.chapterNumber ||
|
||||||
dbChapter.sourceOrder != sourceChapter.sourceOrder
|
dbChapter.sourceOrder != sourceChapter.sourceOrder
|
||||||
|
|
|
||||||
|
|
@ -20,10 +20,8 @@ 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 && now.isBefore(
|
val nextCheckTime = Instant.ofEpochMilli(lastChecked.get()).plus(3, ChronoUnit.DAYS)
|
||||||
Instant.ofEpochMilli(lastChecked.get()).plus(3, ChronoUnit.DAYS),
|
if (!arguments.forceCheck && now.isBefore(nextCheckTime)) {
|
||||||
)
|
|
||||||
) {
|
|
||||||
return Result.NoNewUpdate
|
return Result.NoNewUpdate
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -293,7 +293,7 @@ object FlagKit {
|
||||||
"yt",
|
"yt",
|
||||||
"za",
|
"za",
|
||||||
"zm",
|
"zm",
|
||||||
"zw"
|
"zw",
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -1,3 +1,3 @@
|
||||||
<?xml version="1.0" encoding="utf-8"?>
|
<?xml version="1.0" encoding="utf-8"?>
|
||||||
<resources>
|
<resources>
|
||||||
</resources>
|
</resources>
|
||||||
|
|
|
||||||
|
|
@ -80,4 +80,4 @@
|
||||||
<item quantity="many">منذُ %1$d دقيقة</item>
|
<item quantity="many">منذُ %1$d دقيقة</item>
|
||||||
<item quantity="other">منذُ %1$d دقيقة</item>
|
<item quantity="other">منذُ %1$d دقيقة</item>
|
||||||
</plurals>
|
</plurals>
|
||||||
</resources>
|
</resources>
|
||||||
|
|
|
||||||
|
|
@ -451,4 +451,4 @@
|
||||||
<string name="action_copy_combined_page">نسخ الصفحة المجمعة</string>
|
<string name="action_copy_combined_page">نسخ الصفحة المجمعة</string>
|
||||||
<string name="only_show_updated_entries">إظهار الإدخالات التي تحتوي على فصول جديدة فقط</string>
|
<string name="only_show_updated_entries">إظهار الإدخالات التي تحتوي على فصول جديدة فقط</string>
|
||||||
<string name="pref_crop_borders_pager">قص اطراف الصفحات</string>
|
<string name="pref_crop_borders_pager">قص اطراف الصفحات</string>
|
||||||
</resources>
|
</resources>
|
||||||
|
|
|
||||||
|
|
@ -1,2 +1,2 @@
|
||||||
<?xml version="1.0" encoding="utf-8"?>
|
<?xml version="1.0" encoding="utf-8"?>
|
||||||
<resources></resources>
|
<resources></resources>
|
||||||
|
|
|
||||||
|
|
@ -1,2 +1,2 @@
|
||||||
<?xml version="1.0" encoding="utf-8"?>
|
<?xml version="1.0" encoding="utf-8"?>
|
||||||
<resources></resources>
|
<resources></resources>
|
||||||
|
|
|
||||||
|
|
@ -1,2 +1,2 @@
|
||||||
<?xml version="1.0" encoding="utf-8"?>
|
<?xml version="1.0" encoding="utf-8"?>
|
||||||
<resources></resources>
|
<resources></resources>
|
||||||
|
|
|
||||||
|
|
@ -533,4 +533,4 @@
|
||||||
<string name="group">Grupo</string>
|
<string name="group">Grupo</string>
|
||||||
<string name="uploader_capital">Naka-capitalize ang Uploader</string>
|
<string name="uploader_capital">Naka-capitalize ang Uploader</string>
|
||||||
<string name="deduplication_entry_info">Impo ng entry:</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="one">%1$d seconde auparavant</item>
|
||||||
<item quantity="other">%1$d seconde auparavant</item>
|
<item quantity="other">%1$d seconde auparavant</item>
|
||||||
</plurals>
|
</plurals>
|
||||||
</resources>
|
</resources>
|
||||||
|
|
|
||||||
|
|
@ -72,4 +72,4 @@
|
||||||
<item quantity="one">%1$d detik yang lalu</item>
|
<item quantity="one">%1$d detik yang lalu</item>
|
||||||
<item quantity="other">%1$d detik yang lalu</item>
|
<item quantity="other">%1$d detik yang lalu</item>
|
||||||
</plurals>
|
</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