Removing edit online manga, now only for local

This is a nightmare to maintain and freeing to clean up, so it's out. Local manga will continue to be editable but online editing will remain only for covers (which wlil not be overridden when updating)
This commit is contained in:
Jay 2020-03-16 01:52:30 -07:00
parent d87c1cb5b9
commit 8f884bf222
42 changed files with 206 additions and 265 deletions

View File

@ -34,7 +34,7 @@ android {
minSdkVersion(23)
targetSdkVersion(29)
applicationId = "eu.kanade.tachiyomi"
versionCode = 60
versionCode = 61
versionName = "0.9.81"
testInstrumentationRunner = "androidx.test.runner.AndroidJUnitRunner"
multiDexEnabled = true

View File

@ -5,6 +5,7 @@ import eu.kanade.tachiyomi.data.library.LibraryUpdateJob
import eu.kanade.tachiyomi.data.preference.PreferencesHelper
import eu.kanade.tachiyomi.data.preference.getOrDefault
import eu.kanade.tachiyomi.data.updater.UpdaterJob
import eu.kanade.tachiyomi.ui.library.LibraryPresenter
import java.io.File
object Migrations {
@ -63,6 +64,8 @@ object Migrations {
}
if (oldVersion < 54)
DownloadProvider(context).renameChaapters()
if (oldVersion < 61)
LibraryPresenter.resetCustomManga()
return true
}
return false

View File

@ -15,7 +15,7 @@ object MangaTypeAdapter {
write {
beginArray()
value(it.url)
value(it.originalTitle())
value(it.title)
value(it.source)
value(max(0, it.viewer))
value(it.chapter_flags)

View File

@ -37,7 +37,7 @@ interface Manga : SManga {
fun mangaType(): Int {
val sourceName = Injekt.get<SourceManager>().getOrStub(source).name
val currentTags = currentGenres()?.split(",")?.map { it.trim().toLowerCase(Locale.US) }
val currentTags = genre?.split(",")?.map { it.trim().toLowerCase(Locale.US) }
return if (currentTags?.any
{ tag ->
tag.startsWith("japanese") || tag == "manga"
@ -69,7 +69,7 @@ interface Manga : SManga {
fun defaultReaderType(): Int {
val sourceName = Injekt.get<SourceManager>().getOrStub(source).name
val currentTags = currentGenres()?.split(",")?.map { it.trim().toLowerCase(Locale.US) }
val currentTags = genre?.split(",")?.map { it.trim().toLowerCase(Locale.US) }
return if (currentTags?.any
{ tag ->
tag == "long strip" || tag == "manhwa" ||

View File

@ -42,13 +42,9 @@ open class MangaImpl : Manga {
override fun copyFrom(other: SManga) {
if (other is MangaImpl && (other as MangaImpl)::title.isInitialized &&
!other.title.isBlank() && other.title != originalTitle()) {
val oldTitle = originalTitle()
title = if (currentTitle() != originalTitle()) {
val customTitle = currentTitle()
val trueTitle = other.title
"${customTitle}${SManga.splitter}$trueTitle"
} else other.title
!other.title.isBlank() && other.title != title) {
val oldTitle = title
title = other.title
val db: DownloadManager by injectLazy()
val provider = DownloadProvider(db.context)
provider.renameMangaFolder(oldTitle, title, source)

View File

@ -34,10 +34,11 @@ class MangaInfoPutResolver(val reset: Boolean = false) : PutResolver<Manga>() {
}
fun resetToContentValues(manga: Manga) = ContentValues(1).apply {
put(MangaTable.COL_TITLE, manga.originalTitle())
put(MangaTable.COL_GENRE, manga.originalGenres())
put(MangaTable.COL_AUTHOR, manga.originalAuthor())
put(MangaTable.COL_ARTIST, manga.originalArtist())
put(MangaTable.COL_DESCRIPTION, manga.originalDesc())
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())
}
}

View File

@ -142,10 +142,10 @@ class DownloadCache(
}
val trueMangaDirs = mangaDirs.mapNotNull { mangaDir ->
val manga = sourceMangas.firstOrNull()?.find { DiskUtil.buildValidFilename(
it.originalTitle()).toLowerCase() == mangaDir.key
it.title).toLowerCase() == mangaDir.key
.toLowerCase() && it.source == sourceValue.key }
?: sourceMangas.lastOrNull()?.find { DiskUtil.buildValidFilename(
it.originalTitle()).toLowerCase() == mangaDir.key
it.title).toLowerCase() == mangaDir.key
.toLowerCase() && it.source == sourceValue.key }
val id = manga?.id ?: return@mapNotNull null
id to mangaDir.value.files

View File

@ -84,7 +84,7 @@ internal class DownloadNotifier(private val context: Context) {
}
if (download != null) {
val title = download.manga.currentTitle().chop(15)
val title = download.manga.title.chop(15)
val quotedTitle = Pattern.quote(title)
val chapter = download.chapter.name.replaceFirst("$quotedTitle[\\s]*[-]*[\\s]*"
.toRegex(RegexOption.IGNORE_CASE), "")
@ -129,7 +129,7 @@ internal class DownloadNotifier(private val context: Context) {
NotificationReceiver.pauseDownloadsPendingBroadcast(context))
}
val title = download.manga.currentTitle().chop(15)
val title = download.manga.title.chop(15)
val quotedTitle = Pattern.quote(title)
val chapter = download.chapter.name.replaceFirst("$quotedTitle[\\s]*[-]*[\\s]*".toRegex(RegexOption.IGNORE_CASE), "")
setContentTitle("$title - $chapter".chop(30))

View File

@ -185,7 +185,7 @@ class DownloadProvider(private val context: Context) {
* @param manga the manga to query.
*/
fun getMangaDirName(manga: Manga): String {
return DiskUtil.buildValidFilename(manga.originalTitle())
return DiskUtil.buildValidFilename(manga.title)
}
/**

View File

@ -90,11 +90,8 @@ class MangaModelLoader : ModelLoader<Manga, InputStream> {
): ModelLoader.LoadData<InputStream>? {
// Check thumbnail is not null or empty
val url = manga.thumbnail_url
if (url == null || url.isEmpty()) {
return null
}
if (url.startsWith("http")) {
if (url?.startsWith("http") == true) {
val source = sourceManager.get(manga.source) as? HttpSource
val glideUrl = GlideUrl(url, getHeaders(manga, source))
@ -113,8 +110,14 @@ class MangaModelLoader : ModelLoader<Manga, InputStream> {
// Return an instance of the fetcher providing the needed elements.
return ModelLoader.LoadData(MangaSignature(manga, file), libraryFetcher)
} else {
// Get the file from the url, removing the scheme if present.
val file = File(url.substringAfter("file://"))
// Get the file from the url, removing the scheme if present, or from the cache if no url.
val file = when {
manga.hasCustomCover() -> coverCache.getCoverFile(manga.thumbnail_url!!)
url != null -> File(url.substringAfter("file://"))
else -> null
}
if (file?.exists() != true) return null
// Return an instance of the fetcher providing the needed elements.
return ModelLoader.LoadData(MangaSignature(manga, file), FileFetcher(file))

View File

@ -36,7 +36,7 @@ object LibraryUpdateRanker {
fun lexicographicRanking(): Comparator<Manga> {
return Comparator { mangaFirst: Manga,
mangaSecond: Manga ->
compareValues(mangaFirst.currentTitle(), mangaSecond.currentTitle())
compareValues(mangaFirst.title, mangaSecond.title)
}
}
}

View File

@ -522,7 +522,7 @@ class LibraryUpdateService(
private fun showProgressNotification(manga: Manga, current: Int, total: Int) {
notificationManager.notify(
Notifications.ID_LIBRARY_PROGRESS, progressNotification
.setContentTitle(manga.currentTitle())
.setContentTitle(manga.title)
.setProgress(total, current, false)
.build()
)
@ -549,7 +549,7 @@ class LibraryUpdateService(
} catch (e: Exception) {
}
setGroupAlertBehavior(GROUP_ALERT_SUMMARY)
setContentTitle(manga.currentTitle())
setContentTitle(manga.title)
color = ContextCompat.getColor(this@LibraryUpdateService, R.color.colorAccent)
val chaptersNames = if (chapterNames.size > 5) {
"${chapterNames.take(4).joinToString(", ")}, " +
@ -605,11 +605,11 @@ class LibraryUpdateService(
setStyle(
NotificationCompat.BigTextStyle()
.bigText(updates.keys.joinToString("\n") {
it.currentTitle().chop(45)
it.title.chop(45)
})
)
} else {
setContentText(updates.keys.first().currentTitle().chop(45))
setContentText(updates.keys.first().title.chop(45))
}
priority = NotificationCompat.PRIORITY_HIGH
setGroup(Notifications.GROUP_NEW_CHAPTERS)

View File

@ -65,7 +65,7 @@ class SmartSearchEngine(
return@supervisorScope listOf(SearchEntry(searchResults.mangas.first(), 0.0))
searchResults.mangas.map {
val normalizedDistance = normalizedLevenshtein.similarity(title, it.originalTitle())
val normalizedDistance = normalizedLevenshtein.similarity(title, it.title)
SearchEntry(it, normalizedDistance)
}.filter { (_, normalizedDistance) ->
normalizedDistance >= MIN_NORMAL_ELIGIBLE_THRESHOLD

View File

@ -202,7 +202,7 @@ class LocalSource(private val context: Context) : CatalogueSource {
chapterFile.nameWithoutExtension
}
val chapNameCut =
chapName.replace(manga.originalTitle(), "", true).trim(' ', '-', '_')
chapName.replace(manga.title, "", true).trim(' ', '-', '_')
name = if (chapNameCut.isEmpty()) chapName else chapNameCut
date_upload = chapterFile.lastModified()
ChapterRecognition.parseChapterNumber(this, manga)

View File

@ -23,68 +23,22 @@ interface SManga : Serializable {
var initialized: Boolean
fun currentTitle(): String {
val splitTitle = title.split(splitter)
return splitTitle.first()
}
fun originalTitle(): String {
val splitTitle = title.split(splitter)
return splitTitle.last()
}
fun currentGenres() = split(genre, true)
fun originalGenres() = split(genre, false)
fun currentDesc() = split(description, true)
fun originalDesc() = split(description, false)
fun currentAuthor() = split(author, true)
fun originalAuthor() = split(author, false)
fun currentArtist() = split(artist, true)
fun originalArtist() = split(artist, false)
private fun split(string: String?, first: Boolean): String? {
val split = string?.split(splitter) ?: return null
val s = if (first) split.first() else split.last()
return if (s.isBlank()) null else s
}
fun hasCustomCover() = thumbnail_url?.startsWith("Custom-") == true
fun copyFrom(other: SManga) {
if (other.author != null)
author = if (currentAuthor() != originalAuthor()) {
val current = currentAuthor()
val og = other.author
"${current}$splitter$og"
} else other.author
author = other.author
if (other.artist != null)
artist = if (currentArtist() != originalArtist()) {
val current = currentArtist()
val og = other.artist
"${current}$splitter$og"
} else other.artist
artist = other.artist
if (other.description != null)
description = if (currentDesc() != originalDesc()) {
val current = currentDesc()
val og = other.description
"${current}$splitter$og"
} else other.description
description = other.description
if (other.genre != null)
genre = if (currentGenres() != originalGenres()) {
val current = currentGenres()
val og = other.genre
"${current}$splitter$og"
} else other.genre
genre = other.genre
if (other.thumbnail_url != null)
if (other.thumbnail_url != null && !hasCustomCover())
thumbnail_url = other.thumbnail_url
status = other.status
@ -98,7 +52,6 @@ interface SManga : Serializable {
const val ONGOING = 1
const val COMPLETED = 2
const val LICENSED = 3
const val splitter = "▒ ▒∩▒"
fun create(): SManga {
return MangaImpl()

View File

@ -37,7 +37,7 @@ class CatalogueGridHolder(
*/
override fun onSetValues(manga: Manga) {
// Update the title of the manga.
compact_title.text = manga.currentTitle()
compact_title.text = manga.title
badge_view.setInLibrary(manga.favorite)
// Update the cover.

View File

@ -31,7 +31,7 @@ class CatalogueListHolder(private val view: View, adapter: FlexibleAdapter<IFlex
* @param manga the manga to bind.
*/
override fun onSetValues(manga: Manga) {
title.text = manga.originalTitle()
title.text = manga.title
with(subtitle) {
visibility = if (manga.favorite) View.VISIBLE else View.GONE
text = view.resources.getString(R.string.in_library)

View File

@ -38,7 +38,7 @@ class DownloadHolder(private val view: View, val adapter: DownloadAdapter) :
chapter_title.text = download.chapter.name
// Update the manga title
manga_full_title.text = download.manga.currentTitle()
manga_full_title.text = download.manga.title
// Update the progress bar and the number of downloaded pages
val pages = download.pages

View File

@ -108,7 +108,7 @@ class LibraryCategoryAdapter(val libraryListener: LibraryListener) :
when (preferences.librarySortingMode().getOrDefault()) {
LibrarySort.DRAG_AND_DROP -> {
if (!preferences.hideCategories().getOrDefault()) {
val title = (iFlexible as LibraryItem).manga.currentTitle()
val title = (iFlexible as LibraryItem).manga.title
if (preferences.removeArticles().getOrDefault())
title.removeArticles().substring(0, 1).toUpperCase(Locale.US)
else title.substring(0, 1).toUpperCase(Locale.US)
@ -144,7 +144,7 @@ class LibraryCategoryAdapter(val libraryListener: LibraryListener) :
"N/A"
}
else -> {
val title = (iFlexible as LibraryItem).manga.currentTitle()
val title = (iFlexible as LibraryItem).manga.title
if (preferences.removeArticles().getOrDefault())
title.removeArticles().substring(0, 1).toUpperCase(Locale.US)
else title.substring(0, 1).toUpperCase(Locale.US)

View File

@ -53,8 +53,8 @@ class LibraryGridHolder(
*/
override fun onSetValues(item: LibraryItem) {
// Update the title and subtitle of the manga.
title.text = item.manga.currentTitle()
subtitle.text = item.manga.originalAuthor()?.trim()
title.text = item.manga.title
subtitle.text = item.manga.author?.trim()
compact_title.text = title.text

View File

@ -124,15 +124,14 @@ class LibraryItem(
val sourceManager by injectLazy<SourceManager>()
val sourceName = if (manga.source == 0L) "Local" else
sourceManager.getOrStub(manga.source).name
return manga.currentTitle().contains(constraint, true) ||
manga.originalTitle().contains(constraint, true) ||
(manga.currentAuthor()?.contains(constraint, true) ?: false) ||
(manga.currentArtist()?.contains(constraint, true) ?: false) ||
return manga.title.contains(constraint, true) ||
(manga.author?.contains(constraint, true) ?: false) ||
(manga.artist?.contains(constraint, true) ?: false) ||
sourceName.contains(constraint, true) ||
if (constraint.contains(",")) {
val genres = manga.currentGenres()?.split(", ")
val genres = manga.genre?.split(", ")
constraint.split(",").all { containsGenre(it.trim(), genres) }
} else containsGenre(constraint, manga.currentGenres()?.split(", "))
} else containsGenre(constraint, manga.genre?.split(", "))
}
@SuppressLint("DefaultLocale")

View File

@ -34,11 +34,11 @@ class LibraryListHolder(
*/
override fun onSetValues(item: LibraryItem) {
// Update the title of the manga.
title.text = item.manga.currentTitle()
title.text = item.manga.title
setUnreadBadge(badge_view, item)
subtitle.text = item.manga.originalAuthor()?.trim()
subtitle.visibility = if (!item.manga.originalAuthor().isNullOrBlank()) View.VISIBLE
subtitle.text = item.manga.author?.trim()
subtitle.visibility = if (!item.manga.author.isNullOrBlank()) View.VISIBLE
else View.GONE
play_layout.visibility = if (item.manga.unread > 0 && item.unreadType > 0)

View File

@ -430,8 +430,8 @@ class LibraryPresenter(
private fun sortAlphabetical(i1: LibraryItem, i2: LibraryItem): Int {
return if (preferences.removeArticles().getOrDefault())
i1.manga.currentTitle().removeArticles().compareTo(i2.manga.currentTitle().removeArticles(), true)
else i1.manga.currentTitle().compareTo(i2.manga.currentTitle(), true)
i1.manga.title.removeArticles().compareTo(i2.manga.title.removeArticles(), true)
else i1.manga.title.compareTo(i2.manga.title, true)
}
/**
@ -876,7 +876,17 @@ class LibraryPresenter(
return catId in categories
}
private companion object {
var currentLibrary: Library? = null
companion object {
private var currentLibrary: Library? = null
fun resetCustomManga() {
val db: DatabaseHelper = Injekt.get()
db.inTransaction {
val libraryManga = db.getLibraryMangas().executeAsBlocking()
libraryManga.forEach { manga ->
db.resetMangaInfo(manga).executeAsBlocking()
}
}
}
}
}

View File

@ -44,6 +44,7 @@ import androidx.transition.ChangeImageTransform
import androidx.transition.TransitionManager
import androidx.transition.TransitionSet
import com.afollestad.materialdialogs.MaterialDialog
import com.afollestad.materialdialogs.list.listItems
import com.bluelinelabs.conductor.ControllerChangeHandler
import com.bluelinelabs.conductor.ControllerChangeType
import com.bumptech.glide.load.engine.DiskCacheStrategy
@ -66,6 +67,7 @@ import eu.kanade.tachiyomi.data.download.model.Download
import eu.kanade.tachiyomi.data.glide.GlideApp
import eu.kanade.tachiyomi.data.notification.NotificationReceiver
import eu.kanade.tachiyomi.data.track.model.TrackSearch
import eu.kanade.tachiyomi.source.LocalSource
import eu.kanade.tachiyomi.source.Source
import eu.kanade.tachiyomi.source.SourceManager
import eu.kanade.tachiyomi.source.online.HttpSource
@ -96,6 +98,7 @@ import eu.kanade.tachiyomi.util.view.snack
import eu.kanade.tachiyomi.util.view.updateLayoutParams
import eu.kanade.tachiyomi.util.view.updatePaddingRelative
import java.io.File
import java.io.IOException
import jp.wasabeef.glide.transformations.CropSquareTransformation
import jp.wasabeef.glide.transformations.MaskTransformation
import kotlinx.android.synthetic.main.main_activity.*
@ -152,6 +155,7 @@ class MangaDetailsController : BaseController,
var coverDrawable: Drawable? = null
private var trackingBottomSheet: TrackingBottomSheet? = null
private var startingDLChapterPos: Int? = null
private var editMangaDialog: EditMangaDialog? = null
/**
* Adapter containing a list of chapters.
@ -173,7 +177,7 @@ class MangaDetailsController : BaseController,
}
override fun getTitle(): String? {
return if (toolbarIsColored) manga?.currentTitle() else null
return if (toolbarIsColored) manga?.title else null
}
override fun onViewCreated(view: View) {
@ -480,6 +484,8 @@ class MangaDetailsController : BaseController,
inflater.inflate(R.menu.manga_details, menu)
val editItem = menu.findItem(R.id.action_edit)
editItem.isVisible = presenter.manga.favorite && !presenter.isLockedFromSearch
editItem.title = view?.context?.getString(if (manga?.source == LocalSource.ID)
R.string.action_edit else R.string.action_edit_cover)
menu.findItem(R.id.action_download).isVisible = !presenter.isLockedFromSearch
menu.findItem(R.id.action_mark_all_as_read).isVisible =
presenter.getNextUnreadChapter() != null && !presenter.isLockedFromSearch
@ -489,7 +495,32 @@ class MangaDetailsController : BaseController,
override fun onOptionsItemSelected(item: MenuItem): Boolean {
when (item.itemId) {
R.id.action_edit -> EditMangaDialog(this, presenter.manga).showDialog(router)
R.id.action_edit -> {
if (manga?.source == LocalSource.ID) {
editMangaDialog = EditMangaDialog(this, presenter.manga)
editMangaDialog?.showDialog(router)
} else {
if (manga?.hasCustomCover() == true) {
MaterialDialog(activity!!).listItems(items = listOf(
view!!.context.getString(
R.string.action_edit_cover
), view!!.context.getString(
R.string.action_reset_cover
)
),
waitForPositiveButton = false,
selection = { _, index, _ ->
when (index) {
0 -> changeCover()
else -> presenter.clearCover()
}
})
.show()
} else {
changeCover()
}
}
}
R.id.action_open_in_web_view -> openInWebView()
R.id.action_share -> prepareToShareManga()
R.id.action_add_to_home_screen -> addToHomeScreen()
@ -543,7 +574,7 @@ class MangaDetailsController : BaseController,
val intent = Intent(Intent.ACTION_SEND).apply {
type = "text/*"
putExtra(Intent.EXTRA_TEXT, url)
putExtra(Intent.EXTRA_TITLE, presenter.manga.currentTitle())
putExtra(Intent.EXTRA_TITLE, presenter.manga.title)
flags = Intent.FLAG_GRANT_READ_URI_PERMISSION
if (stream != null) {
clipData = ClipData.newRawUri(null, stream)
@ -566,7 +597,7 @@ class MangaDetailsController : BaseController,
val activity = activity ?: return
val intent = WebViewActivity.newIntent(activity.applicationContext, source.id, url, presenter.manga
.originalTitle())
.title)
startActivity(intent)
}
@ -669,11 +700,11 @@ class MangaDetailsController : BaseController,
// Check if shortcut placement is supported
if (ShortcutManagerCompat.isRequestPinShortcutSupported(activity)) {
val shortcutId = "manga-shortcut-${presenter.manga.originalTitle()}-${presenter.source.name}"
val shortcutId = "manga-shortcut-${presenter.manga.title}-${presenter.source.name}"
// Create shortcut info
val shortcutInfo = ShortcutInfoCompat.Builder(activity, shortcutId)
.setShortLabel(presenter.manga.currentTitle())
.setShortLabel(presenter.manga.title)
.setIcon(IconCompat.createWithBitmap(icon))
.setIntent(shortcutIntent)
.build()
@ -989,6 +1020,38 @@ class MangaDetailsController : BaseController,
return false
}
fun changeCover() {
if (manga?.favorite == true) {
val intent = Intent(Intent.ACTION_GET_CONTENT)
intent.type = "image/*"
startActivityForResult(
Intent.createChooser(intent,
resources?.getString(R.string.file_select_cover)),
101
)
} else {
activity?.toast(R.string.notification_first_add_to_library)
}
}
override fun onActivityResult(requestCode: Int, resultCode: Int, data: Intent?) {
if (requestCode == 101) {
if (data == null || resultCode != Activity.RESULT_OK) return
val activity = activity ?: return
try {
val uri = data.data ?: return
if (editMangaDialog != null) editMangaDialog?.updateCover(uri)
else {
presenter.editCoverWithStream(uri)
setPaletteColor()
}
} catch (error: IOException) {
activity.toast(R.string.notification_cover_update_failed)
Timber.e(error)
}
}
}
override fun zoomImageFromThumb(thumbView: View) {
// If there's an animation in progress, cancel it immediately and proceed with this one.
currentAnimator?.cancel()

View File

@ -24,7 +24,6 @@ import eu.kanade.tachiyomi.data.track.TrackService
import eu.kanade.tachiyomi.source.LocalSource
import eu.kanade.tachiyomi.source.Source
import eu.kanade.tachiyomi.source.model.SChapter
import eu.kanade.tachiyomi.source.model.SManga
import eu.kanade.tachiyomi.ui.manga.chapter.ChapterItem
import eu.kanade.tachiyomi.ui.manga.track.TrackItem
import eu.kanade.tachiyomi.ui.security.SecureActivityDelegate
@ -340,7 +339,7 @@ class MangaDetailsPresenter(
manga.copyFrom(networkManga)
manga.initialized = true
db.insertManga(manga).executeAsBlocking()
if (thumbnailUrl != networkManga.thumbnail_url) {
if (thumbnailUrl != networkManga.thumbnail_url && !manga.hasCustomCover()) {
MangaImpl.setLastCoverFetch(manga.id!!, Date().time)
withContext(Dispatchers.Main) { controller.setPaletteColor() }
}
@ -562,7 +561,7 @@ class MangaDetailsPresenter(
directory.mkdirs()
// Build destination file.
val filename = DiskUtil.buildValidFilename("${manga.originalTitle()} - Cover.jpg")
val filename = DiskUtil.buildValidFilename("${manga.title} - Cover.jpg")
val destFile = File(directory, filename)
val stream: OutputStream = FileOutputStream(destFile)
@ -589,63 +588,23 @@ class MangaDetailsPresenter(
manga.genre = if (tags.isNullOrEmpty()) null else tagsString?.trim()
LocalSource(downloadManager.context).updateMangaInfo(manga)
db.updateMangaInfo(manga).executeAsBlocking()
} else {
var changed = false
val title = title?.trim()
if (!title.isNullOrBlank() && manga.originalTitle().isBlank()) {
manga.title = title
changed = true
} else if (title.isNullOrBlank() && manga.currentTitle() != manga.originalTitle()) {
manga.title = manga.originalTitle()
changed = true
} else if (!title.isNullOrBlank() && title != manga.currentTitle()) {
manga.title = "${title}${SManga.splitter}${manga.originalTitle()}"
changed = true
}
val author = author?.trim()
if (author.isNullOrBlank() && manga.currentAuthor() != manga.originalAuthor()) {
manga.author = manga.originalAuthor()
changed = true
} else if (!author.isNullOrBlank() && author != manga.currentAuthor()) {
manga.author = "${author}${SManga.splitter}${manga.originalAuthor() ?: ""}"
changed = true
}
val artist = artist?.trim()
if (artist.isNullOrBlank() && manga.currentArtist() != manga.originalArtist()) {
manga.artist = manga.originalArtist()
changed = true
} else if (!artist.isNullOrBlank() && artist != manga.currentArtist()) {
manga.artist = "${artist}${SManga.splitter}${manga.originalArtist() ?: ""}"
changed = true
}
val description = description?.trim()
if (description.isNullOrBlank() && manga.currentDesc() != manga.originalDesc()) {
manga.description = manga.originalDesc()
changed = true
} else if (!description.isNullOrBlank() && description != manga.currentDesc()) {
manga.description = "${description}${SManga.splitter}${manga.originalDesc() ?: ""}"
changed = true
}
var tagsString = tags?.joinToString(", ")
if ((tagsString.isNullOrBlank() && manga.currentGenres() != manga.originalGenres()) || tagsString == manga.originalGenres()) {
manga.genre = manga.originalGenres()
changed = true
} else if (!tagsString.isNullOrBlank() && tagsString != manga.currentGenres()) {
tagsString = tags?.joinToString(", ") { it.capitalize() }
manga.genre = "${tagsString}${SManga.splitter}${manga.originalGenres() ?: ""}"
changed = true
}
if (changed) db.updateMangaInfo(manga).executeAsBlocking()
}
if (uri != null) editCoverWithStream(uri)
controller.updateHeader()
}
private fun editCoverWithStream(uri: Uri): Boolean {
fun clearCover() {
if (manga.hasCustomCover()) {
coverCache.deleteFromCache(manga.thumbnail_url!!)
manga.thumbnail_url = manga.thumbnail_url?.removePrefix("Custom-")
db.insertManga(manga).executeAsBlocking()
MangaImpl.setLastCoverFetch(manga.id!!, Date().time)
controller.updateHeader()
controller.setPaletteColor()
}
}
fun editCoverWithStream(uri: Uri): Boolean {
val inputStream =
downloadManager.context.contentResolver.openInputStream(uri) ?: return false
if (manga.source == LocalSource.ID) {
@ -653,8 +612,11 @@ class MangaDetailsPresenter(
return true
}
if (manga.thumbnail_url != null && manga.favorite) {
Injekt.get<PreferencesHelper>().refreshCoversToo().set(false)
if (manga.favorite) {
if (!manga.hasCustomCover()) {
manga.thumbnail_url = "Custom-${manga.thumbnail_url ?: manga.id!!}"
db.insertManga(manga).executeAsBlocking()
}
coverCache.copyToCache(manga.thumbnail_url!!, inputStream)
MangaImpl.setLastCoverFetch(manga.id!!, Date().time)
return true

View File

@ -15,6 +15,7 @@ import eu.kanade.tachiyomi.R
import eu.kanade.tachiyomi.data.database.models.Manga
import eu.kanade.tachiyomi.data.database.models.MangaImpl
import eu.kanade.tachiyomi.data.glide.GlideApp
import eu.kanade.tachiyomi.source.LocalSource
import eu.kanade.tachiyomi.source.model.SManga
import eu.kanade.tachiyomi.ui.base.holder.BaseFlexibleViewHolder
import eu.kanade.tachiyomi.ui.manga.chapter.ChaptersAdapter
@ -86,24 +87,24 @@ class MangaHeaderHolder(
@SuppressLint("SetTextI18n")
fun bind(item: MangaHeaderItem, manga: Manga) {
val presenter = adapter.coverListener.mangaPresenter()
manga_full_title.text = manga.currentTitle()
manga_full_title.text = manga.title
if (manga.currentGenres().isNullOrBlank().not())
manga_genres_tags.setTags(manga.currentGenres()?.split(", ")?.map(String::trim))
if (manga.genre.isNullOrBlank().not())
manga_genres_tags.setTags(manga.genre?.split(", ")?.map(String::trim))
else
manga_genres_tags.setTags(emptyList())
if (manga.currentAuthor() == manga.currentArtist() ||
manga.currentArtist().isNullOrBlank())
manga_author.text = manga.currentAuthor()?.trim()
if (manga.author == manga.artist ||
manga.artist.isNullOrBlank())
manga_author.text = manga.author?.trim()
else {
manga_author.text = "${manga.currentAuthor()?.trim()}, ${manga.currentArtist()}"
manga_author.text = "${manga.author?.trim()}, ${manga.artist}"
}
manga_summary.text = manga.currentDesc()?.trim() ?: itemView.context.getString(R.string
manga_summary.text = manga.description?.trim() ?: itemView.context.getString(R.string
.no_description)
manga_summary.post {
if ((manga_summary.lineCount < 3 && manga.currentGenres().isNullOrBlank()) ||
if ((manga_summary.lineCount < 3 && manga.genre.isNullOrBlank()) ||
less_button.visibility == View.VISIBLE) {
more_button_group.gone()
} else
@ -190,6 +191,11 @@ class MangaHeaderHolder(
filters_text.text = presenter.currentFilters()
if (manga.source == LocalSource.ID) {
webview_button.gone()
share_button.gone()
}
if (!manga.initialized) return
GlideApp.with(view.context).load(manga)
.diskCacheStrategy(DiskCacheStrategy.AUTOMATIC)

View File

@ -1,8 +1,6 @@
package eu.kanade.tachiyomi.ui.manga.info
import android.app.Activity
import android.app.Dialog
import android.content.Intent
import android.net.Uri
import android.os.Bundle
import android.view.View
@ -18,11 +16,7 @@ import eu.kanade.tachiyomi.data.glide.GlideApp
import eu.kanade.tachiyomi.source.LocalSource
import eu.kanade.tachiyomi.ui.base.controller.DialogController
import eu.kanade.tachiyomi.ui.manga.MangaDetailsController
import eu.kanade.tachiyomi.util.lang.chop
import eu.kanade.tachiyomi.util.system.toast
import java.io.IOException
import kotlinx.android.synthetic.main.edit_manga_dialog.view.*
import timber.log.Timber
import uy.kohesive.injekt.Injekt
import uy.kohesive.injekt.api.get
@ -84,77 +78,24 @@ class EditMangaDialog : DialogController {
view.manga_artist.append(manga.artist ?: "")
view.manga_description.append(manga.description ?: "")
view.manga_genres_tags.setTags(manga.genre?.split(", ") ?: emptyList())
} else {
if (manga.currentTitle() != manga.originalTitle())
view.manga_full_title.append(manga.currentTitle())
view.manga_full_title.hint = "${resources?.getString(R.string.title)}: ${manga
.originalTitle()}"
if (manga.currentAuthor() != manga.originalAuthor())
view.manga_author.append(manga.currentAuthor())
if (!manga.originalAuthor().isNullOrBlank())
view.manga_author.hint = "${resources?.getString(R.string
.manga_info_author_label)}: ${manga.originalAuthor()}"
if (manga.currentArtist() != manga.originalArtist())
view.manga_artist.append(manga.currentArtist())
if (!manga.originalArtist().isNullOrBlank())
view.manga_artist.hint = "${resources?.getString(R.string
.manga_info_artist_label)}: ${manga.originalArtist()}"
if (manga.currentDesc() != manga.originalDesc())
view.manga_description.append(manga.currentDesc())
if (!manga.originalDesc().isNullOrBlank())
view.manga_description.hint = "${resources?.getString(R.string.description)}: ${manga
.originalDesc()?.chop(15)}"
if (manga.currentGenres().isNullOrBlank().not()) {
view.manga_genres_tags.setTags(manga.currentGenres()?.split(", "))
}
}
view.manga_genres_tags.clearFocus()
view.cover_layout.setOnClickListener {
changeCover()
infoController.changeCover()
}
view.reset_tags.setOnClickListener { resetTags() }
}
private fun resetTags() {
if (manga.originalGenres().isNullOrBlank() || manga.source == LocalSource.ID)
dialogView?.manga_genres_tags?.setTags(emptyList())
else
dialogView?.manga_genres_tags?.setTags(manga.originalGenres()?.split(", "))
if (manga.genre.isNullOrBlank() || manga.source == LocalSource.ID) dialogView?.manga_genres_tags?.setTags(
emptyList()
)
else dialogView?.manga_genres_tags?.setTags(manga.genre?.split(", "))
}
private fun changeCover() {
if (manga.favorite) {
val intent = Intent(Intent.ACTION_GET_CONTENT)
intent.type = "image/*"
startActivityForResult(
Intent.createChooser(intent,
resources?.getString(R.string.file_select_cover)),
101
)
} else {
activity?.toast(R.string.notification_first_add_to_library)
}
}
override fun onActivityResult(requestCode: Int, resultCode: Int, data: Intent?) {
if (requestCode == 101) {
if (data == null || resultCode != Activity.RESULT_OK) return
val activity = activity ?: return
try {
// Get the file's input stream from the incoming Intent
GlideApp.with(dialogView!!.context)
.load(data.data ?: Uri.EMPTY)
.into(dialogView!!.manga_cover)
customCoverUri = data.data
} catch (error: IOException) {
activity.toast(R.string.notification_cover_update_failed)
Timber.e(error)
}
}
fun updateCover(uri: Uri) {
GlideApp.with(dialogView!!.context).load(uri).into(dialogView!!.manga_cover)
customCoverUri = uri
}
override fun onDestroyView(view: View) {

View File

@ -97,7 +97,7 @@ class TrackSearchDialog : DialogController {
// Do an initial search based on the manga's title
if (savedState == null) {
val title = presenter.manga.originalTitle()
val title = presenter.manga.title
view.track_search.append(title)
search(title)
}

View File

@ -16,8 +16,8 @@ class MangaHolder(
fun bind(item: MangaItem) {
// Update the title of the manga.
title.text = item.manga.currentTitle()
subtitle.text = item.manga.currentAuthor()?.trim()
title.text = item.manga.title
subtitle.text = item.manga.author?.trim()
// Update the cover.
GlideApp.with(itemView.context).clear(cover_thumbnail)

View File

@ -24,7 +24,7 @@ import uy.kohesive.injekt.injectLazy
class SearchController(
private var manga: Manga? = null
) : CatalogueSearchController(manga?.originalTitle()), BottomNavBarInterface {
) : CatalogueSearchController(manga?.title), BottomNavBarInterface {
private var newManga: Manga? = null
private var progress = 1

View File

@ -163,7 +163,7 @@ class MigrationListController(bundle: Bundle? = null) : BaseController(bundle),
} else {*/
val searchResult = smartSearchEngine.normalSearch(
source,
mangaObj.originalTitle()
mangaObj.title
)
if (searchResult != null) {
@ -206,7 +206,7 @@ class MigrationListController(bundle: Bundle? = null) : BaseController(bundle),
val searchResult = try {
val searchResult = smartSearchEngine.normalSearch(
source,
mangaObj.originalTitle()
mangaObj.title
)
if (searchResult != null) {

View File

@ -144,10 +144,10 @@ class MigrationProcessHolder(
compact_title.visible()
gradient.visible()
compact_title.text = if (manga.currentTitle().isBlank()) {
compact_title.text = if (manga.title.isBlank()) {
view.context.getString(R.string.unknown)
} else {
manga.currentTitle()
manga.title
}
gradient.visible()

View File

@ -415,7 +415,7 @@ class ReaderActivity : BaseRxActivity<ReaderPresenter>(),
viewer = newViewer
viewer_container.addView(newViewer.getView())
toolbar.title = manga.currentTitle()
toolbar.title = manga.title
page_seekbar.isRTL = newViewer is R2LPagerViewer

View File

@ -445,7 +445,7 @@ class ReaderPresenter(
// Build destination file.
val filename = DiskUtil.buildValidFilename(
"${manga.currentTitle()} - ${chapter.name}".take(225)
"${manga.title} - ${chapter.name}".take(225)
) + " - ${page.number}.${type.extension}"
val destFile = File(directory, filename)

View File

@ -61,7 +61,7 @@ class RecentChapterHolder(private val view: View, private val adapter: RecentCha
chapter_title.text = item.chapter.name
// Set manga title
manga_full_title.text = item.manga.currentTitle()
manga_full_title.text = item.manga.title
// Set the correct drawable for dropdown and update the tint to match theme.
chapter_menu_icon.setVectorCompat(R.drawable.ic_more_horiz_black_24dp, view.context.getResourceColor(R.attr.icon_color))

View File

@ -44,7 +44,7 @@ class RecentChapterItem(val chapter: Chapter, val manga: Manga, header: DateItem
fun filter(text: String): Boolean {
return chapter.name.contains(text, false) ||
manga.currentTitle().contains(text, false)
manga.title.contains(text, false)
}
override fun equals(other: Any?): Boolean {

View File

@ -48,7 +48,7 @@ class RecentlyReadHolder(
val (manga, chapter, history) = item
// Set manga title
manga_full_title.text = manga.currentTitle()
manga_full_title.text = manga.title
// Set source + chapter title
val formattedNumber = adapter.decimalFormat.format(chapter.chapter_number.toDouble())

View File

@ -74,7 +74,7 @@ object ChapterRecognition {
}
// Remove manga title from chapter title.
val nameWithoutManga = name.replace(manga.originalTitle().toLowerCase(), "").trim()
val nameWithoutManga = name.replace(manga.title.toLowerCase(), "").trim()
// Check if first value is number after title remove.
if (updateChapter(withoutManga.find(nameWithoutManga), chapter))

View File

@ -86,9 +86,11 @@
android:id="@+id/reset_tags"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
style="@style/Theme.Widget.Button.Primary"
android:textAllCaps="false"
android:layout_marginEnd="16dp"
android:layout_marginStart="16dp"
android:text="@string/reset_tags" />
android:text="@string/clear_tags" />
<View
android:layout_width="match_parent"

View File

@ -622,6 +622,6 @@
<string name="use_first_source">Używaj pierwszego źródła z alternatywą</string>
<string name="skip_this_step_next_time">Pomiń ten krok następnym razem</string>
<string name="pre_migration_skip_toast">By pokazać ten ekran ponownie, przejdź do Ustawienia -> Biblioteka.</string>
<string name="reset_tags">Resetuj tagi</string>
<string name="clear_tags">Resetuj tagi</string>
</resources>

View File

@ -493,7 +493,7 @@
<string name="repeating">Перечитываю</string>
<string name="reset_tags">Сбросить теги</string>
<string name="clear_tags">Сбросить теги</string>
<string name="restore_completed">Восстановление закончено</string>
<string name="restore_completed_content">%1$s восстановлено. %2$s ошибок обнаружено.</string>

View File

@ -86,6 +86,8 @@
<string name="action_remove_download">Remove download</string>
<string name="action_update_library">Update library</string>
<string name="action_edit">Edit</string>
<string name="action_edit_cover">Edit cover</string>
<string name="action_reset_cover">Reset cover</string>
<string name="action_add">Add</string>
<string name="action_add_category">Add category</string>
<string name="action_edit_categories">Edit categories</string>
@ -662,7 +664,7 @@
<item quantity="other">and %1$d more extensions</item>
</plurals>
<string name="notification_cover_update_failed">Failed to update cover</string>
<string name="notification_first_add_to_library">Please add the manga to your library before doing this</string>
<string name="notification_first_add_to_library">Manga must be in your library to edit</string>
<string name="notification_action_error_log">View all errors</string>
@ -726,7 +728,7 @@
<string name="use_first_source">Use first source with alternative</string>
<string name="skip_this_step_next_time">Skip this step next time</string>
<string name="pre_migration_skip_toast">To show this screen again, go to Settings -> Library.</string>
<string name="reset_tags">Reset Tags</string>
<string name="clear_tags">Clear Tags</string>
<string name="display_as">Display as</string>
<string name="action_auto">Auto</string>
<string name="more">More</string>