diff --git a/app/src/main/java/eu/kanade/presentation/more/settings/screen/SettingsSyncScreen.kt b/app/src/main/java/eu/kanade/presentation/more/settings/screen/SettingsSyncScreen.kt index b994345f6..bc346082b 100644 --- a/app/src/main/java/eu/kanade/presentation/more/settings/screen/SettingsSyncScreen.kt +++ b/app/src/main/java/eu/kanade/presentation/more/settings/screen/SettingsSyncScreen.kt @@ -22,6 +22,8 @@ import eu.kanade.presentation.more.settings.Preference import eu.kanade.presentation.util.collectAsState import eu.kanade.tachiyomi.R import eu.kanade.tachiyomi.data.sync.SyncDataJob +import eu.kanade.tachiyomi.data.sync.SyncManager +import eu.kanade.tachiyomi.data.sync.SyncManager.SyncService import eu.kanade.tachiyomi.util.system.toast import kotlinx.coroutines.launch import tachiyomi.domain.sync.SyncPreferences @@ -37,7 +39,7 @@ object SettingsSyncScreen : SearchableSettings { @Composable override fun getPreferences(): List { - val syncPreferences = Injekt.get() + val syncPreferences = remember { Injekt.get() } val syncService by syncPreferences.syncService().collectAsState() return listOf( @@ -45,8 +47,8 @@ object SettingsSyncScreen : SearchableSettings { pref = syncPreferences.syncService(), title = stringResource(R.string.pref_sync_service), entries = mapOf( - 0 to stringResource(R.string.off), - 1 to stringResource(R.string.syncyomi), + SyncService.NONE.value to stringResource(R.string.off), + SyncService.SYNCYOMI.value to stringResource(R.string.syncyomi), ), onValueChanged = { true }, ), @@ -55,16 +57,10 @@ object SettingsSyncScreen : SearchableSettings { @Composable private fun getSyncServicePreferences(syncPreferences: SyncPreferences, syncService: Int): List { - val servicePreferences = when (syncService) { - 1 -> getSelfHostPreferences(syncPreferences) - else -> emptyList() - } - - return if (syncService != 0) { - servicePreferences + getSyncNowPref() + getAutomaticSyncGroup(syncPreferences) - } else { - servicePreferences - } + return when (SyncService.fromInt(syncService)) { + SyncService.NONE -> emptyList() + SyncService.SYNCYOMI -> getSelfHostPreferences(syncPreferences) + } + getSyncNowPref() + getAutomaticSyncGroup(syncPreferences) } @Composable @@ -102,7 +98,7 @@ object SettingsSyncScreen : SearchableSettings { onConfirm = { showDialog.value = false scope.launch { - if (!SyncDataJob.isManualJobRunning(context)) { + if (!SyncDataJob.isAnyJobRunning(context)) { SyncDataJob.startNow(context) } else { context.toast(R.string.sync_in_progress) @@ -156,7 +152,7 @@ object SettingsSyncScreen : SearchableSettings { true }, ), - Preference.PreferenceItem.InfoPreference(stringResource(R.string.last_synchronization) + ": " + formattedLastSync), + Preference.PreferenceItem.InfoPreference(stringResource(R.string.last_synchronization, formattedLastSync)), ), ) } diff --git a/app/src/main/java/eu/kanade/tachiyomi/data/backup/BackupManager.kt b/app/src/main/java/eu/kanade/tachiyomi/data/backup/BackupManager.kt index fdf29955c..0d209909c 100644 --- a/app/src/main/java/eu/kanade/tachiyomi/data/backup/BackupManager.kt +++ b/app/src/main/java/eu/kanade/tachiyomi/data/backup/BackupManager.kt @@ -454,7 +454,7 @@ class BackupManager( updatedChapter = updatedChapter.copy(id = dbChapter._id) updatedChapter = updatedChapter.copyFrom(dbChapter) if (dbChapter.read && !updatedChapter.read) { - updatedChapter = updatedChapter.copy(read = chapter.read, lastPageRead = dbChapter.last_page_read) + updatedChapter = updatedChapter.copy(read = true, lastPageRead = dbChapter.last_page_read) } else if (updatedChapter.lastPageRead == 0L && dbChapter.last_page_read != 0L) { updatedChapter = updatedChapter.copy(lastPageRead = dbChapter.last_page_read) } diff --git a/app/src/main/java/eu/kanade/tachiyomi/data/sync/SyncDataJob.kt b/app/src/main/java/eu/kanade/tachiyomi/data/sync/SyncDataJob.kt index 6f57cbce5..a45753d08 100644 --- a/app/src/main/java/eu/kanade/tachiyomi/data/sync/SyncDataJob.kt +++ b/app/src/main/java/eu/kanade/tachiyomi/data/sync/SyncDataJob.kt @@ -56,8 +56,10 @@ class SyncDataJob(private val context: Context, workerParams: WorkerParameters) private const val TAG_AUTO = "$TAG_JOB:auto" private const val TAG_MANUAL = "$TAG_JOB:manual" - fun isManualJobRunning(context: Context): Boolean { - return context.workManager.isRunning(TAG_MANUAL) + private val jobTagList = listOf(TAG_AUTO, TAG_MANUAL) + + fun isAnyJobRunning(context: Context): Boolean { + return jobTagList.any { context.workManager.isRunning(it) } } fun setupTask(context: Context, prefInterval: Int? = null) { diff --git a/app/src/main/java/eu/kanade/tachiyomi/data/sync/SyncManager.kt b/app/src/main/java/eu/kanade/tachiyomi/data/sync/SyncManager.kt index 9d988c53c..eb3e84d35 100644 --- a/app/src/main/java/eu/kanade/tachiyomi/data/sync/SyncManager.kt +++ b/app/src/main/java/eu/kanade/tachiyomi/data/sync/SyncManager.kt @@ -8,7 +8,7 @@ import eu.kanade.tachiyomi.data.backup.BackupRestoreJob import eu.kanade.tachiyomi.data.backup.models.Backup import eu.kanade.tachiyomi.data.backup.models.BackupChapter import eu.kanade.tachiyomi.data.backup.models.BackupManga -import eu.kanade.tachiyomi.data.sync.models.SData +import eu.kanade.tachiyomi.data.sync.models.SyncData import eu.kanade.tachiyomi.data.sync.models.SyncDevice import eu.kanade.tachiyomi.data.sync.models.SyncStatus import eu.kanade.tachiyomi.data.sync.service.SyncYomiSyncService @@ -87,7 +87,7 @@ class SyncManager( ) // Create the SyncData object - val syncData = SData( + val syncData = SyncData( sync = syncStatus, backup = backup, device = device, diff --git a/app/src/main/java/eu/kanade/tachiyomi/data/sync/models/Sync.kt b/app/src/main/java/eu/kanade/tachiyomi/data/sync/models/Sync.kt index d8ecf7f3d..7d1c9ea6e 100644 --- a/app/src/main/java/eu/kanade/tachiyomi/data/sync/models/Sync.kt +++ b/app/src/main/java/eu/kanade/tachiyomi/data/sync/models/Sync.kt @@ -17,7 +17,7 @@ data class SyncDevice( ) @Serializable -data class SData( +data class SyncData( val sync: SyncStatus? = null, val backup: Backup? = null, val device: SyncDevice? = null, diff --git a/app/src/main/java/eu/kanade/tachiyomi/data/sync/service/SyncService.kt b/app/src/main/java/eu/kanade/tachiyomi/data/sync/service/SyncService.kt index 8601978e9..f091cfe3e 100644 --- a/app/src/main/java/eu/kanade/tachiyomi/data/sync/service/SyncService.kt +++ b/app/src/main/java/eu/kanade/tachiyomi/data/sync/service/SyncService.kt @@ -2,7 +2,7 @@ package eu.kanade.tachiyomi.data.sync.service import android.content.Context import eu.kanade.tachiyomi.data.backup.models.Backup -import eu.kanade.tachiyomi.data.sync.models.SData +import eu.kanade.tachiyomi.data.sync.models.SyncData import kotlinx.serialization.json.Json import tachiyomi.domain.sync.SyncPreferences @@ -11,7 +11,7 @@ abstract class SyncService( val json: Json, val syncPreferences: SyncPreferences, ) { - abstract suspend fun doSync(syncData: SData): Backup? + abstract suspend fun doSync(syncData: SyncData): Backup? /** * Decodes the given sync data string into a Backup object. @@ -20,7 +20,7 @@ abstract class SyncService( * @return The decoded Backup object. */ protected fun decodeSyncBackup(data: String): Backup { - val sData = json.decodeFromString(SData.serializer(), data) - return sData.backup!! + val syncData = json.decodeFromString(SyncData.serializer(), data) + return syncData.backup!! } } diff --git a/app/src/main/java/eu/kanade/tachiyomi/data/sync/service/SyncYomiSyncService.kt b/app/src/main/java/eu/kanade/tachiyomi/data/sync/service/SyncYomiSyncService.kt index 873b961e3..8901d167c 100644 --- a/app/src/main/java/eu/kanade/tachiyomi/data/sync/service/SyncYomiSyncService.kt +++ b/app/src/main/java/eu/kanade/tachiyomi/data/sync/service/SyncYomiSyncService.kt @@ -3,7 +3,7 @@ package eu.kanade.tachiyomi.data.sync.service import android.content.Context import eu.kanade.tachiyomi.data.backup.models.Backup import eu.kanade.tachiyomi.data.sync.SyncNotifier -import eu.kanade.tachiyomi.data.sync.models.SData +import eu.kanade.tachiyomi.data.sync.models.SyncData import eu.kanade.tachiyomi.network.POST import kotlinx.serialization.encodeToString import kotlinx.serialization.json.Json @@ -22,7 +22,7 @@ class SyncYomiSyncService( syncPreferences: SyncPreferences, private val notifier: SyncNotifier, ) : SyncService(context, json, syncPreferences) { - override suspend fun doSync(syncData: SData): Backup? { + override suspend fun doSync(syncData: SyncData): Backup? { logcat( LogPriority.DEBUG, ) { "SyncYomi sync started!" } @@ -49,7 +49,7 @@ class SyncYomiSyncService( val responseBody = response.body.string() if (response.isSuccessful) { - val syncDataResponse: SData = json.decodeFromString(responseBody) + val syncDataResponse: SyncData = json.decodeFromString(responseBody) // If the device ID is 0 and not equal to the server device ID (this happens when the DB is fresh and the app is not), update it if (syncPreferences.deviceID().get() == 0 || syncPreferences.deviceID().get() != syncDataResponse.device?.id) { diff --git a/data/src/main/sqldelight/tachiyomi/migrations/24.sqm b/data/src/main/sqldelight/tachiyomi/migrations/24.sqm index d80030ba1..c34ccfa0f 100644 --- a/data/src/main/sqldelight/tachiyomi/migrations/24.sqm +++ b/data/src/main/sqldelight/tachiyomi/migrations/24.sqm @@ -1,144 +1 @@ -import kotlin.collections.List; -import eu.kanade.tachiyomi.source.model.UpdateStrategy; - ALTER TABLE mangas ADD COLUMN calculate_interval INTEGER DEFAULT 0 NOT NULL; - --- Drop indices -DROP INDEX IF EXISTS library_favorite_index; -DROP INDEX IF EXISTS mangas_url_index; -DROP INDEX IF EXISTS chapters_manga_id_index; -DROP INDEX IF EXISTS chapters_unread_by_manga_index; - --- Rename existing tables to temporary tables -ALTER TABLE mangas RENAME TO mangas_temp; -ALTER TABLE chapters RENAME TO chapters_temp; -ALTER TABLE mangas_categories RENAME TO mangas_categories_temp; - --- Create new tables with updated schema -CREATE TABLE mangas( - _id INTEGER NOT NULL PRIMARY KEY, - source INTEGER NOT NULL, - url TEXT NOT NULL, - artist TEXT, - author TEXT, - description TEXT, - genre TEXT AS List, - title TEXT NOT NULL, - status INTEGER NOT NULL, - thumbnail_url TEXT, - favorite INTEGER AS Boolean NOT NULL, - last_update INTEGER AS Long, - next_update INTEGER AS Long, - initialized INTEGER AS Boolean NOT NULL, - viewer INTEGER NOT NULL, - chapter_flags INTEGER NOT NULL, - cover_last_modified INTEGER AS Long NOT NULL, - date_added INTEGER AS Long NOT NULL, - update_strategy INTEGER AS UpdateStrategy NOT NULL DEFAULT 0, - last_modified_at INTEGER AS Long -); - -CREATE TABLE mangas_categories( - _id INTEGER NOT NULL PRIMARY KEY, - manga_id INTEGER NOT NULL, - category_id INTEGER NOT NULL, - last_modified_at INTEGER AS Long, - FOREIGN KEY(category_id) REFERENCES categories (_id) - ON DELETE CASCADE, - FOREIGN KEY(manga_id) REFERENCES mangas (_id) - ON DELETE CASCADE -); - -CREATE TABLE chapters( - _id INTEGER NOT NULL PRIMARY KEY, - manga_id INTEGER NOT NULL, - url TEXT NOT NULL, - name TEXT NOT NULL, - scanlator TEXT, - read INTEGER AS Boolean NOT NULL, - bookmark INTEGER AS Boolean NOT NULL, - last_page_read INTEGER NOT NULL, - chapter_number REAL AS Float NOT NULL, - source_order INTEGER NOT NULL, - date_fetch INTEGER AS Long NOT NULL, - date_upload INTEGER AS Long NOT NULL, - last_modified_at INTEGER AS Long, - FOREIGN KEY(manga_id) REFERENCES mangas (_id) - ON DELETE CASCADE -); - --- Copy data from temporary tables to new tables -INSERT INTO mangas -SELECT _id, source, url, artist, author, description, genre, title, status, thumbnail_url, favorite, last_update, next_update, initialized, viewer, chapter_flags, cover_last_modified, date_added, update_strategy, NULL -FROM mangas_temp; - -INSERT INTO chapters -SELECT _id, manga_id, url, name, scanlator, read, bookmark, last_page_read, chapter_number, source_order, date_fetch, date_upload, NULL -FROM chapters_temp; - -INSERT INTO mangas_categories -SELECT _id, manga_id, category_id, NULL -FROM mangas_categories_temp; - --- Create indices -CREATE INDEX library_favorite_index ON mangas(favorite) WHERE favorite = 1; -CREATE INDEX mangas_url_index ON mangas(url); -CREATE INDEX chapters_manga_id_index ON chapters(manga_id); -CREATE INDEX chapters_unread_by_manga_index ON chapters(manga_id, read) WHERE read = 0; - --- Drop temporary tables -DROP TABLE IF EXISTS mangas_temp; -DROP TABLE IF EXISTS chapters_temp; -DROP TABLE IF EXISTS mangas_categories_temp; - - --- Create triggers -DROP TRIGGER IF EXISTS update_last_modified_at_mangas; -CREATE TRIGGER update_last_modified_at_mangas -AFTER UPDATE ON mangas -FOR EACH ROW -BEGIN - UPDATE mangas - SET last_modified_at = strftime('%s', 'now') - WHERE _id = new._id; -END; - -DROP TRIGGER IF EXISTS insert_last_modified_at_mangas; -CREATE TRIGGER insert_last_modified_at_mangas -AFTER INSERT ON mangas -FOR EACH ROW -BEGIN - UPDATE mangas - SET last_modified_at = strftime('%s', 'now') - WHERE _id = new._id; -END; - -DROP TRIGGER IF EXISTS update_last_modified_at_chapters; -CREATE TRIGGER update_last_modified_at_chapters -AFTER UPDATE ON chapters -FOR EACH ROW -BEGIN - UPDATE chapters - SET last_modified_at = strftime('%s', 'now') - WHERE _id = new._id; -END; - -DROP TRIGGER IF EXISTS update_last_modified_at_mangas_categories; -CREATE TRIGGER update_last_modified_at_mangas_categories -AFTER UPDATE ON mangas_categories -FOR EACH ROW -BEGIN - UPDATE mangas_categories - SET last_modified_at = strftime('%s', 'now') - WHERE _id = new._id; -END; - -DROP TRIGGER IF EXISTS insert_last_modified_at_mangas_categories; -CREATE TRIGGER insert_last_modified_at_mangas_categories -AFTER INSERT ON mangas_categories -FOR EACH ROW -BEGIN - UPDATE mangas_categories - SET last_modified_at = strftime('%s', 'now') - WHERE _id = new._id; -END; diff --git a/data/src/main/sqldelight/tachiyomi/migrations/25.sqm b/data/src/main/sqldelight/tachiyomi/migrations/25.sqm new file mode 100644 index 000000000..50e89b5a8 --- /dev/null +++ b/data/src/main/sqldelight/tachiyomi/migrations/25.sqm @@ -0,0 +1,142 @@ +import kotlin.collections.List; +import eu.kanade.tachiyomi.source.model.UpdateStrategy; + +-- Drop indices +DROP INDEX IF EXISTS library_favorite_index; +DROP INDEX IF EXISTS mangas_url_index; +DROP INDEX IF EXISTS chapters_manga_id_index; +DROP INDEX IF EXISTS chapters_unread_by_manga_index; + +-- Rename existing tables to temporary tables +ALTER TABLE mangas RENAME TO mangas_temp; +ALTER TABLE chapters RENAME TO chapters_temp; +ALTER TABLE mangas_categories RENAME TO mangas_categories_temp; + +-- Create new tables with updated schema +CREATE TABLE mangas( + _id INTEGER NOT NULL PRIMARY KEY, + source INTEGER NOT NULL, + url TEXT NOT NULL, + artist TEXT, + author TEXT, + description TEXT, + genre TEXT AS List, + title TEXT NOT NULL, + status INTEGER NOT NULL, + thumbnail_url TEXT, + favorite INTEGER AS Boolean NOT NULL, + last_update INTEGER AS Long, + next_update INTEGER AS Long, + initialized INTEGER AS Boolean NOT NULL, + viewer INTEGER NOT NULL, + chapter_flags INTEGER NOT NULL, + cover_last_modified INTEGER AS Long NOT NULL, + date_added INTEGER AS Long NOT NULL, + update_strategy INTEGER AS UpdateStrategy NOT NULL DEFAULT 0, + last_modified_at INTEGER AS Long +); + +CREATE TABLE mangas_categories( + _id INTEGER NOT NULL PRIMARY KEY, + manga_id INTEGER NOT NULL, + category_id INTEGER NOT NULL, + last_modified_at INTEGER AS Long, + FOREIGN KEY(category_id) REFERENCES categories (_id) + ON DELETE CASCADE, + FOREIGN KEY(manga_id) REFERENCES mangas (_id) + ON DELETE CASCADE +); + +CREATE TABLE chapters( + _id INTEGER NOT NULL PRIMARY KEY, + manga_id INTEGER NOT NULL, + url TEXT NOT NULL, + name TEXT NOT NULL, + scanlator TEXT, + read INTEGER AS Boolean NOT NULL, + bookmark INTEGER AS Boolean NOT NULL, + last_page_read INTEGER NOT NULL, + chapter_number REAL AS Float NOT NULL, + source_order INTEGER NOT NULL, + date_fetch INTEGER AS Long NOT NULL, + date_upload INTEGER AS Long NOT NULL, + last_modified_at INTEGER AS Long, + FOREIGN KEY(manga_id) REFERENCES mangas (_id) + ON DELETE CASCADE +); + +-- Copy data from temporary tables to new tables +INSERT INTO mangas +SELECT _id, source, url, artist, author, description, genre, title, status, thumbnail_url, favorite, last_update, next_update, initialized, viewer, chapter_flags, cover_last_modified, date_added, update_strategy, NULL +FROM mangas_temp; + +INSERT INTO chapters +SELECT _id, manga_id, url, name, scanlator, read, bookmark, last_page_read, chapter_number, source_order, date_fetch, date_upload, NULL +FROM chapters_temp; + +INSERT INTO mangas_categories +SELECT _id, manga_id, category_id, NULL +FROM mangas_categories_temp; + +-- Create indices +CREATE INDEX library_favorite_index ON mangas(favorite) WHERE favorite = 1; +CREATE INDEX mangas_url_index ON mangas(url); +CREATE INDEX chapters_manga_id_index ON chapters(manga_id); +CREATE INDEX chapters_unread_by_manga_index ON chapters(manga_id, read) WHERE read = 0; + +-- Drop temporary tables +DROP TABLE IF EXISTS mangas_temp; +DROP TABLE IF EXISTS chapters_temp; +DROP TABLE IF EXISTS mangas_categories_temp; + + +-- Create triggers +DROP TRIGGER IF EXISTS update_last_modified_at_mangas; +CREATE TRIGGER update_last_modified_at_mangas +AFTER UPDATE ON mangas +FOR EACH ROW +BEGIN + UPDATE mangas + SET last_modified_at = strftime('%s', 'now') + WHERE _id = new._id; +END; + +DROP TRIGGER IF EXISTS insert_last_modified_at_mangas; +CREATE TRIGGER insert_last_modified_at_mangas +AFTER INSERT ON mangas +FOR EACH ROW +BEGIN + UPDATE mangas + SET last_modified_at = strftime('%s', 'now') + WHERE _id = new._id; +END; + +DROP TRIGGER IF EXISTS update_last_modified_at_chapters; +CREATE TRIGGER update_last_modified_at_chapters +AFTER UPDATE ON chapters +FOR EACH ROW +BEGIN + UPDATE chapters + SET last_modified_at = strftime('%s', 'now') + WHERE _id = new._id; +END; + +DROP TRIGGER IF EXISTS update_last_modified_at_mangas_categories; +CREATE TRIGGER update_last_modified_at_mangas_categories +AFTER UPDATE ON mangas_categories +FOR EACH ROW +BEGIN + UPDATE mangas_categories + SET last_modified_at = strftime('%s', 'now') + WHERE _id = new._id; +END; + +DROP TRIGGER IF EXISTS insert_last_modified_at_mangas_categories; +CREATE TRIGGER insert_last_modified_at_mangas_categories +AFTER INSERT ON mangas_categories +FOR EACH ROW +BEGIN + UPDATE mangas_categories + SET last_modified_at = strftime('%s', 'now') + WHERE _id = new._id; +END; diff --git a/i18n/src/main/res/values/strings.xml b/i18n/src/main/res/values/strings.xml index 0750df909..e043005c0 100644 --- a/i18n/src/main/res/values/strings.xml +++ b/i18n/src/main/res/values/strings.xml @@ -549,7 +549,7 @@ Synchronization frequency SyncYomi Done in %1$s - Last Synchronization + Last Synchronization: %1$s