diff --git a/app/src/main/java/eu/kanade/tachiyomi/data/database/mappers/MangaTypeMapping.kt b/app/src/main/java/eu/kanade/tachiyomi/data/database/mappers/MangaTypeMapping.kt index 79de0f3a1..da256eac9 100755 --- a/app/src/main/java/eu/kanade/tachiyomi/data/database/mappers/MangaTypeMapping.kt +++ b/app/src/main/java/eu/kanade/tachiyomi/data/database/mappers/MangaTypeMapping.kt @@ -59,8 +59,8 @@ class MangaPutResolver : DefaultPutResolver() { COL_DESCRIPTION to obj.originalDescription, COL_GENRE to obj.originalGenre, COL_TITLE to obj.originalTitle, + COL_STATUS to obj.originalStatus, // SY <-- - COL_STATUS to obj.status, COL_THUMBNAIL_URL to obj.thumbnail_url, COL_FAVORITE to obj.favorite, COL_LAST_UPDATE to obj.last_update, diff --git a/app/src/main/java/eu/kanade/tachiyomi/data/database/models/MangaImpl.kt b/app/src/main/java/eu/kanade/tachiyomi/data/database/models/MangaImpl.kt index 934e73cd7..e0a3169ca 100755 --- a/app/src/main/java/eu/kanade/tachiyomi/data/database/models/MangaImpl.kt +++ b/app/src/main/java/eu/kanade/tachiyomi/data/database/models/MangaImpl.kt @@ -40,9 +40,11 @@ open class MangaImpl : Manga { override var genre: String? get() = if (favorite) customMangaManager.getManga(this)?.genre ?: ogGenre else ogGenre set(value) { ogGenre = value } - // SY <-- - override var status: Int = 0 + override var status: Int + get() = if (favorite) customMangaManager.getManga(this)?.status?.takeUnless { it == 0 } ?: ogStatus else ogStatus + set(value) { ogStatus = value } + // SY <-- override var thumbnail_url: String? = null @@ -71,6 +73,8 @@ open class MangaImpl : Manga { private set var ogGenre: String? = null private set + var ogStatus: Int = 0 + private set // SY <-- override fun equals(other: Any?): Boolean { diff --git a/app/src/main/java/eu/kanade/tachiyomi/data/database/queries/MangaQueries.kt b/app/src/main/java/eu/kanade/tachiyomi/data/database/queries/MangaQueries.kt index d63826d18..b4e00c0c5 100755 --- a/app/src/main/java/eu/kanade/tachiyomi/data/database/queries/MangaQueries.kt +++ b/app/src/main/java/eu/kanade/tachiyomi/data/database/queries/MangaQueries.kt @@ -13,6 +13,7 @@ import eu.kanade.tachiyomi.data.database.resolvers.MangaFlagsPutResolver import eu.kanade.tachiyomi.data.database.resolvers.MangaInfoPutResolver import eu.kanade.tachiyomi.data.database.resolvers.MangaLastUpdatedPutResolver import eu.kanade.tachiyomi.data.database.resolvers.MangaMigrationPutResolver +import eu.kanade.tachiyomi.data.database.resolvers.MangaThumbnailPutResolver import eu.kanade.tachiyomi.data.database.resolvers.MangaTitlePutResolver import eu.kanade.tachiyomi.data.database.resolvers.MangaViewerPutResolver import eu.kanade.tachiyomi.data.database.tables.CategoryTable @@ -102,6 +103,11 @@ interface MangaQueries : DbProvider { .`object`(manga) .withPutResolver(MangaMigrationPutResolver()) .prepare() + + fun updateMangaThumbnail(manga: Manga) = db.put() + .`object`(manga) + .withPutResolver(MangaThumbnailPutResolver()) + .prepare() // SY <-- fun insertManga(manga: Manga) = db.put().`object`(manga).prepare() diff --git a/app/src/main/java/eu/kanade/tachiyomi/data/database/resolvers/MangaInfoPutResolver.kt b/app/src/main/java/eu/kanade/tachiyomi/data/database/resolvers/MangaInfoPutResolver.kt index 7995eb13f..411d3e117 100644 --- a/app/src/main/java/eu/kanade/tachiyomi/data/database/resolvers/MangaInfoPutResolver.kt +++ b/app/src/main/java/eu/kanade/tachiyomi/data/database/resolvers/MangaInfoPutResolver.kt @@ -1,6 +1,5 @@ package eu.kanade.tachiyomi.data.database.resolvers -import android.content.ContentValues import androidx.core.content.contentValuesOf import com.pushtorefresh.storio.sqlite.StorIOSQLite import com.pushtorefresh.storio.sqlite.operations.put.PutResolver @@ -9,6 +8,7 @@ import com.pushtorefresh.storio.sqlite.queries.UpdateQuery import eu.kanade.tachiyomi.data.database.inTransactionReturn import eu.kanade.tachiyomi.data.database.models.Manga import eu.kanade.tachiyomi.data.database.tables.MangaTable +import exh.util.nullIfZero class MangaInfoPutResolver(val reset: Boolean = false) : PutResolver() { @@ -31,15 +31,20 @@ class MangaInfoPutResolver(val reset: Boolean = false) : PutResolver() { MangaTable.COL_GENRE to manga.originalGenre, MangaTable.COL_AUTHOR to manga.originalAuthor, MangaTable.COL_ARTIST to manga.originalArtist, - MangaTable.COL_DESCRIPTION to manga.originalDescription + MangaTable.COL_DESCRIPTION to manga.originalDescription, + MangaTable.COL_STATUS to manga.originalStatus ) - fun resetToContentValues(manga: Manga) = ContentValues(1).apply { - val splitter = "▒ ▒∩▒" - put(MangaTable.COL_TITLE, manga.title.split(splitter).last()) - put(MangaTable.COL_GENRE, manga.genre?.split(splitter)?.lastOrNull()) - put(MangaTable.COL_AUTHOR, manga.author?.split(splitter)?.lastOrNull()) - put(MangaTable.COL_ARTIST, manga.artist?.split(splitter)?.lastOrNull()) - put(MangaTable.COL_DESCRIPTION, manga.description?.split(splitter)?.lastOrNull()) + private fun resetToContentValues(manga: Manga) = contentValuesOf( + MangaTable.COL_TITLE to manga.title.split(splitter).last(), + MangaTable.COL_GENRE to manga.genre?.split(splitter)?.lastOrNull(), + MangaTable.COL_AUTHOR to manga.author?.split(splitter)?.lastOrNull(), + MangaTable.COL_ARTIST to manga.artist?.split(splitter)?.lastOrNull(), + MangaTable.COL_DESCRIPTION to manga.description?.split(splitter)?.lastOrNull(), + MangaTable.COL_STATUS to manga.status.nullIfZero()?.toString()?.split(splitter)?.lastOrNull() + ) + + companion object { + const val splitter = "▒ ▒∩▒" } } diff --git a/app/src/main/java/eu/kanade/tachiyomi/data/database/resolvers/MangaThumbnailPutResolver.kt b/app/src/main/java/eu/kanade/tachiyomi/data/database/resolvers/MangaThumbnailPutResolver.kt new file mode 100644 index 000000000..f48206509 --- /dev/null +++ b/app/src/main/java/eu/kanade/tachiyomi/data/database/resolvers/MangaThumbnailPutResolver.kt @@ -0,0 +1,32 @@ +package eu.kanade.tachiyomi.data.database.resolvers + +import androidx.core.content.contentValuesOf +import com.pushtorefresh.storio.sqlite.StorIOSQLite +import com.pushtorefresh.storio.sqlite.operations.put.PutResolver +import com.pushtorefresh.storio.sqlite.operations.put.PutResult +import com.pushtorefresh.storio.sqlite.queries.UpdateQuery +import eu.kanade.tachiyomi.data.database.inTransactionReturn +import eu.kanade.tachiyomi.data.database.models.Manga +import eu.kanade.tachiyomi.data.database.tables.MangaTable + +// SY +class MangaThumbnailPutResolver : PutResolver() { + + override fun performPut(db: StorIOSQLite, manga: Manga) = db.inTransactionReturn { + val updateQuery = mapToUpdateQuery(manga) + val contentValues = mapToContentValues(manga) + + val numberOfRowsUpdated = db.lowLevel().update(updateQuery, contentValues) + PutResult.newUpdateResult(numberOfRowsUpdated, updateQuery.table()) + } + + fun mapToUpdateQuery(manga: Manga) = UpdateQuery.builder() + .table(MangaTable.TABLE) + .where("${MangaTable.COL_ID} = ?") + .whereArgs(manga.id) + .build() + + fun mapToContentValues(manga: Manga) = contentValuesOf( + MangaTable.COL_THUMBNAIL_URL to manga.thumbnail_url + ) +} diff --git a/app/src/main/java/eu/kanade/tachiyomi/data/download/DownloadManager.kt b/app/src/main/java/eu/kanade/tachiyomi/data/download/DownloadManager.kt index 48e7e1368..76d31b219 100755 --- a/app/src/main/java/eu/kanade/tachiyomi/data/download/DownloadManager.kt +++ b/app/src/main/java/eu/kanade/tachiyomi/data/download/DownloadManager.kt @@ -23,7 +23,7 @@ import uy.kohesive.injekt.injectLazy * * @param context the application context. */ -class DownloadManager(/* SY private */ val context: Context) { +class DownloadManager(private val context: Context) { private val sourceManager: SourceManager by injectLazy() private val preferences: PreferencesHelper by injectLazy() diff --git a/app/src/main/java/eu/kanade/tachiyomi/data/library/CustomMangaManager.kt b/app/src/main/java/eu/kanade/tachiyomi/data/library/CustomMangaManager.kt index 3c0315767..0310e704e 100644 --- a/app/src/main/java/eu/kanade/tachiyomi/data/library/CustomMangaManager.kt +++ b/app/src/main/java/eu/kanade/tachiyomi/data/library/CustomMangaManager.kt @@ -32,30 +32,15 @@ class CustomMangaManager(val context: Context) { val mangasJson = json.mangas ?: return mutableMapOf() return mangasJson.mapNotNull { mangaJson -> val id = mangaJson.id ?: return@mapNotNull null - val manga = MangaImpl().apply { - this.id = id - title = mangaJson.title ?: "" - author = mangaJson.author - artist = mangaJson.artist - description = mangaJson.description - genre = mangaJson.genre?.joinToString(", ") - } - id to manga + id to mangaJson.toManga() }.toMap().toMutableMap() } fun saveMangaInfo(manga: MangaJson) { - if (manga.title == null && manga.author == null && manga.artist == null && manga.description == null && manga.genre == null) { + if (manga.title == null && manga.author == null && manga.artist == null && manga.description == null && manga.genre == null && manga.status == null) { customMangaMap.remove(manga.id!!) } else { - customMangaMap[manga.id!!] = MangaImpl().apply { - id = manga.id - title = manga.title ?: "" - author = manga.author - artist = manga.artist - description = manga.description - genre = manga.genre?.joinToString(", ") - } + customMangaMap[manga.id!!] = manga.toManga() } saveCustomInfo() } @@ -75,7 +60,8 @@ class CustomMangaManager(val context: Context) { author, artist, description, - genre?.split(", ") + genre?.split(", "), + status ) } @@ -91,9 +77,20 @@ class CustomMangaManager(val context: Context) { val author: String? = null, val artist: String? = null, val description: String? = null, - val genre: List? = null + val genre: List? = null, + val status: Int? = null ) { + fun toManga() = MangaImpl().apply { + id = this@MangaJson.id + title = this@MangaJson.title ?: "" + author = this@MangaJson.author + artist = this@MangaJson.artist + description = this@MangaJson.description + genre = this@MangaJson.genre?.joinToString(", ") + status = this@MangaJson.status ?: 0 + } + override fun equals(other: Any?): Boolean { if (this === other) return true if (javaClass != other?.javaClass) return false diff --git a/app/src/main/java/eu/kanade/tachiyomi/source/LocalSource.kt b/app/src/main/java/eu/kanade/tachiyomi/source/LocalSource.kt index 13ea42fdd..38f539b31 100755 --- a/app/src/main/java/eu/kanade/tachiyomi/source/LocalSource.kt +++ b/app/src/main/java/eu/kanade/tachiyomi/source/LocalSource.kt @@ -64,6 +64,12 @@ class LocalSource(private val context: Context) : CatalogueSource { val c = context.getString(R.string.app_name) + File.separator + "local" return DiskUtil.getExternalStorages(context).map { File(it.absolutePath, c) } } + + // SY --> + val json = Json { + prettyPrint = true + } + // SY <-- } override val id = ID @@ -151,19 +157,16 @@ class LocalSource(private val context: Context) : CatalogueSource { // SY --> fun updateMangaInfo(manga: SManga) { - val directory = getBaseDirectories(context).mapNotNull { File(it, manga.url) }.find { + val directory = getBaseDirectories(context).map { File(it, manga.url) }.find { it.exists() } ?: return - val json = Json { - prettyPrint = true - } val existingFileName = directory.listFiles()?.find { it.extension == "json" }?.name val file = File(directory, existingFileName ?: "info.json") file.writeText(json.encodeToString(manga.toJson())) } private fun SManga.toJson(): MangaJson { - return MangaJson(title, author, artist, description, genre?.split(", ")?.toTypedArray()) + return MangaJson(title, author, artist, description, genre?.split(", "), status) } @Serializable @@ -172,7 +175,8 @@ class LocalSource(private val context: Context) : CatalogueSource { val author: String?, val artist: String?, val description: String?, - val genre: Array? + val genre: List?, + val status: Int ) { override fun equals(other: Any?): Boolean { diff --git a/app/src/main/java/eu/kanade/tachiyomi/source/model/SManga.kt b/app/src/main/java/eu/kanade/tachiyomi/source/model/SManga.kt index 22d0ab4ba..6792dfc9d 100755 --- a/app/src/main/java/eu/kanade/tachiyomi/source/model/SManga.kt +++ b/app/src/main/java/eu/kanade/tachiyomi/source/model/SManga.kt @@ -35,6 +35,8 @@ interface SManga : Serializable { get() = (this as? MangaImpl)?.ogDesc ?: description val originalGenre: String? get() = (this as? MangaImpl)?.ogGenre ?: genre + val originalStatus: Int + get() = (this as? MangaImpl)?.ogStatus ?: status // SY <-- fun copyFrom(other: SManga) { diff --git a/app/src/main/java/eu/kanade/tachiyomi/ui/manga/EditMangaDialog.kt b/app/src/main/java/eu/kanade/tachiyomi/ui/manga/EditMangaDialog.kt index 52e19bbd1..0af8fae64 100644 --- a/app/src/main/java/eu/kanade/tachiyomi/ui/manga/EditMangaDialog.kt +++ b/app/src/main/java/eu/kanade/tachiyomi/ui/manga/EditMangaDialog.kt @@ -5,6 +5,7 @@ import android.content.Context import android.net.Uri import android.os.Bundle import android.text.InputType +import android.widget.ArrayAdapter import androidx.core.content.ContextCompat import androidx.core.os.bundleOf import androidx.core.view.children @@ -23,10 +24,12 @@ import eu.kanade.tachiyomi.data.glide.GlideApp import eu.kanade.tachiyomi.data.glide.toMangaThumbnail import eu.kanade.tachiyomi.databinding.EditMangaDialogBinding import eu.kanade.tachiyomi.source.LocalSource +import eu.kanade.tachiyomi.source.model.SManga import eu.kanade.tachiyomi.ui.base.controller.DialogController import eu.kanade.tachiyomi.util.lang.chop import eu.kanade.tachiyomi.util.system.getResourceColor import eu.kanade.tachiyomi.util.system.toast +import exh.util.dropBlank import exh.util.trimOrNull import kotlinx.coroutines.flow.launchIn import kotlinx.coroutines.flow.onEach @@ -84,6 +87,36 @@ class EditMangaDialog : DialogController { val isLocal = manga.source == LocalSource.ID + val statusAdapter: ArrayAdapter = ArrayAdapter( + context, + android.R.layout.simple_spinner_item, + listOf( + R.string.manga, + R.string.ongoing, + R.string.completed, + R.string.licensed, + R.string.publication_complete, + R.string.hiatus, + R.string.cancelled + ).map { context.getString(it) } + ) + + binding.status.adapter = statusAdapter + if (manga.status != manga.originalStatus) { + binding.status.setSelection( + when (manga.status) { + SManga.UNKNOWN -> 0 + SManga.ONGOING -> 1 + SManga.COMPLETED -> 2 + SManga.LICENSED -> 3 + SManga.PUBLICATION_COMPLETE -> 4 + SManga.HIATUS -> 5 + SManga.CANCELLED -> 6 + else -> 0 + } + ) + } + if (isLocal) { if (manga.title != manga.url) { binding.title.setText(manga.title) @@ -92,7 +125,7 @@ class EditMangaDialog : DialogController { binding.mangaAuthor.setText(manga.author.orEmpty()) binding.mangaArtist.setText(manga.artist.orEmpty()) binding.mangaDescription.setText(manga.description.orEmpty()) - binding.mangaGenresTags.setChips(manga.getGenres().orEmpty()) + binding.mangaGenresTags.setChips(manga.getGenres().orEmpty().dropBlank()) } else { if (manga.title != manga.originalTitle) { binding.title.append(manga.title) @@ -160,11 +193,23 @@ class EditMangaDialog : DialogController { private fun onPositiveButtonClick() { infoController.presenter.updateMangaInfo( + context, binding.title.text.toString(), binding.mangaAuthor.text.toString(), binding.mangaArtist.text.toString(), binding.mangaDescription.text.toString(), binding.mangaGenresTags.getTextStrings(), + binding.status.selectedItemPosition.let { + when (it) { + 1 -> SManga.ONGOING + 2 -> SManga.COMPLETED + 3 -> SManga.LICENSED + 4 -> SManga.PUBLICATION_COMPLETE + 5 -> SManga.HIATUS + 6 -> SManga.CANCELLED + else -> null + } + }, customCoverUri, willResetCover ) diff --git a/app/src/main/java/eu/kanade/tachiyomi/ui/manga/MangaController.kt b/app/src/main/java/eu/kanade/tachiyomi/ui/manga/MangaController.kt index 0012a6228..b257bef6d 100644 --- a/app/src/main/java/eu/kanade/tachiyomi/ui/manga/MangaController.kt +++ b/app/src/main/java/eu/kanade/tachiyomi/ui/manga/MangaController.kt @@ -706,7 +706,7 @@ class MangaController : // SY --> fun changeCover() { - if (manga?.favorite == true) { + if (manga?.favorite == true || source?.id == LocalSource.ID) { val intent = Intent(Intent.ACTION_GET_CONTENT) intent.type = "image/*" startActivityForResult( @@ -1036,7 +1036,7 @@ class MangaController : val uri = data.data ?: return if (editMangaDialog != null) editMangaDialog?.updateCover(uri) else { - presenter.editCoverWithStream(uri) + presenter.editCoverWithStream(activity, uri) } } catch (error: IOException) { activity.toast(R.string.notification_cover_update_failed) diff --git a/app/src/main/java/eu/kanade/tachiyomi/ui/manga/MangaPresenter.kt b/app/src/main/java/eu/kanade/tachiyomi/ui/manga/MangaPresenter.kt index 095e44f81..a2d91933d 100644 --- a/app/src/main/java/eu/kanade/tachiyomi/ui/manga/MangaPresenter.kt +++ b/app/src/main/java/eu/kanade/tachiyomi/ui/manga/MangaPresenter.kt @@ -314,11 +314,13 @@ class MangaPresenter( // SY --> fun updateMangaInfo( + context: Context, title: String?, author: String?, artist: String?, description: String?, tags: List?, + status: Int?, uri: Uri?, resetCover: Boolean = false ) { @@ -329,7 +331,8 @@ class MangaPresenter( manga.description = description?.trimOrNull() val tagsString = tags?.joinToString() manga.genre = if (tags.isNullOrEmpty()) null else tagsString?.trim() - LocalSource(downloadManager.context).updateMangaInfo(manga) + manga.status = status ?: 0 + (sourceManager.get(LocalSource.ID) as LocalSource).updateMangaInfo(manga) db.updateMangaInfo(manga).executeAsBlocking() } else { val genre = if (!tags.isNullOrEmpty() && tags.joinToString() != manga.originalGenre) { @@ -343,13 +346,14 @@ class MangaPresenter( author?.trimOrNull(), artist?.trimOrNull(), description?.trimOrNull(), - genre + genre, + status.takeUnless { it == manga.originalStatus } ) customMangaManager.saveMangaInfo(manga) } if (uri != null) { - editCoverWithStream(uri) + editCoverWithStream(context, uri) } else if (resetCover) { coverCache.deleteCustomCover(manga) manga.updateCoverLastModified(db) @@ -377,11 +381,14 @@ class MangaPresenter( } } - fun editCoverWithStream(uri: Uri): Boolean { - val inputStream = downloadManager.context.contentResolver.openInputStream(uri) ?: return false + fun editCoverWithStream(context: Context, uri: Uri): Boolean { + val inputStream = context.contentResolver.openInputStream(uri) ?: return false if (manga.source == LocalSource.ID) { - LocalSource.updateCover(downloadManager.context, manga, inputStream) - manga.updateCoverLastModified(db) + val cover = LocalSource.updateCover(context, manga, inputStream) + if (manga.thumbnail_url.isNullOrBlank() && cover != null) { + manga.thumbnail_url = cover.absolutePath + db.updateMangaThumbnail(manga).executeAsBlocking() + } return true } diff --git a/app/src/main/res/layout/edit_manga_dialog.xml b/app/src/main/res/layout/edit_manga_dialog.xml index 79fb2c502..51adabaae 100644 --- a/app/src/main/res/layout/edit_manga_dialog.xml +++ b/app/src/main/res/layout/edit_manga_dialog.xml @@ -22,16 +22,31 @@ android:src="@mipmap/ic_launcher"/> -