Compare commits

...

3 Commits

Author SHA1 Message Date
Fermín Cirella 911e959fcf Add option to reset custom manga info (#1118)
* Add option to reset custom manga info

* Remove extra line

* Update app/src/main/java/eu/kanade/tachiyomi/ui/library/LibraryScreenModel.kt

---------

Co-authored-by: jobobby04 <jobobby04@users.noreply.github.com>
2024-03-16 23:59:19 -04:00
KaiserBh a425cae73b fix: The trigger for library update wasn't working properly. (#1119)
Missed them, so it was always updating library without actually syncing even when the trigger was on.

Signed-off-by: KaiserBh <kaiserbh@proton.me>
2024-03-16 23:56:00 -04:00
Jobobby04 d12a9d329b [skip ci] Add instructions for supporting Cloud Sync Google Drive Impl 2024-03-16 15:59:00 -04:00
11 changed files with 80 additions and 27 deletions
+17
View File
@@ -52,3 +52,20 @@ When creating a fork, remember to:
- To avoid having your data polluting the main app's analytics and crash report services:
- If you want to use Firebase analytics, replace [`google-services.json`](https://github.com/tachiyomiorg/tachiyomi/blob/master/app/src/standard/google-services.json) with your own
- If you want to use ACRA crash reporting, replace the `ACRA_URI` endpoint in [`build.gradle.kts`](https://github.com/tachiyomiorg/tachiyomi/blob/master/app/build.gradle.kts) with your own
### Supporting Cloud Sync - Google Drive Implementation
1. Go to [Google Cloud Console](https://console.cloud.google.com)
2. Create a new project
3. Go to API & Services -> Library -> Google Drive API and click enable
4. Go to API & Services -> Oauth consent screen
5. Create it, fill in the app name, user support email, and developer contact information
6. In the next screen, click add or remove scopes, and add the `.../auth/drive.appdata` and `.../auth/drive.file` scopes
7. Don't add any test users and go back to the dashboard
8. Click publish
9. Go to API & Services -> Credentials
10. Click Create credentials -> Oauth client ID
11. Select Android, give it a name, and set eu.kanade.google.oauth as the package name
12. To get the SHA-1 key, run `keytool -printcert -jarfile app-standard-universal-release.apk` on your apk, and copy the listed SHA-1
13. Expand advanced settings, and enable Custom URL scheme
14. After that just download the json, name it to `client_secrets.json` and put it in `app/src/main/assets/`
@@ -73,7 +73,6 @@ class SyncPreferences(
syncOnChapterOpen = preferenceStore.getBoolean("sync_on_chapter_open", false).get(),
syncOnAppStart = preferenceStore.getBoolean("sync_on_app_start", false).get(),
syncOnAppResume = preferenceStore.getBoolean("sync_on_app_resume", false).get(),
syncOnLibraryUpdate = preferenceStore.getBoolean("sync_on_library_update", false).get(),
)
}
@@ -86,7 +85,5 @@ class SyncPreferences(
.set(syncTriggerOptions.syncOnAppStart)
preferenceStore.getBoolean("sync_on_app_resume", false)
.set(syncTriggerOptions.syncOnAppResume)
preferenceStore.getBoolean("sync_on_library_update", false)
.set(syncTriggerOptions.syncOnLibraryUpdate)
}
}
@@ -239,6 +239,7 @@ fun LibraryBottomActionMenu(
onClickCleanTitles: (() -> Unit)?,
onClickMigrate: (() -> Unit)?,
onClickAddToMangaDex: (() -> Unit)?,
onClickResetInfo: (() -> Unit)?,
// SY <--
modifier: Modifier = Modifier,
) {
@@ -267,7 +268,7 @@ fun LibraryBottomActionMenu(
}
}
// SY -->
val showOverflow = onClickCleanTitles != null || onClickAddToMangaDex != null
val showOverflow = onClickCleanTitles != null || onClickAddToMangaDex != null || onClickResetInfo != null
val configuration = LocalConfiguration.current
val moveMarkPrev = remember { !configuration.isTabletUi() }
var overFlowOpen by remember { mutableStateOf(false) }
@@ -364,6 +365,12 @@ fun LibraryBottomActionMenu(
onClick = onClickAddToMangaDex,
)
}
if (onClickResetInfo != null) {
DropdownMenuItem(
text = { Text(text = stringResource(SYMR.strings.reset_info)) },
onClick = onClickResetInfo,
)
}
}
} else {
Button(
@@ -817,19 +817,11 @@ class LibraryUpdateJob(private val context: Context, workerParams: WorkerParamet
KEY_GROUP_EXTRA to groupExtra,
// SY <--
)
val request = OneTimeWorkRequestBuilder<LibraryUpdateJob>()
.addTag(TAG)
.addTag(WORK_NAME_MANUAL)
.setInputData(inputData)
.build()
wm.enqueueUniqueWork(WORK_NAME_MANUAL, ExistingWorkPolicy.KEEP, request)
val syncPreferences: SyncPreferences = Injekt.get()
// Only proceed with SyncDataJob if sync is enabled and the specific sync on library update flag is set
val syncTriggerOpt = syncPreferences.getSyncTriggerOptions()
if (syncPreferences.isSyncEnabled() && syncTriggerOpt.syncOnLibraryUpdate
) {
// Always sync the data before library update if syncing is enabled.
if (syncPreferences.isSyncEnabled()) {
// Check if SyncDataJob is already running
if (wm.isRunning(SyncDataJob.TAG_MANUAL)) {
// SyncDataJob is already running
@@ -842,7 +834,6 @@ class LibraryUpdateJob(private val context: Context, workerParams: WorkerParamet
.build()
// Chain SyncDataJob to run before LibraryUpdateJob
val inputData = workDataOf(KEY_CATEGORY to category?.id)
val libraryUpdateJob = OneTimeWorkRequestBuilder<LibraryUpdateJob>()
.addTag(TAG)
.addTag(WORK_NAME_MANUAL)
@@ -853,7 +844,6 @@ class LibraryUpdateJob(private val context: Context, workerParams: WorkerParamet
.then(libraryUpdateJob)
.enqueue()
} else {
val inputData = workDataOf(KEY_CATEGORY to category?.id)
val request = OneTimeWorkRequestBuilder<LibraryUpdateJob>()
.addTag(TAG)
.addTag(WORK_NAME_MANUAL)
@@ -9,21 +9,18 @@ data class SyncTriggerOptions(
val syncOnChapterOpen: Boolean = false,
val syncOnAppStart: Boolean = false,
val syncOnAppResume: Boolean = false,
val syncOnLibraryUpdate: Boolean = false,
) {
fun asBooleanArray() = booleanArrayOf(
syncOnChapterRead,
syncOnChapterOpen,
syncOnAppStart,
syncOnAppResume,
syncOnLibraryUpdate,
)
fun anyEnabled() = syncOnChapterRead ||
syncOnChapterOpen ||
syncOnAppStart ||
syncOnAppResume ||
syncOnLibraryUpdate
syncOnAppResume
companion object {
val mainOptions = persistentListOf(
@@ -47,11 +44,6 @@ data class SyncTriggerOptions(
getter = SyncTriggerOptions::syncOnAppResume,
setter = { options, enabled -> options.copy(syncOnAppResume = enabled) },
),
Entry(
label = MR.strings.sync_on_library_update,
getter = SyncTriggerOptions::syncOnLibraryUpdate,
setter = { options, enabled -> options.copy(syncOnLibraryUpdate = enabled) },
),
)
fun fromBooleanArray(array: BooleanArray) = SyncTriggerOptions(
@@ -59,7 +51,6 @@ data class SyncTriggerOptions(
syncOnChapterOpen = array[1],
syncOnAppStart = array[2],
syncOnAppResume = array[3],
syncOnLibraryUpdate = array[4],
)
}
@@ -750,6 +750,24 @@ class LibraryScreenModel(
clearSelection()
}
}
fun resetInfo() {
state.value.selection.fastForEach { (manga) ->
val mangaInfo = CustomMangaInfo(
id = manga.id,
title = null,
author = null,
artist = null,
thumbnailUrl = null,
description = null,
genre = null,
status = null,
)
setCustomMangaInfo.set(mangaInfo)
}
clearSelection()
}
// SY <--
/**
@@ -1336,6 +1354,18 @@ class LibraryScreenModel(
val showAddToMangadex: Boolean by lazy {
selection.any { it.manga.source in mangaDexSourceIds }
}
val showResetInfo: Boolean by lazy {
selection.fastAny { (manga) ->
manga.title != manga.ogTitle ||
manga.author != manga.ogAuthor ||
manga.artist != manga.ogArtist ||
manga.thumbnailUrl != manga.ogThumbnailUrl ||
manga.description != manga.ogDescription ||
manga.genre != manga.ogGenre ||
manga.status != manga.ogStatus
}
}
// SY <--
fun getLibraryItemsByCategoryId(categoryId: Long): List<LibraryItem>? {
@@ -205,6 +205,7 @@ object LibraryTab : Tab {
}
},
onClickAddToMangaDex = screenModel::syncMangaToDex.takeIf { state.showAddToMangadex },
onClickResetInfo = screenModel::resetInfo.takeIf { state.showResetInfo },
// SY <--
)
},
@@ -201,6 +201,7 @@ private fun onViewCreated(manga: Manga, context: Context, binding: EditMangaDial
binding.mangaGenresTags.clearFocus()
binding.resetTags.setOnClickListener { resetTags(manga, binding, scope) }
binding.resetInfo.setOnClickListener { resetInfo(manga, binding, scope) }
}
private fun resetTags(manga: Manga, binding: EditMangaDialogBinding, scope: CoroutineScope) {
@@ -217,6 +218,15 @@ private fun loadCover(manga: Manga, context: Context, binding: EditMangaDialogBi
}
}
private fun resetInfo(manga: Manga, binding: EditMangaDialogBinding, scope: CoroutineScope) {
binding.title.setText("")
binding.mangaAuthor.setText("")
binding.mangaArtist.setText("")
binding.thumbnailUrl.setText("")
binding.mangaDescription.setText("")
resetTags(manga, binding, scope)
}
private fun ChipGroup.setChips(items: List<String>, scope: CoroutineScope) {
removeAllViews()
@@ -139,6 +139,16 @@
android:text="@string/reset_tags"
android:textAllCaps="false" />
<Button
android:id="@+id/reset_info"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginStart="16dp"
android:layout_marginEnd="16dp"
android:layout_marginBottom="8dp"
android:text="@string/reset_info"
android:textAllCaps="false" />
<View
android:layout_width="match_parent"
android:layout_height="1dp"
@@ -350,6 +350,7 @@
<!-- Entry Info Edit -->
<string name="reset_tags">Reset Tags</string>
<string name="add_tag">Add Tag</string>
<string name="reset_info">Reset Info</string>
<string name="title_hint">Title: %1$s</string>
<string name="description_hint">Description: %1$s</string>
<string name="author_hint">Author: %1$s</string>
@@ -591,7 +591,6 @@
<string name="sync_on_chapter_open">Sync on Chapter Open</string>
<string name="sync_on_app_start">Sync on App Start</string>
<string name="sync_on_app_resume">Sync on App Resume</string>
<string name="sync_on_library_update">Sync on Library Update</string>
<string name="sync_library">Sync library</string>
<!-- Advanced section -->