mirror of
https://github.com/tachiyomiorg/tachiyomi.git
synced 2024-11-05 01:35:10 +01:00
UI/Functionality for custom info done
Local Manga is up next
This commit is contained in:
parent
a94d455e79
commit
c92b2bb203
@ -211,7 +211,7 @@ dependencies {
|
||||
implementation 'me.zhanghai.android.systemuihelper:library:1.0.0'
|
||||
implementation 'com.nightlynexus.viewstatepageradapter:viewstatepageradapter:1.1.0'
|
||||
implementation 'com.github.mthli:Slice:v1.2'
|
||||
implementation 'me.gujun.android.taggroup:library:1.4@aar'
|
||||
implementation 'com.github.kizitonwose:AndroidTagGroup:1.6.0'
|
||||
implementation 'com.github.chrisbanes:PhotoView:2.3.0'
|
||||
implementation 'com.github.carlosesco:DirectionalViewPager:a844dbca0a'
|
||||
|
||||
|
@ -14,7 +14,7 @@ object MangaTypeAdapter {
|
||||
write {
|
||||
beginArray()
|
||||
value(it.url)
|
||||
value(it.trueTitle())
|
||||
value(it.originalTitle())
|
||||
value(it.source)
|
||||
value(it.viewer)
|
||||
value(it.chapter_flags)
|
||||
|
@ -36,15 +36,12 @@ open class MangaImpl : Manga {
|
||||
|
||||
override var hide_title: Boolean = false
|
||||
|
||||
var last_cover_fetch: Long = 0
|
||||
|
||||
override fun copyFrom(other: SManga) {
|
||||
if (((other is MangaImpl && (other as MangaImpl)::title.isInitialized)
|
||||
|| other !is MangaImpl) && other.title != title) {
|
||||
title = if (customTitle() != trueTitle()) {
|
||||
val customTitle = customTitle()
|
||||
if ((other is MangaImpl && (other as MangaImpl)::title.isInitialized && other.title != title)) {
|
||||
title = if (currentTitle() != originalTitle()) {
|
||||
val customTitle = currentTitle()
|
||||
val trueTitle = other.title
|
||||
"${customTitle}≡§${trueTitle}"
|
||||
"${customTitle}${SManga.splitter}${trueTitle}"
|
||||
} else other.title
|
||||
}
|
||||
super.copyFrom(other)
|
||||
@ -64,4 +61,14 @@ open class MangaImpl : Manga {
|
||||
return url.hashCode()
|
||||
}
|
||||
|
||||
companion object {
|
||||
private var lastCoverFetch:MutableMap<Long, Long> = mutableMapOf()
|
||||
|
||||
fun setLastCoverFetch(id: Long, time: Long) {
|
||||
lastCoverFetch[id] = time
|
||||
}
|
||||
|
||||
fun getLastCoverFetch(id: Long) = lastCoverFetch[id] ?: 0
|
||||
}
|
||||
|
||||
}
|
||||
|
@ -92,6 +92,16 @@ interface MangaQueries : DbProvider {
|
||||
.withPutResolver(MangaTitlePutResolver())
|
||||
.prepare()
|
||||
|
||||
fun updateMangaInfo(manga: Manga) = db.put()
|
||||
.`object`(manga)
|
||||
.withPutResolver(MangaInfoPutResolver())
|
||||
.prepare()
|
||||
|
||||
fun resetMangaInfo(manga: Manga) = db.put()
|
||||
.`object`(manga)
|
||||
.withPutResolver(MangaInfoPutResolver(true))
|
||||
.prepare()
|
||||
|
||||
fun deleteManga(manga: Manga) = db.delete().`object`(manga).prepare()
|
||||
|
||||
fun deleteMangas(mangas: List<Manga>) = db.delete().objects(mangas).prepare()
|
||||
|
@ -0,0 +1,45 @@
|
||||
package eu.kanade.tachiyomi.data.database.resolvers
|
||||
|
||||
import android.content.ContentValues
|
||||
import com.pushtorefresh.storio.sqlite.StorIOSQLite
|
||||
import com.pushtorefresh.storio.sqlite.operations.put.PutResolver
|
||||
import com.pushtorefresh.storio.sqlite.operations.put.PutResult
|
||||
import com.pushtorefresh.storio.sqlite.queries.UpdateQuery
|
||||
import eu.kanade.tachiyomi.data.database.inTransactionReturn
|
||||
import eu.kanade.tachiyomi.data.database.models.Manga
|
||||
import eu.kanade.tachiyomi.data.database.tables.MangaTable
|
||||
|
||||
class MangaInfoPutResolver(val reset:Boolean = false): PutResolver<Manga>() {
|
||||
|
||||
override fun performPut(db: StorIOSQLite, manga: Manga) = db.inTransactionReturn {
|
||||
val updateQuery = mapToUpdateQuery(manga)
|
||||
val contentValues = if (reset) resetToContentValues(manga) else mapToContentValues(manga)
|
||||
|
||||
val numberOfRowsUpdated = db.lowLevel().update(updateQuery, contentValues)
|
||||
PutResult.newUpdateResult(numberOfRowsUpdated, updateQuery.table())
|
||||
}
|
||||
|
||||
fun mapToUpdateQuery(manga: Manga) = UpdateQuery.builder()
|
||||
.table(MangaTable.TABLE)
|
||||
.where("${MangaTable.COL_ID} = ?")
|
||||
.whereArgs(manga.id)
|
||||
.build()
|
||||
|
||||
fun mapToContentValues(manga: Manga) = ContentValues(1).apply {
|
||||
put(MangaTable.COL_TITLE, manga.title)
|
||||
put(MangaTable.COL_GENRE, manga.genre)
|
||||
put(MangaTable.COL_AUTHOR, manga.author)
|
||||
put(MangaTable.COL_ARTIST, manga.artist)
|
||||
put(MangaTable.COL_DESCRIPTION, manga.description)
|
||||
}
|
||||
|
||||
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())
|
||||
}
|
||||
|
||||
|
||||
}
|
@ -106,7 +106,7 @@ internal class DownloadNotifier(private val context: Context) {
|
||||
NotificationReceiver.pauseDownloadsPendingBroadcast(context))
|
||||
}
|
||||
|
||||
val title = download.manga.customTitle().chop(15)
|
||||
val title = download.manga.currentTitle().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))
|
||||
@ -161,7 +161,7 @@ internal class DownloadNotifier(private val context: Context) {
|
||||
}
|
||||
// Create notification.
|
||||
with(notification) {
|
||||
val title = download.manga.customTitle().chop(15)
|
||||
val title = download.manga.currentTitle().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))
|
||||
|
@ -178,7 +178,7 @@ class DownloadProvider(private val context: Context) {
|
||||
* @param manga the manga to query.
|
||||
*/
|
||||
fun getMangaDirName(manga: Manga): String {
|
||||
return DiskUtil.buildValidFilename(manga.trueTitle())
|
||||
return DiskUtil.buildValidFilename(manga.originalTitle())
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -36,7 +36,7 @@ object LibraryUpdateRanker {
|
||||
fun lexicographicRanking(): Comparator<Manga> {
|
||||
return Comparator { mangaFirst: Manga,
|
||||
mangaSecond: Manga ->
|
||||
compareValues(mangaFirst.customTitle(), mangaSecond.customTitle())
|
||||
compareValues(mangaFirst.currentTitle(), mangaSecond.currentTitle())
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -20,6 +20,7 @@ import eu.kanade.tachiyomi.data.database.models.Category
|
||||
import eu.kanade.tachiyomi.data.database.models.Chapter
|
||||
import eu.kanade.tachiyomi.data.database.models.LibraryManga
|
||||
import eu.kanade.tachiyomi.data.database.models.Manga
|
||||
import eu.kanade.tachiyomi.data.database.models.MangaImpl
|
||||
import eu.kanade.tachiyomi.data.download.DownloadManager
|
||||
import eu.kanade.tachiyomi.data.download.DownloadService
|
||||
import eu.kanade.tachiyomi.data.glide.GlideApp
|
||||
@ -406,7 +407,7 @@ class LibraryUpdateService(
|
||||
manga.copyFrom(networkManga)
|
||||
db.insertManga(manga).executeAsBlocking()
|
||||
coverCache.deleteFromCache(manga.thumbnail_url)
|
||||
manga.last_cover_fetch = Date().time
|
||||
MangaImpl.setLastCoverFetch(manga.id!!, Date().time)
|
||||
manga
|
||||
}
|
||||
.onErrorReturn { manga }
|
||||
@ -461,7 +462,7 @@ class LibraryUpdateService(
|
||||
*/
|
||||
private fun showProgressNotification(manga: Manga, current: Int, total: Int) {
|
||||
notificationManager.notify(Notifications.ID_LIBRARY_PROGRESS, progressNotification
|
||||
.setContentTitle(manga.customTitle())
|
||||
.setContentTitle(manga.currentTitle())
|
||||
.setProgress(total, current, false)
|
||||
.build())
|
||||
}
|
||||
@ -487,7 +488,7 @@ class LibraryUpdateService(
|
||||
}
|
||||
catch (e: Exception) { }
|
||||
setGroupAlertBehavior(GROUP_ALERT_SUMMARY)
|
||||
setContentTitle(manga.customTitle())
|
||||
setContentTitle(manga.currentTitle())
|
||||
color = ContextCompat.getColor(this@LibraryUpdateService, R.color.colorAccentLight)
|
||||
val chaptersNames = if (chapterNames.size > 5) {
|
||||
"${chapterNames.take(4).joinToString(", ")}, " +
|
||||
@ -527,11 +528,11 @@ class LibraryUpdateService(
|
||||
.notification_new_chapters_text,
|
||||
updates.size, updates.size))
|
||||
setStyle(NotificationCompat.BigTextStyle().bigText(updates.joinToString("\n") {
|
||||
it.first.customTitle().chop(45)
|
||||
it.first.currentTitle().chop(45)
|
||||
}))
|
||||
}
|
||||
else {
|
||||
setContentText(updates.first().first.customTitle().chop(45))
|
||||
setContentText(updates.first().first.currentTitle().chop(45))
|
||||
}
|
||||
priority = NotificationCompat.PRIORITY_HIGH
|
||||
setGroup(Notifications.GROUP_NEW_CHAPTERS)
|
||||
|
@ -11,7 +11,6 @@ import info.debatty.java.stringsimilarity.NormalizedLevenshtein
|
||||
import kotlinx.coroutines.CoroutineScope
|
||||
import kotlinx.coroutines.Dispatchers
|
||||
import kotlinx.coroutines.Job
|
||||
import kotlinx.coroutines.async
|
||||
import kotlinx.coroutines.supervisorScope
|
||||
import rx.schedulers.Schedulers
|
||||
import uy.kohesive.injekt.injectLazy
|
||||
@ -65,7 +64,7 @@ class SmartSearchEngine(parentContext: CoroutineContext,
|
||||
return@supervisorScope listOf(SearchEntry(searchResults.mangas.first(), 0.0))
|
||||
|
||||
searchResults.mangas.map {
|
||||
val normalizedDistance = normalizedLevenshtein.similarity(title, it.trueTitle())
|
||||
val normalizedDistance = normalizedLevenshtein.similarity(title, it.originalTitle())
|
||||
SearchEntry(it, normalizedDistance)
|
||||
}.filter { (_, normalizedDistance) ->
|
||||
normalizedDistance >= MIN_NORMAL_ELIGIBLE_THRESHOLD
|
||||
|
@ -161,7 +161,7 @@ class LocalSource(private val context: Context) : CatalogueSource {
|
||||
} else {
|
||||
chapterFile.nameWithoutExtension
|
||||
}
|
||||
val chapNameCut = chapName.replace(manga.trueTitle(), "", true).trim(' ', '-', '_')
|
||||
val chapNameCut = chapName.replace(manga.originalTitle(), "", true).trim(' ', '-', '_')
|
||||
name = if (chapNameCut.isEmpty()) chapName else chapNameCut
|
||||
date_upload = chapterFile.lastModified()
|
||||
ChapterRecognition.parseChapterNumber(this, manga)
|
||||
|
@ -22,28 +22,84 @@ interface SManga : Serializable {
|
||||
|
||||
var initialized: Boolean
|
||||
|
||||
fun customTitle(): String {
|
||||
val splitTitle = title.split("▒")
|
||||
fun currentTitle(): String {
|
||||
val splitTitle = title.split(splitter)
|
||||
return splitTitle.first()
|
||||
}
|
||||
|
||||
fun trueTitle(): String {
|
||||
val splitTitle = title.split("▒")
|
||||
fun originalTitle(): String {
|
||||
val splitTitle = title.split(splitter)
|
||||
return splitTitle.last()
|
||||
}
|
||||
|
||||
fun currentGenres(): String? {
|
||||
val splitGenre = genre?.split(splitter) ?: return null
|
||||
return splitGenre.first()
|
||||
}
|
||||
|
||||
fun originalGenres(): String? {
|
||||
val splitGenre = genre?.split(splitter) ?: return null
|
||||
return splitGenre.last()
|
||||
}
|
||||
|
||||
fun currentDesc(): String? {
|
||||
val splitDesc = description?.split(splitter) ?: return null
|
||||
return splitDesc.first()
|
||||
}
|
||||
|
||||
fun originalDesc(): String? {
|
||||
val splitDesc = description?.split(splitter) ?: return null
|
||||
return splitDesc.last()
|
||||
}
|
||||
|
||||
fun currentAuthor(): String? {
|
||||
val splitAuth = author?.split(splitter) ?: return null
|
||||
return splitAuth.first()
|
||||
}
|
||||
|
||||
fun originalAuthor(): String? {
|
||||
val splitAuth = author?.split(splitter) ?: return null
|
||||
return splitAuth.last()
|
||||
}
|
||||
|
||||
fun currentArtist(): String? {
|
||||
val splitArtist = artist?.split(splitter) ?: return null
|
||||
return splitArtist.first()
|
||||
}
|
||||
|
||||
fun originalArtist(): String? {
|
||||
val splitArtist = artist?.split(splitter) ?: return null
|
||||
return splitArtist.last()
|
||||
}
|
||||
|
||||
fun copyFrom(other: SManga) {
|
||||
if (other.author != null)
|
||||
author = other.author
|
||||
author = if (currentAuthor() != originalAuthor()) {
|
||||
val current = currentAuthor()
|
||||
val og = other.author
|
||||
"${current}$splitter${og}"
|
||||
} else other.author
|
||||
|
||||
if (other.artist != null)
|
||||
artist = other.artist
|
||||
artist = if (currentArtist() != originalArtist()) {
|
||||
val current = currentArtist()
|
||||
val og = other.artist
|
||||
"${current}$splitter${og}"
|
||||
} else other.artist
|
||||
|
||||
if (other.description != null)
|
||||
description = other.description
|
||||
description = if (currentDesc() != originalDesc()) {
|
||||
val current = currentDesc()
|
||||
val og = other.description
|
||||
"${current}$splitter${og}"
|
||||
} else other.description
|
||||
|
||||
if (other.genre != null)
|
||||
genre = other.genre
|
||||
genre = if (currentGenres() != originalGenres()) {
|
||||
val current = currentGenres()
|
||||
val og = other.genre
|
||||
"${current}$splitter${og}"
|
||||
} else other.genre
|
||||
|
||||
if (other.thumbnail_url != null)
|
||||
thumbnail_url = other.thumbnail_url
|
||||
@ -59,6 +115,7 @@ interface SManga : Serializable {
|
||||
const val ONGOING = 1
|
||||
const val COMPLETED = 2
|
||||
const val LICENSED = 3
|
||||
const val splitter = "▒ ▒∩▒"
|
||||
|
||||
fun create(): SManga {
|
||||
return SMangaImpl()
|
||||
|
@ -261,6 +261,7 @@ open class BrowseCataloguePresenter(
|
||||
coverCache.deleteFromCache(manga.thumbnail_url)
|
||||
val downloadManager: DownloadManager = Injekt.get()
|
||||
downloadManager.deleteManga(manga,source)
|
||||
db.resetMangaInfo(manga).executeAsBlocking()
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -29,7 +29,7 @@ class CatalogueGridHolder(private val view: View, private val adapter: FlexibleA
|
||||
*/
|
||||
override fun onSetValues(manga: Manga) {
|
||||
// Set manga title
|
||||
title.text = manga.title
|
||||
title.text = manga.originalTitle()
|
||||
|
||||
// Set alpha of thumbnail.
|
||||
thumbnail.alpha = if (manga.favorite) 0.3f else 1.0f
|
||||
|
@ -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.title
|
||||
title.text = manga.originalTitle()
|
||||
title.setTextColor(if (manga.favorite) favoriteColor else unfavoriteColor)
|
||||
|
||||
setImage(manga)
|
||||
|
@ -38,7 +38,7 @@ class DownloadHolder(private val view: View, val adapter: DownloadAdapter) :
|
||||
chapter_title.text = download.chapter.name
|
||||
|
||||
// Update the manga title
|
||||
manga_title.text = download.manga.customTitle()
|
||||
manga_title.text = download.manga.currentTitle()
|
||||
|
||||
// Update the progress bar and the number of downloaded pages
|
||||
val pages = download.pages
|
||||
|
@ -1,25 +1,15 @@
|
||||
package eu.kanade.tachiyomi.ui.library
|
||||
|
||||
import android.graphics.Color
|
||||
import android.text.format.DateUtils
|
||||
import androidx.core.content.ContextCompat
|
||||
import eu.davidea.flexibleadapter.FlexibleAdapter
|
||||
import eu.davidea.flexibleadapter.items.IFlexible
|
||||
import eu.kanade.tachiyomi.R
|
||||
import eu.kanade.tachiyomi.data.database.DatabaseHelper
|
||||
import eu.kanade.tachiyomi.data.database.models.Manga
|
||||
import eu.kanade.tachiyomi.data.preference.PreferencesHelper
|
||||
import eu.kanade.tachiyomi.data.preference.getOrDefault
|
||||
import eu.kanade.tachiyomi.source.SourceManager
|
||||
import eu.kanade.tachiyomi.ui.category.CategoryAdapter
|
||||
import eu.kanade.tachiyomi.util.getResourceColor
|
||||
import eu.kanade.tachiyomi.util.removeArticles
|
||||
import uy.kohesive.injekt.injectLazy
|
||||
import java.text.DateFormat
|
||||
import java.text.SimpleDateFormat
|
||||
import java.time.LocalDate
|
||||
import java.time.LocalDateTime
|
||||
import java.time.Year
|
||||
import java.util.*
|
||||
|
||||
|
||||
@ -94,7 +84,7 @@ class LibraryCategoryAdapter(val view: LibraryCategoryView) :
|
||||
"N/A"
|
||||
}
|
||||
else -> {
|
||||
val title = (iFlexible as LibraryItem).manga.customTitle()
|
||||
val title = (iFlexible as LibraryItem).manga.currentTitle()
|
||||
if (preferences.removeArticles().getOrDefault())
|
||||
title.removeArticles().substring(0, 1).toUpperCase(Locale.US)
|
||||
else title.substring(0, 1).toUpperCase(Locale.US)
|
||||
|
@ -1,11 +1,8 @@
|
||||
package eu.kanade.tachiyomi.ui.library
|
||||
|
||||
import android.app.Activity
|
||||
import android.content.Context
|
||||
import android.content.Intent
|
||||
import android.content.res.Configuration
|
||||
import android.graphics.Color
|
||||
import android.net.Uri
|
||||
import android.os.Bundle
|
||||
import android.view.LayoutInflater
|
||||
import android.view.Menu
|
||||
@ -18,7 +15,6 @@ import android.view.inputmethod.InputMethodManager
|
||||
import androidx.appcompat.app.AppCompatActivity
|
||||
import androidx.appcompat.view.ActionMode
|
||||
import androidx.appcompat.widget.SearchView
|
||||
import androidx.core.content.ContextCompat.getSystemService
|
||||
import androidx.core.graphics.drawable.DrawableCompat
|
||||
import androidx.core.view.GravityCompat
|
||||
import androidx.drawerlayout.widget.DrawerLayout
|
||||
@ -57,15 +53,12 @@ import eu.kanade.tachiyomi.util.inflate
|
||||
import eu.kanade.tachiyomi.util.marginBottom
|
||||
import eu.kanade.tachiyomi.util.marginTop
|
||||
import eu.kanade.tachiyomi.util.snack
|
||||
import eu.kanade.tachiyomi.util.toast
|
||||
import eu.kanade.tachiyomi.util.updatePaddingRelative
|
||||
import kotlinx.android.synthetic.main.library_controller.*
|
||||
import kotlinx.android.synthetic.main.main_activity.*
|
||||
import rx.Subscription
|
||||
import timber.log.Timber
|
||||
import uy.kohesive.injekt.Injekt
|
||||
import uy.kohesive.injekt.api.get
|
||||
import java.io.IOException
|
||||
|
||||
class LibraryController(
|
||||
bundle: Bundle? = null,
|
||||
@ -522,7 +515,6 @@ class LibraryController(
|
||||
destroyActionModeIfNeeded()
|
||||
} else {
|
||||
mode.title = resources?.getString(R.string.label_selected, count)
|
||||
menu.findItem(R.id.action_edit_cover)?.isVisible = count == 1
|
||||
menu.findItem(R.id.action_hide_title)?.isVisible =
|
||||
!preferences.libraryAsList().getOrDefault()
|
||||
if (!preferences.libraryAsList().getOrDefault()) {
|
||||
@ -544,10 +536,6 @@ class LibraryController(
|
||||
|
||||
override fun onActionItemClicked(mode: ActionMode, item: MenuItem): Boolean {
|
||||
when (item.itemId) {
|
||||
R.id.action_edit_cover -> {
|
||||
changeSelectedCover()
|
||||
destroyActionModeIfNeeded()
|
||||
}
|
||||
R.id.action_move_to_category -> showChangeMangaCategoriesDialog()
|
||||
R.id.action_delete -> deleteMangasFromLibrary()
|
||||
R.id.action_select_all -> {
|
||||
@ -672,55 +660,6 @@ class LibraryController(
|
||||
presenter.moveMangasToCategories(categories, mangas)
|
||||
destroyActionModeIfNeeded()
|
||||
}
|
||||
|
||||
/**
|
||||
* Changes the cover for the selected manga.
|
||||
*/
|
||||
private fun changeSelectedCover() {
|
||||
val manga = selectedMangas.firstOrNull() ?: return
|
||||
selectedCoverManga = manga
|
||||
|
||||
if (manga.favorite) {
|
||||
val intent = Intent(Intent.ACTION_GET_CONTENT)
|
||||
intent.type = "image/*"
|
||||
startActivityForResult(Intent.createChooser(intent,
|
||||
resources?.getString(R.string.file_select_cover)), REQUEST_IMAGE_OPEN)
|
||||
} else {
|
||||
activity?.toast(R.string.notification_first_add_to_library)
|
||||
}
|
||||
}
|
||||
|
||||
override fun onActivityResult(requestCode: Int, resultCode: Int, data: Intent?) {
|
||||
if (requestCode == REQUEST_IMAGE_OPEN) {
|
||||
if (data == null || resultCode != Activity.RESULT_OK) return
|
||||
val activity = activity ?: return
|
||||
val manga = selectedCoverManga ?: return
|
||||
|
||||
try {
|
||||
// Get the file's input stream from the incoming Intent
|
||||
activity.contentResolver.openInputStream(data.data ?: Uri.EMPTY).use {
|
||||
// Update cover to selected file, show error if something went wrong
|
||||
if (it != null && presenter.editCoverWithStream(it, manga)) {
|
||||
// TODO refresh cover
|
||||
} else {
|
||||
activity.toast(R.string.notification_cover_update_failed)
|
||||
}
|
||||
}
|
||||
} catch (error: IOException) {
|
||||
activity.toast(R.string.notification_cover_update_failed)
|
||||
Timber.e(error)
|
||||
}
|
||||
selectedCoverManga = null
|
||||
}
|
||||
}
|
||||
|
||||
private companion object {
|
||||
/**
|
||||
* Key to change the cover of a manga in [onActivityResult].
|
||||
*/
|
||||
const val REQUEST_IMAGE_OPEN = 101
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
object HeightTopWindowInsetsListener : View.OnApplyWindowInsetsListener {
|
||||
|
@ -6,9 +6,11 @@ import com.bumptech.glide.load.engine.DiskCacheStrategy
|
||||
import com.bumptech.glide.signature.ObjectKey
|
||||
import eu.davidea.flexibleadapter.FlexibleAdapter
|
||||
import eu.davidea.flexibleadapter.items.IFlexible
|
||||
import eu.kanade.tachiyomi.data.database.models.MangaImpl
|
||||
import eu.kanade.tachiyomi.data.glide.GlideApp
|
||||
import eu.kanade.tachiyomi.source.LocalSource
|
||||
import kotlinx.android.synthetic.main.catalogue_grid_item.*
|
||||
import java.util.Date
|
||||
|
||||
/**
|
||||
* Class used to hold the displayed data of a manga in the library, like the cover or the title.
|
||||
@ -35,7 +37,7 @@ class LibraryGridHolder(
|
||||
// Update the title of the manga.
|
||||
with(title) {
|
||||
visibility = if (item.manga.hide_title) View.GONE else View.VISIBLE
|
||||
text = item.manga.customTitle()
|
||||
text = item.manga.currentTitle()
|
||||
}
|
||||
gradient.visibility = if (item.manga.hide_title) View.GONE else View.VISIBLE
|
||||
|
||||
@ -57,7 +59,7 @@ class LibraryGridHolder(
|
||||
GlideApp.with(view.context)
|
||||
.load(item.manga)
|
||||
.diskCacheStrategy(DiskCacheStrategy.RESOURCE)
|
||||
.signature(ObjectKey(item.manga.last_cover_fetch.toString()))
|
||||
.signature(ObjectKey(MangaImpl.getLastCoverFetch(item.manga.id!!).toString()))
|
||||
.centerCrop()
|
||||
.into(thumbnail)
|
||||
}
|
||||
|
@ -71,13 +71,14 @@ class LibraryItem(val manga: LibraryManga, private val libraryAsList: Preference
|
||||
val sourceManager by injectLazy<SourceManager>()
|
||||
val sourceName = sourceManager.getOrStub(manga.source).name
|
||||
return manga.title.contains(constraint, true) ||
|
||||
(manga.author?.contains(constraint, true) ?: false) ||
|
||||
(manga.currentAuthor()?.contains(constraint, true) ?: false) ||
|
||||
(manga.currentArtist()?.contains(constraint, true) ?: false) ||
|
||||
sourceName.contains(constraint, true) ||
|
||||
if (constraint.contains(",")) {
|
||||
val genres = manga.genre?.split(", ")
|
||||
val genres = manga.currentGenres()?.split(", ")
|
||||
constraint.split(",").all { containsGenre(it.trim(), genres) }
|
||||
}
|
||||
else containsGenre(constraint, manga.genre?.split(", "))
|
||||
else containsGenre(constraint, manga.currentGenres()?.split(", "))
|
||||
}
|
||||
|
||||
@SuppressLint("DefaultLocale")
|
||||
|
@ -9,6 +9,7 @@ import kotlinx.android.synthetic.main.catalogue_list_item.*
|
||||
import androidx.recyclerview.widget.RecyclerView
|
||||
import com.bumptech.glide.signature.ObjectKey
|
||||
import eu.davidea.flexibleadapter.items.IFlexible
|
||||
import eu.kanade.tachiyomi.data.database.models.MangaImpl
|
||||
|
||||
/**
|
||||
* Class used to hold the displayed data of a manga in the library, like the cover or the title.
|
||||
@ -33,7 +34,7 @@ class LibraryListHolder(
|
||||
*/
|
||||
override fun onSetValues(item: LibraryItem) {
|
||||
// Update the title of the manga.
|
||||
title.text = item.manga.customTitle()
|
||||
title.text = item.manga.currentTitle()
|
||||
|
||||
// Update the unread count and its visibility.
|
||||
with(unread_text) {
|
||||
@ -59,7 +60,7 @@ class LibraryListHolder(
|
||||
GlideApp.with(itemView.context)
|
||||
.load(item.manga)
|
||||
.diskCacheStrategy(DiskCacheStrategy.RESOURCE)
|
||||
.signature(ObjectKey(item.manga.last_cover_fetch.toString()))
|
||||
.signature(ObjectKey(MangaImpl.getLastCoverFetch(item.manga.id!!).toString()))
|
||||
.centerCrop()
|
||||
.circleCrop()
|
||||
.dontAnimate()
|
||||
|
@ -2,7 +2,6 @@ package eu.kanade.tachiyomi.ui.library
|
||||
|
||||
import android.os.Bundle
|
||||
import com.jakewharton.rxrelay.BehaviorRelay
|
||||
import eu.kanade.tachiyomi.R
|
||||
import eu.kanade.tachiyomi.data.cache.CoverCache
|
||||
import eu.kanade.tachiyomi.data.database.DatabaseHelper
|
||||
import eu.kanade.tachiyomi.data.database.models.Category
|
||||
@ -280,8 +279,8 @@ class LibraryPresenter(
|
||||
|
||||
private fun sortAlphabetical(i1: LibraryItem, i2: LibraryItem): Int {
|
||||
return if (preferences.removeArticles().getOrDefault())
|
||||
i1.manga.customTitle().removeArticles().compareTo(i2.manga.customTitle().removeArticles(), true)
|
||||
else i1.manga.customTitle().compareTo(i2.manga.customTitle(), true)
|
||||
i1.manga.currentTitle().removeArticles().compareTo(i2.manga.currentTitle().removeArticles(), true)
|
||||
else i1.manga.currentTitle().compareTo(i2.manga.currentTitle(), true)
|
||||
}
|
||||
|
||||
/**
|
||||
@ -385,6 +384,7 @@ class LibraryPresenter(
|
||||
Observable.fromCallable {
|
||||
val mangaToDelete = mangas.distinctBy { it.id }
|
||||
mangaToDelete.forEach { manga ->
|
||||
db.resetMangaInfo(manga).executeAsBlocking()
|
||||
coverCache.deleteFromCache(manga.thumbnail_url)
|
||||
val source = sourceManager.get(manga.source) as? HttpSource
|
||||
if (source != null)
|
||||
@ -503,27 +503,4 @@ class LibraryPresenter(
|
||||
db.updateMangaTitle(manga).executeAsBlocking()
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Update cover with local file.
|
||||
*
|
||||
* @param inputStream the new cover.
|
||||
* @param manga the manga edited.
|
||||
* @return true if the cover is updated, false otherwise
|
||||
*/
|
||||
@Throws(IOException::class)
|
||||
fun editCoverWithStream(inputStream: InputStream, manga: Manga): Boolean {
|
||||
if (manga.source == LocalSource.ID) {
|
||||
LocalSource.updateCover(context, manga, inputStream)
|
||||
return true
|
||||
}
|
||||
|
||||
if (manga.thumbnail_url != null && manga.favorite) {
|
||||
coverCache.copyToCache(manga.thumbnail_url!!, inputStream)
|
||||
(manga as? MangaImpl)?.last_cover_fetch = Date().time
|
||||
return true
|
||||
}
|
||||
return false
|
||||
}
|
||||
|
||||
}
|
||||
|
@ -27,7 +27,6 @@ import eu.kanade.tachiyomi.ui.base.controller.RxController
|
||||
import eu.kanade.tachiyomi.ui.base.controller.TabbedController
|
||||
import eu.kanade.tachiyomi.ui.base.controller.requestPermissionsSafe
|
||||
import eu.kanade.tachiyomi.ui.catalogue.CatalogueController
|
||||
import eu.kanade.tachiyomi.ui.main.MainActivity
|
||||
import eu.kanade.tachiyomi.ui.main.SearchActivity
|
||||
import eu.kanade.tachiyomi.ui.manga.chapter.ChaptersController
|
||||
import eu.kanade.tachiyomi.ui.manga.info.MangaInfoController
|
||||
@ -116,7 +115,7 @@ class MangaController : RxController, TabbedController {
|
||||
private var trackingIconSubscription: Subscription? = null
|
||||
|
||||
override fun getTitle(): String? {
|
||||
return manga?.customTitle()
|
||||
return manga?.currentTitle()
|
||||
}
|
||||
|
||||
override fun inflateView(inflater: LayoutInflater, container: ViewGroup): View {
|
||||
@ -156,6 +155,11 @@ class MangaController : RxController, TabbedController {
|
||||
else activity?.tabs
|
||||
}
|
||||
|
||||
fun updateTitle(manga: Manga) {
|
||||
this.manga?.title = manga.title
|
||||
setTitle()
|
||||
}
|
||||
|
||||
override fun onChangeEnded(handler: ControllerChangeHandler, type: ControllerChangeType) {
|
||||
super.onChangeEnded(handler, type)
|
||||
if (manga == null || source == null) {
|
||||
|
@ -1,59 +1,53 @@
|
||||
package eu.kanade.tachiyomi.ui.manga.info
|
||||
|
||||
import android.app.Activity
|
||||
import android.app.Dialog
|
||||
import android.content.Intent
|
||||
import android.graphics.drawable.Drawable
|
||||
import android.net.Uri
|
||||
import android.os.Bundle
|
||||
import android.view.View
|
||||
import android.view.WindowManager
|
||||
import com.afollestad.materialdialogs.MaterialDialog
|
||||
import com.afollestad.materialdialogs.WhichButton
|
||||
import com.afollestad.materialdialogs.actions.setActionButtonEnabled
|
||||
import com.afollestad.materialdialogs.customview.customView
|
||||
import com.jakewharton.rxbinding.widget.itemClicks
|
||||
import com.jakewharton.rxbinding.widget.textChanges
|
||||
import com.bluelinelabs.conductor.Router
|
||||
import com.bumptech.glide.load.engine.DiskCacheStrategy
|
||||
import com.bumptech.glide.request.target.CustomTarget
|
||||
import com.bumptech.glide.request.transition.Transition
|
||||
import com.bumptech.glide.signature.ObjectKey
|
||||
import eu.kanade.tachiyomi.R
|
||||
import eu.kanade.tachiyomi.data.database.DatabaseHelper
|
||||
import eu.kanade.tachiyomi.data.database.models.Manga
|
||||
import eu.kanade.tachiyomi.data.database.models.Track
|
||||
import eu.kanade.tachiyomi.data.track.TrackManager
|
||||
import eu.kanade.tachiyomi.data.track.TrackService
|
||||
import eu.kanade.tachiyomi.data.track.model.TrackSearch
|
||||
import eu.kanade.tachiyomi.data.database.models.MangaImpl
|
||||
import eu.kanade.tachiyomi.data.glide.GlideApp
|
||||
import eu.kanade.tachiyomi.ui.base.controller.DialogController
|
||||
import eu.kanade.tachiyomi.ui.manga.track.TrackController
|
||||
import eu.kanade.tachiyomi.ui.manga.track.TrackSearchAdapter
|
||||
import eu.kanade.tachiyomi.ui.manga.track.TrackSearchDialog
|
||||
import eu.kanade.tachiyomi.util.plusAssign
|
||||
import kotlinx.android.synthetic.main.track_controller.*
|
||||
import kotlinx.android.synthetic.main.track_search_dialog.view.*
|
||||
import rx.Subscription
|
||||
import rx.android.schedulers.AndroidSchedulers
|
||||
import rx.subscriptions.CompositeSubscription
|
||||
import eu.kanade.tachiyomi.ui.library.LibraryController
|
||||
import eu.kanade.tachiyomi.util.chop
|
||||
import eu.kanade.tachiyomi.util.toast
|
||||
import kotlinx.android.synthetic.main.edit_manga_dialog.view.*
|
||||
import kotlinx.android.synthetic.main.edit_manga_dialog.view.manga_title
|
||||
import me.gujun.android.taggroup.TagGroup
|
||||
import timber.log.Timber
|
||||
import uy.kohesive.injekt.Injekt
|
||||
import uy.kohesive.injekt.api.get
|
||||
import java.util.concurrent.TimeUnit
|
||||
import java.io.IOException
|
||||
import java.io.InputStream
|
||||
|
||||
class EditMangaDialog : DialogController {
|
||||
|
||||
private var dialogView: View? = null
|
||||
|
||||
private var adapter: TrackSearchAdapter? = null
|
||||
|
||||
private var selectedItem: Track? = null
|
||||
|
||||
private val manga: Manga
|
||||
|
||||
private var subscriptions = CompositeSubscription()
|
||||
private var customCoverUri:Uri? = null
|
||||
|
||||
private var searchTextSubscription: Subscription? = null
|
||||
private val infoController
|
||||
get() = targetController as MangaInfoController
|
||||
|
||||
private val trackController
|
||||
get() = targetController as TrackController
|
||||
|
||||
private var wasPreviouslyTracked:Boolean = false
|
||||
|
||||
constructor(target: TrackController, manga: Manga, wasTracked:Boolean) : super(Bundle()
|
||||
constructor(target: MangaInfoController, manga: Manga) : super(Bundle()
|
||||
.apply {
|
||||
putLong(KEY_MANGA, manga.id!!)
|
||||
}) {
|
||||
wasPreviouslyTracked = wasTracked
|
||||
targetController = target
|
||||
this.manga = manga
|
||||
}
|
||||
@ -64,101 +58,112 @@ class EditMangaDialog : DialogController {
|
||||
.executeAsBlocking()!!
|
||||
}
|
||||
|
||||
override fun showDialog(router: Router) {
|
||||
super.showDialog(router)
|
||||
dialog?.window?.setSoftInputMode(WindowManager.LayoutParams.SOFT_INPUT_STATE_HIDDEN)
|
||||
}
|
||||
|
||||
override fun onCreateDialog(savedViewState: Bundle?): Dialog {
|
||||
val dialog = MaterialDialog(activity!!).apply {
|
||||
customView(viewRes = R.layout.track_search_dialog, scrollable = false)
|
||||
customView(viewRes = R.layout.edit_manga_dialog, scrollable = true)
|
||||
negativeButton(android.R.string.cancel)
|
||||
positiveButton(
|
||||
if (wasPreviouslyTracked) R.string.action_clear
|
||||
else R.string.action_track){ onPositiveButtonClick() }
|
||||
setActionButtonEnabled(WhichButton.POSITIVE, wasPreviouslyTracked)
|
||||
}
|
||||
|
||||
if (subscriptions.isUnsubscribed) {
|
||||
subscriptions = CompositeSubscription()
|
||||
positiveButton(R.string.action_save) { onPositiveButtonClick() }
|
||||
}
|
||||
|
||||
dialogView = dialog.view
|
||||
onViewCreated(dialog.view, savedViewState)
|
||||
|
||||
return dialog
|
||||
}
|
||||
|
||||
fun onViewCreated(view: View, savedState: Bundle?) {
|
||||
// Create adapter
|
||||
val adapter = TrackSearchAdapter(view.context)
|
||||
this.adapter = adapter
|
||||
view.track_search_list.adapter = adapter
|
||||
GlideApp.with(view.context)
|
||||
.asDrawable()
|
||||
.load(manga)
|
||||
.diskCacheStrategy(DiskCacheStrategy.RESOURCE)
|
||||
.signature(ObjectKey(MangaImpl.getLastCoverFetch(manga.id!!).toString()))
|
||||
.dontAnimate()
|
||||
.into(view.manga_cover)
|
||||
|
||||
// Set listeners
|
||||
selectedItem = null
|
||||
if (manga.currentTitle() != manga.originalTitle())
|
||||
view.manga_title.append(manga.currentTitle())
|
||||
view.manga_title.hint = "${resources?.getString(R.string.title)}: ${manga.originalTitle()}"
|
||||
|
||||
subscriptions += view.track_search_list.itemClicks().subscribe { position ->
|
||||
selectedItem = adapter.getItem(position)
|
||||
(dialog as? MaterialDialog)?.positiveButton(R.string.action_track)
|
||||
(dialog as? MaterialDialog)?.setActionButtonEnabled(WhichButton.POSITIVE, true)
|
||||
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()}"
|
||||
|
||||
view.cover_layout.setOnClickListener {
|
||||
changeCover()
|
||||
}
|
||||
|
||||
// Do an initial search based on the manga's title
|
||||
if (savedState == null) {
|
||||
val title = trackController.presenter.manga.trueTitle()
|
||||
view.track_search.append(title)
|
||||
search(title)
|
||||
if (manga.currentArtist() != manga.originalArtist())
|
||||
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.reset_tags.setOnClickListener { resetTags() }
|
||||
}
|
||||
|
||||
private fun resetTags() {
|
||||
if (manga.originalGenres().isNullOrBlank() || manga.originalGenres() == "null")
|
||||
dialogView?.manga_genres_tags?.setTags(emptyList())
|
||||
else
|
||||
dialogView?.manga_genres_tags?.setTags(manga.originalGenres()?.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)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
override fun onDestroyView(view: View) {
|
||||
super.onDestroyView(view)
|
||||
subscriptions.unsubscribe()
|
||||
dialogView = null
|
||||
adapter = null
|
||||
}
|
||||
|
||||
override fun onAttach(view: View) {
|
||||
super.onAttach(view)
|
||||
searchTextSubscription = dialogView!!.track_search.textChanges()
|
||||
.skip(1)
|
||||
.debounce(1, TimeUnit.SECONDS, AndroidSchedulers.mainThread())
|
||||
.map { it.toString() }
|
||||
.filter(String::isNotBlank)
|
||||
.subscribe { search(it) }
|
||||
}
|
||||
|
||||
override fun onDetach(view: View) {
|
||||
super.onDetach(view)
|
||||
searchTextSubscription?.unsubscribe()
|
||||
}
|
||||
|
||||
private fun search(query: String) {
|
||||
val view = dialogView ?: return
|
||||
view.progress.visibility = View.VISIBLE
|
||||
view.track_search_list.visibility = View.INVISIBLE
|
||||
//trackController.presenter.search(query, service)
|
||||
}
|
||||
|
||||
fun onSearchResults(results: List<TrackSearch>) {
|
||||
selectedItem = null
|
||||
val view = dialogView ?: return
|
||||
view.progress.visibility = View.INVISIBLE
|
||||
view.track_search_list.visibility = View.VISIBLE
|
||||
adapter?.setItems(results)
|
||||
if (results.size == 1 && !wasPreviouslyTracked) {
|
||||
selectedItem = adapter?.getItem(0)
|
||||
(dialog as? MaterialDialog)?.positiveButton(R.string.action_track)
|
||||
(dialog as? MaterialDialog)?.setActionButtonEnabled(WhichButton.POSITIVE, true)
|
||||
}
|
||||
}
|
||||
|
||||
fun onSearchResultsError() {
|
||||
val view = dialogView ?: return
|
||||
view.progress.visibility = View.VISIBLE
|
||||
view.track_search_list.visibility = View.INVISIBLE
|
||||
adapter?.setItems(emptyList())
|
||||
}
|
||||
|
||||
private fun onPositiveButtonClick() {
|
||||
//trackController.swipe_refresh.isRefreshing = true
|
||||
//trackController.presenter.registerTracking(selectedItem, service)
|
||||
infoController.presenter.updateManga(dialogView?.manga_title?.text.toString(),
|
||||
dialogView?.manga_author?.text.toString(), dialogView?.manga_artist?.text.toString(),
|
||||
customCoverUri, dialogView?.manga_description?.text.toString(),
|
||||
dialogView?.manga_genres_tags?.tags)
|
||||
infoController.updateTitle()
|
||||
}
|
||||
|
||||
private companion object {
|
||||
|
@ -70,8 +70,9 @@ import eu.kanade.tachiyomi.util.updateLayoutParams
|
||||
import eu.kanade.tachiyomi.util.updatePaddingRelative
|
||||
import jp.wasabeef.glide.transformations.CropSquareTransformation
|
||||
import jp.wasabeef.glide.transformations.MaskTransformation
|
||||
import kotlinx.android.synthetic.main.main_activity.*
|
||||
import kotlinx.android.synthetic.main.manga_info_controller.*
|
||||
import kotlinx.android.synthetic.main.manga_info_controller.manga_cover
|
||||
import kotlinx.android.synthetic.main.manga_info_controller.manga_genres_tags
|
||||
import uy.kohesive.injekt.injectLazy
|
||||
import java.io.File
|
||||
import java.text.DateFormat
|
||||
@ -181,7 +182,7 @@ class MangaInfoController : NucleusController<MangaInfoPresenter>(),
|
||||
shortAnimationDuration = resources?.getInteger(android.R.integer.config_shortAnimTime) ?: 0
|
||||
|
||||
manga_cover.longClicks().subscribeUntilDestroy {
|
||||
copyToClipboard(view.context.getString(R.string.title), presenter.manga.customTitle(), R.string
|
||||
copyToClipboard(view.context.getString(R.string.title), presenter.manga.currentTitle(), R.string
|
||||
.manga_info_full_title_label)
|
||||
}
|
||||
container = (view as ViewGroup).findViewById(R.id.manga_info_layout) as? View
|
||||
@ -219,11 +220,14 @@ class MangaInfoController : NucleusController<MangaInfoPresenter>(),
|
||||
|
||||
override fun onCreateOptionsMenu(menu: Menu, inflater: MenuInflater) {
|
||||
inflater.inflate(R.menu.manga_info, menu)
|
||||
|
||||
val editItem = menu.findItem(R.id.action_edit)
|
||||
editItem.isVisible = presenter.manga.favorite
|
||||
}
|
||||
|
||||
override fun onOptionsItemSelected(item: MenuItem): Boolean {
|
||||
when (item.itemId) {
|
||||
R.id.action_edit -> { }
|
||||
R.id.action_edit -> EditMangaDialog(this, presenter.manga).showDialog(router)
|
||||
R.id.action_open_in_browser -> openInBrowser()
|
||||
R.id.action_open_in_web_view -> openInWebView()
|
||||
R.id.action_share -> prepareToShareManga()
|
||||
@ -262,39 +266,39 @@ class MangaInfoController : NucleusController<MangaInfoPresenter>(),
|
||||
val view = view ?: return
|
||||
|
||||
//update full title TextView.
|
||||
manga_full_title.text = if (manga.customTitle().isBlank()) {
|
||||
manga_full_title.text = if (manga.currentTitle().isBlank()) {
|
||||
view.context.getString(R.string.unknown)
|
||||
} else {
|
||||
manga.customTitle()
|
||||
manga.currentTitle()
|
||||
}
|
||||
|
||||
// Update artist TextView.
|
||||
manga_artist.text = if (manga.artist.isNullOrBlank()) {
|
||||
manga_artist.text = if (manga.currentArtist().isNullOrBlank()) {
|
||||
view.context.getString(R.string.unknown)
|
||||
} else {
|
||||
manga.artist
|
||||
manga.currentArtist()
|
||||
}
|
||||
|
||||
// Update author TextView.
|
||||
manga_author.text = if (manga.author.isNullOrBlank()) {
|
||||
manga_author.text = if (manga.currentAuthor().isNullOrBlank()) {
|
||||
view.context.getString(R.string.unknown)
|
||||
} else {
|
||||
manga.author
|
||||
manga.currentAuthor()
|
||||
}
|
||||
|
||||
// If manga source is known update source TextView.
|
||||
manga_source.text = source?.toString() ?: view.context.getString(R.string.unknown)
|
||||
|
||||
// Update genres list
|
||||
if (manga.genre.isNullOrBlank().not()) {
|
||||
manga_genres_tags.setTags(manga.genre?.split(", "))
|
||||
if (manga.currentGenres().isNullOrBlank().not()) {
|
||||
manga_genres_tags.setTags(manga.currentGenres()?.split(", "))
|
||||
}
|
||||
|
||||
// Update description TextView.
|
||||
manga_summary.text = if (manga.description.isNullOrBlank()) {
|
||||
manga_summary.text = if (manga.currentDesc().isNullOrBlank()) {
|
||||
view.context.getString(R.string.unknown)
|
||||
} else {
|
||||
manga.description
|
||||
manga.currentDesc()
|
||||
}
|
||||
|
||||
// Update status TextView.
|
||||
@ -307,19 +311,20 @@ class MangaInfoController : NucleusController<MangaInfoPresenter>(),
|
||||
|
||||
// Set the favorite drawable to the correct one.
|
||||
setFavoriteDrawable(manga.favorite)
|
||||
activity?.invalidateOptionsMenu()
|
||||
|
||||
// Set cover if it wasn't already.
|
||||
if (!manga.thumbnail_url.isNullOrEmpty()) {
|
||||
GlideApp.with(view.context)
|
||||
.load(manga)
|
||||
.diskCacheStrategy(DiskCacheStrategy.RESOURCE)
|
||||
.signature(ObjectKey((manga as MangaImpl).last_cover_fetch.toString()))
|
||||
.signature(ObjectKey(MangaImpl.getLastCoverFetch(manga.id!!).toString()))
|
||||
//.centerCrop()
|
||||
.into(manga_cover)
|
||||
if (manga_cover_full != null) {
|
||||
GlideApp.with(view.context).asDrawable().load(manga)
|
||||
.diskCacheStrategy(DiskCacheStrategy.RESOURCE)
|
||||
.signature(ObjectKey(manga.last_cover_fetch.toString()))
|
||||
.signature(ObjectKey(MangaImpl.getLastCoverFetch(manga.id!!).toString()))
|
||||
.override(CustomTarget.SIZE_ORIGINAL, CustomTarget.SIZE_ORIGINAL)
|
||||
.into(object : CustomTarget<Drawable>() {
|
||||
override fun onResourceReady(resource: Drawable,
|
||||
@ -336,7 +341,7 @@ class MangaInfoController : NucleusController<MangaInfoPresenter>(),
|
||||
GlideApp.with(view.context)
|
||||
.load(manga)
|
||||
.diskCacheStrategy(DiskCacheStrategy.RESOURCE)
|
||||
.signature(ObjectKey(manga.last_cover_fetch.toString()))
|
||||
.signature(ObjectKey(MangaImpl.getLastCoverFetch(manga.id!!).toString()))
|
||||
.centerCrop()
|
||||
.into(backdrop)
|
||||
}
|
||||
@ -397,7 +402,7 @@ class MangaInfoController : NucleusController<MangaInfoPresenter>(),
|
||||
}
|
||||
|
||||
val activity = activity ?: return
|
||||
val intent = WebViewActivity.newIntent(activity, source.id, url, presenter.manga.trueTitle())
|
||||
val intent = WebViewActivity.newIntent(activity, source.id, url, presenter.manga.originalTitle())
|
||||
startActivity(intent)
|
||||
}
|
||||
|
||||
@ -433,7 +438,7 @@ class MangaInfoController : NucleusController<MangaInfoPresenter>(),
|
||||
val intent = Intent(Intent.ACTION_SEND).apply {
|
||||
type = "text/*"
|
||||
putExtra(Intent.EXTRA_TEXT, url)
|
||||
putExtra(Intent.EXTRA_TITLE, presenter.manga.customTitle())
|
||||
putExtra(Intent.EXTRA_TITLE, presenter.manga.currentTitle())
|
||||
flags = Intent.FLAG_GRANT_READ_URI_PERMISSION
|
||||
if (stream != null) {
|
||||
clipData = ClipData.newRawUri(null, stream)
|
||||
@ -710,11 +715,11 @@ class MangaInfoController : NucleusController<MangaInfoPresenter>(),
|
||||
|
||||
// Check if shortcut placement is supported
|
||||
if (ShortcutManagerCompat.isRequestPinShortcutSupported(activity)) {
|
||||
val shortcutId = "manga-shortcut-${presenter.manga.trueTitle()}-${presenter.source.name}"
|
||||
val shortcutId = "manga-shortcut-${presenter.manga.originalTitle()}-${presenter.source.name}"
|
||||
|
||||
// Create shortcut info
|
||||
val shortcutInfo = ShortcutInfoCompat.Builder(activity, shortcutId)
|
||||
.setShortLabel(presenter.manga.customTitle())
|
||||
.setShortLabel(presenter.manga.currentTitle())
|
||||
.setIcon(IconCompat.createWithBitmap(icon))
|
||||
.setIntent(shortcutIntent)
|
||||
.build()
|
||||
@ -735,6 +740,11 @@ class MangaInfoController : NucleusController<MangaInfoPresenter>(),
|
||||
}
|
||||
}
|
||||
|
||||
fun updateTitle() {
|
||||
setMangaInfo(presenter.manga, presenter.source)
|
||||
(parentController as? MangaController)?.updateTitle(presenter.manga)
|
||||
}
|
||||
|
||||
private fun setFullCoverToThumb() {
|
||||
if (setUpFullCover) return
|
||||
val expandedImageView = manga_cover_full ?: return
|
||||
|
@ -2,6 +2,7 @@ package eu.kanade.tachiyomi.ui.manga.info
|
||||
|
||||
import android.app.Application
|
||||
import android.graphics.Bitmap
|
||||
import android.net.Uri
|
||||
import android.os.Bundle
|
||||
import com.jakewharton.rxrelay.BehaviorRelay
|
||||
import com.jakewharton.rxrelay.PublishRelay
|
||||
@ -12,10 +13,11 @@ import eu.kanade.tachiyomi.data.database.models.Manga
|
||||
import eu.kanade.tachiyomi.data.database.models.MangaCategory
|
||||
import eu.kanade.tachiyomi.data.database.models.MangaImpl
|
||||
import eu.kanade.tachiyomi.data.download.DownloadManager
|
||||
import eu.kanade.tachiyomi.source.LocalSource
|
||||
import eu.kanade.tachiyomi.source.Source
|
||||
import eu.kanade.tachiyomi.source.model.SManga
|
||||
import eu.kanade.tachiyomi.ui.base.presenter.BasePresenter
|
||||
import eu.kanade.tachiyomi.util.DiskUtil
|
||||
import eu.kanade.tachiyomi.util.ImageUtil
|
||||
import eu.kanade.tachiyomi.util.isNullOrUnsubscribed
|
||||
import rx.Observable
|
||||
import rx.Subscription
|
||||
@ -24,7 +26,6 @@ import rx.schedulers.Schedulers
|
||||
import uy.kohesive.injekt.Injekt
|
||||
import uy.kohesive.injekt.api.get
|
||||
import java.io.File
|
||||
import java.io.FileInputStream
|
||||
import java.io.FileOutputStream
|
||||
import java.io.InputStream
|
||||
import java.io.OutputStream
|
||||
@ -94,7 +95,7 @@ class MangaInfoPresenter(
|
||||
manga.initialized = true
|
||||
db.insertManga(manga).executeAsBlocking()
|
||||
coverCache.deleteFromCache(manga.thumbnail_url)
|
||||
(manga as? MangaImpl)?.last_cover_fetch = Date().time
|
||||
MangaImpl.setLastCoverFetch(manga.id!!, Date().time)
|
||||
manga
|
||||
}
|
||||
.subscribeOn(Schedulers.io())
|
||||
@ -119,6 +120,7 @@ class MangaInfoPresenter(
|
||||
|
||||
fun confirmDeletion() {
|
||||
coverCache.deleteFromCache(manga.thumbnail_url)
|
||||
db.resetMangaInfo(manga).executeAsBlocking()
|
||||
downloadManager.deleteManga(manga, source)
|
||||
}
|
||||
|
||||
@ -148,7 +150,7 @@ class MangaInfoPresenter(
|
||||
directory.mkdirs()
|
||||
|
||||
// Build destination file.
|
||||
val filename = DiskUtil.buildValidFilename("${manga.trueTitle()} - Cover.jpg")
|
||||
val filename = DiskUtil.buildValidFilename("${manga.originalTitle()} - Cover.jpg")
|
||||
|
||||
val destFile = File(directory, filename)
|
||||
val stream: OutputStream = FileOutputStream(destFile)
|
||||
@ -199,4 +201,71 @@ class MangaInfoPresenter(
|
||||
moveMangaToCategories(manga, listOfNotNull(category))
|
||||
}
|
||||
|
||||
fun updateManga(title:String?, author:String?, artist: String?, uri: Uri?,
|
||||
description: String?, tags: Array<String>?) {
|
||||
var changed = false
|
||||
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
|
||||
}
|
||||
|
||||
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
|
||||
}
|
||||
|
||||
if (artist.isNullOrBlank() && manga.currentArtist() != manga.currentArtist()) {
|
||||
manga.artist = manga.originalArtist()
|
||||
changed = true
|
||||
} else if (!artist.isNullOrBlank() && artist != manga.currentArtist()) {
|
||||
manga.artist = "${artist}${SManga.splitter}${manga.originalArtist()}"
|
||||
changed = true
|
||||
}
|
||||
|
||||
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()) {
|
||||
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 (uri != null) editCoverWithStream(uri)
|
||||
|
||||
|
||||
if (changed) db.updateMangaInfo(manga).executeAsBlocking()
|
||||
}
|
||||
|
||||
private fun editCoverWithStream(uri: Uri): Boolean {
|
||||
val inputStream = downloadManager.context.contentResolver.openInputStream(uri) ?:
|
||||
return false
|
||||
if (manga.source == LocalSource.ID) {
|
||||
LocalSource.updateCover(downloadManager.context, manga, inputStream)
|
||||
return true
|
||||
}
|
||||
|
||||
if (manga.thumbnail_url != null && manga.favorite) {
|
||||
coverCache.copyToCache(manga.thumbnail_url!!, inputStream)
|
||||
MangaImpl.setLastCoverFetch(manga.id!!, Date().time)
|
||||
return true
|
||||
}
|
||||
return false
|
||||
}
|
||||
|
||||
}
|
||||
|
@ -95,7 +95,7 @@ class TrackSearchDialog : DialogController {
|
||||
|
||||
// Do an initial search based on the manga's title
|
||||
if (savedState == null) {
|
||||
val title = trackController.presenter.manga.trueTitle()
|
||||
val title = trackController.presenter.manga.originalTitle()
|
||||
view.track_search.append(title)
|
||||
search(title)
|
||||
}
|
||||
|
@ -16,7 +16,7 @@ class MangaHolder(
|
||||
|
||||
fun bind(item: MangaItem) {
|
||||
// Update the title of the manga.
|
||||
title.text = item.manga.customTitle()
|
||||
title.text = item.manga.currentTitle()
|
||||
|
||||
// Create thumbnail onclick to simulate long click
|
||||
thumbnail.setOnClickListener {
|
||||
|
@ -23,7 +23,7 @@ import uy.kohesive.injekt.injectLazy
|
||||
|
||||
class SearchController(
|
||||
private var manga: Manga? = null
|
||||
) : CatalogueSearchController(manga?.trueTitle()) {
|
||||
) : CatalogueSearchController(manga?.originalTitle()) {
|
||||
|
||||
private var newManga: Manga? = null
|
||||
private var progress = 1
|
||||
|
@ -14,7 +14,6 @@ import androidx.core.graphics.ColorUtils
|
||||
import androidx.recyclerview.widget.LinearLayoutManager
|
||||
import androidx.vectordrawable.graphics.drawable.VectorDrawableCompat
|
||||
import com.afollestad.materialdialogs.MaterialDialog
|
||||
import com.bluelinelabs.conductor.ControllerChangeHandler
|
||||
import eu.kanade.tachiyomi.R
|
||||
import eu.kanade.tachiyomi.data.database.DatabaseHelper
|
||||
import eu.kanade.tachiyomi.data.database.models.Manga
|
||||
@ -155,7 +154,7 @@ class MigrationListController(bundle: Bundle? = null) : BaseController(bundle),
|
||||
smartSearchEngine.smartSearch(source, mangaObj.title)
|
||||
} else {*/
|
||||
val searchResult = smartSearchEngine
|
||||
.normalSearch(source, mangaObj.trueTitle())
|
||||
.normalSearch(source, mangaObj.originalTitle())
|
||||
|
||||
if(searchResult != null) {
|
||||
val localManga = smartSearchEngine.networkToLocalManga(searchResult, source.id)
|
||||
@ -185,7 +184,7 @@ class MigrationListController(bundle: Bundle? = null) : BaseController(bundle),
|
||||
validSources.forEachIndexed { index, source ->
|
||||
val searchResult = try {
|
||||
val searchResult = smartSearchEngine
|
||||
.normalSearch(source, mangaObj.trueTitle())
|
||||
.normalSearch(source, mangaObj.originalTitle())
|
||||
|
||||
if (searchResult != null) {
|
||||
val localManga = smartSearchEngine.networkToLocalManga(searchResult, source.id)
|
||||
|
@ -132,10 +132,10 @@ class MigrationProcessHolder(
|
||||
.centerCrop()
|
||||
.into(thumbnail)
|
||||
|
||||
title.text = if (manga.customTitle().isBlank()) {
|
||||
title.text = if (manga.currentTitle().isBlank()) {
|
||||
view.context.getString(R.string.unknown)
|
||||
} else {
|
||||
manga.customTitle()
|
||||
manga.currentTitle()
|
||||
}
|
||||
|
||||
gradient.visible()
|
||||
|
@ -381,7 +381,7 @@ class ReaderActivity : BaseRxActivity<ReaderPresenter>(),
|
||||
viewer = newViewer
|
||||
viewer_container.addView(newViewer.getView())
|
||||
|
||||
toolbar.title = manga.customTitle()
|
||||
toolbar.title = manga.currentTitle()
|
||||
|
||||
page_seekbar.isRTL = newViewer is R2LPagerViewer
|
||||
|
||||
|
@ -444,7 +444,7 @@ class ReaderPresenter(
|
||||
|
||||
// Build destination file.
|
||||
val filename = DiskUtil.buildValidFilename(
|
||||
"${manga.customTitle()} - ${chapter.name}".take(225)
|
||||
"${manga.currentTitle()} - ${chapter.name}".take(225)
|
||||
) + " - ${page.number}.${type.extension}"
|
||||
|
||||
val destFile = File(directory, filename)
|
||||
@ -531,7 +531,7 @@ class ReaderPresenter(
|
||||
val thumbUrl = manga.thumbnail_url ?: throw Exception("Image url not found")
|
||||
if (manga.favorite) {
|
||||
coverCache.copyToCache(thumbUrl, stream())
|
||||
(manga as? MangaImpl)?.last_cover_fetch = Date().time
|
||||
MangaImpl.setLastCoverFetch(manga.id!!, Date().time)
|
||||
SetAsCoverResult.Success
|
||||
} else {
|
||||
SetAsCoverResult.AddToLibraryFirst
|
||||
|
@ -61,7 +61,7 @@ class RecentChapterHolder(private val view: View, private val adapter: RecentCha
|
||||
chapter_title.text = item.chapter.name
|
||||
|
||||
// Set manga title
|
||||
manga_title.text = item.manga.customTitle()
|
||||
manga_title.text = item.manga.currentTitle()
|
||||
|
||||
// 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))
|
||||
|
@ -61,7 +61,7 @@ class RecentlyReadHolder(
|
||||
val (manga, chapter, history) = item
|
||||
|
||||
// Set manga title
|
||||
manga_title.text = manga.customTitle()
|
||||
manga_title.text = manga.currentTitle()
|
||||
|
||||
// Set source + chapter title
|
||||
val formattedNumber = adapter.decimalFormat.format(chapter.chapter_number.toDouble())
|
||||
|
@ -74,7 +74,7 @@ object ChapterRecognition {
|
||||
}
|
||||
|
||||
// Remove manga title from chapter title.
|
||||
val nameWithoutManga = name.replace(manga.trueTitle().toLowerCase(), "").trim()
|
||||
val nameWithoutManga = name.replace(manga.originalTitle().toLowerCase(), "").trim()
|
||||
|
||||
// Check if first value is number after title remove.
|
||||
if (updateChapter(withoutManga.find(nameWithoutManga), chapter))
|
||||
|
6
app/src/main/res/drawable/circle_backdrop.xml
Normal file
6
app/src/main/res/drawable/circle_backdrop.xml
Normal file
@ -0,0 +1,6 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<shape xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
android:shape="oval">
|
||||
<solid
|
||||
android:color="?attr/colorPrimary"/>
|
||||
</shape>
|
@ -1,9 +0,0 @@
|
||||
<vector xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
android:width="24dp"
|
||||
android:height="24dp"
|
||||
android:viewportWidth="24.0"
|
||||
android:viewportHeight="24.0">
|
||||
<path
|
||||
android:fillColor="#FFFFFFFF"
|
||||
android:pathData="M3,17.25V21h3.75L17.81,9.94l-3.75,-3.75L3,17.25zM20.71,7.04c0.39,-0.39 0.39,-1.02 0,-1.41l-2.34,-2.34c-0.39,-0.39 -1.02,-0.39 -1.41,0l-1.83,1.83 3.75,3.75 1.83,-1.83z"/>
|
||||
</vector>
|
@ -0,0 +1,7 @@
|
||||
<vector android:height="24dp"
|
||||
android:viewportHeight="24.0" android:viewportWidth="24.0"
|
||||
android:width="24dp" xmlns:android="http://schemas.android.com/apk/res/android">
|
||||
<path android:fillColor="#FFFFFFFF"
|
||||
android:pathData="M3,17.25V21h3.75L17.81,9.94l-3.75,-3.75L3,17.25zM20.71,7.04c0.39,-0.39 0.39,-1.02 0,-1.41l-2.34,-2.34c-0.39,-0.39 -1.02,-0.39 -1.41,0l-1.83,1.83 3.75,3.75 1.83,-1.83z"
|
||||
android:strokeColor="#000000" android:strokeWidth="0.5"/>
|
||||
</vector>
|
7
app/src/main/res/drawable/image_border_background.xml
Normal file
7
app/src/main/res/drawable/image_border_background.xml
Normal file
@ -0,0 +1,7 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<shape xmlns:android="http://schemas.android.com/apk/res/android">
|
||||
<solid android:color="@android:color/white" />
|
||||
<stroke android:width="1dp" android:color="@color/snackbarBackground" />
|
||||
<padding android:left="1dp" android:top="1dp" android:right="1dp"
|
||||
android:bottom="1dp" />
|
||||
</shape>
|
112
app/src/main/res/layout/edit_manga_dialog.xml
Normal file
112
app/src/main/res/layout/edit_manga_dialog.xml
Normal file
@ -0,0 +1,112 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<LinearLayout
|
||||
xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
xmlns:tools="http://schemas.android.com/tools"
|
||||
xmlns:app="http://schemas.android.com/apk/res-auto"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="match_parent"
|
||||
android:orientation="vertical">
|
||||
|
||||
<FrameLayout
|
||||
android:id="@+id/cover_layout"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_gravity="center"
|
||||
android:layout_marginBottom="10dp">
|
||||
|
||||
<ImageView
|
||||
android:id="@+id/manga_cover"
|
||||
android:layout_width="wrap_content"
|
||||
android:adjustViewBounds="true"
|
||||
android:layout_height="150dp"
|
||||
android:background="@drawable/image_border_background"
|
||||
android:src="@mipmap/ic_launcher"/>
|
||||
|
||||
<FrameLayout
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_marginStart="4dp"
|
||||
android:layout_gravity="end|bottom"
|
||||
android:layout_marginEnd="4dp"
|
||||
android:layout_marginBottom="4dp">
|
||||
<ImageView
|
||||
android:layout_width="24dp"
|
||||
android:layout_height="24dp"
|
||||
android:layout_gravity="center"
|
||||
android:src="@drawable/ic_edit_outlined_white_24dp"/>
|
||||
</FrameLayout>
|
||||
</FrameLayout>
|
||||
|
||||
<EditText
|
||||
android:id="@+id/manga_title"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:hint="@string/title"
|
||||
android:layout_marginEnd="16dp"
|
||||
android:layout_marginStart="16dp"
|
||||
android:inputType="text"
|
||||
android:maxLines="1"/>
|
||||
<EditText
|
||||
android:id="@+id/manga_author"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:hint="@string/manga_info_author_label"
|
||||
android:layout_marginEnd="16dp"
|
||||
android:layout_marginStart="16dp"
|
||||
android:inputType="text"
|
||||
android:maxLines="1"/>
|
||||
|
||||
<EditText
|
||||
android:id="@+id/manga_artist"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:hint="@string/manga_info_artist_label"
|
||||
android:layout_marginEnd="16dp"
|
||||
android:layout_marginStart="16dp"
|
||||
android:inputType="text"
|
||||
android:maxLines="1"/>
|
||||
|
||||
<Button
|
||||
android:id="@+id/reset_tags"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_marginEnd="16dp"
|
||||
android:layout_marginStart="16dp"
|
||||
android:layout_marginTop="16dp"
|
||||
android:text="@string/reset_tags" />
|
||||
|
||||
<me.gujun.android.taggroup.TagGroup
|
||||
android:id="@+id/manga_genres_tags"
|
||||
style="@style/TagGroup"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_marginEnd="16dp"
|
||||
android:layout_marginStart="16dp"
|
||||
android:layout_marginTop="8dp"
|
||||
android:layout_marginBottom="8dp"
|
||||
app:atg_borderStrokeWidth="1dp"
|
||||
app:atg_backgroundColor="@android:color/transparent"
|
||||
app:atg_isAppendMode="true"
|
||||
app:atg_inputHintColor="?android:attr/textColorSecondary"
|
||||
app:atg_inputTextColor="?android:attr/textColorPrimary"
|
||||
app:atg_checkedBackgroundColor="@color/red_error"
|
||||
app:atg_checkedBorderColor="@color/red_error"
|
||||
app:atg_borderColor="@color/md_blue_A400"
|
||||
app:atg_textColor="@color/md_blue_A400" />
|
||||
|
||||
<EditText
|
||||
android:id="@+id/manga_description"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:hint="@string/description"
|
||||
android:layout_marginEnd="16dp"
|
||||
android:layout_marginStart="16dp"
|
||||
android:inputType="text|textMultiLine"
|
||||
android:scrollHorizontally="false"/>
|
||||
|
||||
<View
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="1dp"
|
||||
android:background="?android:attr/divider"/>
|
||||
|
||||
</LinearLayout>
|
@ -5,7 +5,7 @@
|
||||
|
||||
<item android:id="@+id/action_edit"
|
||||
android:title="@string/action_edit"
|
||||
android:icon="@drawable/ic_create_white_24dp"
|
||||
android:icon="@drawable/ic_edit_white_24dp"
|
||||
app:showAsAction="ifRoom"/>
|
||||
|
||||
<item android:id="@+id/action_delete"
|
||||
|
@ -3,11 +3,6 @@
|
||||
<menu xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
xmlns:app="http://schemas.android.com/apk/res-auto">
|
||||
|
||||
<item android:id="@+id/action_edit_cover"
|
||||
android:title="@string/action_edit_cover"
|
||||
android:icon="@drawable/ic_create_white_24dp"
|
||||
app:showAsAction="ifRoom"/>
|
||||
|
||||
<item android:id="@+id/action_move_to_category"
|
||||
android:title="@string/action_move_category"
|
||||
android:icon="@drawable/ic_label_white_24dp"
|
||||
|
@ -644,5 +644,6 @@
|
||||
<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>
|
||||
|
||||
</resources>
|
||||
|
Loading…
Reference in New Issue
Block a user