Merge branch 'mihonapp:main' into Add-Hikka-Tracker

This commit is contained in:
LorgOn 2024-10-17 18:42:14 +03:00 committed by GitHub
commit 32db1da753
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
29 changed files with 126 additions and 88 deletions

View File

@ -1,10 +1,13 @@
name: PR build check
on:
pull_request:
paths-ignore:
- '**.md'
- 'i18n/src/commonMain/moko-resources/**/strings.xml'
- 'i18n/src/commonMain/moko-resources/**/plurals.xml'
paths:
- '**'
- '!**.md'
- '!i18n/src/commonMain/moko-resources/**/strings.xml'
- '!i18n/src/commonMain/moko-resources/**/plurals.xml'
- 'i18n/src/commonMain/moko-resources/base/strings.xml'
- 'i18n/src/commonMain/moko-resources/base/plurals.xml'
concurrency:
group: ${{ github.workflow }}-${{ github.event.pull_request.number }}

22
.gitignore vendored
View File

@ -1,18 +1,16 @@
# Build files
.gradle
.kotlin
/local.properties
/.idea/workspace.xml
.DS_Store
build
# IDE files
*.iml
.idea/*
!.idea/icon.png
*iml
*.iml
/captures
# Built files
*/build
/build
*.apk
app/**/output.json
# Configuration files
local.properties
# Unnecessary file
*.swp
# macOS specific files
.DS_Store

3
app/.gitignore vendored
View File

@ -1,3 +0,0 @@
/build
*iml
*.iml

View File

@ -5,6 +5,7 @@ import eu.kanade.domain.track.model.toDomainTrack
import eu.kanade.tachiyomi.data.database.models.Track
import eu.kanade.tachiyomi.data.track.EnhancedTracker
import eu.kanade.tachiyomi.data.track.Tracker
import eu.kanade.tachiyomi.data.track.TrackerManager
import eu.kanade.tachiyomi.source.Source
import eu.kanade.tachiyomi.util.lang.convertEpochMillisZone
import logcat.LogPriority
@ -14,17 +15,16 @@ import tachiyomi.core.common.util.system.logcat
import tachiyomi.domain.chapter.interactor.GetChaptersByMangaId
import tachiyomi.domain.history.interactor.GetHistory
import tachiyomi.domain.manga.model.Manga
import tachiyomi.domain.track.interactor.GetTracks
import tachiyomi.domain.track.interactor.InsertTrack
import uy.kohesive.injekt.Injekt
import uy.kohesive.injekt.api.get
import java.time.ZoneOffset
class AddTracks(
private val getTracks: GetTracks,
private val insertTrack: InsertTrack,
private val syncChapterProgressWithTrack: SyncChapterProgressWithTrack,
private val getChaptersByMangaId: GetChaptersByMangaId,
private val trackerManager: TrackerManager,
) {
// TODO: update all trackers based on common data
@ -79,7 +79,7 @@ class AddTracks(
suspend fun bindEnhancedTrackers(manga: Manga, source: Source) = withNonCancellableContext {
withIOContext {
getTracks.await(manga.id)
trackerManager.loggedInTrackers()
.filterIsInstance<EnhancedTracker>()
.filter { it.accept(source) }
.forEach { service ->
@ -87,11 +87,11 @@ class AddTracks(
service.match(manga)?.let { track ->
track.manga_id = manga.id
(service as Tracker).bind(track)
insertTrack.await(track.toDomainTrack()!!)
insertTrack.await(track.toDomainTrack(idRequired = false)!!)
syncChapterProgressWithTrack.await(
manga.id,
track.toDomainTrack()!!,
track.toDomainTrack(idRequired = false)!!,
service,
)
}

View File

@ -166,23 +166,27 @@ private fun ColumnScope.SortPage(
val sortingMode = category.sort.type
val sortDescending = !category.sort.isAscending
val trackerSortOption = if (trackers.isEmpty()) {
emptyList()
} else {
listOf(MR.strings.action_sort_tracker_score to LibrarySort.Type.TrackerMean)
val options = remember(trackers.isEmpty()) {
val trackerMeanPair = if (trackers.isNotEmpty()) {
MR.strings.action_sort_tracker_score to LibrarySort.Type.TrackerMean
} else {
null
}
listOfNotNull(
MR.strings.action_sort_alpha to LibrarySort.Type.Alphabetical,
MR.strings.action_sort_total to LibrarySort.Type.TotalChapters,
MR.strings.action_sort_last_read to LibrarySort.Type.LastRead,
MR.strings.action_sort_last_manga_update to LibrarySort.Type.LastUpdate,
MR.strings.action_sort_unread_count to LibrarySort.Type.UnreadCount,
MR.strings.action_sort_latest_chapter to LibrarySort.Type.LatestChapter,
MR.strings.action_sort_chapter_fetch_date to LibrarySort.Type.ChapterFetchDate,
MR.strings.action_sort_date_added to LibrarySort.Type.DateAdded,
trackerMeanPair,
MR.strings.action_sort_random to LibrarySort.Type.Random,
)
}
listOf(
MR.strings.action_sort_alpha to LibrarySort.Type.Alphabetical,
MR.strings.action_sort_total to LibrarySort.Type.TotalChapters,
MR.strings.action_sort_last_read to LibrarySort.Type.LastRead,
MR.strings.action_sort_last_manga_update to LibrarySort.Type.LastUpdate,
MR.strings.action_sort_unread_count to LibrarySort.Type.UnreadCount,
MR.strings.action_sort_latest_chapter to LibrarySort.Type.LatestChapter,
MR.strings.action_sort_chapter_fetch_date to LibrarySort.Type.ChapterFetchDate,
MR.strings.action_sort_date_added to LibrarySort.Type.DateAdded,
MR.strings.action_sort_random to LibrarySort.Type.Random,
).plus(trackerSortOption).map { (titleRes, mode) ->
options.map { (titleRes, mode) ->
if (mode == LibrarySort.Type.Random) {
BaseSortItem(
label = stringResource(titleRes),

View File

@ -45,8 +45,8 @@ fun ReaderAppBars(
onClickTopAppBar: () -> Unit,
bookmarked: Boolean,
onToggleBookmarked: () -> Unit,
onOpenInBrowser: (() -> Unit)?,
onOpenInWebView: (() -> Unit)?,
onOpenInBrowser: (() -> Unit)?,
onShare: (() -> Unit)?,
viewer: Viewer?,
@ -120,14 +120,6 @@ fun ReaderAppBars(
onClick = onToggleBookmarked,
),
)
onOpenInBrowser?.let {
add(
AppBar.OverflowAction(
title = stringResource(MR.strings.action_open_in_browser),
onClick = it,
),
)
}
onOpenInWebView?.let {
add(
AppBar.OverflowAction(
@ -136,6 +128,14 @@ fun ReaderAppBars(
),
)
}
onOpenInBrowser?.let {
add(
AppBar.OverflowAction(
title = stringResource(MR.strings.action_open_in_browser),
onClick = it,
),
)
}
onShare?.let {
add(
AppBar.OverflowAction(

View File

@ -27,6 +27,7 @@ import tachiyomi.core.common.util.system.logcat
import tachiyomi.domain.backup.service.BackupPreferences
import tachiyomi.domain.manga.interactor.GetFavorites
import tachiyomi.domain.manga.model.Manga
import tachiyomi.domain.manga.repository.MangaRepository
import tachiyomi.i18n.MR
import uy.kohesive.injekt.Injekt
import uy.kohesive.injekt.api.get
@ -43,6 +44,7 @@ class BackupCreator(
private val parser: ProtoBuf = Injekt.get(),
private val getFavorites: GetFavorites = Injekt.get(),
private val backupPreferences: BackupPreferences = Injekt.get(),
private val mangaRepository: MangaRepository = Injekt.get(),
private val categoriesBackupCreator: CategoriesBackupCreator = CategoriesBackupCreator(),
private val mangaBackupCreator: MangaBackupCreator = MangaBackupCreator(),
@ -75,7 +77,9 @@ class BackupCreator(
throw IllegalStateException(context.stringResource(MR.strings.create_backup_file_error))
}
val backupManga = backupMangas(getFavorites.await(), options)
val nonFavoriteManga = if (options.readEntries) mangaRepository.getReadMangaNotInLibrary() else emptyList()
val backupManga = backupMangas(getFavorites.await() + nonFavoriteManga, options)
val backup = Backup(
backupManga = backupManga,
backupCategories = backupCategories(options),

View File

@ -10,6 +10,7 @@ data class BackupOptions(
val chapters: Boolean = true,
val tracking: Boolean = true,
val history: Boolean = true,
val readEntries: Boolean = true,
val appSettings: Boolean = true,
val extensionRepoSettings: Boolean = true,
val sourceSettings: Boolean = true,
@ -22,6 +23,7 @@ data class BackupOptions(
chapters,
tracking,
history,
readEntries,
appSettings,
extensionRepoSettings,
sourceSettings,
@ -60,6 +62,12 @@ data class BackupOptions(
getter = BackupOptions::categories,
setter = { options, enabled -> options.copy(categories = enabled) },
),
Entry(
label = MR.strings.non_library_settings,
getter = BackupOptions::readEntries,
setter = { options, enabled -> options.copy(readEntries = enabled) },
enabled = { it.libraryEntries },
),
)
val settingsOptions = persistentListOf(
@ -92,10 +100,11 @@ data class BackupOptions(
chapters = array[2],
tracking = array[3],
history = array[4],
appSettings = array[5],
extensionRepoSettings = array[6],
sourceSettings = array[7],
privateSettings = array[8],
readEntries = array[5],
appSettings = array[6],
extensionRepoSettings = array[7],
sourceSettings = array[8],
privateSettings = array[9],
)
}

View File

@ -390,8 +390,8 @@ class ReaderActivity : BaseActivity() {
onClickTopAppBar = ::openMangaScreen,
bookmarked = state.bookmarked,
onToggleBookmarked = viewModel::toggleChapterBookmark,
onOpenInBrowser = ::openChapterInBrowser.takeIf { isHttpSource },
onOpenInWebView = ::openChapterInWebView.takeIf { isHttpSource },
onOpenInBrowser = ::openChapterInBrowser.takeIf { isHttpSource },
onShare = ::shareChapter.takeIf { isHttpSource },
viewer = state.viewer,
@ -565,12 +565,6 @@ class ReaderActivity : BaseActivity() {
}
}
private fun openChapterInBrowser() {
assistUrl?.let {
openInBrowser(it.toUri(), forceDefaultBrowser = false)
}
}
private fun openChapterInWebView() {
val manga = viewModel.manga ?: return
val source = viewModel.getSource() ?: return
@ -580,6 +574,12 @@ class ReaderActivity : BaseActivity() {
}
}
private fun openChapterInBrowser() {
assistUrl?.let {
openInBrowser(it.toUri(), forceDefaultBrowser = false)
}
}
private fun shareChapter() {
assistUrl?.let {
val intent = it.toUri().toShareIntent(this, type = "text/plain")

1
buildSrc/.gitignore vendored
View File

@ -1 +0,0 @@
/build

View File

@ -6,6 +6,18 @@ plugins {
val libs = the<LibrariesForLibs>()
val xmlFormatExclude = buildList(2) {
add("**/build/**/*.xml")
projectDir
.resolve("src/commonMain/moko-resources")
.takeIf { it.isDirectory }
?.let(::fileTree)
?.matching { exclude("/base/**") }
?.let(::add)
}
.toTypedArray()
spotless {
kotlin {
target("**/*.kt", "**/*.kts")
@ -23,7 +35,7 @@ spotless {
}
format("xml") {
target("**/*.xml")
targetExclude("**/build/**/*.xml")
targetExclude(*xmlFormatExclude)
trimTrailingWhitespace()
endWithNewline()
}

View File

@ -1 +0,0 @@
/build

View File

@ -1 +0,0 @@
/build

View File

@ -1 +0,0 @@
/build

1
data/.gitignore vendored
View File

@ -1 +0,0 @@
/build

View File

@ -49,6 +49,10 @@ class MangaRepositoryImpl(
return handler.awaitList { mangasQueries.getFavorites(MangaMapper::mapManga) }
}
override suspend fun getReadMangaNotInLibrary(): List<Manga> {
return handler.awaitList { mangasQueries.getReadMangaNotInLibrary(MangaMapper::mapManga) }
}
override suspend fun getLibraryManga(): List<LibraryManga> {
return handler.awaitList { libraryViewQueries.library(MangaMapper::mapLibraryManga) }
}

View File

@ -78,6 +78,15 @@ SELECT *
FROM mangas
WHERE favorite = 1;
getReadMangaNotInLibrary:
SELECT *
FROM mangas
WHERE favorite = 0 AND _id IN (
SELECT DISTINCT chapters.manga_id
FROM chapters
WHERE read = 1 OR last_page_read != 0
);
getAllManga:
SELECT *
FROM mangas;

1
domain/.gitignore vendored
View File

@ -1 +0,0 @@
/build

View File

@ -17,6 +17,8 @@ interface MangaRepository {
suspend fun getFavorites(): List<Manga>
suspend fun getReadMangaNotInLibrary(): List<Manga>
suspend fun getLibraryManga(): List<LibraryManga>
fun getLibraryMangaAsFlow(): Flow<List<LibraryManga>>

View File

@ -1,5 +1,5 @@
[versions]
agp_version = "8.7.0"
agp_version = "8.7.1"
lifecycle_version = "2.8.6"
paging_version = "3.3.2"
interpolator_version = "1.0.0"

0
i18n/.gitignore vendored
View File

View File

@ -2,4 +2,4 @@
This module houses the string resources and translations.
Original English strings are manged in `src/commonMain/resources/MR/base/`. Translations are done externally via Weblate. See [our website](https://mihon.app/docs/contribute#translation) for more details.
Original English strings are managed in `src/commonMain/moko-resources/base/`. Translations are done externally via Weblate. See [our website](https://mihon.app/docs/contribute#translation) for more details.

View File

@ -546,6 +546,7 @@
<string name="source_settings">Source settings</string>
<string name="extensionRepo_settings">Extension repos</string>
<string name="private_settings">Include sensitive settings (e.g., tracker login tokens)</string>
<string name="non_library_settings">All read entries</string>
<string name="creating_backup">Creating backup</string>
<string name="creating_backup_error">Backup failed</string>
<string name="missing_storage_permission">Storage permissions not granted</string>

View File

@ -1 +0,0 @@
/build

View File

@ -1 +0,0 @@
/build

View File

@ -9,11 +9,11 @@ import androidx.compose.animation.fadeIn
import androidx.compose.animation.fadeOut
import androidx.compose.animation.shrinkHorizontally
import androidx.compose.foundation.interaction.MutableInteractionSource
import androidx.compose.foundation.layout.Arrangement
import androidx.compose.foundation.layout.Box
import androidx.compose.foundation.layout.Row
import androidx.compose.foundation.layout.Spacer
import androidx.compose.foundation.layout.padding
import androidx.compose.foundation.layout.sizeIn
import androidx.compose.foundation.layout.width
import androidx.compose.material3.FloatingActionButton
import androidx.compose.material3.FloatingActionButtonDefaults
import androidx.compose.material3.FloatingActionButtonElevation
@ -46,12 +46,8 @@ fun ExtendedFloatingActionButton(
contentColor: Color = contentColorFor(containerColor),
elevation: FloatingActionButtonElevation = FloatingActionButtonDefaults.elevation(),
) {
val minWidth by animateDpAsState(
targetValue = if (expanded) ExtendedFabMinimumWidth else FabContainerWidth,
label = "minWidth",
)
FloatingActionButton(
modifier = modifier.sizeIn(minWidth = minWidth),
modifier = modifier,
onClick = onClick,
interactionSource = interactionSource,
shape = shape,
@ -59,18 +55,29 @@ fun ExtendedFloatingActionButton(
contentColor = contentColor,
elevation = elevation,
) {
val minWidth by animateDpAsState(
targetValue = if (expanded) ExtendedFabMinimumWidth else FabContainerWidth,
animationSpec = tween(
durationMillis = 500,
easing = EasingEmphasizedCubicBezier,
),
label = "minWidth",
)
val startPadding by animateDpAsState(
targetValue = if (expanded) ExtendedFabIconSize / 2 else 0.dp,
animationSpec = tween(
durationMillis = if (expanded) 300 else 900,
easing = EasingEmphasizedCubicBezier,
),
label = "startPadding",
)
val endPadding by animateDpAsState(
targetValue = if (expanded) ExtendedFabTextPadding else 0.dp,
label = "endPadding",
)
Row(
modifier = Modifier.padding(start = startPadding, end = endPadding),
modifier = Modifier
.sizeIn(minWidth = minWidth)
.padding(start = startPadding),
verticalAlignment = Alignment.CenterVertically,
horizontalArrangement = Arrangement.Center,
) {
icon()
AnimatedVisibility(
@ -78,8 +85,7 @@ fun ExtendedFloatingActionButton(
enter = ExtendedFabExpandAnimation,
exit = ExtendedFabCollapseAnimation,
) {
Row {
Spacer(Modifier.width(ExtendedFabIconPadding))
Box(modifier = Modifier.padding(start = ExtendedFabIconPadding, end = ExtendedFabTextPadding)) {
text()
}
}

View File

@ -1 +0,0 @@
/build

View File

@ -1 +0,0 @@
/build

View File

@ -1 +0,0 @@
/build