mirror of
https://github.com/tachiyomiorg/tachiyomi.git
synced 2024-11-14 05:05:06 +01:00
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:
parent
d87c1cb5b9
commit
8f884bf222
@ -34,7 +34,7 @@ android {
|
|||||||
minSdkVersion(23)
|
minSdkVersion(23)
|
||||||
targetSdkVersion(29)
|
targetSdkVersion(29)
|
||||||
applicationId = "eu.kanade.tachiyomi"
|
applicationId = "eu.kanade.tachiyomi"
|
||||||
versionCode = 60
|
versionCode = 61
|
||||||
versionName = "0.9.81"
|
versionName = "0.9.81"
|
||||||
testInstrumentationRunner = "androidx.test.runner.AndroidJUnitRunner"
|
testInstrumentationRunner = "androidx.test.runner.AndroidJUnitRunner"
|
||||||
multiDexEnabled = true
|
multiDexEnabled = true
|
||||||
|
@ -5,6 +5,7 @@ import eu.kanade.tachiyomi.data.library.LibraryUpdateJob
|
|||||||
import eu.kanade.tachiyomi.data.preference.PreferencesHelper
|
import eu.kanade.tachiyomi.data.preference.PreferencesHelper
|
||||||
import eu.kanade.tachiyomi.data.preference.getOrDefault
|
import eu.kanade.tachiyomi.data.preference.getOrDefault
|
||||||
import eu.kanade.tachiyomi.data.updater.UpdaterJob
|
import eu.kanade.tachiyomi.data.updater.UpdaterJob
|
||||||
|
import eu.kanade.tachiyomi.ui.library.LibraryPresenter
|
||||||
import java.io.File
|
import java.io.File
|
||||||
|
|
||||||
object Migrations {
|
object Migrations {
|
||||||
@ -63,6 +64,8 @@ object Migrations {
|
|||||||
}
|
}
|
||||||
if (oldVersion < 54)
|
if (oldVersion < 54)
|
||||||
DownloadProvider(context).renameChaapters()
|
DownloadProvider(context).renameChaapters()
|
||||||
|
if (oldVersion < 61)
|
||||||
|
LibraryPresenter.resetCustomManga()
|
||||||
return true
|
return true
|
||||||
}
|
}
|
||||||
return false
|
return false
|
||||||
|
@ -15,7 +15,7 @@ object MangaTypeAdapter {
|
|||||||
write {
|
write {
|
||||||
beginArray()
|
beginArray()
|
||||||
value(it.url)
|
value(it.url)
|
||||||
value(it.originalTitle())
|
value(it.title)
|
||||||
value(it.source)
|
value(it.source)
|
||||||
value(max(0, it.viewer))
|
value(max(0, it.viewer))
|
||||||
value(it.chapter_flags)
|
value(it.chapter_flags)
|
||||||
|
@ -37,7 +37,7 @@ interface Manga : SManga {
|
|||||||
|
|
||||||
fun mangaType(): Int {
|
fun mangaType(): Int {
|
||||||
val sourceName = Injekt.get<SourceManager>().getOrStub(source).name
|
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
|
return if (currentTags?.any
|
||||||
{ tag ->
|
{ tag ->
|
||||||
tag.startsWith("japanese") || tag == "manga"
|
tag.startsWith("japanese") || tag == "manga"
|
||||||
@ -69,7 +69,7 @@ interface Manga : SManga {
|
|||||||
|
|
||||||
fun defaultReaderType(): Int {
|
fun defaultReaderType(): Int {
|
||||||
val sourceName = Injekt.get<SourceManager>().getOrStub(source).name
|
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
|
return if (currentTags?.any
|
||||||
{ tag ->
|
{ tag ->
|
||||||
tag == "long strip" || tag == "manhwa" ||
|
tag == "long strip" || tag == "manhwa" ||
|
||||||
|
@ -42,13 +42,9 @@ open class MangaImpl : Manga {
|
|||||||
|
|
||||||
override fun copyFrom(other: SManga) {
|
override fun copyFrom(other: SManga) {
|
||||||
if (other is MangaImpl && (other as MangaImpl)::title.isInitialized &&
|
if (other is MangaImpl && (other as MangaImpl)::title.isInitialized &&
|
||||||
!other.title.isBlank() && other.title != originalTitle()) {
|
!other.title.isBlank() && other.title != title) {
|
||||||
val oldTitle = originalTitle()
|
val oldTitle = title
|
||||||
title = if (currentTitle() != originalTitle()) {
|
title = other.title
|
||||||
val customTitle = currentTitle()
|
|
||||||
val trueTitle = other.title
|
|
||||||
"${customTitle}${SManga.splitter}$trueTitle"
|
|
||||||
} else other.title
|
|
||||||
val db: DownloadManager by injectLazy()
|
val db: DownloadManager by injectLazy()
|
||||||
val provider = DownloadProvider(db.context)
|
val provider = DownloadProvider(db.context)
|
||||||
provider.renameMangaFolder(oldTitle, title, source)
|
provider.renameMangaFolder(oldTitle, title, source)
|
||||||
|
@ -34,10 +34,11 @@ class MangaInfoPutResolver(val reset: Boolean = false) : PutResolver<Manga>() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
fun resetToContentValues(manga: Manga) = ContentValues(1).apply {
|
fun resetToContentValues(manga: Manga) = ContentValues(1).apply {
|
||||||
put(MangaTable.COL_TITLE, manga.originalTitle())
|
val splitter = "▒ ▒∩▒"
|
||||||
put(MangaTable.COL_GENRE, manga.originalGenres())
|
put(MangaTable.COL_TITLE, manga.title.split(splitter).last())
|
||||||
put(MangaTable.COL_AUTHOR, manga.originalAuthor())
|
put(MangaTable.COL_GENRE, manga.genre?.split(splitter)?.lastOrNull())
|
||||||
put(MangaTable.COL_ARTIST, manga.originalArtist())
|
put(MangaTable.COL_AUTHOR, manga.author?.split(splitter)?.lastOrNull())
|
||||||
put(MangaTable.COL_DESCRIPTION, manga.originalDesc())
|
put(MangaTable.COL_ARTIST, manga.artist?.split(splitter)?.lastOrNull())
|
||||||
|
put(MangaTable.COL_DESCRIPTION, manga.description?.split(splitter)?.lastOrNull())
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -142,10 +142,10 @@ class DownloadCache(
|
|||||||
}
|
}
|
||||||
val trueMangaDirs = mangaDirs.mapNotNull { mangaDir ->
|
val trueMangaDirs = mangaDirs.mapNotNull { mangaDir ->
|
||||||
val manga = sourceMangas.firstOrNull()?.find { DiskUtil.buildValidFilename(
|
val manga = sourceMangas.firstOrNull()?.find { DiskUtil.buildValidFilename(
|
||||||
it.originalTitle()).toLowerCase() == mangaDir.key
|
it.title).toLowerCase() == mangaDir.key
|
||||||
.toLowerCase() && it.source == sourceValue.key }
|
.toLowerCase() && it.source == sourceValue.key }
|
||||||
?: sourceMangas.lastOrNull()?.find { DiskUtil.buildValidFilename(
|
?: sourceMangas.lastOrNull()?.find { DiskUtil.buildValidFilename(
|
||||||
it.originalTitle()).toLowerCase() == mangaDir.key
|
it.title).toLowerCase() == mangaDir.key
|
||||||
.toLowerCase() && it.source == sourceValue.key }
|
.toLowerCase() && it.source == sourceValue.key }
|
||||||
val id = manga?.id ?: return@mapNotNull null
|
val id = manga?.id ?: return@mapNotNull null
|
||||||
id to mangaDir.value.files
|
id to mangaDir.value.files
|
||||||
|
@ -84,7 +84,7 @@ internal class DownloadNotifier(private val context: Context) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (download != null) {
|
if (download != null) {
|
||||||
val title = download.manga.currentTitle().chop(15)
|
val title = download.manga.title.chop(15)
|
||||||
val quotedTitle = Pattern.quote(title)
|
val quotedTitle = Pattern.quote(title)
|
||||||
val chapter = download.chapter.name.replaceFirst("$quotedTitle[\\s]*[-]*[\\s]*"
|
val chapter = download.chapter.name.replaceFirst("$quotedTitle[\\s]*[-]*[\\s]*"
|
||||||
.toRegex(RegexOption.IGNORE_CASE), "")
|
.toRegex(RegexOption.IGNORE_CASE), "")
|
||||||
@ -129,7 +129,7 @@ internal class DownloadNotifier(private val context: Context) {
|
|||||||
NotificationReceiver.pauseDownloadsPendingBroadcast(context))
|
NotificationReceiver.pauseDownloadsPendingBroadcast(context))
|
||||||
}
|
}
|
||||||
|
|
||||||
val title = download.manga.currentTitle().chop(15)
|
val title = download.manga.title.chop(15)
|
||||||
val quotedTitle = Pattern.quote(title)
|
val quotedTitle = Pattern.quote(title)
|
||||||
val chapter = download.chapter.name.replaceFirst("$quotedTitle[\\s]*[-]*[\\s]*".toRegex(RegexOption.IGNORE_CASE), "")
|
val chapter = download.chapter.name.replaceFirst("$quotedTitle[\\s]*[-]*[\\s]*".toRegex(RegexOption.IGNORE_CASE), "")
|
||||||
setContentTitle("$title - $chapter".chop(30))
|
setContentTitle("$title - $chapter".chop(30))
|
||||||
|
@ -185,7 +185,7 @@ class DownloadProvider(private val context: Context) {
|
|||||||
* @param manga the manga to query.
|
* @param manga the manga to query.
|
||||||
*/
|
*/
|
||||||
fun getMangaDirName(manga: Manga): String {
|
fun getMangaDirName(manga: Manga): String {
|
||||||
return DiskUtil.buildValidFilename(manga.originalTitle())
|
return DiskUtil.buildValidFilename(manga.title)
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -90,11 +90,8 @@ class MangaModelLoader : ModelLoader<Manga, InputStream> {
|
|||||||
): ModelLoader.LoadData<InputStream>? {
|
): ModelLoader.LoadData<InputStream>? {
|
||||||
// Check thumbnail is not null or empty
|
// Check thumbnail is not null or empty
|
||||||
val url = manga.thumbnail_url
|
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 source = sourceManager.get(manga.source) as? HttpSource
|
||||||
val glideUrl = GlideUrl(url, getHeaders(manga, source))
|
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 an instance of the fetcher providing the needed elements.
|
||||||
return ModelLoader.LoadData(MangaSignature(manga, file), libraryFetcher)
|
return ModelLoader.LoadData(MangaSignature(manga, file), libraryFetcher)
|
||||||
} else {
|
} else {
|
||||||
// Get the file from the url, removing the scheme if present.
|
// Get the file from the url, removing the scheme if present, or from the cache if no url.
|
||||||
val file = File(url.substringAfter("file://"))
|
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 an instance of the fetcher providing the needed elements.
|
||||||
return ModelLoader.LoadData(MangaSignature(manga, file), FileFetcher(file))
|
return ModelLoader.LoadData(MangaSignature(manga, file), FileFetcher(file))
|
||||||
|
@ -36,7 +36,7 @@ object LibraryUpdateRanker {
|
|||||||
fun lexicographicRanking(): Comparator<Manga> {
|
fun lexicographicRanking(): Comparator<Manga> {
|
||||||
return Comparator { mangaFirst: Manga,
|
return Comparator { mangaFirst: Manga,
|
||||||
mangaSecond: Manga ->
|
mangaSecond: Manga ->
|
||||||
compareValues(mangaFirst.currentTitle(), mangaSecond.currentTitle())
|
compareValues(mangaFirst.title, mangaSecond.title)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -522,7 +522,7 @@ class LibraryUpdateService(
|
|||||||
private fun showProgressNotification(manga: Manga, current: Int, total: Int) {
|
private fun showProgressNotification(manga: Manga, current: Int, total: Int) {
|
||||||
notificationManager.notify(
|
notificationManager.notify(
|
||||||
Notifications.ID_LIBRARY_PROGRESS, progressNotification
|
Notifications.ID_LIBRARY_PROGRESS, progressNotification
|
||||||
.setContentTitle(manga.currentTitle())
|
.setContentTitle(manga.title)
|
||||||
.setProgress(total, current, false)
|
.setProgress(total, current, false)
|
||||||
.build()
|
.build()
|
||||||
)
|
)
|
||||||
@ -549,7 +549,7 @@ class LibraryUpdateService(
|
|||||||
} catch (e: Exception) {
|
} catch (e: Exception) {
|
||||||
}
|
}
|
||||||
setGroupAlertBehavior(GROUP_ALERT_SUMMARY)
|
setGroupAlertBehavior(GROUP_ALERT_SUMMARY)
|
||||||
setContentTitle(manga.currentTitle())
|
setContentTitle(manga.title)
|
||||||
color = ContextCompat.getColor(this@LibraryUpdateService, R.color.colorAccent)
|
color = ContextCompat.getColor(this@LibraryUpdateService, R.color.colorAccent)
|
||||||
val chaptersNames = if (chapterNames.size > 5) {
|
val chaptersNames = if (chapterNames.size > 5) {
|
||||||
"${chapterNames.take(4).joinToString(", ")}, " +
|
"${chapterNames.take(4).joinToString(", ")}, " +
|
||||||
@ -605,11 +605,11 @@ class LibraryUpdateService(
|
|||||||
setStyle(
|
setStyle(
|
||||||
NotificationCompat.BigTextStyle()
|
NotificationCompat.BigTextStyle()
|
||||||
.bigText(updates.keys.joinToString("\n") {
|
.bigText(updates.keys.joinToString("\n") {
|
||||||
it.currentTitle().chop(45)
|
it.title.chop(45)
|
||||||
})
|
})
|
||||||
)
|
)
|
||||||
} else {
|
} else {
|
||||||
setContentText(updates.keys.first().currentTitle().chop(45))
|
setContentText(updates.keys.first().title.chop(45))
|
||||||
}
|
}
|
||||||
priority = NotificationCompat.PRIORITY_HIGH
|
priority = NotificationCompat.PRIORITY_HIGH
|
||||||
setGroup(Notifications.GROUP_NEW_CHAPTERS)
|
setGroup(Notifications.GROUP_NEW_CHAPTERS)
|
||||||
|
@ -65,7 +65,7 @@ class SmartSearchEngine(
|
|||||||
return@supervisorScope listOf(SearchEntry(searchResults.mangas.first(), 0.0))
|
return@supervisorScope listOf(SearchEntry(searchResults.mangas.first(), 0.0))
|
||||||
|
|
||||||
searchResults.mangas.map {
|
searchResults.mangas.map {
|
||||||
val normalizedDistance = normalizedLevenshtein.similarity(title, it.originalTitle())
|
val normalizedDistance = normalizedLevenshtein.similarity(title, it.title)
|
||||||
SearchEntry(it, normalizedDistance)
|
SearchEntry(it, normalizedDistance)
|
||||||
}.filter { (_, normalizedDistance) ->
|
}.filter { (_, normalizedDistance) ->
|
||||||
normalizedDistance >= MIN_NORMAL_ELIGIBLE_THRESHOLD
|
normalizedDistance >= MIN_NORMAL_ELIGIBLE_THRESHOLD
|
||||||
|
@ -202,7 +202,7 @@ class LocalSource(private val context: Context) : CatalogueSource {
|
|||||||
chapterFile.nameWithoutExtension
|
chapterFile.nameWithoutExtension
|
||||||
}
|
}
|
||||||
val chapNameCut =
|
val chapNameCut =
|
||||||
chapName.replace(manga.originalTitle(), "", true).trim(' ', '-', '_')
|
chapName.replace(manga.title, "", true).trim(' ', '-', '_')
|
||||||
name = if (chapNameCut.isEmpty()) chapName else chapNameCut
|
name = if (chapNameCut.isEmpty()) chapName else chapNameCut
|
||||||
date_upload = chapterFile.lastModified()
|
date_upload = chapterFile.lastModified()
|
||||||
ChapterRecognition.parseChapterNumber(this, manga)
|
ChapterRecognition.parseChapterNumber(this, manga)
|
||||||
|
@ -23,68 +23,22 @@ interface SManga : Serializable {
|
|||||||
|
|
||||||
var initialized: Boolean
|
var initialized: Boolean
|
||||||
|
|
||||||
fun currentTitle(): String {
|
fun hasCustomCover() = thumbnail_url?.startsWith("Custom-") == true
|
||||||
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 copyFrom(other: SManga) {
|
fun copyFrom(other: SManga) {
|
||||||
if (other.author != null)
|
if (other.author != null)
|
||||||
author = if (currentAuthor() != originalAuthor()) {
|
author = other.author
|
||||||
val current = currentAuthor()
|
|
||||||
val og = other.author
|
|
||||||
"${current}$splitter$og"
|
|
||||||
} else other.author
|
|
||||||
|
|
||||||
if (other.artist != null)
|
if (other.artist != null)
|
||||||
artist = if (currentArtist() != originalArtist()) {
|
artist = other.artist
|
||||||
val current = currentArtist()
|
|
||||||
val og = other.artist
|
|
||||||
"${current}$splitter$og"
|
|
||||||
} else other.artist
|
|
||||||
|
|
||||||
if (other.description != null)
|
if (other.description != null)
|
||||||
description = if (currentDesc() != originalDesc()) {
|
description = other.description
|
||||||
val current = currentDesc()
|
|
||||||
val og = other.description
|
|
||||||
"${current}$splitter$og"
|
|
||||||
} else other.description
|
|
||||||
|
|
||||||
if (other.genre != null)
|
if (other.genre != null)
|
||||||
genre = if (currentGenres() != originalGenres()) {
|
genre = other.genre
|
||||||
val current = currentGenres()
|
|
||||||
val og = other.genre
|
|
||||||
"${current}$splitter$og"
|
|
||||||
} else other.genre
|
|
||||||
|
|
||||||
if (other.thumbnail_url != null)
|
if (other.thumbnail_url != null && !hasCustomCover())
|
||||||
thumbnail_url = other.thumbnail_url
|
thumbnail_url = other.thumbnail_url
|
||||||
|
|
||||||
status = other.status
|
status = other.status
|
||||||
@ -98,7 +52,6 @@ interface SManga : Serializable {
|
|||||||
const val ONGOING = 1
|
const val ONGOING = 1
|
||||||
const val COMPLETED = 2
|
const val COMPLETED = 2
|
||||||
const val LICENSED = 3
|
const val LICENSED = 3
|
||||||
const val splitter = "▒ ▒∩▒"
|
|
||||||
|
|
||||||
fun create(): SManga {
|
fun create(): SManga {
|
||||||
return MangaImpl()
|
return MangaImpl()
|
||||||
|
@ -37,7 +37,7 @@ class CatalogueGridHolder(
|
|||||||
*/
|
*/
|
||||||
override fun onSetValues(manga: Manga) {
|
override fun onSetValues(manga: Manga) {
|
||||||
// Update the title of the manga.
|
// Update the title of the manga.
|
||||||
compact_title.text = manga.currentTitle()
|
compact_title.text = manga.title
|
||||||
badge_view.setInLibrary(manga.favorite)
|
badge_view.setInLibrary(manga.favorite)
|
||||||
|
|
||||||
// Update the cover.
|
// Update the cover.
|
||||||
|
@ -31,7 +31,7 @@ class CatalogueListHolder(private val view: View, adapter: FlexibleAdapter<IFlex
|
|||||||
* @param manga the manga to bind.
|
* @param manga the manga to bind.
|
||||||
*/
|
*/
|
||||||
override fun onSetValues(manga: Manga) {
|
override fun onSetValues(manga: Manga) {
|
||||||
title.text = manga.originalTitle()
|
title.text = manga.title
|
||||||
with(subtitle) {
|
with(subtitle) {
|
||||||
visibility = if (manga.favorite) View.VISIBLE else View.GONE
|
visibility = if (manga.favorite) View.VISIBLE else View.GONE
|
||||||
text = view.resources.getString(R.string.in_library)
|
text = view.resources.getString(R.string.in_library)
|
||||||
|
@ -38,7 +38,7 @@ class DownloadHolder(private val view: View, val adapter: DownloadAdapter) :
|
|||||||
chapter_title.text = download.chapter.name
|
chapter_title.text = download.chapter.name
|
||||||
|
|
||||||
// Update the manga title
|
// 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
|
// Update the progress bar and the number of downloaded pages
|
||||||
val pages = download.pages
|
val pages = download.pages
|
||||||
|
@ -108,7 +108,7 @@ class LibraryCategoryAdapter(val libraryListener: LibraryListener) :
|
|||||||
when (preferences.librarySortingMode().getOrDefault()) {
|
when (preferences.librarySortingMode().getOrDefault()) {
|
||||||
LibrarySort.DRAG_AND_DROP -> {
|
LibrarySort.DRAG_AND_DROP -> {
|
||||||
if (!preferences.hideCategories().getOrDefault()) {
|
if (!preferences.hideCategories().getOrDefault()) {
|
||||||
val title = (iFlexible as LibraryItem).manga.currentTitle()
|
val title = (iFlexible as LibraryItem).manga.title
|
||||||
if (preferences.removeArticles().getOrDefault())
|
if (preferences.removeArticles().getOrDefault())
|
||||||
title.removeArticles().substring(0, 1).toUpperCase(Locale.US)
|
title.removeArticles().substring(0, 1).toUpperCase(Locale.US)
|
||||||
else title.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"
|
"N/A"
|
||||||
}
|
}
|
||||||
else -> {
|
else -> {
|
||||||
val title = (iFlexible as LibraryItem).manga.currentTitle()
|
val title = (iFlexible as LibraryItem).manga.title
|
||||||
if (preferences.removeArticles().getOrDefault())
|
if (preferences.removeArticles().getOrDefault())
|
||||||
title.removeArticles().substring(0, 1).toUpperCase(Locale.US)
|
title.removeArticles().substring(0, 1).toUpperCase(Locale.US)
|
||||||
else title.substring(0, 1).toUpperCase(Locale.US)
|
else title.substring(0, 1).toUpperCase(Locale.US)
|
||||||
|
@ -53,8 +53,8 @@ class LibraryGridHolder(
|
|||||||
*/
|
*/
|
||||||
override fun onSetValues(item: LibraryItem) {
|
override fun onSetValues(item: LibraryItem) {
|
||||||
// Update the title and subtitle of the manga.
|
// Update the title and subtitle of the manga.
|
||||||
title.text = item.manga.currentTitle()
|
title.text = item.manga.title
|
||||||
subtitle.text = item.manga.originalAuthor()?.trim()
|
subtitle.text = item.manga.author?.trim()
|
||||||
|
|
||||||
compact_title.text = title.text
|
compact_title.text = title.text
|
||||||
|
|
||||||
|
@ -124,15 +124,14 @@ class LibraryItem(
|
|||||||
val sourceManager by injectLazy<SourceManager>()
|
val sourceManager by injectLazy<SourceManager>()
|
||||||
val sourceName = if (manga.source == 0L) "Local" else
|
val sourceName = if (manga.source == 0L) "Local" else
|
||||||
sourceManager.getOrStub(manga.source).name
|
sourceManager.getOrStub(manga.source).name
|
||||||
return manga.currentTitle().contains(constraint, true) ||
|
return manga.title.contains(constraint, true) ||
|
||||||
manga.originalTitle().contains(constraint, true) ||
|
(manga.author?.contains(constraint, true) ?: false) ||
|
||||||
(manga.currentAuthor()?.contains(constraint, true) ?: false) ||
|
(manga.artist?.contains(constraint, true) ?: false) ||
|
||||||
(manga.currentArtist()?.contains(constraint, true) ?: false) ||
|
|
||||||
sourceName.contains(constraint, true) ||
|
sourceName.contains(constraint, true) ||
|
||||||
if (constraint.contains(",")) {
|
if (constraint.contains(",")) {
|
||||||
val genres = manga.currentGenres()?.split(", ")
|
val genres = manga.genre?.split(", ")
|
||||||
constraint.split(",").all { containsGenre(it.trim(), genres) }
|
constraint.split(",").all { containsGenre(it.trim(), genres) }
|
||||||
} else containsGenre(constraint, manga.currentGenres()?.split(", "))
|
} else containsGenre(constraint, manga.genre?.split(", "))
|
||||||
}
|
}
|
||||||
|
|
||||||
@SuppressLint("DefaultLocale")
|
@SuppressLint("DefaultLocale")
|
||||||
|
@ -34,11 +34,11 @@ class LibraryListHolder(
|
|||||||
*/
|
*/
|
||||||
override fun onSetValues(item: LibraryItem) {
|
override fun onSetValues(item: LibraryItem) {
|
||||||
// Update the title of the manga.
|
// Update the title of the manga.
|
||||||
title.text = item.manga.currentTitle()
|
title.text = item.manga.title
|
||||||
setUnreadBadge(badge_view, item)
|
setUnreadBadge(badge_view, item)
|
||||||
|
|
||||||
subtitle.text = item.manga.originalAuthor()?.trim()
|
subtitle.text = item.manga.author?.trim()
|
||||||
subtitle.visibility = if (!item.manga.originalAuthor().isNullOrBlank()) View.VISIBLE
|
subtitle.visibility = if (!item.manga.author.isNullOrBlank()) View.VISIBLE
|
||||||
else View.GONE
|
else View.GONE
|
||||||
|
|
||||||
play_layout.visibility = if (item.manga.unread > 0 && item.unreadType > 0)
|
play_layout.visibility = if (item.manga.unread > 0 && item.unreadType > 0)
|
||||||
|
@ -430,8 +430,8 @@ class LibraryPresenter(
|
|||||||
|
|
||||||
private fun sortAlphabetical(i1: LibraryItem, i2: LibraryItem): Int {
|
private fun sortAlphabetical(i1: LibraryItem, i2: LibraryItem): Int {
|
||||||
return if (preferences.removeArticles().getOrDefault())
|
return if (preferences.removeArticles().getOrDefault())
|
||||||
i1.manga.currentTitle().removeArticles().compareTo(i2.manga.currentTitle().removeArticles(), true)
|
i1.manga.title.removeArticles().compareTo(i2.manga.title.removeArticles(), true)
|
||||||
else i1.manga.currentTitle().compareTo(i2.manga.currentTitle(), true)
|
else i1.manga.title.compareTo(i2.manga.title, true)
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -876,7 +876,17 @@ class LibraryPresenter(
|
|||||||
return catId in categories
|
return catId in categories
|
||||||
}
|
}
|
||||||
|
|
||||||
private companion object {
|
companion object {
|
||||||
var currentLibrary: Library? = null
|
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()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -44,6 +44,7 @@ import androidx.transition.ChangeImageTransform
|
|||||||
import androidx.transition.TransitionManager
|
import androidx.transition.TransitionManager
|
||||||
import androidx.transition.TransitionSet
|
import androidx.transition.TransitionSet
|
||||||
import com.afollestad.materialdialogs.MaterialDialog
|
import com.afollestad.materialdialogs.MaterialDialog
|
||||||
|
import com.afollestad.materialdialogs.list.listItems
|
||||||
import com.bluelinelabs.conductor.ControllerChangeHandler
|
import com.bluelinelabs.conductor.ControllerChangeHandler
|
||||||
import com.bluelinelabs.conductor.ControllerChangeType
|
import com.bluelinelabs.conductor.ControllerChangeType
|
||||||
import com.bumptech.glide.load.engine.DiskCacheStrategy
|
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.glide.GlideApp
|
||||||
import eu.kanade.tachiyomi.data.notification.NotificationReceiver
|
import eu.kanade.tachiyomi.data.notification.NotificationReceiver
|
||||||
import eu.kanade.tachiyomi.data.track.model.TrackSearch
|
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.Source
|
||||||
import eu.kanade.tachiyomi.source.SourceManager
|
import eu.kanade.tachiyomi.source.SourceManager
|
||||||
import eu.kanade.tachiyomi.source.online.HttpSource
|
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.updateLayoutParams
|
||||||
import eu.kanade.tachiyomi.util.view.updatePaddingRelative
|
import eu.kanade.tachiyomi.util.view.updatePaddingRelative
|
||||||
import java.io.File
|
import java.io.File
|
||||||
|
import java.io.IOException
|
||||||
import jp.wasabeef.glide.transformations.CropSquareTransformation
|
import jp.wasabeef.glide.transformations.CropSquareTransformation
|
||||||
import jp.wasabeef.glide.transformations.MaskTransformation
|
import jp.wasabeef.glide.transformations.MaskTransformation
|
||||||
import kotlinx.android.synthetic.main.main_activity.*
|
import kotlinx.android.synthetic.main.main_activity.*
|
||||||
@ -152,6 +155,7 @@ class MangaDetailsController : BaseController,
|
|||||||
var coverDrawable: Drawable? = null
|
var coverDrawable: Drawable? = null
|
||||||
private var trackingBottomSheet: TrackingBottomSheet? = null
|
private var trackingBottomSheet: TrackingBottomSheet? = null
|
||||||
private var startingDLChapterPos: Int? = null
|
private var startingDLChapterPos: Int? = null
|
||||||
|
private var editMangaDialog: EditMangaDialog? = null
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Adapter containing a list of chapters.
|
* Adapter containing a list of chapters.
|
||||||
@ -173,7 +177,7 @@ class MangaDetailsController : BaseController,
|
|||||||
}
|
}
|
||||||
|
|
||||||
override fun getTitle(): String? {
|
override fun getTitle(): String? {
|
||||||
return if (toolbarIsColored) manga?.currentTitle() else null
|
return if (toolbarIsColored) manga?.title else null
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun onViewCreated(view: View) {
|
override fun onViewCreated(view: View) {
|
||||||
@ -480,6 +484,8 @@ class MangaDetailsController : BaseController,
|
|||||||
inflater.inflate(R.menu.manga_details, menu)
|
inflater.inflate(R.menu.manga_details, menu)
|
||||||
val editItem = menu.findItem(R.id.action_edit)
|
val editItem = menu.findItem(R.id.action_edit)
|
||||||
editItem.isVisible = presenter.manga.favorite && !presenter.isLockedFromSearch
|
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_download).isVisible = !presenter.isLockedFromSearch
|
||||||
menu.findItem(R.id.action_mark_all_as_read).isVisible =
|
menu.findItem(R.id.action_mark_all_as_read).isVisible =
|
||||||
presenter.getNextUnreadChapter() != null && !presenter.isLockedFromSearch
|
presenter.getNextUnreadChapter() != null && !presenter.isLockedFromSearch
|
||||||
@ -489,7 +495,32 @@ class MangaDetailsController : BaseController,
|
|||||||
|
|
||||||
override fun onOptionsItemSelected(item: MenuItem): Boolean {
|
override fun onOptionsItemSelected(item: MenuItem): Boolean {
|
||||||
when (item.itemId) {
|
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_open_in_web_view -> openInWebView()
|
||||||
R.id.action_share -> prepareToShareManga()
|
R.id.action_share -> prepareToShareManga()
|
||||||
R.id.action_add_to_home_screen -> addToHomeScreen()
|
R.id.action_add_to_home_screen -> addToHomeScreen()
|
||||||
@ -543,7 +574,7 @@ class MangaDetailsController : BaseController,
|
|||||||
val intent = Intent(Intent.ACTION_SEND).apply {
|
val intent = Intent(Intent.ACTION_SEND).apply {
|
||||||
type = "text/*"
|
type = "text/*"
|
||||||
putExtra(Intent.EXTRA_TEXT, url)
|
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
|
flags = Intent.FLAG_GRANT_READ_URI_PERMISSION
|
||||||
if (stream != null) {
|
if (stream != null) {
|
||||||
clipData = ClipData.newRawUri(null, stream)
|
clipData = ClipData.newRawUri(null, stream)
|
||||||
@ -566,7 +597,7 @@ class MangaDetailsController : BaseController,
|
|||||||
|
|
||||||
val activity = activity ?: return
|
val activity = activity ?: return
|
||||||
val intent = WebViewActivity.newIntent(activity.applicationContext, source.id, url, presenter.manga
|
val intent = WebViewActivity.newIntent(activity.applicationContext, source.id, url, presenter.manga
|
||||||
.originalTitle())
|
.title)
|
||||||
startActivity(intent)
|
startActivity(intent)
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -669,11 +700,11 @@ class MangaDetailsController : BaseController,
|
|||||||
|
|
||||||
// Check if shortcut placement is supported
|
// Check if shortcut placement is supported
|
||||||
if (ShortcutManagerCompat.isRequestPinShortcutSupported(activity)) {
|
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
|
// Create shortcut info
|
||||||
val shortcutInfo = ShortcutInfoCompat.Builder(activity, shortcutId)
|
val shortcutInfo = ShortcutInfoCompat.Builder(activity, shortcutId)
|
||||||
.setShortLabel(presenter.manga.currentTitle())
|
.setShortLabel(presenter.manga.title)
|
||||||
.setIcon(IconCompat.createWithBitmap(icon))
|
.setIcon(IconCompat.createWithBitmap(icon))
|
||||||
.setIntent(shortcutIntent)
|
.setIntent(shortcutIntent)
|
||||||
.build()
|
.build()
|
||||||
@ -989,6 +1020,38 @@ class MangaDetailsController : BaseController,
|
|||||||
return false
|
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) {
|
override fun zoomImageFromThumb(thumbView: View) {
|
||||||
// If there's an animation in progress, cancel it immediately and proceed with this one.
|
// If there's an animation in progress, cancel it immediately and proceed with this one.
|
||||||
currentAnimator?.cancel()
|
currentAnimator?.cancel()
|
||||||
|
@ -24,7 +24,6 @@ import eu.kanade.tachiyomi.data.track.TrackService
|
|||||||
import eu.kanade.tachiyomi.source.LocalSource
|
import eu.kanade.tachiyomi.source.LocalSource
|
||||||
import eu.kanade.tachiyomi.source.Source
|
import eu.kanade.tachiyomi.source.Source
|
||||||
import eu.kanade.tachiyomi.source.model.SChapter
|
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.chapter.ChapterItem
|
||||||
import eu.kanade.tachiyomi.ui.manga.track.TrackItem
|
import eu.kanade.tachiyomi.ui.manga.track.TrackItem
|
||||||
import eu.kanade.tachiyomi.ui.security.SecureActivityDelegate
|
import eu.kanade.tachiyomi.ui.security.SecureActivityDelegate
|
||||||
@ -340,7 +339,7 @@ class MangaDetailsPresenter(
|
|||||||
manga.copyFrom(networkManga)
|
manga.copyFrom(networkManga)
|
||||||
manga.initialized = true
|
manga.initialized = true
|
||||||
db.insertManga(manga).executeAsBlocking()
|
db.insertManga(manga).executeAsBlocking()
|
||||||
if (thumbnailUrl != networkManga.thumbnail_url) {
|
if (thumbnailUrl != networkManga.thumbnail_url && !manga.hasCustomCover()) {
|
||||||
MangaImpl.setLastCoverFetch(manga.id!!, Date().time)
|
MangaImpl.setLastCoverFetch(manga.id!!, Date().time)
|
||||||
withContext(Dispatchers.Main) { controller.setPaletteColor() }
|
withContext(Dispatchers.Main) { controller.setPaletteColor() }
|
||||||
}
|
}
|
||||||
@ -562,7 +561,7 @@ class MangaDetailsPresenter(
|
|||||||
directory.mkdirs()
|
directory.mkdirs()
|
||||||
|
|
||||||
// Build destination file.
|
// 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 destFile = File(directory, filename)
|
||||||
val stream: OutputStream = FileOutputStream(destFile)
|
val stream: OutputStream = FileOutputStream(destFile)
|
||||||
@ -589,63 +588,23 @@ class MangaDetailsPresenter(
|
|||||||
manga.genre = if (tags.isNullOrEmpty()) null else tagsString?.trim()
|
manga.genre = if (tags.isNullOrEmpty()) null else tagsString?.trim()
|
||||||
LocalSource(downloadManager.context).updateMangaInfo(manga)
|
LocalSource(downloadManager.context).updateMangaInfo(manga)
|
||||||
db.updateMangaInfo(manga).executeAsBlocking()
|
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)
|
if (uri != null) editCoverWithStream(uri)
|
||||||
controller.updateHeader()
|
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 =
|
val inputStream =
|
||||||
downloadManager.context.contentResolver.openInputStream(uri) ?: return false
|
downloadManager.context.contentResolver.openInputStream(uri) ?: return false
|
||||||
if (manga.source == LocalSource.ID) {
|
if (manga.source == LocalSource.ID) {
|
||||||
@ -653,8 +612,11 @@ class MangaDetailsPresenter(
|
|||||||
return true
|
return true
|
||||||
}
|
}
|
||||||
|
|
||||||
if (manga.thumbnail_url != null && manga.favorite) {
|
if (manga.favorite) {
|
||||||
Injekt.get<PreferencesHelper>().refreshCoversToo().set(false)
|
if (!manga.hasCustomCover()) {
|
||||||
|
manga.thumbnail_url = "Custom-${manga.thumbnail_url ?: manga.id!!}"
|
||||||
|
db.insertManga(manga).executeAsBlocking()
|
||||||
|
}
|
||||||
coverCache.copyToCache(manga.thumbnail_url!!, inputStream)
|
coverCache.copyToCache(manga.thumbnail_url!!, inputStream)
|
||||||
MangaImpl.setLastCoverFetch(manga.id!!, Date().time)
|
MangaImpl.setLastCoverFetch(manga.id!!, Date().time)
|
||||||
return true
|
return true
|
||||||
|
@ -15,6 +15,7 @@ import eu.kanade.tachiyomi.R
|
|||||||
import eu.kanade.tachiyomi.data.database.models.Manga
|
import eu.kanade.tachiyomi.data.database.models.Manga
|
||||||
import eu.kanade.tachiyomi.data.database.models.MangaImpl
|
import eu.kanade.tachiyomi.data.database.models.MangaImpl
|
||||||
import eu.kanade.tachiyomi.data.glide.GlideApp
|
import eu.kanade.tachiyomi.data.glide.GlideApp
|
||||||
|
import eu.kanade.tachiyomi.source.LocalSource
|
||||||
import eu.kanade.tachiyomi.source.model.SManga
|
import eu.kanade.tachiyomi.source.model.SManga
|
||||||
import eu.kanade.tachiyomi.ui.base.holder.BaseFlexibleViewHolder
|
import eu.kanade.tachiyomi.ui.base.holder.BaseFlexibleViewHolder
|
||||||
import eu.kanade.tachiyomi.ui.manga.chapter.ChaptersAdapter
|
import eu.kanade.tachiyomi.ui.manga.chapter.ChaptersAdapter
|
||||||
@ -86,24 +87,24 @@ class MangaHeaderHolder(
|
|||||||
@SuppressLint("SetTextI18n")
|
@SuppressLint("SetTextI18n")
|
||||||
fun bind(item: MangaHeaderItem, manga: Manga) {
|
fun bind(item: MangaHeaderItem, manga: Manga) {
|
||||||
val presenter = adapter.coverListener.mangaPresenter()
|
val presenter = adapter.coverListener.mangaPresenter()
|
||||||
manga_full_title.text = manga.currentTitle()
|
manga_full_title.text = manga.title
|
||||||
|
|
||||||
if (manga.currentGenres().isNullOrBlank().not())
|
if (manga.genre.isNullOrBlank().not())
|
||||||
manga_genres_tags.setTags(manga.currentGenres()?.split(", ")?.map(String::trim))
|
manga_genres_tags.setTags(manga.genre?.split(", ")?.map(String::trim))
|
||||||
else
|
else
|
||||||
manga_genres_tags.setTags(emptyList())
|
manga_genres_tags.setTags(emptyList())
|
||||||
|
|
||||||
if (manga.currentAuthor() == manga.currentArtist() ||
|
if (manga.author == manga.artist ||
|
||||||
manga.currentArtist().isNullOrBlank())
|
manga.artist.isNullOrBlank())
|
||||||
manga_author.text = manga.currentAuthor()?.trim()
|
manga_author.text = manga.author?.trim()
|
||||||
else {
|
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)
|
.no_description)
|
||||||
|
|
||||||
manga_summary.post {
|
manga_summary.post {
|
||||||
if ((manga_summary.lineCount < 3 && manga.currentGenres().isNullOrBlank()) ||
|
if ((manga_summary.lineCount < 3 && manga.genre.isNullOrBlank()) ||
|
||||||
less_button.visibility == View.VISIBLE) {
|
less_button.visibility == View.VISIBLE) {
|
||||||
more_button_group.gone()
|
more_button_group.gone()
|
||||||
} else
|
} else
|
||||||
@ -190,6 +191,11 @@ class MangaHeaderHolder(
|
|||||||
|
|
||||||
filters_text.text = presenter.currentFilters()
|
filters_text.text = presenter.currentFilters()
|
||||||
|
|
||||||
|
if (manga.source == LocalSource.ID) {
|
||||||
|
webview_button.gone()
|
||||||
|
share_button.gone()
|
||||||
|
}
|
||||||
|
|
||||||
if (!manga.initialized) return
|
if (!manga.initialized) return
|
||||||
GlideApp.with(view.context).load(manga)
|
GlideApp.with(view.context).load(manga)
|
||||||
.diskCacheStrategy(DiskCacheStrategy.AUTOMATIC)
|
.diskCacheStrategy(DiskCacheStrategy.AUTOMATIC)
|
||||||
|
@ -1,8 +1,6 @@
|
|||||||
package eu.kanade.tachiyomi.ui.manga.info
|
package eu.kanade.tachiyomi.ui.manga.info
|
||||||
|
|
||||||
import android.app.Activity
|
|
||||||
import android.app.Dialog
|
import android.app.Dialog
|
||||||
import android.content.Intent
|
|
||||||
import android.net.Uri
|
import android.net.Uri
|
||||||
import android.os.Bundle
|
import android.os.Bundle
|
||||||
import android.view.View
|
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.source.LocalSource
|
||||||
import eu.kanade.tachiyomi.ui.base.controller.DialogController
|
import eu.kanade.tachiyomi.ui.base.controller.DialogController
|
||||||
import eu.kanade.tachiyomi.ui.manga.MangaDetailsController
|
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 kotlinx.android.synthetic.main.edit_manga_dialog.view.*
|
||||||
import timber.log.Timber
|
|
||||||
import uy.kohesive.injekt.Injekt
|
import uy.kohesive.injekt.Injekt
|
||||||
import uy.kohesive.injekt.api.get
|
import uy.kohesive.injekt.api.get
|
||||||
|
|
||||||
@ -84,77 +78,24 @@ class EditMangaDialog : DialogController {
|
|||||||
view.manga_artist.append(manga.artist ?: "")
|
view.manga_artist.append(manga.artist ?: "")
|
||||||
view.manga_description.append(manga.description ?: "")
|
view.manga_description.append(manga.description ?: "")
|
||||||
view.manga_genres_tags.setTags(manga.genre?.split(", ") ?: emptyList())
|
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.manga_genres_tags.clearFocus()
|
||||||
view.cover_layout.setOnClickListener {
|
view.cover_layout.setOnClickListener {
|
||||||
changeCover()
|
infoController.changeCover()
|
||||||
}
|
}
|
||||||
view.reset_tags.setOnClickListener { resetTags() }
|
view.reset_tags.setOnClickListener { resetTags() }
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun resetTags() {
|
private fun resetTags() {
|
||||||
if (manga.originalGenres().isNullOrBlank() || manga.source == LocalSource.ID)
|
if (manga.genre.isNullOrBlank() || manga.source == LocalSource.ID) dialogView?.manga_genres_tags?.setTags(
|
||||||
dialogView?.manga_genres_tags?.setTags(emptyList())
|
emptyList()
|
||||||
else
|
)
|
||||||
dialogView?.manga_genres_tags?.setTags(manga.originalGenres()?.split(", "))
|
else dialogView?.manga_genres_tags?.setTags(manga.genre?.split(", "))
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun changeCover() {
|
fun updateCover(uri: Uri) {
|
||||||
if (manga.favorite) {
|
GlideApp.with(dialogView!!.context).load(uri).into(dialogView!!.manga_cover)
|
||||||
val intent = Intent(Intent.ACTION_GET_CONTENT)
|
customCoverUri = uri
|
||||||
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)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun onDestroyView(view: View) {
|
override fun onDestroyView(view: View) {
|
||||||
|
@ -97,7 +97,7 @@ class TrackSearchDialog : DialogController {
|
|||||||
|
|
||||||
// Do an initial search based on the manga's title
|
// Do an initial search based on the manga's title
|
||||||
if (savedState == null) {
|
if (savedState == null) {
|
||||||
val title = presenter.manga.originalTitle()
|
val title = presenter.manga.title
|
||||||
view.track_search.append(title)
|
view.track_search.append(title)
|
||||||
search(title)
|
search(title)
|
||||||
}
|
}
|
||||||
|
@ -16,8 +16,8 @@ class MangaHolder(
|
|||||||
|
|
||||||
fun bind(item: MangaItem) {
|
fun bind(item: MangaItem) {
|
||||||
// Update the title of the manga.
|
// Update the title of the manga.
|
||||||
title.text = item.manga.currentTitle()
|
title.text = item.manga.title
|
||||||
subtitle.text = item.manga.currentAuthor()?.trim()
|
subtitle.text = item.manga.author?.trim()
|
||||||
|
|
||||||
// Update the cover.
|
// Update the cover.
|
||||||
GlideApp.with(itemView.context).clear(cover_thumbnail)
|
GlideApp.with(itemView.context).clear(cover_thumbnail)
|
||||||
|
@ -24,7 +24,7 @@ import uy.kohesive.injekt.injectLazy
|
|||||||
|
|
||||||
class SearchController(
|
class SearchController(
|
||||||
private var manga: Manga? = null
|
private var manga: Manga? = null
|
||||||
) : CatalogueSearchController(manga?.originalTitle()), BottomNavBarInterface {
|
) : CatalogueSearchController(manga?.title), BottomNavBarInterface {
|
||||||
|
|
||||||
private var newManga: Manga? = null
|
private var newManga: Manga? = null
|
||||||
private var progress = 1
|
private var progress = 1
|
||||||
|
@ -163,7 +163,7 @@ class MigrationListController(bundle: Bundle? = null) : BaseController(bundle),
|
|||||||
} else {*/
|
} else {*/
|
||||||
val searchResult = smartSearchEngine.normalSearch(
|
val searchResult = smartSearchEngine.normalSearch(
|
||||||
source,
|
source,
|
||||||
mangaObj.originalTitle()
|
mangaObj.title
|
||||||
)
|
)
|
||||||
|
|
||||||
if (searchResult != null) {
|
if (searchResult != null) {
|
||||||
@ -206,7 +206,7 @@ class MigrationListController(bundle: Bundle? = null) : BaseController(bundle),
|
|||||||
val searchResult = try {
|
val searchResult = try {
|
||||||
val searchResult = smartSearchEngine.normalSearch(
|
val searchResult = smartSearchEngine.normalSearch(
|
||||||
source,
|
source,
|
||||||
mangaObj.originalTitle()
|
mangaObj.title
|
||||||
)
|
)
|
||||||
|
|
||||||
if (searchResult != null) {
|
if (searchResult != null) {
|
||||||
|
@ -144,10 +144,10 @@ class MigrationProcessHolder(
|
|||||||
|
|
||||||
compact_title.visible()
|
compact_title.visible()
|
||||||
gradient.visible()
|
gradient.visible()
|
||||||
compact_title.text = if (manga.currentTitle().isBlank()) {
|
compact_title.text = if (manga.title.isBlank()) {
|
||||||
view.context.getString(R.string.unknown)
|
view.context.getString(R.string.unknown)
|
||||||
} else {
|
} else {
|
||||||
manga.currentTitle()
|
manga.title
|
||||||
}
|
}
|
||||||
|
|
||||||
gradient.visible()
|
gradient.visible()
|
||||||
|
@ -415,7 +415,7 @@ class ReaderActivity : BaseRxActivity<ReaderPresenter>(),
|
|||||||
viewer = newViewer
|
viewer = newViewer
|
||||||
viewer_container.addView(newViewer.getView())
|
viewer_container.addView(newViewer.getView())
|
||||||
|
|
||||||
toolbar.title = manga.currentTitle()
|
toolbar.title = manga.title
|
||||||
|
|
||||||
page_seekbar.isRTL = newViewer is R2LPagerViewer
|
page_seekbar.isRTL = newViewer is R2LPagerViewer
|
||||||
|
|
||||||
|
@ -445,7 +445,7 @@ class ReaderPresenter(
|
|||||||
|
|
||||||
// Build destination file.
|
// Build destination file.
|
||||||
val filename = DiskUtil.buildValidFilename(
|
val filename = DiskUtil.buildValidFilename(
|
||||||
"${manga.currentTitle()} - ${chapter.name}".take(225)
|
"${manga.title} - ${chapter.name}".take(225)
|
||||||
) + " - ${page.number}.${type.extension}"
|
) + " - ${page.number}.${type.extension}"
|
||||||
|
|
||||||
val destFile = File(directory, filename)
|
val destFile = File(directory, filename)
|
||||||
|
@ -61,7 +61,7 @@ class RecentChapterHolder(private val view: View, private val adapter: RecentCha
|
|||||||
chapter_title.text = item.chapter.name
|
chapter_title.text = item.chapter.name
|
||||||
|
|
||||||
// Set manga title
|
// 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.
|
// 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))
|
chapter_menu_icon.setVectorCompat(R.drawable.ic_more_horiz_black_24dp, view.context.getResourceColor(R.attr.icon_color))
|
||||||
|
@ -44,7 +44,7 @@ class RecentChapterItem(val chapter: Chapter, val manga: Manga, header: DateItem
|
|||||||
|
|
||||||
fun filter(text: String): Boolean {
|
fun filter(text: String): Boolean {
|
||||||
return chapter.name.contains(text, false) ||
|
return chapter.name.contains(text, false) ||
|
||||||
manga.currentTitle().contains(text, false)
|
manga.title.contains(text, false)
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun equals(other: Any?): Boolean {
|
override fun equals(other: Any?): Boolean {
|
||||||
|
@ -48,7 +48,7 @@ class RecentlyReadHolder(
|
|||||||
val (manga, chapter, history) = item
|
val (manga, chapter, history) = item
|
||||||
|
|
||||||
// Set manga title
|
// Set manga title
|
||||||
manga_full_title.text = manga.currentTitle()
|
manga_full_title.text = manga.title
|
||||||
|
|
||||||
// Set source + chapter title
|
// Set source + chapter title
|
||||||
val formattedNumber = adapter.decimalFormat.format(chapter.chapter_number.toDouble())
|
val formattedNumber = adapter.decimalFormat.format(chapter.chapter_number.toDouble())
|
||||||
|
@ -74,7 +74,7 @@ object ChapterRecognition {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Remove manga title from chapter title.
|
// 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.
|
// Check if first value is number after title remove.
|
||||||
if (updateChapter(withoutManga.find(nameWithoutManga), chapter))
|
if (updateChapter(withoutManga.find(nameWithoutManga), chapter))
|
||||||
|
@ -86,9 +86,11 @@
|
|||||||
android:id="@+id/reset_tags"
|
android:id="@+id/reset_tags"
|
||||||
android:layout_width="wrap_content"
|
android:layout_width="wrap_content"
|
||||||
android:layout_height="wrap_content"
|
android:layout_height="wrap_content"
|
||||||
|
style="@style/Theme.Widget.Button.Primary"
|
||||||
|
android:textAllCaps="false"
|
||||||
android:layout_marginEnd="16dp"
|
android:layout_marginEnd="16dp"
|
||||||
android:layout_marginStart="16dp"
|
android:layout_marginStart="16dp"
|
||||||
android:text="@string/reset_tags" />
|
android:text="@string/clear_tags" />
|
||||||
|
|
||||||
<View
|
<View
|
||||||
android:layout_width="match_parent"
|
android:layout_width="match_parent"
|
||||||
|
@ -622,6 +622,6 @@
|
|||||||
<string name="use_first_source">Używaj pierwszego źródła z alternatywą</string>
|
<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="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="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>
|
</resources>
|
||||||
|
@ -493,7 +493,7 @@
|
|||||||
|
|
||||||
<string name="repeating">Перечитываю</string>
|
<string name="repeating">Перечитываю</string>
|
||||||
|
|
||||||
<string name="reset_tags">Сбросить теги</string>
|
<string name="clear_tags">Сбросить теги</string>
|
||||||
|
|
||||||
<string name="restore_completed">Восстановление закончено</string>
|
<string name="restore_completed">Восстановление закончено</string>
|
||||||
<string name="restore_completed_content">%1$s восстановлено. %2$s ошибок обнаружено.</string>
|
<string name="restore_completed_content">%1$s восстановлено. %2$s ошибок обнаружено.</string>
|
||||||
|
@ -86,6 +86,8 @@
|
|||||||
<string name="action_remove_download">Remove download</string>
|
<string name="action_remove_download">Remove download</string>
|
||||||
<string name="action_update_library">Update library</string>
|
<string name="action_update_library">Update library</string>
|
||||||
<string name="action_edit">Edit</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">Add</string>
|
||||||
<string name="action_add_category">Add category</string>
|
<string name="action_add_category">Add category</string>
|
||||||
<string name="action_edit_categories">Edit categories</string>
|
<string name="action_edit_categories">Edit categories</string>
|
||||||
@ -662,7 +664,7 @@
|
|||||||
<item quantity="other">and %1$d more extensions</item>
|
<item quantity="other">and %1$d more extensions</item>
|
||||||
</plurals>
|
</plurals>
|
||||||
<string name="notification_cover_update_failed">Failed to update cover</string>
|
<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>
|
<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="use_first_source">Use first source with alternative</string>
|
||||||
<string name="skip_this_step_next_time">Skip this step next time</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="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="display_as">Display as</string>
|
||||||
<string name="action_auto">Auto</string>
|
<string name="action_auto">Auto</string>
|
||||||
<string name="more">More</string>
|
<string name="more">More</string>
|
||||||
|
Loading…
Reference in New Issue
Block a user