mirror of
https://github.com/mihonapp/mihon.git
synced 2024-12-24 01:48:24 +01:00
Restrict line length with ktlint
This commit is contained in:
parent
056dbaefda
commit
1d144e6767
@ -1,7 +1,8 @@
|
||||
[*.{kt,kts}]
|
||||
indent_size=4
|
||||
insert_final_newline=true
|
||||
ij_kotlin_allow_trailing_comma=true
|
||||
ij_kotlin_allow_trailing_comma_on_call_site=true
|
||||
ij_kotlin_name_count_to_use_star_import=2147483647
|
||||
ij_kotlin_name_count_to_use_star_import_for_members=2147483647
|
||||
max_line_length = 120
|
||||
indent_size = 4
|
||||
insert_final_newline = true
|
||||
ij_kotlin_allow_trailing_comma = true
|
||||
ij_kotlin_allow_trailing_comma_on_call_site = true
|
||||
ij_kotlin_name_count_to_use_star_import = 2147483647
|
||||
ij_kotlin_name_count_to_use_star_import_for_members = 2147483647
|
||||
|
@ -23,7 +23,12 @@ fun List<Chapter>.applyFilters(manga: Manga, downloadManager: DownloadManager):
|
||||
.filter { chapter -> applyFilter(bookmarkedFilter) { chapter.bookmark } }
|
||||
.filter { chapter ->
|
||||
applyFilter(downloadedFilter) {
|
||||
val downloaded = downloadManager.isChapterDownloaded(chapter.name, chapter.scanlator, manga.title, manga.source)
|
||||
val downloaded = downloadManager.isChapterDownloaded(
|
||||
chapter.name,
|
||||
chapter.scanlator,
|
||||
manga.title,
|
||||
manga.source,
|
||||
)
|
||||
downloaded || isLocalManga
|
||||
}
|
||||
}
|
||||
|
@ -11,7 +11,12 @@ class SourcePreferences(
|
||||
private val preferenceStore: PreferenceStore,
|
||||
) {
|
||||
|
||||
fun sourceDisplayMode() = preferenceStore.getObject("pref_display_mode_catalogue", LibraryDisplayMode.default, LibraryDisplayMode.Serializer::serialize, LibraryDisplayMode.Serializer::deserialize)
|
||||
fun sourceDisplayMode() = preferenceStore.getObject(
|
||||
"pref_display_mode_catalogue",
|
||||
LibraryDisplayMode.default,
|
||||
LibraryDisplayMode.Serializer::serialize,
|
||||
LibraryDisplayMode.Serializer::deserialize,
|
||||
)
|
||||
|
||||
fun enabledLanguages() = preferenceStore.getStringSet("source_languages", LocaleHelper.getDefaultEnabledLanguages())
|
||||
|
||||
@ -28,7 +33,10 @@ class SourcePreferences(
|
||||
|
||||
fun migrationSortingMode() = preferenceStore.getEnum("pref_migration_sorting", SetMigrateSorting.Mode.ALPHABETICAL)
|
||||
|
||||
fun migrationSortingDirection() = preferenceStore.getEnum("pref_migration_direction", SetMigrateSorting.Direction.ASCENDING)
|
||||
fun migrationSortingDirection() = preferenceStore.getEnum(
|
||||
"pref_migration_direction",
|
||||
SetMigrateSorting.Direction.ASCENDING,
|
||||
)
|
||||
|
||||
fun extensionUpdatesCount() = preferenceStore.getInt("ext_updates_count", 0)
|
||||
|
||||
|
@ -61,7 +61,10 @@ class AddTracks(
|
||||
?.readAt
|
||||
|
||||
firstReadChapterDate?.let {
|
||||
val startDate = firstReadChapterDate.time.convertEpochMillisZone(ZoneOffset.systemDefault(), ZoneOffset.UTC)
|
||||
val startDate = firstReadChapterDate.time.convertEpochMillisZone(
|
||||
ZoneOffset.systemDefault(),
|
||||
ZoneOffset.UTC,
|
||||
)
|
||||
track = track.copy(
|
||||
startDate = startDate,
|
||||
)
|
||||
|
@ -43,7 +43,9 @@ class DelayedTrackingUpdateJob(private val context: Context, workerParams: Worke
|
||||
track?.copy(lastChapterRead = it.lastChapterRead.toDouble())
|
||||
}
|
||||
.forEach { track ->
|
||||
logcat(LogPriority.DEBUG) { "Updating delayed track item: ${track.mangaId}, last chapter read: ${track.lastChapterRead}" }
|
||||
logcat(LogPriority.DEBUG) {
|
||||
"Updating delayed track item: ${track.mangaId}, last chapter read: ${track.lastChapterRead}"
|
||||
}
|
||||
trackChapter.await(context, track.mangaId, track.lastChapterRead)
|
||||
}
|
||||
}
|
||||
|
@ -102,14 +102,26 @@ private fun MigrateSourceList(
|
||||
|
||||
IconButton(onClick = onToggleSortingMode) {
|
||||
when (sortingMode) {
|
||||
SetMigrateSorting.Mode.ALPHABETICAL -> Icon(Icons.Outlined.SortByAlpha, contentDescription = stringResource(R.string.action_sort_alpha))
|
||||
SetMigrateSorting.Mode.TOTAL -> Icon(Icons.Outlined.Numbers, contentDescription = stringResource(R.string.action_sort_count))
|
||||
SetMigrateSorting.Mode.ALPHABETICAL -> Icon(
|
||||
Icons.Outlined.SortByAlpha,
|
||||
contentDescription = stringResource(R.string.action_sort_alpha),
|
||||
)
|
||||
SetMigrateSorting.Mode.TOTAL -> Icon(
|
||||
Icons.Outlined.Numbers,
|
||||
contentDescription = stringResource(R.string.action_sort_count),
|
||||
)
|
||||
}
|
||||
}
|
||||
IconButton(onClick = onToggleSortingDirection) {
|
||||
when (sortingDirection) {
|
||||
SetMigrateSorting.Direction.ASCENDING -> Icon(Icons.Outlined.ArrowUpward, contentDescription = stringResource(R.string.action_asc))
|
||||
SetMigrateSorting.Direction.DESCENDING -> Icon(Icons.Outlined.ArrowDownward, contentDescription = stringResource(R.string.action_desc))
|
||||
SetMigrateSorting.Direction.ASCENDING -> Icon(
|
||||
Icons.Outlined.ArrowUpward,
|
||||
contentDescription = stringResource(R.string.action_asc),
|
||||
)
|
||||
SetMigrateSorting.Direction.DESCENDING -> Icon(
|
||||
Icons.Outlined.ArrowDownward,
|
||||
contentDescription = stringResource(R.string.action_desc),
|
||||
)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -144,7 +144,13 @@ private fun SourcePinButton(
|
||||
onClick: () -> Unit,
|
||||
) {
|
||||
val icon = if (isPinned) Icons.Filled.PushPin else Icons.Outlined.PushPin
|
||||
val tint = if (isPinned) MaterialTheme.colorScheme.primary else MaterialTheme.colorScheme.onBackground.copy(alpha = SecondaryItemAlpha)
|
||||
val tint = if (isPinned) {
|
||||
MaterialTheme.colorScheme.primary
|
||||
} else {
|
||||
MaterialTheme.colorScheme.onBackground.copy(
|
||||
alpha = SecondaryItemAlpha,
|
||||
)
|
||||
}
|
||||
val description = if (isPinned) R.string.action_unpin else R.string.action_pin
|
||||
IconButton(onClick = onClick) {
|
||||
Icon(
|
||||
|
@ -25,7 +25,9 @@ fun BaseSourceItem(
|
||||
action: @Composable RowScope.(Source) -> Unit = {},
|
||||
content: @Composable RowScope.(Source, String?) -> Unit = defaultContent,
|
||||
) {
|
||||
val sourceLangString = LocaleHelper.getSourceDisplayName(source.lang, LocalContext.current).takeIf { showLanguageInContent }
|
||||
val sourceLangString = LocaleHelper.getSourceDisplayName(source.lang, LocalContext.current).takeIf {
|
||||
showLanguageInContent
|
||||
}
|
||||
BaseBrowseItem(
|
||||
modifier = modifier,
|
||||
onClickItem = onClickItem,
|
||||
|
@ -71,7 +71,10 @@ fun CategoryListItem(
|
||||
}
|
||||
Spacer(modifier = Modifier.weight(1f))
|
||||
IconButton(onClick = onRename) {
|
||||
Icon(imageVector = Icons.Outlined.Edit, contentDescription = stringResource(R.string.action_rename_category))
|
||||
Icon(
|
||||
imageVector = Icons.Outlined.Edit,
|
||||
contentDescription = stringResource(R.string.action_rename_category),
|
||||
)
|
||||
}
|
||||
IconButton(onClick = onDelete) {
|
||||
Icon(imageVector = Icons.Outlined.Delete, contentDescription = stringResource(R.string.action_delete))
|
||||
|
@ -614,7 +614,9 @@ fun MangaScreenLargeImpl(
|
||||
val isReading = remember(state.chapters) {
|
||||
state.chapters.fastAny { it.chapter.read }
|
||||
}
|
||||
Text(text = stringResource(if (isReading) R.string.action_resume else R.string.action_start))
|
||||
Text(
|
||||
text = stringResource(if (isReading) R.string.action_resume else R.string.action_start),
|
||||
)
|
||||
},
|
||||
icon = { Icon(imageVector = Icons.Filled.PlayArrow, contentDescription = null) },
|
||||
onClick = onContinueReading,
|
||||
|
@ -189,7 +189,11 @@ fun MangaActionRow(
|
||||
)
|
||||
if (onEditIntervalClicked != null && fetchInterval != null) {
|
||||
MangaActionButton(
|
||||
title = pluralStringResource(id = R.plurals.day, count = fetchInterval.absoluteValue, fetchInterval.absoluteValue),
|
||||
title = pluralStringResource(
|
||||
id = R.plurals.day,
|
||||
count = fetchInterval.absoluteValue,
|
||||
fetchInterval.absoluteValue,
|
||||
),
|
||||
icon = Icons.Default.HourglassEmpty,
|
||||
color = if (isUserIntervalMode) MaterialTheme.colorScheme.primary else defaultActionButtonColor,
|
||||
onClick = onEditIntervalClicked,
|
||||
@ -587,7 +591,9 @@ private fun MangaSummary(
|
||||
val image = AnimatedImageVector.animatedVectorResource(R.drawable.anim_caret_down)
|
||||
Icon(
|
||||
painter = rememberAnimatedVectorPainter(image, !expanded),
|
||||
contentDescription = stringResource(if (expanded) R.string.manga_info_collapse else R.string.manga_info_expand),
|
||||
contentDescription = stringResource(
|
||||
if (expanded) R.string.manga_info_collapse else R.string.manga_info_expand,
|
||||
),
|
||||
tint = MaterialTheme.colorScheme.onBackground,
|
||||
modifier = Modifier.background(Brush.radialGradient(colors = colors.asReversed())),
|
||||
)
|
||||
|
@ -62,7 +62,9 @@ fun MoreScreen(
|
||||
WarningBanner(
|
||||
textRes = R.string.fdroid_warning,
|
||||
modifier = Modifier.clickable {
|
||||
uriHandler.openUri("https://tachiyomi.org/docs/faq/general#how-do-i-update-from-the-f-droid-builds")
|
||||
uriHandler.openUri(
|
||||
"https://tachiyomi.org/docs/faq/general#how-do-i-update-from-the-f-droid-builds",
|
||||
)
|
||||
},
|
||||
)
|
||||
}
|
||||
|
@ -31,7 +31,8 @@ fun getCategoriesLabel(
|
||||
|
||||
val includedItemsText = when {
|
||||
// Some selected, but not all
|
||||
includedCategories.isNotEmpty() && includedCategories.size != allCategories.size -> includedCategories.joinToString { it.visualName(context) }
|
||||
includedCategories.isNotEmpty() && includedCategories.size != allCategories.size ->
|
||||
includedCategories.joinToString { it.visualName(context) }
|
||||
// All explicitly selected
|
||||
includedCategories.size == allCategories.size -> stringResource(R.string.all)
|
||||
allExcluded -> stringResource(R.string.none)
|
||||
|
@ -120,7 +120,9 @@ object SettingsAppearanceScreen : SearchableSettings {
|
||||
uiPreferences: UiPreferences,
|
||||
): Preference.PreferenceGroup {
|
||||
val langs = remember { getLangs(context) }
|
||||
var currentLanguage by remember { mutableStateOf(AppCompatDelegate.getApplicationLocales().get(0)?.toLanguageTag() ?: "") }
|
||||
var currentLanguage by remember {
|
||||
mutableStateOf(AppCompatDelegate.getApplicationLocales().get(0)?.toLanguageTag() ?: "")
|
||||
}
|
||||
val now = remember { Date().time }
|
||||
|
||||
val dateFormat by uiPreferences.dateFormat().collectAsState()
|
||||
|
@ -115,7 +115,9 @@ class WorkerInfoScreen : Screen() {
|
||||
private val workManager = context.workManager
|
||||
|
||||
val finished = workManager
|
||||
.getWorkInfosLiveData(WorkQuery.fromStates(WorkInfo.State.SUCCEEDED, WorkInfo.State.FAILED, WorkInfo.State.CANCELLED))
|
||||
.getWorkInfosLiveData(
|
||||
WorkQuery.fromStates(WorkInfo.State.SUCCEEDED, WorkInfo.State.FAILED, WorkInfo.State.CANCELLED),
|
||||
)
|
||||
.asFlow()
|
||||
.map(::constructString)
|
||||
.stateIn(ioCoroutineScope, SharingStarted.WhileSubscribed(), "")
|
||||
|
@ -115,8 +115,16 @@ fun <T> TriStateListDialog(
|
||||
}
|
||||
}
|
||||
|
||||
if (!listState.isScrolledToStart()) HorizontalDivider(modifier = Modifier.align(Alignment.TopCenter))
|
||||
if (!listState.isScrolledToEnd()) HorizontalDivider(modifier = Modifier.align(Alignment.BottomCenter))
|
||||
if (!listState.isScrolledToStart()) {
|
||||
HorizontalDivider(
|
||||
modifier = Modifier.align(Alignment.TopCenter),
|
||||
)
|
||||
}
|
||||
if (!listState.isScrolledToEnd()) {
|
||||
HorizontalDivider(
|
||||
modifier = Modifier.align(Alignment.BottomCenter),
|
||||
)
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
|
@ -77,7 +77,9 @@ fun ChapterNavigator(
|
||||
) {
|
||||
Icon(
|
||||
imageVector = Icons.Outlined.SkipPrevious,
|
||||
contentDescription = stringResource(if (isRtl) R.string.action_next_chapter else R.string.action_previous_chapter),
|
||||
contentDescription = stringResource(
|
||||
if (isRtl) R.string.action_next_chapter else R.string.action_previous_chapter,
|
||||
),
|
||||
)
|
||||
}
|
||||
|
||||
@ -127,7 +129,9 @@ fun ChapterNavigator(
|
||||
) {
|
||||
Icon(
|
||||
imageVector = Icons.Outlined.SkipNext,
|
||||
contentDescription = stringResource(if (isRtl) R.string.action_previous_chapter else R.string.action_next_chapter),
|
||||
contentDescription = stringResource(
|
||||
if (isRtl) R.string.action_previous_chapter else R.string.action_next_chapter,
|
||||
),
|
||||
)
|
||||
}
|
||||
}
|
||||
|
@ -99,7 +99,9 @@ fun ReaderAppBars(
|
||||
AppBarActions(
|
||||
listOfNotNull(
|
||||
AppBar.Action(
|
||||
title = stringResource(if (bookmarked) R.string.action_remove_bookmark else R.string.action_bookmark),
|
||||
title = stringResource(
|
||||
if (bookmarked) R.string.action_remove_bookmark else R.string.action_bookmark,
|
||||
),
|
||||
icon = if (bookmarked) Icons.Outlined.Bookmark else Icons.Outlined.BookmarkBorder,
|
||||
onClick = onToggleBookmarked,
|
||||
),
|
||||
|
@ -173,7 +173,9 @@ fun WebViewScreenContent(
|
||||
modifier = Modifier
|
||||
.clip(MaterialTheme.shapes.small)
|
||||
.clickable {
|
||||
uriHandler.openUri("https://tachiyomi.org/docs/guides/troubleshooting/#cloudflare")
|
||||
uriHandler.openUri(
|
||||
"https://tachiyomi.org/docs/guides/troubleshooting/#cloudflare",
|
||||
)
|
||||
},
|
||||
)
|
||||
}
|
||||
|
@ -223,7 +223,12 @@ class App : Application(), DefaultLifecycleObserver, ImageLoaderFactory {
|
||||
|
||||
fun register() {
|
||||
if (!registered) {
|
||||
ContextCompat.registerReceiver(this@App, this, IntentFilter(ACTION_DISABLE_INCOGNITO_MODE), ContextCompat.RECEIVER_NOT_EXPORTED)
|
||||
ContextCompat.registerReceiver(
|
||||
this@App,
|
||||
this,
|
||||
IntentFilter(ACTION_DISABLE_INCOGNITO_MODE),
|
||||
ContextCompat.RECEIVER_NOT_EXPORTED,
|
||||
)
|
||||
registered = true
|
||||
}
|
||||
}
|
||||
|
@ -121,13 +121,22 @@ object Migrations {
|
||||
}
|
||||
}
|
||||
prefs.edit {
|
||||
putInt(libraryPreferences.filterDownloaded().key(), convertBooleanPrefToTriState("pref_filter_downloaded_key"))
|
||||
putInt(
|
||||
libraryPreferences.filterDownloaded().key(),
|
||||
convertBooleanPrefToTriState("pref_filter_downloaded_key"),
|
||||
)
|
||||
remove("pref_filter_downloaded_key")
|
||||
|
||||
putInt(libraryPreferences.filterUnread().key(), convertBooleanPrefToTriState("pref_filter_unread_key"))
|
||||
putInt(
|
||||
libraryPreferences.filterUnread().key(),
|
||||
convertBooleanPrefToTriState("pref_filter_unread_key"),
|
||||
)
|
||||
remove("pref_filter_unread_key")
|
||||
|
||||
putInt(libraryPreferences.filterCompleted().key(), convertBooleanPrefToTriState("pref_filter_completed_key"))
|
||||
putInt(
|
||||
libraryPreferences.filterCompleted().key(),
|
||||
convertBooleanPrefToTriState("pref_filter_completed_key"),
|
||||
)
|
||||
remove("pref_filter_completed_key")
|
||||
}
|
||||
}
|
||||
@ -242,7 +251,10 @@ object Migrations {
|
||||
if (oldSecureScreen) {
|
||||
securityPreferences.secureScreen().set(SecurityPreferences.SecureScreenMode.ALWAYS)
|
||||
}
|
||||
if (DeviceUtil.isMiui && basePreferences.extensionInstaller().get() == BasePreferences.ExtensionInstaller.PACKAGEINSTALLER) {
|
||||
if (
|
||||
DeviceUtil.isMiui &&
|
||||
basePreferences.extensionInstaller().get() == BasePreferences.ExtensionInstaller.PACKAGEINSTALLER
|
||||
) {
|
||||
basePreferences.extensionInstaller().set(BasePreferences.ExtensionInstaller.LEGACY)
|
||||
}
|
||||
}
|
||||
@ -259,7 +271,12 @@ object Migrations {
|
||||
if (oldVersion < 81) {
|
||||
// Handle renamed enum values
|
||||
prefs.edit {
|
||||
val newSortingMode = when (val oldSortingMode = prefs.getString(libraryPreferences.sortingMode().key(), "ALPHABETICAL")) {
|
||||
val newSortingMode = when (
|
||||
val oldSortingMode = prefs.getString(
|
||||
libraryPreferences.sortingMode().key(),
|
||||
"ALPHABETICAL",
|
||||
)
|
||||
) {
|
||||
"LAST_CHECKED" -> "LAST_MANGA_UPDATE"
|
||||
"UNREAD" -> "UNREAD_COUNT"
|
||||
"DATE_FETCHED" -> "CHAPTER_FETCH_DATE"
|
||||
|
@ -20,7 +20,9 @@ class BackupNotifier(private val context: Context) {
|
||||
|
||||
private val preferences: SecurityPreferences by injectLazy()
|
||||
|
||||
private val progressNotificationBuilder = context.notificationBuilder(Notifications.CHANNEL_BACKUP_RESTORE_PROGRESS) {
|
||||
private val progressNotificationBuilder = context.notificationBuilder(
|
||||
Notifications.CHANNEL_BACKUP_RESTORE_PROGRESS,
|
||||
) {
|
||||
setLargeIcon(BitmapFactory.decodeResource(context.resources, R.mipmap.ic_launcher))
|
||||
setSmallIcon(R.drawable.ic_tachi)
|
||||
setAutoCancel(false)
|
||||
@ -28,7 +30,9 @@ class BackupNotifier(private val context: Context) {
|
||||
setOnlyAlertOnce(true)
|
||||
}
|
||||
|
||||
private val completeNotificationBuilder = context.notificationBuilder(Notifications.CHANNEL_BACKUP_RESTORE_COMPLETE) {
|
||||
private val completeNotificationBuilder = context.notificationBuilder(
|
||||
Notifications.CHANNEL_BACKUP_RESTORE_COMPLETE,
|
||||
) {
|
||||
setLargeIcon(BitmapFactory.decodeResource(context.resources, R.mipmap.ic_launcher))
|
||||
setSmallIcon(R.drawable.ic_tachi)
|
||||
setAutoCancel(false)
|
||||
@ -72,14 +76,25 @@ class BackupNotifier(private val context: Context) {
|
||||
addAction(
|
||||
R.drawable.ic_share_24dp,
|
||||
context.getString(R.string.action_share),
|
||||
NotificationReceiver.shareBackupPendingBroadcast(context, unifile.uri, Notifications.ID_BACKUP_COMPLETE),
|
||||
NotificationReceiver.shareBackupPendingBroadcast(
|
||||
context,
|
||||
unifile.uri,
|
||||
Notifications.ID_BACKUP_COMPLETE,
|
||||
),
|
||||
)
|
||||
|
||||
show(Notifications.ID_BACKUP_COMPLETE)
|
||||
}
|
||||
}
|
||||
|
||||
fun showRestoreProgress(content: String = "", contentTitle: String = context.getString(R.string.restoring_backup), progress: Int = 0, maxAmount: Int = 100): NotificationCompat.Builder {
|
||||
fun showRestoreProgress(
|
||||
content: String = "",
|
||||
contentTitle: String = context.getString(
|
||||
R.string.restoring_backup,
|
||||
),
|
||||
progress: Int = 0,
|
||||
maxAmount: Int = 100,
|
||||
): NotificationCompat.Builder {
|
||||
val builder = with(progressNotificationBuilder) {
|
||||
setContentTitle(contentTitle)
|
||||
|
||||
@ -114,7 +129,15 @@ class BackupNotifier(private val context: Context) {
|
||||
}
|
||||
}
|
||||
|
||||
fun showRestoreComplete(time: Long, errorCount: Int, path: String?, file: String?, contentTitle: String = context.getString(R.string.restore_completed)) {
|
||||
fun showRestoreComplete(
|
||||
time: Long,
|
||||
errorCount: Int,
|
||||
path: String?,
|
||||
file: String?,
|
||||
contentTitle: String = context.getString(
|
||||
R.string.restore_completed,
|
||||
),
|
||||
) {
|
||||
context.cancelNotification(Notifications.ID_RESTORE_PROGRESS)
|
||||
|
||||
val timeString = context.getString(
|
||||
@ -127,7 +150,14 @@ class BackupNotifier(private val context: Context) {
|
||||
|
||||
with(completeNotificationBuilder) {
|
||||
setContentTitle(contentTitle)
|
||||
setContentText(context.resources.getQuantityString(R.plurals.restore_completed_message, errorCount, timeString, errorCount))
|
||||
setContentText(
|
||||
context.resources.getQuantityString(
|
||||
R.plurals.restore_completed_message,
|
||||
errorCount,
|
||||
timeString,
|
||||
errorCount,
|
||||
),
|
||||
)
|
||||
|
||||
clearActions()
|
||||
if (errorCount > 0 && !path.isNullOrEmpty() && !file.isNullOrEmpty()) {
|
||||
|
@ -88,7 +88,13 @@ class BackupRestorer(
|
||||
val logFile = writeErrorLog()
|
||||
|
||||
if (sync) {
|
||||
notifier.showRestoreComplete(time, errors.size, logFile.parent, logFile.name, contentTitle = context.getString(R.string.library_sync_complete))
|
||||
notifier.showRestoreComplete(
|
||||
time,
|
||||
errors.size,
|
||||
logFile.parent,
|
||||
logFile.name,
|
||||
contentTitle = context.getString(R.string.library_sync_complete),
|
||||
)
|
||||
} else {
|
||||
notifier.showRestoreComplete(time, errors.size, logFile.parent, logFile.name)
|
||||
}
|
||||
@ -183,7 +189,12 @@ class BackupRestorer(
|
||||
)
|
||||
|
||||
restoreProgress += 1
|
||||
showRestoreProgress(restoreProgress, restoreAmount, context.getString(R.string.categories), context.getString(R.string.restoring_backup))
|
||||
showRestoreProgress(
|
||||
restoreProgress,
|
||||
restoreAmount,
|
||||
context.getString(R.string.categories),
|
||||
context.getString(R.string.restoring_backup),
|
||||
)
|
||||
}
|
||||
|
||||
private suspend fun restoreManga(backupManga: BackupManga, backupCategories: List<BackupCategory>, sync: Boolean) {
|
||||
@ -214,9 +225,19 @@ class BackupRestorer(
|
||||
|
||||
restoreProgress += 1
|
||||
if (sync) {
|
||||
showRestoreProgress(restoreProgress, restoreAmount, manga.title, context.getString(R.string.syncing_library))
|
||||
showRestoreProgress(
|
||||
restoreProgress,
|
||||
restoreAmount,
|
||||
manga.title,
|
||||
context.getString(R.string.syncing_library),
|
||||
)
|
||||
} else {
|
||||
showRestoreProgress(restoreProgress, restoreAmount, manga.title, context.getString(R.string.restoring_backup))
|
||||
showRestoreProgress(
|
||||
restoreProgress,
|
||||
restoreAmount,
|
||||
manga.title,
|
||||
context.getString(R.string.restoring_backup),
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
@ -603,7 +624,12 @@ class BackupRestorer(
|
||||
BackupCreateJob.setupTask(context)
|
||||
|
||||
restoreProgress += 1
|
||||
showRestoreProgress(restoreProgress, restoreAmount, context.getString(R.string.app_settings), context.getString(R.string.restoring_backup))
|
||||
showRestoreProgress(
|
||||
restoreProgress,
|
||||
restoreAmount,
|
||||
context.getString(R.string.app_settings),
|
||||
context.getString(R.string.restoring_backup),
|
||||
)
|
||||
}
|
||||
|
||||
private fun restoreSourcePreferences(preferences: List<BackupSourcePreferences>) {
|
||||
@ -613,7 +639,12 @@ class BackupRestorer(
|
||||
}
|
||||
|
||||
restoreProgress += 1
|
||||
showRestoreProgress(restoreProgress, restoreAmount, context.getString(R.string.source_settings), context.getString(R.string.restoring_backup))
|
||||
showRestoreProgress(
|
||||
restoreProgress,
|
||||
restoreAmount,
|
||||
context.getString(R.string.source_settings),
|
||||
context.getString(R.string.restoring_backup),
|
||||
)
|
||||
}
|
||||
|
||||
private fun restorePreferences(
|
||||
|
@ -148,7 +148,10 @@ class DownloadCache(
|
||||
if (sourceDir != null) {
|
||||
val mangaDir = sourceDir.mangaDirs[provider.getMangaDirName(mangaTitle)]
|
||||
if (mangaDir != null) {
|
||||
return provider.getValidChapterDirNames(chapterName, chapterScanlator).any { it in mangaDir.chapterDirs }
|
||||
return provider.getValidChapterDirNames(
|
||||
chapterName,
|
||||
chapterScanlator,
|
||||
).any { it in mangaDir.chapterDirs }
|
||||
}
|
||||
}
|
||||
return false
|
||||
|
@ -95,7 +95,10 @@ internal class DownloadNotifier(private val context: Context) {
|
||||
} else {
|
||||
val title = download.manga.title.chop(15)
|
||||
val quotedTitle = Pattern.quote(title)
|
||||
val chapter = download.chapter.name.replaceFirst("$quotedTitle[\\s]*[-]*[\\s]*".toRegex(RegexOption.IGNORE_CASE), "")
|
||||
val chapter = download.chapter.name.replaceFirst(
|
||||
"$quotedTitle[\\s]*[-]*[\\s]*".toRegex(RegexOption.IGNORE_CASE),
|
||||
"",
|
||||
)
|
||||
setContentTitle("$title - $chapter".chop(30))
|
||||
setContentText(downloadingProgressText)
|
||||
}
|
||||
|
@ -324,7 +324,11 @@ class Downloader(
|
||||
val availSpace = DiskUtil.getAvailableStorageSpace(mangaDir)
|
||||
if (availSpace != -1L && availSpace < MIN_DISK_SPACE) {
|
||||
download.status = Download.State.ERROR
|
||||
notifier.onError(context.getString(R.string.download_insufficient_space), download.chapter.name, download.manga.title)
|
||||
notifier.onError(
|
||||
context.getString(R.string.download_insufficient_space),
|
||||
download.chapter.name,
|
||||
download.manga.title,
|
||||
)
|
||||
return
|
||||
}
|
||||
|
||||
@ -432,13 +436,17 @@ class Downloader(
|
||||
tmpFile?.delete()
|
||||
|
||||
// Try to find the image file
|
||||
val imageFile = tmpDir.listFiles()?.firstOrNull { it.name!!.startsWith("$filename.") || it.name!!.startsWith("${filename}__001") }
|
||||
val imageFile = tmpDir.listFiles()?.firstOrNull {
|
||||
it.name!!.startsWith("$filename.") || it.name!!.startsWith("${filename}__001")
|
||||
}
|
||||
|
||||
try {
|
||||
// If the image is already downloaded, do nothing. Otherwise download from network
|
||||
val file = when {
|
||||
imageFile != null -> imageFile
|
||||
chapterCache.isImageInCache(page.imageUrl!!) -> copyImageFromCache(chapterCache.getImageFile(page.imageUrl!!), tmpDir, filename)
|
||||
chapterCache.isImageInCache(
|
||||
page.imageUrl!!,
|
||||
) -> copyImageFromCache(chapterCache.getImageFile(page.imageUrl!!), tmpDir, filename)
|
||||
else -> downloadImage(page, download.source, tmpDir, filename)
|
||||
}
|
||||
|
||||
|
@ -296,7 +296,9 @@ class LibraryUpdateJob(private val context: Context, workerParams: WorkerParamet
|
||||
val errorMessage = when (e) {
|
||||
is NoChaptersException -> context.getString(R.string.no_chapters_error)
|
||||
// failedUpdates will already have the source, don't need to copy it into the message
|
||||
is SourceNotInstalledException -> context.getString(R.string.loader_not_implemented_error)
|
||||
is SourceNotInstalledException -> context.getString(
|
||||
R.string.loader_not_implemented_error,
|
||||
)
|
||||
else -> e.message
|
||||
}
|
||||
failedUpdates.add(manga to errorMessage)
|
||||
@ -500,7 +502,9 @@ class LibraryUpdateJob(private val context: Context, workerParams: WorkerParamet
|
||||
if (interval > 0) {
|
||||
val restrictions = preferences.autoUpdateDeviceRestrictions().get()
|
||||
val constraints = Constraints(
|
||||
requiredNetworkType = if (DEVICE_NETWORK_NOT_METERED in restrictions) { NetworkType.UNMETERED } else { NetworkType.CONNECTED },
|
||||
requiredNetworkType = if (DEVICE_NETWORK_NOT_METERED in restrictions) {
|
||||
NetworkType.UNMETERED
|
||||
} else { NetworkType.CONNECTED },
|
||||
requiresCharging = DEVICE_CHARGING in restrictions,
|
||||
requiresBatteryNotLow = true,
|
||||
)
|
||||
@ -517,7 +521,11 @@ class LibraryUpdateJob(private val context: Context, workerParams: WorkerParamet
|
||||
.setBackoffCriteria(BackoffPolicy.LINEAR, 10, TimeUnit.MINUTES)
|
||||
.build()
|
||||
|
||||
context.workManager.enqueueUniquePeriodicWork(WORK_NAME_AUTO, ExistingPeriodicWorkPolicy.UPDATE, request)
|
||||
context.workManager.enqueueUniquePeriodicWork(
|
||||
WORK_NAME_AUTO,
|
||||
ExistingPeriodicWorkPolicy.UPDATE,
|
||||
request,
|
||||
)
|
||||
} else {
|
||||
context.workManager.cancelUniqueWork(WORK_NAME_AUTO)
|
||||
}
|
||||
|
@ -82,7 +82,12 @@ class LibraryUpdateNotifier(private val context: Context) {
|
||||
} else {
|
||||
val updatingText = manga.joinToString("\n") { it.title.chop(40) }
|
||||
progressNotificationBuilder
|
||||
.setContentTitle(context.getString(R.string.notification_updating_progress, percentFormatter.format(current.toFloat() / total)))
|
||||
.setContentTitle(
|
||||
context.getString(
|
||||
R.string.notification_updating_progress,
|
||||
percentFormatter.format(current.toFloat() / total),
|
||||
),
|
||||
)
|
||||
.setStyle(NotificationCompat.BigTextStyle().bigText(updatingText))
|
||||
}
|
||||
|
||||
@ -166,7 +171,13 @@ class LibraryUpdateNotifier(private val context: Context) {
|
||||
if (updates.size == 1 && !preferences.hideNotificationContent().get()) {
|
||||
setContentText(updates.first().first.title.chop(NOTIF_TITLE_MAX_LEN))
|
||||
} else {
|
||||
setContentText(context.resources.getQuantityString(R.plurals.notification_new_chapters_summary, updates.size, updates.size))
|
||||
setContentText(
|
||||
context.resources.getQuantityString(
|
||||
R.plurals.notification_new_chapters_summary,
|
||||
updates.size,
|
||||
updates.size,
|
||||
),
|
||||
)
|
||||
|
||||
if (!preferences.hideNotificationContent().get()) {
|
||||
setStyle(
|
||||
@ -196,7 +207,10 @@ class LibraryUpdateNotifier(private val context: Context) {
|
||||
launchUI {
|
||||
context.notify(
|
||||
updates.map { (manga, chapters) ->
|
||||
NotificationManagerCompat.NotificationWithIdAndTag(manga.id.hashCode(), createNewChaptersNotification(manga, chapters))
|
||||
NotificationManagerCompat.NotificationWithIdAndTag(
|
||||
manga.id.hashCode(),
|
||||
createNewChaptersNotification(manga, chapters),
|
||||
)
|
||||
},
|
||||
)
|
||||
}
|
||||
@ -292,17 +306,28 @@ class LibraryUpdateNotifier(private val context: Context) {
|
||||
// No sensible chapter numbers to show (i.e. no chapters have parsed chapter number)
|
||||
0 -> {
|
||||
// "1 new chapter" or "5 new chapters"
|
||||
context.resources.getQuantityString(R.plurals.notification_chapters_generic, chapters.size, chapters.size)
|
||||
context.resources.getQuantityString(
|
||||
R.plurals.notification_chapters_generic,
|
||||
chapters.size,
|
||||
chapters.size,
|
||||
)
|
||||
}
|
||||
// Only 1 chapter has a parsed chapter number
|
||||
1 -> {
|
||||
val remaining = chapters.size - displayableChapterNumbers.size
|
||||
if (remaining == 0) {
|
||||
// "Chapter 2.5"
|
||||
context.resources.getString(R.string.notification_chapters_single, displayableChapterNumbers.first())
|
||||
context.resources.getString(
|
||||
R.string.notification_chapters_single,
|
||||
displayableChapterNumbers.first(),
|
||||
)
|
||||
} else {
|
||||
// "Chapter 2.5 and 10 more"
|
||||
context.resources.getString(R.string.notification_chapters_single_and_more, displayableChapterNumbers.first(), remaining)
|
||||
context.resources.getString(
|
||||
R.string.notification_chapters_single_and_more,
|
||||
displayableChapterNumbers.first(),
|
||||
remaining,
|
||||
)
|
||||
}
|
||||
}
|
||||
// Everything else (i.e. multiple parsed chapter numbers)
|
||||
@ -312,10 +337,18 @@ class LibraryUpdateNotifier(private val context: Context) {
|
||||
// "Chapters 1, 2.5, 3, 4, 5 and 10 more"
|
||||
val remaining = displayableChapterNumbers.size - NOTIF_MAX_CHAPTERS
|
||||
val joinedChapterNumbers = displayableChapterNumbers.take(NOTIF_MAX_CHAPTERS).joinToString(", ")
|
||||
context.resources.getQuantityString(R.plurals.notification_chapters_multiple_and_more, remaining, joinedChapterNumbers, remaining)
|
||||
context.resources.getQuantityString(
|
||||
R.plurals.notification_chapters_multiple_and_more,
|
||||
remaining,
|
||||
joinedChapterNumbers,
|
||||
remaining,
|
||||
)
|
||||
} else {
|
||||
// "Chapters 1, 2.5, 3"
|
||||
context.resources.getString(R.string.notification_chapters_multiple, displayableChapterNumbers.joinToString(", "))
|
||||
context.resources.getString(
|
||||
R.string.notification_chapters_multiple,
|
||||
displayableChapterNumbers.joinToString(", "),
|
||||
)
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -329,7 +362,12 @@ class LibraryUpdateNotifier(private val context: Context) {
|
||||
flags = Intent.FLAG_ACTIVITY_CLEAR_TOP or Intent.FLAG_ACTIVITY_SINGLE_TOP
|
||||
action = Constants.SHORTCUT_UPDATES
|
||||
}
|
||||
return PendingIntent.getActivity(context, 0, intent, PendingIntent.FLAG_UPDATE_CURRENT or PendingIntent.FLAG_IMMUTABLE)
|
||||
return PendingIntent.getActivity(
|
||||
context,
|
||||
0,
|
||||
intent,
|
||||
PendingIntent.FLAG_UPDATE_CURRENT or PendingIntent.FLAG_IMMUTABLE,
|
||||
)
|
||||
}
|
||||
|
||||
companion object {
|
||||
|
@ -23,7 +23,12 @@ object NotificationHandler {
|
||||
flags = Intent.FLAG_ACTIVITY_CLEAR_TOP or Intent.FLAG_ACTIVITY_SINGLE_TOP
|
||||
action = Constants.SHORTCUT_DOWNLOADS
|
||||
}
|
||||
return PendingIntent.getActivity(context, 0, intent, PendingIntent.FLAG_UPDATE_CURRENT or PendingIntent.FLAG_IMMUTABLE)
|
||||
return PendingIntent.getActivity(
|
||||
context,
|
||||
0,
|
||||
intent,
|
||||
PendingIntent.FLAG_UPDATE_CURRENT or PendingIntent.FLAG_IMMUTABLE,
|
||||
)
|
||||
}
|
||||
|
||||
/**
|
||||
@ -37,7 +42,12 @@ object NotificationHandler {
|
||||
setDataAndType(uri, "image/*")
|
||||
flags = Intent.FLAG_ACTIVITY_NEW_TASK or Intent.FLAG_GRANT_READ_URI_PERMISSION
|
||||
}
|
||||
return PendingIntent.getActivity(context, 0, intent, PendingIntent.FLAG_UPDATE_CURRENT or PendingIntent.FLAG_IMMUTABLE)
|
||||
return PendingIntent.getActivity(
|
||||
context,
|
||||
0,
|
||||
intent,
|
||||
PendingIntent.FLAG_UPDATE_CURRENT or PendingIntent.FLAG_IMMUTABLE,
|
||||
)
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -306,7 +306,12 @@ class NotificationReceiver : BroadcastReceiver() {
|
||||
val intent = Intent(context, NotificationReceiver::class.java).apply {
|
||||
action = ACTION_RESUME_DOWNLOADS
|
||||
}
|
||||
return PendingIntent.getBroadcast(context, 0, intent, PendingIntent.FLAG_UPDATE_CURRENT or PendingIntent.FLAG_IMMUTABLE)
|
||||
return PendingIntent.getBroadcast(
|
||||
context,
|
||||
0,
|
||||
intent,
|
||||
PendingIntent.FLAG_UPDATE_CURRENT or PendingIntent.FLAG_IMMUTABLE,
|
||||
)
|
||||
}
|
||||
|
||||
/**
|
||||
@ -319,7 +324,12 @@ class NotificationReceiver : BroadcastReceiver() {
|
||||
val intent = Intent(context, NotificationReceiver::class.java).apply {
|
||||
action = ACTION_PAUSE_DOWNLOADS
|
||||
}
|
||||
return PendingIntent.getBroadcast(context, 0, intent, PendingIntent.FLAG_UPDATE_CURRENT or PendingIntent.FLAG_IMMUTABLE)
|
||||
return PendingIntent.getBroadcast(
|
||||
context,
|
||||
0,
|
||||
intent,
|
||||
PendingIntent.FLAG_UPDATE_CURRENT or PendingIntent.FLAG_IMMUTABLE,
|
||||
)
|
||||
}
|
||||
|
||||
/**
|
||||
@ -332,7 +342,12 @@ class NotificationReceiver : BroadcastReceiver() {
|
||||
val intent = Intent(context, NotificationReceiver::class.java).apply {
|
||||
action = ACTION_CLEAR_DOWNLOADS
|
||||
}
|
||||
return PendingIntent.getBroadcast(context, 0, intent, PendingIntent.FLAG_UPDATE_CURRENT or PendingIntent.FLAG_IMMUTABLE)
|
||||
return PendingIntent.getBroadcast(
|
||||
context,
|
||||
0,
|
||||
intent,
|
||||
PendingIntent.FLAG_UPDATE_CURRENT or PendingIntent.FLAG_IMMUTABLE,
|
||||
)
|
||||
}
|
||||
|
||||
/**
|
||||
@ -347,7 +362,12 @@ class NotificationReceiver : BroadcastReceiver() {
|
||||
action = ACTION_DISMISS_NOTIFICATION
|
||||
putExtra(EXTRA_NOTIFICATION_ID, notificationId)
|
||||
}
|
||||
return PendingIntent.getBroadcast(context, 0, intent, PendingIntent.FLAG_UPDATE_CURRENT or PendingIntent.FLAG_IMMUTABLE)
|
||||
return PendingIntent.getBroadcast(
|
||||
context,
|
||||
0,
|
||||
intent,
|
||||
PendingIntent.FLAG_UPDATE_CURRENT or PendingIntent.FLAG_IMMUTABLE,
|
||||
)
|
||||
}
|
||||
|
||||
/**
|
||||
@ -402,7 +422,12 @@ class NotificationReceiver : BroadcastReceiver() {
|
||||
putExtra(EXTRA_FILE_LOCATION, path)
|
||||
putExtra(EXTRA_NOTIFICATION_ID, notificationId)
|
||||
}
|
||||
return PendingIntent.getBroadcast(context, 0, intent, PendingIntent.FLAG_UPDATE_CURRENT or PendingIntent.FLAG_IMMUTABLE)
|
||||
return PendingIntent.getBroadcast(
|
||||
context,
|
||||
0,
|
||||
intent,
|
||||
PendingIntent.FLAG_UPDATE_CURRENT or PendingIntent.FLAG_IMMUTABLE,
|
||||
)
|
||||
}
|
||||
|
||||
/**
|
||||
@ -419,7 +444,12 @@ class NotificationReceiver : BroadcastReceiver() {
|
||||
putExtra(EXTRA_FILE_LOCATION, path)
|
||||
putExtra(EXTRA_NOTIFICATION_ID, notificationId)
|
||||
}
|
||||
return PendingIntent.getBroadcast(context, 0, intent, PendingIntent.FLAG_UPDATE_CURRENT or PendingIntent.FLAG_IMMUTABLE)
|
||||
return PendingIntent.getBroadcast(
|
||||
context,
|
||||
0,
|
||||
intent,
|
||||
PendingIntent.FLAG_UPDATE_CURRENT or PendingIntent.FLAG_IMMUTABLE,
|
||||
)
|
||||
}
|
||||
|
||||
/**
|
||||
@ -431,7 +461,12 @@ class NotificationReceiver : BroadcastReceiver() {
|
||||
*/
|
||||
internal fun openChapterPendingActivity(context: Context, manga: Manga, chapter: Chapter): PendingIntent {
|
||||
val newIntent = ReaderActivity.newIntent(context, manga.id, chapter.id)
|
||||
return PendingIntent.getActivity(context, manga.id.hashCode(), newIntent, PendingIntent.FLAG_UPDATE_CURRENT or PendingIntent.FLAG_IMMUTABLE)
|
||||
return PendingIntent.getActivity(
|
||||
context,
|
||||
manga.id.hashCode(),
|
||||
newIntent,
|
||||
PendingIntent.FLAG_UPDATE_CURRENT or PendingIntent.FLAG_IMMUTABLE,
|
||||
)
|
||||
}
|
||||
|
||||
/**
|
||||
@ -447,7 +482,12 @@ class NotificationReceiver : BroadcastReceiver() {
|
||||
.putExtra(Constants.MANGA_EXTRA, manga.id)
|
||||
.putExtra("notificationId", manga.id.hashCode())
|
||||
.putExtra("groupId", groupId)
|
||||
return PendingIntent.getActivity(context, manga.id.hashCode(), newIntent, PendingIntent.FLAG_UPDATE_CURRENT or PendingIntent.FLAG_IMMUTABLE)
|
||||
return PendingIntent.getActivity(
|
||||
context,
|
||||
manga.id.hashCode(),
|
||||
newIntent,
|
||||
PendingIntent.FLAG_UPDATE_CURRENT or PendingIntent.FLAG_IMMUTABLE,
|
||||
)
|
||||
}
|
||||
|
||||
/**
|
||||
@ -469,7 +509,12 @@ class NotificationReceiver : BroadcastReceiver() {
|
||||
putExtra(EXTRA_NOTIFICATION_ID, manga.id.hashCode())
|
||||
putExtra(EXTRA_GROUP_ID, groupId)
|
||||
}
|
||||
return PendingIntent.getBroadcast(context, manga.id.hashCode(), newIntent, PendingIntent.FLAG_UPDATE_CURRENT or PendingIntent.FLAG_IMMUTABLE)
|
||||
return PendingIntent.getBroadcast(
|
||||
context,
|
||||
manga.id.hashCode(),
|
||||
newIntent,
|
||||
PendingIntent.FLAG_UPDATE_CURRENT or PendingIntent.FLAG_IMMUTABLE,
|
||||
)
|
||||
}
|
||||
|
||||
/**
|
||||
@ -491,7 +536,12 @@ class NotificationReceiver : BroadcastReceiver() {
|
||||
putExtra(EXTRA_NOTIFICATION_ID, manga.id.hashCode())
|
||||
putExtra(EXTRA_GROUP_ID, groupId)
|
||||
}
|
||||
return PendingIntent.getBroadcast(context, manga.id.hashCode(), newIntent, PendingIntent.FLAG_UPDATE_CURRENT or PendingIntent.FLAG_IMMUTABLE)
|
||||
return PendingIntent.getBroadcast(
|
||||
context,
|
||||
manga.id.hashCode(),
|
||||
newIntent,
|
||||
PendingIntent.FLAG_UPDATE_CURRENT or PendingIntent.FLAG_IMMUTABLE,
|
||||
)
|
||||
}
|
||||
|
||||
/**
|
||||
@ -504,7 +554,12 @@ class NotificationReceiver : BroadcastReceiver() {
|
||||
val intent = Intent(context, NotificationReceiver::class.java).apply {
|
||||
action = ACTION_CANCEL_LIBRARY_UPDATE
|
||||
}
|
||||
return PendingIntent.getBroadcast(context, 0, intent, PendingIntent.FLAG_UPDATE_CURRENT or PendingIntent.FLAG_IMMUTABLE)
|
||||
return PendingIntent.getBroadcast(
|
||||
context,
|
||||
0,
|
||||
intent,
|
||||
PendingIntent.FLAG_UPDATE_CURRENT or PendingIntent.FLAG_IMMUTABLE,
|
||||
)
|
||||
}
|
||||
|
||||
/**
|
||||
@ -513,12 +568,21 @@ class NotificationReceiver : BroadcastReceiver() {
|
||||
* @param context context of application
|
||||
* @return [PendingIntent]
|
||||
*/
|
||||
internal fun downloadAppUpdatePendingBroadcast(context: Context, url: String, title: String? = null): PendingIntent {
|
||||
internal fun downloadAppUpdatePendingBroadcast(
|
||||
context: Context,
|
||||
url: String,
|
||||
title: String? = null,
|
||||
): PendingIntent {
|
||||
return Intent(context, NotificationReceiver::class.java).run {
|
||||
action = ACTION_START_APP_UPDATE
|
||||
putExtra(AppUpdateDownloadJob.EXTRA_DOWNLOAD_URL, url)
|
||||
title?.let { putExtra(AppUpdateDownloadJob.EXTRA_DOWNLOAD_TITLE, it) }
|
||||
PendingIntent.getBroadcast(context, 0, this, PendingIntent.FLAG_UPDATE_CURRENT or PendingIntent.FLAG_IMMUTABLE)
|
||||
PendingIntent.getBroadcast(
|
||||
context,
|
||||
0,
|
||||
this,
|
||||
PendingIntent.FLAG_UPDATE_CURRENT or PendingIntent.FLAG_IMMUTABLE,
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
@ -529,7 +593,12 @@ class NotificationReceiver : BroadcastReceiver() {
|
||||
val intent = Intent(context, NotificationReceiver::class.java).apply {
|
||||
action = ACTION_CANCEL_APP_UPDATE_DOWNLOAD
|
||||
}
|
||||
return PendingIntent.getBroadcast(context, 0, intent, PendingIntent.FLAG_UPDATE_CURRENT or PendingIntent.FLAG_IMMUTABLE)
|
||||
return PendingIntent.getBroadcast(
|
||||
context,
|
||||
0,
|
||||
intent,
|
||||
PendingIntent.FLAG_UPDATE_CURRENT or PendingIntent.FLAG_IMMUTABLE,
|
||||
)
|
||||
}
|
||||
|
||||
/**
|
||||
@ -543,7 +612,12 @@ class NotificationReceiver : BroadcastReceiver() {
|
||||
action = Constants.SHORTCUT_EXTENSIONS
|
||||
addFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP)
|
||||
}
|
||||
return PendingIntent.getActivity(context, 0, intent, PendingIntent.FLAG_UPDATE_CURRENT or PendingIntent.FLAG_IMMUTABLE)
|
||||
return PendingIntent.getActivity(
|
||||
context,
|
||||
0,
|
||||
intent,
|
||||
PendingIntent.FLAG_UPDATE_CURRENT or PendingIntent.FLAG_IMMUTABLE,
|
||||
)
|
||||
}
|
||||
|
||||
/**
|
||||
@ -560,7 +634,12 @@ class NotificationReceiver : BroadcastReceiver() {
|
||||
putExtra(EXTRA_URI, uri)
|
||||
putExtra(EXTRA_NOTIFICATION_ID, notificationId)
|
||||
}
|
||||
return PendingIntent.getBroadcast(context, 0, intent, PendingIntent.FLAG_UPDATE_CURRENT or PendingIntent.FLAG_IMMUTABLE)
|
||||
return PendingIntent.getBroadcast(
|
||||
context,
|
||||
0,
|
||||
intent,
|
||||
PendingIntent.FLAG_UPDATE_CURRENT or PendingIntent.FLAG_IMMUTABLE,
|
||||
)
|
||||
}
|
||||
|
||||
/**
|
||||
@ -591,7 +670,12 @@ class NotificationReceiver : BroadcastReceiver() {
|
||||
action = ACTION_CANCEL_RESTORE
|
||||
putExtra(EXTRA_NOTIFICATION_ID, notificationId)
|
||||
}
|
||||
return PendingIntent.getBroadcast(context, 0, intent, PendingIntent.FLAG_UPDATE_CURRENT or PendingIntent.FLAG_IMMUTABLE)
|
||||
return PendingIntent.getBroadcast(
|
||||
context,
|
||||
0,
|
||||
intent,
|
||||
PendingIntent.FLAG_UPDATE_CURRENT or PendingIntent.FLAG_IMMUTABLE,
|
||||
)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -48,11 +48,15 @@ class KavitaApi(private val client: OkHttpClient, interceptor: KavitaInterceptor
|
||||
when (it.code) {
|
||||
200 -> return it.parseAs<AuthenticationDto>().token
|
||||
401 -> {
|
||||
logcat(LogPriority.WARN) { "Unauthorized / api key not valid: Cleaned api URL: $apiUrl, Api key is empty: ${apiKey.isEmpty()}" }
|
||||
logcat(LogPriority.WARN) {
|
||||
"Unauthorized / API key not valid: API URL: $apiUrl, empty API key: ${apiKey.isEmpty()}"
|
||||
}
|
||||
throw IOException("Unauthorized / api key not valid")
|
||||
}
|
||||
500 -> {
|
||||
logcat(LogPriority.WARN) { "Error fetching JWT token. Cleaned api URL: $apiUrl, Api key is empty: ${apiKey.isEmpty()}" }
|
||||
logcat(
|
||||
LogPriority.WARN,
|
||||
) { "Error fetching JWT token. API URL: $apiUrl, empty API key: ${apiKey.isEmpty()}" }
|
||||
throw IOException("Error fetching JWT token")
|
||||
}
|
||||
else -> {}
|
||||
@ -62,12 +66,12 @@ class KavitaApi(private val client: OkHttpClient, interceptor: KavitaInterceptor
|
||||
// Not sure which one to catch
|
||||
} catch (e: SocketTimeoutException) {
|
||||
logcat(LogPriority.WARN) {
|
||||
"Could not fetch JWT token. Probably due to connectivity issue or the url '$apiUrl' is not available, skipping"
|
||||
"Could not fetch JWT token. Probably due to connectivity issue or URL '$apiUrl' not available, skipping"
|
||||
}
|
||||
return null
|
||||
} catch (e: Exception) {
|
||||
logcat(LogPriority.ERROR) {
|
||||
"Unhandled exception fetching JWT token for url: '$apiUrl'"
|
||||
"Unhandled exception fetching JWT token for URL: '$apiUrl'"
|
||||
}
|
||||
throw IOException(e)
|
||||
}
|
||||
@ -129,7 +133,10 @@ class KavitaApi(private val client: OkHttpClient, interceptor: KavitaInterceptor
|
||||
}
|
||||
}
|
||||
} catch (e: Exception) {
|
||||
logcat(LogPriority.WARN, e) { "Exception getting latest chapter read. Could not get itemRequest: $requestUrl" }
|
||||
logcat(
|
||||
LogPriority.WARN,
|
||||
e,
|
||||
) { "Exception getting latest chapter read. Could not get itemRequest: $requestUrl" }
|
||||
throw e
|
||||
}
|
||||
return 0F
|
||||
@ -164,8 +171,14 @@ class KavitaApi(private val client: OkHttpClient, interceptor: KavitaInterceptor
|
||||
}
|
||||
|
||||
suspend fun updateProgress(track: Track): Track {
|
||||
val requestUrl = "${getApiFromUrl(track.tracking_url)}/Tachiyomi/mark-chapter-until-as-read?seriesId=${getIdFromUrl(track.tracking_url)}&chapterNumber=${track.last_chapter_read}"
|
||||
authClient.newCall(POST(requestUrl, body = "{}".toRequestBody("application/json; charset=utf-8".toMediaTypeOrNull())))
|
||||
val requestUrl = "${getApiFromUrl(
|
||||
track.tracking_url,
|
||||
)}/Tachiyomi/mark-chapter-until-as-read?seriesId=${getIdFromUrl(
|
||||
track.tracking_url,
|
||||
)}&chapterNumber=${track.last_chapter_read}"
|
||||
authClient.newCall(
|
||||
POST(requestUrl, body = "{}".toRequestBody("application/json; charset=utf-8".toMediaTypeOrNull())),
|
||||
)
|
||||
.awaitSuccess()
|
||||
return getTrackSearch(track.tracking_url)
|
||||
}
|
||||
|
@ -101,7 +101,10 @@ class MyAnimeListApi(
|
||||
return withIOContext {
|
||||
val url = "$baseApiUrl/manga".toUri().buildUpon()
|
||||
.appendPath(id.toString())
|
||||
.appendQueryParameter("fields", "id,title,synopsis,num_chapters,main_picture,status,media_type,start_date")
|
||||
.appendQueryParameter(
|
||||
"fields",
|
||||
"id,title,synopsis,num_chapters,main_picture,status,media_type,start_date",
|
||||
)
|
||||
.build()
|
||||
with(json) {
|
||||
authClient.newCall(GET(url.toString()))
|
||||
|
@ -91,7 +91,9 @@ class Suwayomi(id: Long) : BaseTracker(id, "Suwayomi"), EnhancedTracker {
|
||||
null
|
||||
}
|
||||
|
||||
override fun isTrackFrom(track: DomainTrack, manga: DomainManga, source: Source?): Boolean = source?.let { accept(it) } == true
|
||||
override fun isTrackFrom(track: DomainTrack, manga: DomainManga, source: Source?): Boolean = source?.let {
|
||||
accept(it)
|
||||
} == true
|
||||
|
||||
override fun migrateTrack(track: DomainTrack, manga: DomainManga, newSource: Source): DomainTrack? =
|
||||
if (accept(newSource)) {
|
||||
|
@ -32,7 +32,9 @@ class AppUpdateChecker {
|
||||
|
||||
when (result) {
|
||||
is GetApplicationRelease.Result.NewUpdate -> AppUpdateNotifier(context).promptUpdate(result.release)
|
||||
is GetApplicationRelease.Result.ThirdPartyInstallation -> AppUpdateNotifier(context).promptFdroidUpdate()
|
||||
is GetApplicationRelease.Result.ThirdPartyInstallation -> AppUpdateNotifier(
|
||||
context,
|
||||
).promptFdroidUpdate()
|
||||
else -> {}
|
||||
}
|
||||
|
||||
|
@ -42,7 +42,12 @@ internal class AppUpdateNotifier(private val context: Context) {
|
||||
|
||||
val releaseIntent = Intent(Intent.ACTION_VIEW, release.releaseLink.toUri()).run {
|
||||
flags = Intent.FLAG_ACTIVITY_NEW_TASK or Intent.FLAG_ACTIVITY_CLEAR_TOP
|
||||
PendingIntent.getActivity(context, release.hashCode(), this, PendingIntent.FLAG_UPDATE_CURRENT or PendingIntent.FLAG_IMMUTABLE)
|
||||
PendingIntent.getActivity(
|
||||
context,
|
||||
release.hashCode(),
|
||||
this,
|
||||
PendingIntent.FLAG_UPDATE_CURRENT or PendingIntent.FLAG_IMMUTABLE,
|
||||
)
|
||||
}
|
||||
|
||||
with(notificationBuilder) {
|
||||
@ -143,7 +148,12 @@ internal class AppUpdateNotifier(private val context: Context) {
|
||||
setContentTitle(context.getString(R.string.update_check_notification_update_available))
|
||||
setContentText(context.getString(R.string.update_check_fdroid_migration_info))
|
||||
setSmallIcon(R.drawable.ic_tachi)
|
||||
setContentIntent(NotificationHandler.openUrl(context, "https://tachiyomi.org/docs/faq/general#how-do-i-update-from-the-f-droid-builds"))
|
||||
setContentIntent(
|
||||
NotificationHandler.openUrl(
|
||||
context,
|
||||
"https://tachiyomi.org/docs/faq/general#how-do-i-update-from-the-f-droid-builds",
|
||||
),
|
||||
)
|
||||
}
|
||||
notificationBuilder.show(Notifications.ID_APP_UPDATE_PROMPT)
|
||||
}
|
||||
|
@ -101,7 +101,12 @@ class PackageInstallerInstaller(private val service: Service) : Installer(servic
|
||||
}
|
||||
|
||||
init {
|
||||
ContextCompat.registerReceiver(service, packageActionReceiver, IntentFilter(INSTALL_ACTION), ContextCompat.RECEIVER_EXPORTED)
|
||||
ContextCompat.registerReceiver(
|
||||
service,
|
||||
packageActionReceiver,
|
||||
IntentFilter(INSTALL_ACTION),
|
||||
ContextCompat.RECEIVER_EXPORTED,
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -108,7 +108,9 @@ internal class ExtensionInstallReceiver(private val listener: Listener) :
|
||||
logcat(LogPriority.WARN) { "Package name not found" }
|
||||
return LoadResult.Error
|
||||
}
|
||||
return GlobalScope.async(Dispatchers.Default, CoroutineStart.DEFAULT) { ExtensionLoader.loadExtensionFromPkgName(context, pkgName) }.await()
|
||||
return GlobalScope.async(Dispatchers.Default, CoroutineStart.DEFAULT) {
|
||||
ExtensionLoader.loadExtensionFromPkgName(context, pkgName)
|
||||
}.await()
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -36,7 +36,9 @@ class AndroidSourceManager(
|
||||
|
||||
private val stubSourcesMap = ConcurrentHashMap<Long, StubSource>()
|
||||
|
||||
override val catalogueSources: Flow<List<CatalogueSource>> = sourcesMapFlow.map { it.values.filterIsInstance<CatalogueSource>() }
|
||||
override val catalogueSources: Flow<List<CatalogueSource>> = sourcesMapFlow.map {
|
||||
it.values.filterIsInstance<CatalogueSource>()
|
||||
}
|
||||
|
||||
init {
|
||||
scope.launch {
|
||||
|
@ -264,7 +264,9 @@ class BrowseSourceScreenModel(
|
||||
// Choose a category
|
||||
else -> {
|
||||
val preselectedIds = getCategories.await(manga.id).map { it.id }
|
||||
setDialog(Dialog.ChangeMangaCategory(manga, categories.mapAsCheckboxState { it.id in preselectedIds }))
|
||||
setDialog(
|
||||
Dialog.ChangeMangaCategory(manga, categories.mapAsCheckboxState { it.id in preselectedIds }),
|
||||
)
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -314,7 +316,10 @@ class BrowseSourceScreenModel(
|
||||
sealed class Listing(open val query: String?, open val filters: FilterList) {
|
||||
data object Popular : Listing(query = GetRemoteManga.QUERY_POPULAR, filters = FilterList())
|
||||
data object Latest : Listing(query = GetRemoteManga.QUERY_LATEST, filters = FilterList())
|
||||
data class Search(override val query: String?, override val filters: FilterList) : Listing(query = query, filters = filters)
|
||||
data class Search(
|
||||
override val query: String?,
|
||||
override val filters: FilterList,
|
||||
) : Listing(query = query, filters = filters)
|
||||
|
||||
companion object {
|
||||
fun valueOf(query: String?): Listing {
|
||||
|
@ -543,7 +543,8 @@ class LibraryScreenModel(
|
||||
}
|
||||
|
||||
fun getColumnsPreferenceForCurrentOrientation(isLandscape: Boolean): PreferenceMutableState<Int> {
|
||||
return (if (isLandscape) libraryPreferences.landscapeColumns() else libraryPreferences.portraitColumns()).asState(screenModelScope)
|
||||
return (if (isLandscape) libraryPreferences.landscapeColumns() else libraryPreferences.portraitColumns())
|
||||
.asState(screenModelScope)
|
||||
}
|
||||
|
||||
suspend fun getRandomLibraryItemForCurrentCategory(): LibraryItem? {
|
||||
|
@ -178,7 +178,9 @@ object LibraryTab : Tab {
|
||||
scope.launchIO {
|
||||
val chapter = screenModel.getNextUnreadChapter(it.manga)
|
||||
if (chapter != null) {
|
||||
context.startActivity(ReaderActivity.newIntent(context, chapter.mangaId, chapter.id))
|
||||
context.startActivity(
|
||||
ReaderActivity.newIntent(context, chapter.mangaId, chapter.id),
|
||||
)
|
||||
} else {
|
||||
snackbarHostState.showSnackbar(context.getString(R.string.no_next_chapter))
|
||||
}
|
||||
|
@ -388,7 +388,11 @@ class MainActivity : BaseActivity() {
|
||||
private fun handleIntentAction(intent: Intent, navigator: Navigator): Boolean {
|
||||
val notificationId = intent.getIntExtra("notificationId", -1)
|
||||
if (notificationId > -1) {
|
||||
NotificationReceiver.dismissNotification(applicationContext, notificationId, intent.getIntExtra("groupId", 0))
|
||||
NotificationReceiver.dismissNotification(
|
||||
applicationContext,
|
||||
notificationId,
|
||||
intent.getIntExtra("groupId", 0),
|
||||
)
|
||||
}
|
||||
|
||||
val tabToOpen = when (intent.action) {
|
||||
|
@ -112,8 +112,20 @@ class MangaScreen(
|
||||
screenModel.toggleFavorite()
|
||||
haptic.performHapticFeedback(HapticFeedbackType.LongPress)
|
||||
},
|
||||
onWebViewClicked = { openMangaInWebView(navigator, screenModel.manga, screenModel.source) }.takeIf { isHttpSource },
|
||||
onWebViewLongClicked = { copyMangaUrl(context, screenModel.manga, screenModel.source) }.takeIf { isHttpSource },
|
||||
onWebViewClicked = {
|
||||
openMangaInWebView(
|
||||
navigator,
|
||||
screenModel.manga,
|
||||
screenModel.source,
|
||||
)
|
||||
}.takeIf { isHttpSource },
|
||||
onWebViewLongClicked = {
|
||||
copyMangaUrl(
|
||||
context,
|
||||
screenModel.manga,
|
||||
screenModel.source,
|
||||
)
|
||||
}.takeIf { isHttpSource },
|
||||
onTrackingClicked = screenModel::showTrackDialog.takeIf { successState.trackingAvailable },
|
||||
onTagSearch = { scope.launch { performGenreSearch(navigator, it, screenModel.source!!) } },
|
||||
onFilterButtonClicked = screenModel::showSettingsDialog,
|
||||
@ -124,8 +136,12 @@ class MangaScreen(
|
||||
onShareClicked = { shareManga(context, screenModel.manga, screenModel.source) }.takeIf { isHttpSource },
|
||||
onDownloadActionClicked = screenModel::runDownloadAction.takeIf { !successState.source.isLocalOrStub() },
|
||||
onEditCategoryClicked = screenModel::showChangeCategoryDialog.takeIf { successState.manga.favorite },
|
||||
onEditFetchIntervalClicked = screenModel::showSetFetchIntervalDialog.takeIf { screenModel.isUpdateIntervalEnabled && successState.manga.favorite },
|
||||
onMigrateClicked = { navigator.push(MigrateSearchScreen(successState.manga.id)) }.takeIf { successState.manga.favorite },
|
||||
onEditFetchIntervalClicked = screenModel::showSetFetchIntervalDialog.takeIf {
|
||||
screenModel.isUpdateIntervalEnabled && successState.manga.favorite
|
||||
},
|
||||
onMigrateClicked = {
|
||||
navigator.push(MigrateSearchScreen(successState.manga.id))
|
||||
}.takeIf { successState.manga.favorite },
|
||||
onMultiBookmarkClicked = screenModel::bookmarkChapters,
|
||||
onMultiMarkAsReadClicked = screenModel::markChaptersRead,
|
||||
onMarkPreviousAsReadClicked = screenModel::markPreviousChapterRead,
|
||||
|
@ -160,8 +160,18 @@ class ReaderViewModel @JvmOverloads constructor(
|
||||
readerPreferences.skipFiltered().get() -> {
|
||||
(manga.unreadFilterRaw == Manga.CHAPTER_SHOW_READ && !it.read) ||
|
||||
(manga.unreadFilterRaw == Manga.CHAPTER_SHOW_UNREAD && it.read) ||
|
||||
(manga.downloadedFilterRaw == Manga.CHAPTER_SHOW_DOWNLOADED && !downloadManager.isChapterDownloaded(it.name, it.scanlator, manga.title, manga.source)) ||
|
||||
(manga.downloadedFilterRaw == Manga.CHAPTER_SHOW_NOT_DOWNLOADED && downloadManager.isChapterDownloaded(it.name, it.scanlator, manga.title, manga.source)) ||
|
||||
(
|
||||
manga.downloadedFilterRaw == Manga.CHAPTER_SHOW_DOWNLOADED &&
|
||||
!downloadManager.isChapterDownloaded(
|
||||
it.name, it.scanlator, manga.title, manga.source,
|
||||
)
|
||||
) ||
|
||||
(
|
||||
manga.downloadedFilterRaw == Manga.CHAPTER_SHOW_NOT_DOWNLOADED &&
|
||||
downloadManager.isChapterDownloaded(
|
||||
it.name, it.scanlator, manga.title, manga.source,
|
||||
)
|
||||
) ||
|
||||
(manga.bookmarkedFilterRaw == Manga.CHAPTER_SHOW_BOOKMARKED && !it.bookmark) ||
|
||||
(manga.bookmarkedFilterRaw == Manga.CHAPTER_SHOW_NOT_BOOKMARKED && it.bookmark)
|
||||
}
|
||||
@ -759,7 +769,13 @@ class ReaderViewModel @JvmOverloads constructor(
|
||||
val filename = generateFilename(manga, page)
|
||||
|
||||
// Pictures directory.
|
||||
val relativePath = if (readerPreferences.folderPerManga().get()) DiskUtil.buildValidFilename(manga.title) else ""
|
||||
val relativePath = if (readerPreferences.folderPerManga().get()) {
|
||||
DiskUtil.buildValidFilename(
|
||||
manga.title,
|
||||
)
|
||||
} else {
|
||||
""
|
||||
}
|
||||
|
||||
// Copy file in background.
|
||||
viewModelScope.launchNonCancellable {
|
||||
|
@ -75,7 +75,13 @@ class ChapterLoader(
|
||||
*/
|
||||
private fun getPageLoader(chapter: ReaderChapter): PageLoader {
|
||||
val dbChapter = chapter.chapter
|
||||
val isDownloaded = downloadManager.isChapterDownloaded(dbChapter.name, dbChapter.scanlator, manga.title, manga.source, skipCache = true)
|
||||
val isDownloaded = downloadManager.isChapterDownloaded(
|
||||
dbChapter.name,
|
||||
dbChapter.scanlator,
|
||||
manga.title,
|
||||
manga.source,
|
||||
skipCache = true,
|
||||
)
|
||||
return when {
|
||||
isDownloaded -> DownloadPageLoader(chapter, manga, source, downloadManager, downloadProvider)
|
||||
source is LocalSource -> source.getFormat(chapter.chapter).let { format ->
|
||||
|
@ -5,14 +5,54 @@ import androidx.annotation.DrawableRes
|
||||
import androidx.annotation.StringRes
|
||||
import eu.kanade.tachiyomi.R
|
||||
|
||||
enum class OrientationType(val flag: Int, @StringRes val stringRes: Int, @DrawableRes val iconRes: Int, val flagValue: Int) {
|
||||
DEFAULT(ActivityInfo.SCREEN_ORIENTATION_UNSPECIFIED, R.string.label_default, R.drawable.ic_screen_rotation_24dp, 0x00000000),
|
||||
FREE(ActivityInfo.SCREEN_ORIENTATION_UNSPECIFIED, R.string.rotation_free, R.drawable.ic_screen_rotation_24dp, 0x00000008),
|
||||
PORTRAIT(ActivityInfo.SCREEN_ORIENTATION_SENSOR_PORTRAIT, R.string.rotation_portrait, R.drawable.ic_stay_current_portrait_24dp, 0x00000010),
|
||||
LANDSCAPE(ActivityInfo.SCREEN_ORIENTATION_SENSOR_LANDSCAPE, R.string.rotation_landscape, R.drawable.ic_stay_current_landscape_24dp, 0x00000018),
|
||||
LOCKED_PORTRAIT(ActivityInfo.SCREEN_ORIENTATION_PORTRAIT, R.string.rotation_force_portrait, R.drawable.ic_screen_lock_portrait_24dp, 0x00000020),
|
||||
LOCKED_LANDSCAPE(ActivityInfo.SCREEN_ORIENTATION_LANDSCAPE, R.string.rotation_force_landscape, R.drawable.ic_screen_lock_landscape_24dp, 0x00000028),
|
||||
REVERSE_PORTRAIT(ActivityInfo.SCREEN_ORIENTATION_REVERSE_PORTRAIT, R.string.rotation_reverse_portrait, R.drawable.ic_stay_current_portrait_24dp, 0x00000030),
|
||||
enum class OrientationType(
|
||||
val flag: Int,
|
||||
@StringRes val stringRes: Int,
|
||||
@DrawableRes val iconRes: Int,
|
||||
val flagValue: Int,
|
||||
) {
|
||||
DEFAULT(
|
||||
ActivityInfo.SCREEN_ORIENTATION_UNSPECIFIED,
|
||||
R.string.label_default,
|
||||
R.drawable.ic_screen_rotation_24dp,
|
||||
0x00000000,
|
||||
),
|
||||
FREE(
|
||||
ActivityInfo.SCREEN_ORIENTATION_UNSPECIFIED,
|
||||
R.string.rotation_free,
|
||||
R.drawable.ic_screen_rotation_24dp,
|
||||
0x00000008,
|
||||
),
|
||||
PORTRAIT(
|
||||
ActivityInfo.SCREEN_ORIENTATION_SENSOR_PORTRAIT,
|
||||
R.string.rotation_portrait,
|
||||
R.drawable.ic_stay_current_portrait_24dp,
|
||||
0x00000010,
|
||||
),
|
||||
LANDSCAPE(
|
||||
ActivityInfo.SCREEN_ORIENTATION_SENSOR_LANDSCAPE,
|
||||
R.string.rotation_landscape,
|
||||
R.drawable.ic_stay_current_landscape_24dp,
|
||||
0x00000018,
|
||||
),
|
||||
LOCKED_PORTRAIT(
|
||||
ActivityInfo.SCREEN_ORIENTATION_PORTRAIT,
|
||||
R.string.rotation_force_portrait,
|
||||
R.drawable.ic_screen_lock_portrait_24dp,
|
||||
0x00000020,
|
||||
),
|
||||
LOCKED_LANDSCAPE(
|
||||
ActivityInfo.SCREEN_ORIENTATION_LANDSCAPE,
|
||||
R.string.rotation_force_landscape,
|
||||
R.drawable.ic_screen_lock_landscape_24dp,
|
||||
0x00000028,
|
||||
),
|
||||
REVERSE_PORTRAIT(
|
||||
ActivityInfo.SCREEN_ORIENTATION_REVERSE_PORTRAIT,
|
||||
R.string.rotation_reverse_portrait,
|
||||
R.drawable.ic_stay_current_portrait_24dp,
|
||||
0x00000030,
|
||||
),
|
||||
;
|
||||
|
||||
companion object {
|
||||
|
@ -30,9 +30,15 @@ class ReaderPreferences(
|
||||
|
||||
fun keepScreenOn() = preferenceStore.getBoolean("pref_keep_screen_on_key", true)
|
||||
|
||||
fun defaultReadingMode() = preferenceStore.getInt("pref_default_reading_mode_key", ReadingModeType.RIGHT_TO_LEFT.flagValue)
|
||||
fun defaultReadingMode() = preferenceStore.getInt(
|
||||
"pref_default_reading_mode_key",
|
||||
ReadingModeType.RIGHT_TO_LEFT.flagValue,
|
||||
)
|
||||
|
||||
fun defaultOrientationType() = preferenceStore.getInt("pref_default_orientation_type_key", OrientationType.FREE.flagValue)
|
||||
fun defaultOrientationType() = preferenceStore.getInt(
|
||||
"pref_default_orientation_type_key",
|
||||
OrientationType.FREE.flagValue,
|
||||
)
|
||||
|
||||
fun webtoonDoubleTapZoomEnabled() = preferenceStore.getBoolean("pref_enable_double_tap_zoom_webtoon", true)
|
||||
|
||||
|
@ -10,7 +10,11 @@ import eu.kanade.tachiyomi.ui.reader.viewer.pager.R2LPagerViewer
|
||||
import eu.kanade.tachiyomi.ui.reader.viewer.pager.VerticalPagerViewer
|
||||
import eu.kanade.tachiyomi.ui.reader.viewer.webtoon.WebtoonViewer
|
||||
|
||||
enum class ReadingModeType(@StringRes val stringRes: Int, @DrawableRes val iconRes: Int, val flagValue: Int) {
|
||||
enum class ReadingModeType(
|
||||
@StringRes val stringRes: Int,
|
||||
@DrawableRes val iconRes: Int,
|
||||
val flagValue: Int,
|
||||
) {
|
||||
DEFAULT(R.string.label_default, R.drawable.ic_reader_default_24dp, 0x00000000),
|
||||
LEFT_TO_RIGHT(R.string.left_to_right_viewer, R.drawable.ic_reader_ltr_24dp, 0x00000001),
|
||||
RIGHT_TO_LEFT(R.string.right_to_left_viewer, R.drawable.ic_reader_rtl_24dp, 0x00000002),
|
||||
|
@ -87,7 +87,9 @@ object UpdatesTab : Tab {
|
||||
LaunchedEffect(Unit) {
|
||||
screenModel.events.collectLatest { event ->
|
||||
when (event) {
|
||||
Event.InternalError -> screenModel.snackbarHostState.showSnackbar(context.getString(R.string.internal_error))
|
||||
Event.InternalError -> screenModel.snackbarHostState.showSnackbar(
|
||||
context.getString(R.string.internal_error),
|
||||
)
|
||||
is Event.LibraryUpdateTriggered -> {
|
||||
val msg = if (event.started) {
|
||||
R.string.updating_library
|
||||
|
@ -36,9 +36,17 @@ fun File.copyAndSetReadOnlyTo(target: File, overwrite: Boolean = false, bufferSi
|
||||
|
||||
if (target.exists()) {
|
||||
if (!overwrite) {
|
||||
throw FileAlreadyExistsException(file = this, other = target, reason = "The destination file already exists.")
|
||||
throw FileAlreadyExistsException(
|
||||
file = this,
|
||||
other = target,
|
||||
reason = "The destination file already exists.",
|
||||
)
|
||||
} else if (!target.delete()) {
|
||||
throw FileAlreadyExistsException(file = this, other = target, reason = "Tried to overwrite the destination, but failed to delete it.")
|
||||
throw FileAlreadyExistsException(
|
||||
file = this,
|
||||
other = target,
|
||||
reason = "Tried to overwrite the destination, but failed to delete it.",
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -59,7 +59,9 @@ fun Context.copyToClipboard(label: String, content: String) {
|
||||
* @param permission the permission to check.
|
||||
* @return true if it has permissions.
|
||||
*/
|
||||
fun Context.hasPermission(permission: String) = PermissionChecker.checkSelfPermission(this, permission) == PermissionChecker.PERMISSION_GRANTED
|
||||
fun Context.hasPermission(
|
||||
permission: String,
|
||||
) = PermissionChecker.checkSelfPermission(this, permission) == PermissionChecker.PERMISSION_GRANTED
|
||||
|
||||
val Context.powerManager: PowerManager
|
||||
get() = getSystemService()!!
|
||||
@ -105,7 +107,10 @@ fun Context.openInBrowser(uri: Uri, forceDefaultBrowser: Boolean = false) {
|
||||
private fun Context.defaultBrowserPackageName(): String? {
|
||||
val browserIntent = Intent(Intent.ACTION_VIEW, "http://".toUri())
|
||||
val resolveInfo = if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.TIRAMISU) {
|
||||
packageManager.resolveActivity(browserIntent, PackageManager.ResolveInfoFlags.of(PackageManager.MATCH_DEFAULT_ONLY.toLong()))
|
||||
packageManager.resolveActivity(
|
||||
browserIntent,
|
||||
PackageManager.ResolveInfoFlags.of(PackageManager.MATCH_DEFAULT_ONLY.toLong()),
|
||||
)
|
||||
} else {
|
||||
packageManager.resolveActivity(browserIntent, PackageManager.MATCH_DEFAULT_ONLY)
|
||||
}
|
||||
|
@ -49,7 +49,10 @@ fun Context.cancelNotification(id: Int) {
|
||||
* @param block the function that will execute inside the builder.
|
||||
* @return a notification to be displayed or updated.
|
||||
*/
|
||||
fun Context.notificationBuilder(channelId: String, block: (NotificationCompat.Builder.() -> Unit)? = null): NotificationCompat.Builder {
|
||||
fun Context.notificationBuilder(
|
||||
channelId: String,
|
||||
block: (NotificationCompat.Builder.() -> Unit)? = null,
|
||||
): NotificationCompat.Builder {
|
||||
val builder = NotificationCompat.Builder(this, channelId)
|
||||
.setColor(getColor(R.color.accent_blue))
|
||||
if (block != null) {
|
||||
|
@ -91,6 +91,7 @@ fun View?.isVisibleOnScreen(): Boolean {
|
||||
}
|
||||
val actualPosition = Rect()
|
||||
this.getGlobalVisibleRect(actualPosition)
|
||||
val screen = Rect(0, 0, Resources.getSystem().displayMetrics.widthPixels, Resources.getSystem().displayMetrics.heightPixels)
|
||||
val screen =
|
||||
Rect(0, 0, Resources.getSystem().displayMetrics.widthPixels, Resources.getSystem().displayMetrics.heightPixels)
|
||||
return actualPosition.intersect(screen)
|
||||
}
|
||||
|
@ -89,7 +89,8 @@ abstract class WebViewInterceptor(
|
||||
}
|
||||
}
|
||||
|
||||
// Based on [IsRequestHeaderSafe] in https://source.chromium.org/chromium/chromium/src/+/main:services/network/public/cpp/header_util.cc
|
||||
// Based on [IsRequestHeaderSafe] in
|
||||
// https://source.chromium.org/chromium/chromium/src/+/main:services/network/public/cpp/header_util.cc
|
||||
private fun isRequestHeaderSafe(_name: String, _value: String): Boolean {
|
||||
val name = _name.lowercase(Locale.ENGLISH)
|
||||
val value = _value.lowercase(Locale.ENGLISH)
|
||||
@ -97,4 +98,6 @@ private fun isRequestHeaderSafe(_name: String, _value: String): Boolean {
|
||||
if (name == "connection" && value == "upgrade") return false
|
||||
return true
|
||||
}
|
||||
private val unsafeHeaderNames = listOf("content-length", "host", "trailer", "te", "upgrade", "cookie2", "keep-alive", "transfer-encoding", "set-cookie")
|
||||
private val unsafeHeaderNames = listOf(
|
||||
"content-length", "host", "trailer", "te", "upgrade", "cookie2", "keep-alive", "transfer-encoding", "set-cookie",
|
||||
)
|
||||
|
@ -271,7 +271,9 @@ object ImageUtil {
|
||||
}
|
||||
}
|
||||
|
||||
private fun splitImageName(filenamePrefix: String, index: Int) = "${filenamePrefix}__${"%03d".format(index + 1)}.jpg"
|
||||
private fun splitImageName(filenamePrefix: String, index: Int) = "${filenamePrefix}__${"%03d".format(
|
||||
index + 1,
|
||||
)}.jpg"
|
||||
|
||||
private val BitmapFactory.Options.splitData
|
||||
get(): List<SplitData> {
|
||||
@ -356,10 +358,12 @@ object ImageUtil {
|
||||
val botLeftIsDark = botLeftPixel.isDark()
|
||||
val botRightIsDark = botRightPixel.isDark()
|
||||
|
||||
var darkBG = (topLeftIsDark && (botLeftIsDark || botRightIsDark || topRightIsDark || midLeftIsDark || topMidIsDark)) ||
|
||||
(topRightIsDark && (botRightIsDark || botLeftIsDark || midRightIsDark || topMidIsDark))
|
||||
var darkBG =
|
||||
(topLeftIsDark && (botLeftIsDark || botRightIsDark || topRightIsDark || midLeftIsDark || topMidIsDark)) ||
|
||||
(topRightIsDark && (botRightIsDark || botLeftIsDark || midRightIsDark || topMidIsDark))
|
||||
|
||||
val topAndBotPixels = listOf(topLeftPixel, topCenterPixel, topRightPixel, botRightPixel, bottomCenterPixel, botLeftPixel)
|
||||
val topAndBotPixels =
|
||||
listOf(topLeftPixel, topCenterPixel, topRightPixel, botRightPixel, bottomCenterPixel, botLeftPixel)
|
||||
val isNotWhiteAndCloseTo = topAndBotPixels.mapIndexed { index, color ->
|
||||
val other = topAndBotPixels[(index + 1) % topAndBotPixels.size]
|
||||
!color.isWhite() && color.isCloseTo(other)
|
||||
@ -504,10 +508,16 @@ object ImageUtil {
|
||||
darkBG -> {
|
||||
return ColorDrawable(blackColor)
|
||||
}
|
||||
topIsBlackStreak || (topCornersIsDark && topOffsetCornersIsDark && (topMidIsDark || overallBlackPixels > 9)) -> {
|
||||
topIsBlackStreak || (
|
||||
topCornersIsDark && topOffsetCornersIsDark &&
|
||||
(topMidIsDark || overallBlackPixels > 9)
|
||||
) -> {
|
||||
intArrayOf(blackColor, blackColor, whiteColor, whiteColor)
|
||||
}
|
||||
bottomIsBlackStreak || (botCornersIsDark && botOffsetCornersIsDark && (bottomCenterPixel.isDark() || overallBlackPixels > 9)) -> {
|
||||
bottomIsBlackStreak || (
|
||||
botCornersIsDark && botOffsetCornersIsDark &&
|
||||
(bottomCenterPixel.isDark() || overallBlackPixels > 9)
|
||||
) -> {
|
||||
intArrayOf(whiteColor, whiteColor, blackColor, blackColor)
|
||||
}
|
||||
else -> {
|
||||
|
@ -8,9 +8,8 @@ import eu.kanade.tachiyomi.source.model.SManga
|
||||
import tachiyomi.core.util.lang.withIOContext
|
||||
import tachiyomi.domain.source.repository.SourcePagingSourceType
|
||||
|
||||
class SourceSearchPagingSource(source: CatalogueSource, val query: String, val filters: FilterList) : SourcePagingSource(
|
||||
source,
|
||||
) {
|
||||
class SourceSearchPagingSource(source: CatalogueSource, val query: String, val filters: FilterList) :
|
||||
SourcePagingSource(source) {
|
||||
override suspend fun requestNextPage(currentPage: Int): MangasPage {
|
||||
return source.getSearchManga(currentPage, query, filters)
|
||||
}
|
||||
|
@ -16,5 +16,18 @@ data class ChapterUpdate(
|
||||
)
|
||||
|
||||
fun Chapter.toChapterUpdate(): ChapterUpdate {
|
||||
return ChapterUpdate(id, mangaId, read, bookmark, lastPageRead, dateFetch, sourceOrder, url, name, dateUpload, chapterNumber, scanlator)
|
||||
return ChapterUpdate(
|
||||
id,
|
||||
mangaId,
|
||||
read,
|
||||
bookmark,
|
||||
lastPageRead,
|
||||
dateFetch,
|
||||
sourceOrder,
|
||||
url,
|
||||
name,
|
||||
dateUpload,
|
||||
chapterNumber,
|
||||
scanlator,
|
||||
)
|
||||
}
|
||||
|
@ -95,7 +95,10 @@ fun VerticalFastScroller(
|
||||
}
|
||||
|
||||
val thumbBottomPadding = with(LocalDensity.current) { bottomContentPadding.toPx() }
|
||||
val heightPx = contentHeight.toFloat() - thumbTopPadding - thumbBottomPadding - listState.layoutInfo.afterContentPadding
|
||||
val heightPx = contentHeight.toFloat() -
|
||||
thumbTopPadding -
|
||||
thumbBottomPadding -
|
||||
listState.layoutInfo.afterContentPadding
|
||||
val thumbHeightPx = with(LocalDensity.current) { ThumbLength.toPx() }
|
||||
val trackHeightPx = heightPx - thumbHeightPx
|
||||
|
||||
@ -261,7 +264,10 @@ fun VerticalGridFastScroller(
|
||||
}
|
||||
|
||||
val thumbBottomPadding = with(LocalDensity.current) { bottomContentPadding.toPx() }
|
||||
val heightPx = contentHeight.toFloat() - thumbTopPadding - thumbBottomPadding - state.layoutInfo.afterContentPadding
|
||||
val heightPx = contentHeight.toFloat() -
|
||||
thumbTopPadding -
|
||||
thumbBottomPadding -
|
||||
state.layoutInfo.afterContentPadding
|
||||
val thumbHeightPx = with(LocalDensity.current) { ThumbLength.toPx() }
|
||||
val trackHeightPx = heightPx - thumbHeightPx
|
||||
|
||||
|
@ -121,7 +121,11 @@ private fun Modifier.drawScrollbar(
|
||||
items
|
||||
.fastFirstOrNull { (it.key as? String)?.startsWith(STICKY_HEADER_KEY_PREFIX)?.not() ?: true }!!
|
||||
.run {
|
||||
val startPadding = if (reverseDirection) layoutInfo.afterContentPadding else layoutInfo.beforeContentPadding
|
||||
val startPadding = if (reverseDirection) {
|
||||
layoutInfo.afterContentPadding
|
||||
} else {
|
||||
layoutInfo.beforeContentPadding
|
||||
}
|
||||
startPadding + ((estimatedItemSize * index - offset) / totalSize * viewportSize)
|
||||
}
|
||||
}
|
||||
|
@ -70,7 +70,10 @@ fun UpdatesWidget(
|
||||
.padding(horizontal = 3.dp),
|
||||
contentAlignment = Alignment.Center,
|
||||
) {
|
||||
val intent = Intent(LocalContext.current, Class.forName(Constants.MAIN_ACTIVITY)).apply {
|
||||
val intent = Intent(
|
||||
LocalContext.current,
|
||||
Class.forName(Constants.MAIN_ACTIVITY),
|
||||
).apply {
|
||||
action = Constants.SHORTCUT_MANGA
|
||||
putExtra(Constants.MANGA_EXTRA, mangaId)
|
||||
addFlags(Intent.FLAG_ACTIVITY_NEW_TASK)
|
||||
|
@ -72,7 +72,13 @@ actual class LocalSource(
|
||||
|
||||
override suspend fun getSearchManga(page: Int, query: String, filters: FilterList): MangasPage {
|
||||
val baseDirsFiles = fileSystem.getFilesInBaseDirectories()
|
||||
val lastModifiedLimit by lazy { if (filters === LATEST_FILTERS) System.currentTimeMillis() - LATEST_THRESHOLD else 0L }
|
||||
val lastModifiedLimit by lazy {
|
||||
if (filters === LATEST_FILTERS) {
|
||||
System.currentTimeMillis() - LATEST_THRESHOLD
|
||||
} else {
|
||||
0L
|
||||
}
|
||||
}
|
||||
var mangaDirs = baseDirsFiles
|
||||
// Filter out files that are hidden and is not a folder
|
||||
.filter { it.isDirectory && !it.name.startsWith('.') }
|
||||
|
Loading…
Reference in New Issue
Block a user