Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat: add cross device sync #1005

Merged
merged 32 commits into from
Mar 16, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
32 commits
Select commit Hold shift + click to select a range
c586c98
feat: add cross device sync.
kaiserbh Jan 11, 2024
d2d2b38
chore: add google api.
kaiserbh Jan 11, 2024
26e96b2
chore: add SY specifics.
kaiserbh Jan 11, 2024
b8f34d5
feat: add backupSource, backupPref, and "SY" backupSavedSearches.
kaiserbh Jan 11, 2024
ac5ba84
feat(sync): Allow to choose what to sync.
kaiserbh Jan 13, 2024
f609455
oops.
kaiserbh Jan 13, 2024
71a802b
Merge branch 'master' of https://github.com/jobobby04/TachiyomiSY int…
kaiserbh Jan 26, 2024
961efcf
refactor: fix up the sync triggers, and update imports.
kaiserbh Jan 20, 2024
b6bc6e0
refactor
kaiserbh Jan 18, 2024
b699554
chore: review pointers.
kaiserbh Jan 20, 2024
5d86b5d
refactor: update imports
kaiserbh Jan 20, 2024
c312aa2
refactor: add more error guard for gdrive.
kaiserbh Jan 25, 2024
2e1fd11
fix: conflict and refactor.
kaiserbh Jan 26, 2024
e95e79c
fix: conflict and refactor.
kaiserbh Feb 18, 2024
c7efcbb
refactor: update imports.
kaiserbh Feb 1, 2024
aff0e9d
chore: fix some of detekt error.
kaiserbh Feb 5, 2024
ad7957f
refactor: add breaks and max retries.
kaiserbh Feb 6, 2024
6b0769f
feat: db changes to accommodate new syncing logic.
kaiserbh Feb 23, 2024
74ff7d2
chore: add migrations
kaiserbh Feb 23, 2024
3370904
chore: version and is_syncing fields.
kaiserbh Feb 23, 2024
e2d06cc
chore: add SY only stuff.
kaiserbh Feb 23, 2024
be0eed9
fix: oops wrong index.
kaiserbh Feb 23, 2024
f1c883a
chore: review pointers.
kaiserbh Feb 25, 2024
d7da83f
chore: remove the option to reset timestamp
kaiserbh Feb 25, 2024
75c3f86
refactor: Forgot to use the new versioning system.
kaiserbh Feb 23, 2024
ecbddd2
chore: remove isSyncing from Chapter/Manga model.
kaiserbh Feb 26, 2024
95a2a00
chore: remove unused import.
kaiserbh Feb 26, 2024
008a19f
chore: remove isSyncing leftover.
kaiserbh Feb 26, 2024
b8e570e
chore: remove isSyncing.
kaiserbh Feb 27, 2024
f8a996d
refactor: make sure the manga version is bumped.
kaiserbh Feb 29, 2024
4341602
chore: merge upstream changes
kaiserbh Mar 4, 2024
8baffbd
chore: merge upstream changes
kaiserbh Mar 16, 2024
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 3 additions & 0 deletions app/build.gradle.kts
Original file line number Diff line number Diff line change
Expand Up @@ -248,6 +248,9 @@ dependencies {
implementation(libs.compose.materialmotion)
implementation(libs.swipe)

implementation(libs.google.api.services.drive)
implementation(libs.google.api.client.oauth)

// Logging
implementation(libs.logcat)

Expand Down
23 changes: 22 additions & 1 deletion app/proguard-rules.pro
Original file line number Diff line number Diff line change
Expand Up @@ -126,6 +126,12 @@
-keep class com.google.firebase.installations.** { *; }
-keep interface com.google.firebase.installations.** { *; }

# Google Drive
-keep class com.google.api.services.** { *; }

# Google OAuth
-keep class com.google.api.client.** { *; }

# SY -->
# SqlCipher
-keepclassmembers class net.zetetic.database.sqlcipher.SQLiteCustomFunction { *; }
Expand Down Expand Up @@ -260,6 +266,9 @@
-keep,allowoptimization class * extends uy.kohesive.injekt.api.TypeReference
-keep,allowoptimization public class io.requery.android.database.sqlite.SQLiteConnection { *; }

# Keep apache http client
-keep class org.apache.http.** { *; }

# Suggested rules
-dontwarn com.oracle.svm.core.annotate.AutomaticFeature
-dontwarn com.oracle.svm.core.annotate.Delete
Expand All @@ -272,4 +281,16 @@
-dontwarn org.slf4j.impl.StaticLoggerBinder
-dontwarn java.lang.Module
-dontwarn org.graalvm.nativeimage.hosted.RuntimeResourceAccess
-dontwarn org.jspecify.annotations.NullMarked
-dontwarn org.jspecify.annotations.NullMarked
-dontwarn javax.naming.InvalidNameException
-dontwarn javax.naming.NamingException
-dontwarn javax.naming.directory.Attribute
-dontwarn javax.naming.directory.Attributes
-dontwarn javax.naming.ldap.LdapName
-dontwarn javax.naming.ldap.Rdn
-dontwarn org.ietf.jgss.GSSContext
-dontwarn org.ietf.jgss.GSSCredential
-dontwarn org.ietf.jgss.GSSException
-dontwarn org.ietf.jgss.GSSManager
-dontwarn org.ietf.jgss.GSSName
-dontwarn org.ietf.jgss.Oid
14 changes: 14 additions & 0 deletions app/src/main/AndroidManifest.xml
Original file line number Diff line number Diff line change
Expand Up @@ -188,6 +188,20 @@
<data android:host="shikimori-auth" />
</intent-filter>
</activity>
<activity
android:name=".ui.setting.track.GoogleDriveLoginActivity"
android:label="GoogleDrive"
android:exported="true">
<intent-filter>
<action android:name="android.intent.action.VIEW" />

<category android:name="android.intent.category.DEFAULT" />
<category android:name="android.intent.category.BROWSABLE" />

<data
android:scheme="eu.kanade.google.oauth" />
</intent-filter>
</activity>

<activity
android:name="exh.ui.login.EhLoginActivity"
Expand Down
1 change: 1 addition & 0 deletions app/src/main/assets/client_secrets.json
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
{"installed":{"client_id":"1046609911130-tbp79niehhuii976ekep1us06e9a8lne.apps.googleusercontent.com","project_id":"tachiyomi","auth_uri":"https://accounts.google.com/o/oauth2/auth","token_uri":"https://oauth2.googleapis.com/token","auth_provider_x509_cert_url":"https://www.googleapis.com/oauth2/v1/certs"}}
Original file line number Diff line number Diff line change
Expand Up @@ -39,4 +39,5 @@ fun Chapter.toDbChapter(): DbChapter = ChapterImpl().also {
it.date_upload = dateUpload
it.chapter_number = chapterNumber.toFloat()
it.source_order = sourceOrder.toInt()
it.last_modified = lastModifiedAt
}
92 changes: 92 additions & 0 deletions app/src/main/java/eu/kanade/domain/sync/SyncPreferences.kt
Original file line number Diff line number Diff line change
@@ -0,0 +1,92 @@
package eu.kanade.domain.sync

import eu.kanade.domain.sync.models.SyncSettings
import eu.kanade.tachiyomi.data.sync.models.SyncTriggerOptions
import tachiyomi.core.common.preference.Preference
import tachiyomi.core.common.preference.PreferenceStore
import java.util.UUID

class SyncPreferences(
private val preferenceStore: PreferenceStore,
) {
fun clientHost() = preferenceStore.getString("sync_client_host", "https://sync.tachiyomi.org")
fun clientAPIKey() = preferenceStore.getString("sync_client_api_key", "")
fun lastSyncTimestamp() = preferenceStore.getLong(Preference.appStateKey("last_sync_timestamp"), 0L)

fun syncInterval() = preferenceStore.getInt("sync_interval", 0)
fun syncService() = preferenceStore.getInt("sync_service", 0)

fun googleDriveAccessToken() = preferenceStore.getString(
Preference.appStateKey("google_drive_access_token"),
"",
)

fun googleDriveRefreshToken() = preferenceStore.getString(
Preference.appStateKey("google_drive_refresh_token"),
"",
)

fun uniqueDeviceID(): String {
val uniqueIDPreference = preferenceStore.getString("unique_device_id", "")

// Retrieve the current value of the preference
var uniqueID = uniqueIDPreference.get()
if (uniqueID.isBlank()) {
uniqueID = UUID.randomUUID().toString()
uniqueIDPreference.set(uniqueID)
}

return uniqueID
}

fun isSyncEnabled(): Boolean {
return syncService().get() != 0
}

fun getSyncSettings(): SyncSettings {
return SyncSettings(
libraryEntries = preferenceStore.getBoolean("library_entries", true).get(),
categories = preferenceStore.getBoolean("categories", true).get(),
chapters = preferenceStore.getBoolean("chapters", true).get(),
tracking = preferenceStore.getBoolean("tracking", true).get(),
history = preferenceStore.getBoolean("history", true).get(),
appSettings = preferenceStore.getBoolean("appSettings", true).get(),
sourceSettings = preferenceStore.getBoolean("sourceSettings", true).get(),
privateSettings = preferenceStore.getBoolean("privateSettings", true).get(),
)
}

fun setSyncSettings(syncSettings: SyncSettings) {
preferenceStore.getBoolean("library_entries", true).set(syncSettings.libraryEntries)
preferenceStore.getBoolean("categories", true).set(syncSettings.categories)
preferenceStore.getBoolean("chapters", true).set(syncSettings.chapters)
preferenceStore.getBoolean("tracking", true).set(syncSettings.tracking)
preferenceStore.getBoolean("history", true).set(syncSettings.history)
preferenceStore.getBoolean("appSettings", true).set(syncSettings.appSettings)
preferenceStore.getBoolean("sourceSettings", true).set(syncSettings.sourceSettings)
preferenceStore.getBoolean("privateSettings", true).set(syncSettings.privateSettings)
}

fun getSyncTriggerOptions(): SyncTriggerOptions {
return SyncTriggerOptions(
syncOnChapterRead = preferenceStore.getBoolean("sync_on_chapter_read", false).get(),
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(),
)
}

fun setSyncTriggerOptions(syncTriggerOptions: SyncTriggerOptions) {
preferenceStore.getBoolean("sync_on_chapter_read", false)
.set(syncTriggerOptions.syncOnChapterRead)
preferenceStore.getBoolean("sync_on_chapter_open", false)
.set(syncTriggerOptions.syncOnChapterOpen)
preferenceStore.getBoolean("sync_on_app_start", false)
.set(syncTriggerOptions.syncOnAppStart)
preferenceStore.getBoolean("sync_on_app_resume", false)
.set(syncTriggerOptions.syncOnAppResume)
preferenceStore.getBoolean("sync_on_library_update", false)
.set(syncTriggerOptions.syncOnLibraryUpdate)
}
}
12 changes: 12 additions & 0 deletions app/src/main/java/eu/kanade/domain/sync/models/SyncSettings.kt
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
package eu.kanade.domain.sync.models

data class SyncSettings(
val libraryEntries: Boolean = true,
val categories: Boolean = true,
val chapters: Boolean = true,
val tracking: Boolean = true,
val history: Boolean = true,
val appSettings: Boolean = true,
val sourceSettings: Boolean = true,
val privateSettings: Boolean = false,
)
Original file line number Diff line number Diff line change
Expand Up @@ -38,6 +38,7 @@ fun LibraryToolbar(
onClickRefresh: () -> Unit,
onClickGlobalUpdate: () -> Unit,
onClickOpenRandomManga: () -> Unit,
onClickSyncNow: () -> Unit,
// SY -->
onClickSyncExh: (() -> Unit)?,
// SY <--
Expand All @@ -60,6 +61,7 @@ fun LibraryToolbar(
onClickRefresh = onClickRefresh,
onClickGlobalUpdate = onClickGlobalUpdate,
onClickOpenRandomManga = onClickOpenRandomManga,
onClickSyncNow = onClickSyncNow,
// SY -->
onClickSyncExh = onClickSyncExh,
// SY <--
Expand All @@ -77,6 +79,7 @@ private fun LibraryRegularToolbar(
onClickRefresh: () -> Unit,
onClickGlobalUpdate: () -> Unit,
onClickOpenRandomManga: () -> Unit,
onClickSyncNow: () -> Unit,
// SY -->
onClickSyncExh: (() -> Unit)?,
// SY <--
Expand Down Expand Up @@ -125,7 +128,10 @@ private fun LibraryRegularToolbar(
title = stringResource(MR.strings.action_open_random_manga),
onClick = onClickOpenRandomManga,
),

AppBar.OverflowAction(
title = stringResource(MR.strings.sync_library),
onClick = onClickSyncNow,
),
).builder().apply {
// SY -->
if (onClickSyncExh != null) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -60,7 +60,6 @@ import eu.kanade.tachiyomi.util.CrashLogUtil
import eu.kanade.tachiyomi.util.storage.DiskUtil
import eu.kanade.tachiyomi.util.system.isDevFlavor
import eu.kanade.tachiyomi.util.system.isPreviewBuildType
import eu.kanade.tachiyomi.util.system.isReleaseBuildType
import eu.kanade.tachiyomi.util.system.isShizukuInstalled
import eu.kanade.tachiyomi.util.system.powerManager
import eu.kanade.tachiyomi.util.system.setDefaultSettings
Expand Down
Loading