Running kotlinter

This commit is contained in:
Jays2Kings 2021-03-25 14:58:46 -04:00
parent 7914b26488
commit fccd3a0ddb
145 changed files with 678 additions and 668 deletions

View File

@ -25,7 +25,6 @@ import uy.kohesive.injekt.api.get
class AppModule(val app: Application) : InjektModule { class AppModule(val app: Application) : InjektModule {
override fun InjektRegistrar.registerInjectables() { override fun InjektRegistrar.registerInjectables() {
addSingleton(app) addSingleton(app)
addSingletonFactory { PreferencesHelper(app) } addSingletonFactory { PreferencesHelper(app) }

View File

@ -70,8 +70,9 @@ object Migrations {
} }
} }
} }
if (oldVersion < 54) if (oldVersion < 54) {
DownloadProvider(context).renameChapters() DownloadProvider(context).renameChapters()
}
if (oldVersion < 62) { if (oldVersion < 62) {
LibraryPresenter.updateDB() LibraryPresenter.updateDB()
// Restore jobs after migrating from Evernote's job scheduler to WorkManager. // Restore jobs after migrating from Evernote's job scheduler to WorkManager.

View File

@ -79,8 +79,9 @@ class ChapterCache(private val context: Context) {
*/ */
fun removeFileFromCache(file: String): Boolean { fun removeFileFromCache(file: String): Boolean {
// Make sure we don't delete the journal file (keeps track of cache). // Make sure we don't delete the journal file (keeps track of cache).
if (file == "journal" || file.startsWith("journal.")) if (file == "journal" || file.startsWith("journal.")) {
return false return false
}
try { try {
// Remove the extension from the file to get the key of the cache // Remove the extension from the file to get the key of the cache

View File

@ -41,9 +41,9 @@ class CategoryPutResolver : DefaultPutResolver<Category>() {
put(COL_NAME, obj.name) put(COL_NAME, obj.name)
put(COL_ORDER, obj.order) put(COL_ORDER, obj.order)
put(COL_FLAGS, obj.flags) put(COL_FLAGS, obj.flags)
if (obj.mangaSort != null) if (obj.mangaSort != null) {
put(COL_MANGA_ORDER, obj.mangaSort.toString()) put(COL_MANGA_ORDER, obj.mangaSort.toString())
else { } else {
val orderString = obj.mangaOrder.joinToString("/") val orderString = obj.mangaOrder.joinToString("/")
put(COL_MANGA_ORDER, orderString) put(COL_MANGA_ORDER, orderString)
} }

View File

@ -105,17 +105,17 @@ interface Manga : SManga {
{ tag -> { tag ->
tag == "long strip" || tag == "manhwa" || tag.contains("webtoon") tag == "long strip" || tag == "manhwa" || tag.contains("webtoon")
} == true || isWebtoonSource(sourceName) } == true || isWebtoonSource(sourceName)
) ) {
ReaderActivity.WEBTOON ReaderActivity.WEBTOON
else if (currentTags?.any } else if (currentTags?.any
{ tag -> { tag ->
tag == "chinese" || tag == "manhua" || tag == "chinese" || tag == "manhua" ||
tag.startsWith("english") || tag == "comic" tag.startsWith("english") || tag == "comic"
} == true || (isComicSource(sourceName) && !sourceName.contains("tapas", true)) || } == true || (isComicSource(sourceName) && !sourceName.contains("tapas", true)) ||
sourceName.contains("manhua", true) sourceName.contains("manhua", true)
) ) {
ReaderActivity.LEFT_TO_RIGHT ReaderActivity.LEFT_TO_RIGHT
else 0 } else 0
} }
fun isMangaTag(tag: String): Boolean { fun isMangaTag(tag: String): Boolean {
@ -127,7 +127,7 @@ interface Manga : SManga {
} }
fun isManhwaTag(tag: String): Boolean { fun isManhwaTag(tag: String): Boolean {
return tag in listOf("long strip", "manhwa", "манхва", "kr") || tag.startsWith("korean") return tag in listOf("long strip", "manhwa", "манхва", "kr") || tag.startsWith("korean")
} }
fun isComicTag(tag: String): Boolean { fun isComicTag(tag: String): Boolean {

View File

@ -90,7 +90,6 @@ class DownloadCache(
checkRenew() checkRenew()
if (forceCheckFolder) { if (forceCheckFolder) {
val source = sourceManager.get(manga.source) ?: return 0 val source = sourceManager.get(manga.source) ?: return 0
val mangaDir = provider.findMangaDir(manga, source) val mangaDir = provider.findMangaDir(manga, source)
@ -173,7 +172,6 @@ class DownloadCache(
*/ */
@Synchronized @Synchronized
fun addChapter(chapterDirName: String, mangaUniFile: UniFile, manga: Manga) { fun addChapter(chapterDirName: String, mangaUniFile: UniFile, manga: Manga) {
val id = manga.id ?: return val id = manga.id ?: return
val files = mangaFiles[id] val files = mangaFiles[id]
if (files == null) { if (files == null) {

View File

@ -110,10 +110,11 @@ class DownloadManager(val context: Context) {
queue.add(0, download) queue.add(0, download)
reorderQueue(queue) reorderQueue(queue)
if (isPaused()) { if (isPaused()) {
if (DownloadService.isRunning(context)) if (DownloadService.isRunning(context)) {
downloader.start() downloader.start()
else } else {
DownloadService.start(context) DownloadService.start(context)
}
} }
} }

View File

@ -55,8 +55,9 @@ internal class DownloadNotifier(private val context: Context) {
* Clear old actions if they exist. * Clear old actions if they exist.
*/ */
private fun clearActions() = with(notification) { private fun clearActions() = with(notification) {
if (!mActions.isEmpty()) if (!mActions.isEmpty()) {
mActions.clear() mActions.clear()
}
} }
/** /**

View File

@ -201,10 +201,11 @@ class DownloadService : Service() {
*/ */
private fun listenDownloaderState() { private fun listenDownloaderState() {
subscriptions += downloadManager.runningRelay.subscribe { running -> subscriptions += downloadManager.runningRelay.subscribe { running ->
if (running) if (running) {
wakeLock.acquireIfNeeded() wakeLock.acquireIfNeeded()
else } else {
wakeLock.releaseIfNeeded() wakeLock.releaseIfNeeded()
}
} }
} }

View File

@ -469,7 +469,6 @@ class Downloader(
tmpDir: UniFile, tmpDir: UniFile,
dirname: String dirname: String
) { ) {
// Ensure that the chapter folder has all the images. // Ensure that the chapter folder has all the images.
val downloadedImages = tmpDir.listFiles().orEmpty().filterNot { it.name!!.endsWith(".tmp") } val downloadedImages = tmpDir.listFiles().orEmpty().filterNot { it.name!!.endsWith(".tmp") }

View File

@ -11,11 +11,14 @@ class Download(val source: HttpSource, val manga: Manga, val chapter: Chapter) {
var pages: List<Page>? = null var pages: List<Page>? = null
@Volatile @Transient var totalProgress: Int = 0 @Volatile @Transient
var totalProgress: Int = 0
@Volatile @Transient var downloadedImages: Int = 0 @Volatile @Transient
var downloadedImages: Int = 0
@Volatile @Transient var status: Int = 0 @Volatile @Transient
var status: Int = 0
set(status) { set(status) {
field = status field = status
statusSubject?.onNext(this) statusSubject?.onNext(this)

View File

@ -37,8 +37,9 @@ class DownloadQueue(
store.remove(download) store.remove(download)
download.setStatusSubject(null) download.setStatusSubject(null)
download.setStatusCallback(null) download.setStatusCallback(null)
if (download.status == Download.DOWNLOADING || download.status == Download.QUEUE) if (download.status == Download.DOWNLOADING || download.status == Download.QUEUE) {
download.status = Download.NOT_DOWNLOADED download.status = Download.NOT_DOWNLOADED
}
downloadListeners.forEach { it.updateDownload(download) } downloadListeners.forEach { it.updateDownload(download) }
if (removed) { if (removed) {
updatedRelay.call(Unit) updatedRelay.call(Unit)
@ -65,8 +66,9 @@ class DownloadQueue(
queue.forEach { download -> queue.forEach { download ->
download.setStatusSubject(null) download.setStatusSubject(null)
download.setStatusCallback(null) download.setStatusCallback(null)
if (download.status == Download.DOWNLOADING || download.status == Download.QUEUE) if (download.status == Download.DOWNLOADING || download.status == Download.QUEUE) {
download.status = Download.NOT_DOWNLOADED download.status = Download.NOT_DOWNLOADED
}
downloadListeners.forEach { it.updateDownload(download) } downloadListeners.forEach { it.updateDownload(download) }
} }
queue.clear() queue.clear()
@ -85,11 +87,12 @@ class DownloadQueue(
private fun setPagesFor(download: Download) { private fun setPagesFor(download: Download) {
if (download.status == Download.DOWNLOADING) { if (download.status == Download.DOWNLOADING) {
if (download.pages != null) if (download.pages != null) {
for (page in download.pages!!) for (page in download.pages!!)
page.setStatusCallback { page.setStatusCallback {
callListeners(download) callListeners(download)
} }
}
downloadListeners.forEach { it.updateDownload(download) } downloadListeners.forEach { it.updateDownload(download) }
} else if (download.status == Download.DOWNLOADED || download.status == Download.ERROR) { } else if (download.status == Download.DOWNLOADED || download.status == Download.ERROR) {
setPagesSubject(download.pages, null) setPagesSubject(download.pages, null)

View File

@ -31,10 +31,11 @@ class LibraryUpdateJob(private val context: Context, workerParams: WorkerParamet
if (interval > 0) { if (interval > 0) {
val restrictions = preferences.libraryUpdateRestriction()!! val restrictions = preferences.libraryUpdateRestriction()!!
val acRestriction = "ac" in restrictions val acRestriction = "ac" in restrictions
val wifiRestriction = if ("wifi" in restrictions) val wifiRestriction = if ("wifi" in restrictions) {
NetworkType.UNMETERED NetworkType.UNMETERED
else } else {
NetworkType.CONNECTED NetworkType.CONNECTED
}
val constraints = Constraints.Builder() val constraints = Constraints.Builder()
.setRequiredNetworkType(wifiRestriction) .setRequiredNetworkType(wifiRestriction)

View File

@ -195,7 +195,6 @@ class LibraryUpdateNotifier(private val context: Context) {
} }
NotificationManagerCompat.from(context).apply { NotificationManagerCompat.from(context).apply {
notify( notify(
Notifications.ID_NEW_CHAPTERS, Notifications.ID_NEW_CHAPTERS,
context.notification(Notifications.CHANNEL_NEW_CHAPTERS) { context.notification(Notifications.CHANNEL_NEW_CHAPTERS) {

View File

@ -114,7 +114,9 @@ class LibraryUpdateService(
enum class Target { enum class Target {
CHAPTERS, // Manga chapters CHAPTERS, // Manga chapters
DETAILS, // Manga metadata DETAILS, // Manga metadata
TRACKING // Tracking metadata TRACKING // Tracking metadata
} }
@ -172,8 +174,9 @@ class LibraryUpdateService(
*/ */
override fun onDestroy() { override fun onDestroy() {
job?.cancel() job?.cancel()
if (instance == this) if (instance == this) {
instance = null instance = null
}
if (wakeLock.isHeld) { if (wakeLock.isHeld) {
wakeLock.release() wakeLock.release()
} }
@ -380,47 +383,47 @@ class LibraryUpdateService(
shouldDownload: Boolean shouldDownload: Boolean
): ):
Boolean { Boolean {
try { try {
var hasDownloads = false var hasDownloads = false
if (job?.isCancelled == true) { if (job?.isCancelled == true) {
return false
}
notifier.showProgressNotification(manga, progress, mangaToUpdate.size)
val source = sourceManager.get(manga.source) as? HttpSource ?: return false
val fetchedChapters = withContext(Dispatchers.IO) {
source.fetchChapterList(manga).toBlocking().single()
} ?: emptyList()
if (fetchedChapters.isNotEmpty()) {
val newChapters = syncChaptersWithSource(db, fetchedChapters, manga, source)
if (newChapters.first.isNotEmpty()) {
if (shouldDownload) {
downloadChapters(manga, newChapters.first.sortedBy { it.chapter_number })
hasDownloads = true
}
newUpdates[manga] =
newChapters.first.sortedBy { it.chapter_number }.toTypedArray()
}
if (deleteRemoved && newChapters.second.isNotEmpty()) {
val removedChapters = newChapters.second.filter {
downloadManager.isChapterDownloaded(it, manga)
}
if (removedChapters.isNotEmpty()) {
downloadManager.deleteChapters(removedChapters, manga, source)
}
}
if (newChapters.first.size + newChapters.second.size > 0) listener?.onUpdateManga(
manga
)
}
return hasDownloads
} catch (e: Exception) {
if (e !is CancellationException) {
failedUpdates[manga] = e.message
Timber.e("Failed updating: ${manga.title}: $e")
}
return false return false
} }
notifier.showProgressNotification(manga, progress, mangaToUpdate.size)
val source = sourceManager.get(manga.source) as? HttpSource ?: return false
val fetchedChapters = withContext(Dispatchers.IO) {
source.fetchChapterList(manga).toBlocking().single()
} ?: emptyList()
if (fetchedChapters.isNotEmpty()) {
val newChapters = syncChaptersWithSource(db, fetchedChapters, manga, source)
if (newChapters.first.isNotEmpty()) {
if (shouldDownload) {
downloadChapters(manga, newChapters.first.sortedBy { it.chapter_number })
hasDownloads = true
}
newUpdates[manga] =
newChapters.first.sortedBy { it.chapter_number }.toTypedArray()
}
if (deleteRemoved && newChapters.second.isNotEmpty()) {
val removedChapters = newChapters.second.filter {
downloadManager.isChapterDownloaded(it, manga)
}
if (removedChapters.isNotEmpty()) {
downloadManager.deleteChapters(removedChapters, manga, source)
}
}
if (newChapters.first.size + newChapters.second.size > 0) listener?.onUpdateManga(
manga
)
}
return hasDownloads
} catch (e: Exception) {
if (e !is CancellationException) {
failedUpdates[manga] = e.message
Timber.e("Failed updating: ${manga.title}: $e")
}
return false
} }
}
private fun downloadChapters(manga: Manga, chapters: List<Chapter>) { private fun downloadChapters(manga: Manga, chapters: List<Chapter>) {
// We don't want to start downloading while the library is updating, because websites // We don't want to start downloading while the library is updating, because websites

View File

@ -448,19 +448,19 @@ class NotificationReceiver : BroadcastReceiver() {
*/ */
internal fun openChapterPendingActivity(context: Context, manga: Manga, groupId: Int): internal fun openChapterPendingActivity(context: Context, manga: Manga, groupId: Int):
PendingIntent { PendingIntent {
val newIntent = val newIntent =
Intent(context, MainActivity::class.java).setAction(MainActivity.SHORTCUT_MANGA) Intent(context, MainActivity::class.java).setAction(MainActivity.SHORTCUT_MANGA)
.addFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP or Intent.FLAG_ACTIVITY_SINGLE_TOP) .addFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP or Intent.FLAG_ACTIVITY_SINGLE_TOP)
.putExtra(MangaDetailsController.MANGA_EXTRA, manga.id) .putExtra(MangaDetailsController.MANGA_EXTRA, manga.id)
.putExtra("notificationId", manga.id.hashCode()) .putExtra("notificationId", manga.id.hashCode())
.putExtra("groupId", groupId) .putExtra("groupId", groupId)
return PendingIntent.getActivity( return PendingIntent.getActivity(
context, context,
manga.id.hashCode(), manga.id.hashCode(),
newIntent, newIntent,
PendingIntent.FLAG_UPDATE_CURRENT PendingIntent.FLAG_UPDATE_CURRENT
) )
} }
/** /**
* Returns [PendingIntent] that opens the error log file in an external viewer * Returns [PendingIntent] that opens the error log file in an external viewer
@ -522,15 +522,15 @@ class NotificationReceiver : BroadcastReceiver() {
groupId: Int groupId: Int
): ):
PendingIntent { PendingIntent {
val newIntent = Intent(context, NotificationReceiver::class.java).apply { val newIntent = Intent(context, NotificationReceiver::class.java).apply {
action = ACTION_MARK_AS_READ action = ACTION_MARK_AS_READ
putExtra(EXTRA_CHAPTER_URL, chapters.map { it.url }.toTypedArray()) putExtra(EXTRA_CHAPTER_URL, chapters.map { it.url }.toTypedArray())
putExtra(EXTRA_MANGA_ID, manga.id) putExtra(EXTRA_MANGA_ID, manga.id)
putExtra(EXTRA_NOTIFICATION_ID, manga.id.hashCode()) putExtra(EXTRA_NOTIFICATION_ID, manga.id.hashCode())
putExtra(EXTRA_GROUP_ID, groupId) putExtra(EXTRA_GROUP_ID, groupId)
}
return PendingIntent.getBroadcast(context, manga.id.hashCode(), newIntent, PendingIntent.FLAG_UPDATE_CURRENT)
} }
return PendingIntent.getBroadcast(context, manga.id.hashCode(), newIntent, PendingIntent.FLAG_UPDATE_CURRENT)
}
/** /**
* Returns [PendingIntent] that starts a service which stops the library update * Returns [PendingIntent] that starts a service which stops the library update

View File

@ -6,11 +6,9 @@ import androidx.annotation.StringRes
import eu.kanade.tachiyomi.data.database.DatabaseHelper import eu.kanade.tachiyomi.data.database.DatabaseHelper
import eu.kanade.tachiyomi.data.database.models.Track import eu.kanade.tachiyomi.data.database.models.Track
import eu.kanade.tachiyomi.data.preference.PreferencesHelper import eu.kanade.tachiyomi.data.preference.PreferencesHelper
import eu.kanade.tachiyomi.data.track.anilist.Anilist
import eu.kanade.tachiyomi.data.track.model.TrackSearch import eu.kanade.tachiyomi.data.track.model.TrackSearch
import eu.kanade.tachiyomi.network.NetworkHelper import eu.kanade.tachiyomi.network.NetworkHelper
import eu.kanade.tachiyomi.source.model.SManga import eu.kanade.tachiyomi.source.model.SManga
import eu.kanade.tachiyomi.ui.manga.track.SetTrackReadingDatesDialog
import eu.kanade.tachiyomi.util.system.executeOnIO import eu.kanade.tachiyomi.util.system.executeOnIO
import okhttp3.OkHttpClient import okhttp3.OkHttpClient
import uy.kohesive.injekt.injectLazy import uy.kohesive.injekt.injectLazy

View File

@ -25,7 +25,6 @@ import okhttp3.RequestBody.Companion.toRequestBody
import okhttp3.Response import okhttp3.Response
import timber.log.Timber import timber.log.Timber
import java.util.Calendar import java.util.Calendar
import java.util.Date
import java.util.concurrent.TimeUnit import java.util.concurrent.TimeUnit
class AnilistApi(val client: OkHttpClient, interceptor: AnilistInterceptor) { class AnilistApi(val client: OkHttpClient, interceptor: AnilistInterceptor) {
@ -34,7 +33,6 @@ class AnilistApi(val client: OkHttpClient, interceptor: AnilistInterceptor) {
suspend fun addLibManga(track: Track): Track { suspend fun addLibManga(track: Track): Track {
return withContext(Dispatchers.IO) { return withContext(Dispatchers.IO) {
val variables = jsonObject( val variables = jsonObject(
"mangaId" to track.media_id, "mangaId" to track.media_id,
"progress" to track.last_chapter_read, "progress" to track.last_chapter_read,
@ -105,7 +103,6 @@ class AnilistApi(val client: OkHttpClient, interceptor: AnilistInterceptor) {
} }
suspend fun findLibManga(track: Track, userid: Int): Track? { suspend fun findLibManga(track: Track, userid: Int): Track? {
return withContext(Dispatchers.IO) { return withContext(Dispatchers.IO) {
val variables = jsonObject( val variables = jsonObject(
"id" to userid, "id" to userid,
@ -141,7 +138,6 @@ class AnilistApi(val client: OkHttpClient, interceptor: AnilistInterceptor) {
suspend fun remove(track: Track): Boolean { suspend fun remove(track: Track): Boolean {
return withContext(Dispatchers.IO) { return withContext(Dispatchers.IO) {
try { try {
val variables = jsonObject( val variables = jsonObject(
"listId" to track.library_id "listId" to track.library_id
) )

View File

@ -114,7 +114,6 @@ class Bangumi(private val context: Context, id: Int) : TrackService(id) {
suspend fun login(code: String): Boolean { suspend fun login(code: String): Boolean {
try { try {
val oauth = api.accessToken(code) val oauth = api.accessToken(code)
interceptor.newAuth(oauth) interceptor.newAuth(oauth)
saveCredentials(oauth.user_id.toString(), oauth.access_token) saveCredentials(oauth.user_id.toString(), oauth.access_token)

View File

@ -5,14 +5,12 @@ import android.graphics.Color
import androidx.annotation.StringRes import androidx.annotation.StringRes
import eu.kanade.tachiyomi.R import eu.kanade.tachiyomi.R
import eu.kanade.tachiyomi.data.database.models.Track import eu.kanade.tachiyomi.data.database.models.Track
import eu.kanade.tachiyomi.data.preference.getOrDefault
import eu.kanade.tachiyomi.data.track.TrackService import eu.kanade.tachiyomi.data.track.TrackService
import eu.kanade.tachiyomi.data.track.model.TrackSearch import eu.kanade.tachiyomi.data.track.model.TrackSearch
import eu.kanade.tachiyomi.data.track.updateNewTrackInfo import eu.kanade.tachiyomi.data.track.updateNewTrackInfo
import kotlinx.serialization.decodeFromString import kotlinx.serialization.decodeFromString
import kotlinx.serialization.encodeToString import kotlinx.serialization.encodeToString
import kotlinx.serialization.json.Json import kotlinx.serialization.json.Json
import okhttp3.HttpUrl.Companion.toHttpUrlOrNull
import timber.log.Timber import timber.log.Timber
import uy.kohesive.injekt.injectLazy import uy.kohesive.injekt.injectLazy
@ -89,7 +87,6 @@ class MyAnimeList(private val context: Context, id: Int) : TrackService(id) {
// Set default fields if it's not found in the list // Set default fields if it's not found in the list
add(track) add(track)
} }
} }
override fun canRemoveFromService(): Boolean = true override fun canRemoveFromService(): Boolean = true

View File

@ -8,17 +8,11 @@ import eu.kanade.tachiyomi.data.track.model.TrackSearch
import eu.kanade.tachiyomi.network.GET import eu.kanade.tachiyomi.network.GET
import eu.kanade.tachiyomi.network.POST import eu.kanade.tachiyomi.network.POST
import eu.kanade.tachiyomi.network.await import eu.kanade.tachiyomi.network.await
import eu.kanade.tachiyomi.network.consumeBody
import eu.kanade.tachiyomi.network.consumeXmlBody
import eu.kanade.tachiyomi.network.parseAs import eu.kanade.tachiyomi.network.parseAs
import eu.kanade.tachiyomi.util.PkceUtil import eu.kanade.tachiyomi.util.PkceUtil
import eu.kanade.tachiyomi.util.selectInt
import eu.kanade.tachiyomi.util.selectText
import eu.kanade.tachiyomi.util.system.withIOContext import eu.kanade.tachiyomi.util.system.withIOContext
import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.async import kotlinx.coroutines.async
import kotlinx.coroutines.awaitAll import kotlinx.coroutines.awaitAll
import kotlinx.coroutines.withContext
import kotlinx.serialization.json.JsonObject import kotlinx.serialization.json.JsonObject
import kotlinx.serialization.json.boolean import kotlinx.serialization.json.boolean
import kotlinx.serialization.json.contentOrNull import kotlinx.serialization.json.contentOrNull
@ -27,17 +21,9 @@ import kotlinx.serialization.json.jsonArray
import kotlinx.serialization.json.jsonObject import kotlinx.serialization.json.jsonObject
import kotlinx.serialization.json.jsonPrimitive import kotlinx.serialization.json.jsonPrimitive
import okhttp3.FormBody import okhttp3.FormBody
import okhttp3.MediaType.Companion.toMediaTypeOrNull
import okhttp3.OkHttpClient import okhttp3.OkHttpClient
import okhttp3.Request import okhttp3.Request
import okhttp3.RequestBody import okhttp3.RequestBody
import okhttp3.RequestBody.Companion.toRequestBody
import org.json.JSONObject
import org.jsoup.Jsoup
import org.jsoup.nodes.Document
import org.jsoup.nodes.Element
import org.jsoup.parser.Parser
import retrofit2.http.DELETE
import timber.log.Timber import timber.log.Timber
import java.text.SimpleDateFormat import java.text.SimpleDateFormat
import java.util.* import java.util.*
@ -49,91 +35,90 @@ class MyAnimeListApi(private val client: OkHttpClient, interceptor: MyAnimeListI
suspend fun getAccessToken(authCode: String): OAuth { suspend fun getAccessToken(authCode: String): OAuth {
return withIOContext { return withIOContext {
val formBody: RequestBody = FormBody.Builder() val formBody: RequestBody = FormBody.Builder()
.add("client_id", clientId) .add("client_id", clientId)
.add("code", authCode) .add("code", authCode)
.add("code_verifier", codeVerifier) .add("code_verifier", codeVerifier)
.add("grant_type", "authorization_code") .add("grant_type", "authorization_code")
.build() .build()
client.newCall(POST("$baseOAuthUrl/token", body = formBody)) client.newCall(POST("$baseOAuthUrl/token", body = formBody))
.await() .await()
.parseAs() .parseAs()
} }
} }
suspend fun getCurrentUser(): String { suspend fun getCurrentUser(): String {
return withIOContext { return withIOContext {
val request = Request.Builder() val request = Request.Builder()
.url("$baseApiUrl/users/@me") .url("$baseApiUrl/users/@me")
.get() .get()
.build() .build()
authClient.newCall(request) authClient.newCall(request)
.await() .await()
.parseAs<JsonObject>() .parseAs<JsonObject>()
.let { it["name"]!!.jsonPrimitive.content } .let { it["name"]!!.jsonPrimitive.content }
} }
} }
suspend fun search(query: String): List<TrackSearch> { suspend fun search(query: String): List<TrackSearch> {
return withIOContext { return withIOContext {
val url = "$baseApiUrl/manga".toUri().buildUpon() val url = "$baseApiUrl/manga".toUri().buildUpon()
.appendQueryParameter("q", query) .appendQueryParameter("q", query)
.appendQueryParameter("nsfw", "true") .appendQueryParameter("nsfw", "true")
.build() .build()
authClient.newCall(GET(url.toString())) authClient.newCall(GET(url.toString()))
.await() .await()
.parseAs<JsonObject>() .parseAs<JsonObject>()
.let { .let {
it["data"]!!.jsonArray it["data"]!!.jsonArray
.map { data -> data.jsonObject["node"]!!.jsonObject } .map { data -> data.jsonObject["node"]!!.jsonObject }
.map { node -> .map { node ->
val id = node["id"]!!.jsonPrimitive.int val id = node["id"]!!.jsonPrimitive.int
async { getMangaDetails(id) } async { getMangaDetails(id) }
} }
.awaitAll() .awaitAll()
.filter { trackSearch -> trackSearch.publishing_type != "novel" } .filter { trackSearch -> trackSearch.publishing_type != "novel" }
} }
} }
} }
suspend fun getMangaDetails(id: Int): TrackSearch { suspend fun getMangaDetails(id: Int): TrackSearch {
return withIOContext { return withIOContext {
val url = "$baseApiUrl/manga".toUri().buildUpon() val url = "$baseApiUrl/manga".toUri().buildUpon()
.appendPath(id.toString()) .appendPath(id.toString())
.appendQueryParameter("fields", "id,title,synopsis,num_chapters,main_picture,status,media_type,start_date") .appendQueryParameter("fields", "id,title,synopsis,num_chapters,main_picture,status,media_type,start_date")
.build() .build()
authClient.newCall(GET(url.toString())) authClient.newCall(GET(url.toString()))
.await() .await()
.parseAs<JsonObject>() .parseAs<JsonObject>()
.let { .let {
val obj = it.jsonObject val obj = it.jsonObject
TrackSearch.create(TrackManager.MYANIMELIST).apply { TrackSearch.create(TrackManager.MYANIMELIST).apply {
media_id = obj["id"]!!.jsonPrimitive.int media_id = obj["id"]!!.jsonPrimitive.int
title = obj["title"]!!.jsonPrimitive.content title = obj["title"]!!.jsonPrimitive.content
summary = obj["synopsis"]?.jsonPrimitive?.content ?: "" summary = obj["synopsis"]?.jsonPrimitive?.content ?: ""
total_chapters = obj["num_chapters"]!!.jsonPrimitive.int total_chapters = obj["num_chapters"]!!.jsonPrimitive.int
cover_url = obj["main_picture"]?.jsonObject?.get("large")?.jsonPrimitive?.content ?: "" cover_url = obj["main_picture"]?.jsonObject?.get("large")?.jsonPrimitive?.content ?: ""
tracking_url = "https://myanimelist.net/manga/$media_id" tracking_url = "https://myanimelist.net/manga/$media_id"
publishing_status = obj["status"]!!.jsonPrimitive.content.replace("_", " ") publishing_status = obj["status"]!!.jsonPrimitive.content.replace("_", " ")
publishing_type = obj["media_type"]!!.jsonPrimitive.content.replace("_", " ") publishing_type = obj["media_type"]!!.jsonPrimitive.content.replace("_", " ")
start_date = try { start_date = try {
val outputDf = SimpleDateFormat("yyyy-MM-dd", Locale.US) val outputDf = SimpleDateFormat("yyyy-MM-dd", Locale.US)
outputDf.format(obj["start_date"]!!) outputDf.format(obj["start_date"]!!)
} catch (e: Exception) { } catch (e: Exception) {
"" ""
}
} }
} }
}
} }
} }
suspend fun updateItem(track: Track): Track { suspend fun updateItem(track: Track): Track {
return withIOContext { return withIOContext {
val formBodyBuilder = FormBody.Builder() val formBodyBuilder = FormBody.Builder()
.add("status", track.toMyAnimeListStatus() ?: "reading") .add("status", track.toMyAnimeListStatus() ?: "reading")
.add("is_rereading", (track.status == MyAnimeList.REREADING).toString()) .add("is_rereading", (track.status == MyAnimeList.REREADING).toString())
.add("score", track.score.toString()) .add("score", track.score.toString())
.add("num_chapters_read", track.last_chapter_read.toString()) .add("num_chapters_read", track.last_chapter_read.toString())
convertToIsoDate(track.started_reading_date)?.let { convertToIsoDate(track.started_reading_date)?.let {
formBodyBuilder.add("start_date", it) formBodyBuilder.add("start_date", it)
} }
@ -142,32 +127,31 @@ class MyAnimeListApi(private val client: OkHttpClient, interceptor: MyAnimeListI
} }
val request = Request.Builder() val request = Request.Builder()
.url(mangaUrl(track.media_id).toString()) .url(mangaUrl(track.media_id).toString())
.put(formBodyBuilder.build()) .put(formBodyBuilder.build())
.build() .build()
authClient.newCall(request) authClient.newCall(request)
.await() .await()
.parseAs<JsonObject>() .parseAs<JsonObject>()
.let { parseMangaItem(it, track) } .let { parseMangaItem(it, track) }
} }
} }
suspend fun findListItem(track: Track): Track? { suspend fun findListItem(track: Track): Track? {
return withIOContext { return withIOContext {
val uri = "$baseApiUrl/manga".toUri().buildUpon() val uri = "$baseApiUrl/manga".toUri().buildUpon()
.appendPath(track.media_id.toString()) .appendPath(track.media_id.toString())
.appendQueryParameter("fields", "num_chapters,my_list_status{start_date,finish_date}") .appendQueryParameter("fields", "num_chapters,my_list_status{start_date,finish_date}")
.build() .build()
authClient.newCall(GET(uri.toString())) authClient.newCall(GET(uri.toString()))
.await() .await()
.parseAs<JsonObject>() .parseAs<JsonObject>()
.let { obj -> .let { obj ->
track.total_chapters = obj["num_chapters"]!!.jsonPrimitive.int track.total_chapters = obj["num_chapters"]!!.jsonPrimitive.int
obj.jsonObject["my_list_status"]?.jsonObject?.let { obj.jsonObject["my_list_status"]?.jsonObject?.let {
parseMangaItem(it, track) parseMangaItem(it, track)
}
} }
}
} }
} }
@ -177,17 +161,17 @@ class MyAnimeListApi(private val client: OkHttpClient, interceptor: MyAnimeListI
val obj = json.jsonObject val obj = json.jsonObject
val matches = obj["data"]!!.jsonArray val matches = obj["data"]!!.jsonArray
.filter { .filter {
it.jsonObject["node"]!!.jsonObject["title"]!!.jsonPrimitive.content.contains( it.jsonObject["node"]!!.jsonObject["title"]!!.jsonPrimitive.content.contains(
query, query,
ignoreCase = true ignoreCase = true
) )
} }
.map { .map {
val id = it.jsonObject["node"]!!.jsonObject["id"]!!.jsonPrimitive.int val id = it.jsonObject["node"]!!.jsonObject["id"]!!.jsonPrimitive.int
async { getMangaDetails(id) } async { getMangaDetails(id) }
} }
.awaitAll() .awaitAll()
// Check next page if there's more // Check next page if there's more
if (!obj["paging"]!!.jsonObject["next"]?.jsonPrimitive?.contentOrNull.isNullOrBlank()) { if (!obj["paging"]!!.jsonObject["next"]?.jsonPrimitive?.contentOrNull.isNullOrBlank()) {
@ -201,19 +185,19 @@ class MyAnimeListApi(private val client: OkHttpClient, interceptor: MyAnimeListI
private suspend fun getListPage(offset: Int): JsonObject { private suspend fun getListPage(offset: Int): JsonObject {
return withIOContext { return withIOContext {
val urlBuilder = "$baseApiUrl/users/@me/mangalist".toUri().buildUpon() val urlBuilder = "$baseApiUrl/users/@me/mangalist".toUri().buildUpon()
.appendQueryParameter("fields", "list_status{start_date,finish_date}") .appendQueryParameter("fields", "list_status{start_date,finish_date}")
.appendQueryParameter("limit", listPaginationAmount.toString()) .appendQueryParameter("limit", listPaginationAmount.toString())
if (offset > 0) { if (offset > 0) {
urlBuilder.appendQueryParameter("offset", offset.toString()) urlBuilder.appendQueryParameter("offset", offset.toString())
} }
val request = Request.Builder() val request = Request.Builder()
.url(urlBuilder.build().toString()) .url(urlBuilder.build().toString())
.get() .get()
.build() .build()
authClient.newCall(request) authClient.newCall(request)
.await() .await()
.parseAs() .parseAs()
} }
} }
@ -251,7 +235,7 @@ class MyAnimeListApi(private val client: OkHttpClient, interceptor: MyAnimeListI
suspend fun remove(track: Track): Boolean { suspend fun remove(track: Track): Boolean {
return withIOContext { return withIOContext {
try { try {
val request = Request.Builder() val request = Request.Builder()
.url(mangaUrl(track.media_id).toString()) .url(mangaUrl(track.media_id).toString())
.delete() .delete()
@ -277,22 +261,22 @@ class MyAnimeListApi(private val client: OkHttpClient, interceptor: MyAnimeListI
private var codeVerifier: String = "" private var codeVerifier: String = ""
fun authUrl(): Uri = "$baseOAuthUrl/authorize".toUri().buildUpon() fun authUrl(): Uri = "$baseOAuthUrl/authorize".toUri().buildUpon()
.appendQueryParameter("client_id", clientId) .appendQueryParameter("client_id", clientId)
.appendQueryParameter("code_challenge", getPkceChallengeCode()) .appendQueryParameter("code_challenge", getPkceChallengeCode())
.appendQueryParameter("response_type", "code") .appendQueryParameter("response_type", "code")
.build() .build()
fun mangaUrl(id: Int): Uri = "$baseApiUrl/manga".toUri().buildUpon() fun mangaUrl(id: Int): Uri = "$baseApiUrl/manga".toUri().buildUpon()
.appendPath(id.toString()) .appendPath(id.toString())
.appendPath("my_list_status") .appendPath("my_list_status")
.build() .build()
fun refreshTokenRequest(refreshToken: String): Request { fun refreshTokenRequest(refreshToken: String): Request {
val formBody: RequestBody = FormBody.Builder() val formBody: RequestBody = FormBody.Builder()
.add("client_id", clientId) .add("client_id", clientId)
.add("refresh_token", refreshToken) .add("refresh_token", refreshToken)
.add("grant_type", "refresh_token") .add("grant_type", "refresh_token")
.build() .build()
return POST("$baseOAuthUrl/token", body = formBody) return POST("$baseOAuthUrl/token", body = formBody)
} }

View File

@ -3,16 +3,10 @@ package eu.kanade.tachiyomi.data.track.myanimelist
import kotlinx.coroutines.CoroutineScope import kotlinx.coroutines.CoroutineScope
import kotlinx.coroutines.Dispatchers import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.Job import kotlinx.coroutines.Job
import kotlinx.coroutines.runBlocking
import kotlinx.serialization.decodeFromString import kotlinx.serialization.decodeFromString
import kotlinx.serialization.json.Json import kotlinx.serialization.json.Json
import okhttp3.Interceptor import okhttp3.Interceptor
import okhttp3.Request
import okhttp3.RequestBody
import okhttp3.RequestBody.Companion.toRequestBody
import okhttp3.Response import okhttp3.Response
import okio.Buffer
import org.json.JSONObject
import uy.kohesive.injekt.injectLazy import uy.kohesive.injekt.injectLazy
class MyAnimeListInterceptor(private val myanimelist: MyAnimeList, private var token: String?) : Interceptor { class MyAnimeListInterceptor(private val myanimelist: MyAnimeList, private var token: String?) : Interceptor {
@ -51,8 +45,8 @@ class MyAnimeListInterceptor(private val myanimelist: MyAnimeList, private var t
// Add the authorization header to the original request. // Add the authorization header to the original request.
val authRequest = originalRequest.newBuilder() val authRequest = originalRequest.newBuilder()
.addHeader("Authorization", "Bearer ${oauth!!.access_token}") .addHeader("Authorization", "Bearer ${oauth!!.access_token}")
.build() .build()
return chain.proceed(authRequest) return chain.proceed(authRequest)
} }

View File

@ -69,8 +69,9 @@ class ExtensionManager(
} }
fun removeListener(listener: ExtensionsChangedListener) { fun removeListener(listener: ExtensionsChangedListener) {
if (this.listener == listener) if (this.listener == listener) {
this.listener = null this.listener = null
}
} }
fun getAppIconForSource(source: Source): Drawable? { fun getAppIconForSource(source: Source): Drawable? {

View File

@ -62,17 +62,17 @@ internal class ExtensionGithubApi {
libVersion >= ExtensionLoader.LIB_VERSION_MIN && libVersion <= ExtensionLoader.LIB_VERSION_MAX libVersion >= ExtensionLoader.LIB_VERSION_MIN && libVersion <= ExtensionLoader.LIB_VERSION_MAX
} }
.map { element -> .map { element ->
val name = element.jsonObject["name"]!!.jsonPrimitive.content.substringAfter("Tachiyomi: ") val name = element.jsonObject["name"]!!.jsonPrimitive.content.substringAfter("Tachiyomi: ")
val pkgName = element.jsonObject["pkg"]!!.jsonPrimitive.content val pkgName = element.jsonObject["pkg"]!!.jsonPrimitive.content
val apkName = element.jsonObject["apk"]!!.jsonPrimitive.content val apkName = element.jsonObject["apk"]!!.jsonPrimitive.content
val versionName = element.jsonObject["version"]!!.jsonPrimitive.content val versionName = element.jsonObject["version"]!!.jsonPrimitive.content
val versionCode = element.jsonObject["code"]!!.jsonPrimitive.int val versionCode = element.jsonObject["code"]!!.jsonPrimitive.int
val lang = element.jsonObject["lang"]!!.jsonPrimitive.content val lang = element.jsonObject["lang"]!!.jsonPrimitive.content
val nsfw = element.jsonObject["nsfw"]!!.jsonPrimitive.int == 1 val nsfw = element.jsonObject["nsfw"]!!.jsonPrimitive.int == 1
val icon = "${REPO_URL_PREFIX}icon/${apkName.replace(".apk", ".png")}" val icon = "${REPO_URL_PREFIX}icon/${apkName.replace(".apk", ".png")}"
Extension.Available(name, pkgName, versionName, versionCode, lang, nsfw, apkName, icon) Extension.Available(name, pkgName, versionName, versionCode, lang, nsfw, apkName, icon)
} }
} }
fun getApkUrl(extension: Extension.Available): String { fun getApkUrl(extension: Extension.Available): String {

View File

@ -144,10 +144,11 @@ internal object ExtensionLoader {
.split(";") .split(";")
.map { .map {
val sourceClass = it.trim() val sourceClass = it.trim()
if (sourceClass.startsWith(".")) if (sourceClass.startsWith(".")) {
pkgInfo.packageName + sourceClass pkgInfo.packageName + sourceClass
else } else {
sourceClass sourceClass
}
} }
.flatMap { .flatMap {
try { try {

View File

@ -16,7 +16,6 @@ fun GET(
headers: Headers = DEFAULT_HEADERS, headers: Headers = DEFAULT_HEADERS,
cache: CacheControl = DEFAULT_CACHE_CONTROL cache: CacheControl = DEFAULT_CACHE_CONTROL
): Request { ): Request {
return Request.Builder() return Request.Builder()
.url(url) .url(url)
.headers(headers) .headers(headers)
@ -30,7 +29,6 @@ fun POST(
body: RequestBody = DEFAULT_BODY, body: RequestBody = DEFAULT_BODY,
cache: CacheControl = DEFAULT_CACHE_CONTROL cache: CacheControl = DEFAULT_CACHE_CONTROL
): Request { ): Request {
return Request.Builder() return Request.Builder()
.url(url) .url(url)
.post(body) .post(body)

View File

@ -61,8 +61,9 @@ class SmartSearchEngine(
} else title } else title
val searchResults = source.fetchSearchManga(1, searchQuery, FilterList()).toSingle().await(Schedulers.io()) val searchResults = source.fetchSearchManga(1, searchQuery, FilterList()).toSingle().await(Schedulers.io())
if (searchResults.mangas.size == 1) if (searchResults.mangas.size == 1) {
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.title) val normalizedDistance = normalizedLevenshtein.similarity(title, it.title)

View File

@ -15,14 +15,16 @@ open class Page(
val number: Int val number: Int
get() = index + 1 get() = index + 1
@Transient @Volatile var status: Int = 0 @Transient @Volatile
var status: Int = 0
set(value) { set(value) {
field = value field = value
statusSubject?.onNext(value) statusSubject?.onNext(value)
statusCallback?.invoke(this) statusCallback?.invoke(this)
} }
@Transient @Volatile var progress: Int = 0 @Transient @Volatile
var progress: Int = 0
set(value) { set(value) {
field = value field = value
statusCallback?.invoke(this) statusCallback?.invoke(this)

View File

@ -36,25 +36,31 @@ interface SManga : Serializable {
get() = (this as? MangaImpl)?.ogGenre ?: genre get() = (this as? MangaImpl)?.ogGenre ?: genre
fun copyFrom(other: SManga) { fun copyFrom(other: SManga) {
if (other.author != null) if (other.author != null) {
author = other.originalAuthor author = other.originalAuthor
}
if (other.artist != null) if (other.artist != null) {
artist = other.originalArtist artist = other.originalArtist
}
if (other.description != null) if (other.description != null) {
description = other.originalDescription description = other.originalDescription
}
if (other.genre != null) if (other.genre != null) {
genre = other.originalGenre genre = other.originalGenre
}
if (other.thumbnail_url != null) if (other.thumbnail_url != null) {
thumbnail_url = other.thumbnail_url thumbnail_url = other.thumbnail_url
}
status = other.status status = other.status
if (!initialized) if (!initialized) {
initialized = other.initialized initialized = other.initialized
}
} }
companion object { companion object {

View File

@ -29,7 +29,8 @@ abstract class BaseActivity : AppCompatActivity() {
override fun onResume() { override fun onResume() {
super.onResume() super.onResume()
if (this !is BiometricActivity && this !is SearchActivity) if (this !is BiometricActivity && this !is SearchActivity) {
SecureActivityDelegate.promptLockIfNeeded(this) SecureActivityDelegate.promptLockIfNeeded(this)
}
} }
} }

View File

@ -84,8 +84,9 @@ abstract class BaseController(bundle: Bundle? = null) :
parentController = parentController.parentController parentController = parentController.parentController
} }
if (router.backstack.lastOrNull()?.controller() == this) if (router.backstack.lastOrNull()?.controller() == this) {
(activity as? AppCompatActivity)?.supportActionBar?.title = getTitle() (activity as? AppCompatActivity)?.supportActionBar?.title = getTitle()
}
} }
private fun Controller.instance(): String { private fun Controller.instance(): String {

View File

@ -43,12 +43,10 @@ abstract class RxController(bundle: Bundle? = null) : BaseController(bundle) {
} }
fun <T> Observable<T>.subscribeUntilDetach(): Subscription { fun <T> Observable<T>.subscribeUntilDetach(): Subscription {
return subscribe().also { untilDetachSubscriptions.add(it) } return subscribe().also { untilDetachSubscriptions.add(it) }
} }
fun <T> Observable<T>.subscribeUntilDetach(onNext: (T) -> Unit): Subscription { fun <T> Observable<T>.subscribeUntilDetach(onNext: (T) -> Unit): Subscription {
return subscribe(onNext).also { untilDetachSubscriptions.add(it) } return subscribe(onNext).also { untilDetachSubscriptions.add(it) }
} }
@ -56,7 +54,6 @@ abstract class RxController(bundle: Bundle? = null) : BaseController(bundle) {
onNext: (T) -> Unit, onNext: (T) -> Unit,
onError: (Throwable) -> Unit onError: (Throwable) -> Unit
): Subscription { ): Subscription {
return subscribe(onNext, onError).also { untilDetachSubscriptions.add(it) } return subscribe(onNext, onError).also { untilDetachSubscriptions.add(it) }
} }
@ -65,17 +62,14 @@ abstract class RxController(bundle: Bundle? = null) : BaseController(bundle) {
onError: (Throwable) -> Unit, onError: (Throwable) -> Unit,
onCompleted: () -> Unit onCompleted: () -> Unit
): Subscription { ): Subscription {
return subscribe(onNext, onError, onCompleted).also { untilDetachSubscriptions.add(it) } return subscribe(onNext, onError, onCompleted).also { untilDetachSubscriptions.add(it) }
} }
fun <T> Observable<T>.subscribeUntilDestroy(): Subscription { fun <T> Observable<T>.subscribeUntilDestroy(): Subscription {
return subscribe().also { untilDestroySubscriptions.add(it) } return subscribe().also { untilDestroySubscriptions.add(it) }
} }
fun <T> Observable<T>.subscribeUntilDestroy(onNext: (T) -> Unit): Subscription { fun <T> Observable<T>.subscribeUntilDestroy(onNext: (T) -> Unit): Subscription {
return subscribe(onNext).also { untilDestroySubscriptions.add(it) } return subscribe(onNext).also { untilDestroySubscriptions.add(it) }
} }
@ -83,7 +77,6 @@ abstract class RxController(bundle: Bundle? = null) : BaseController(bundle) {
onNext: (T) -> Unit, onNext: (T) -> Unit,
onError: (Throwable) -> Unit onError: (Throwable) -> Unit
): Subscription { ): Subscription {
return subscribe(onNext, onError).also { untilDestroySubscriptions.add(it) } return subscribe(onNext, onError).also { untilDestroySubscriptions.add(it) }
} }
@ -92,7 +85,6 @@ abstract class RxController(bundle: Bundle? = null) : BaseController(bundle) {
onError: (Throwable) -> Unit, onError: (Throwable) -> Unit,
onCompleted: () -> Unit onCompleted: () -> Unit
): Subscription { ): Subscription {
return subscribe(onNext, onError, onCompleted).also { untilDestroySubscriptions.add(it) } return subscribe(onNext, onError, onCompleted).also { untilDestroySubscriptions.add(it) }
} }
} }

View File

@ -122,8 +122,9 @@ class CategoryController(bundle: Bundle? = null) :
override fun onCategoryRename(position: Int, newName: String): Boolean { override fun onCategoryRename(position: Int, newName: String): Boolean {
val category = adapter?.getItem(position)?.category ?: return false val category = adapter?.getItem(position)?.category ?: return false
if (category.order == CREATE_CATEGORY_ORDER) if (category.order == CREATE_CATEGORY_ORDER) {
return (presenter.createCategory(newName)) return (presenter.createCategory(newName))
}
return (presenter.renameCategory(category, newName)) return (presenter.renameCategory(category, newName))
} }
@ -185,6 +186,7 @@ class CategoryController(bundle: Bundle? = null) :
override fun shouldMoveItem(fromPosition: Int, toPosition: Int): Boolean { override fun shouldMoveItem(fromPosition: Int, toPosition: Int): Boolean {
return toPosition > 0 return toPosition > 0
} }
/** /**
* Called from the presenter when a category with the given name already exists. * Called from the presenter when a category with the given name already exists.
*/ */

View File

@ -121,8 +121,9 @@ class CategoryHolder(view: View, val adapter: CategoryAdapter) : BaseFlexibleVie
) { ) {
isEditing(false) isEditing(false)
edit_text.inputType = InputType.TYPE_NULL edit_text.inputType = InputType.TYPE_NULL
if (!createCategory) if (!createCategory) {
title.text = edit_text.text.toString() title.text = edit_text.text.toString()
}
} }
} else { } else {
itemView.performClick() itemView.performClick()

View File

@ -105,10 +105,11 @@ class ManageCategoryDialog(bundle: Bundle? = null) :
preferences.downloadNewCategories(), preferences.downloadNewCategories(),
true true
) )
if (downloadNew && preferences.downloadNewCategories().get().isEmpty()) if (downloadNew && preferences.downloadNewCategories().get().isEmpty()) {
view.download_new.gone() view.download_new.gone()
else if (!downloadNew) } else if (!downloadNew) {
view.download_new.visible() view.download_new.visible()
}
view.download_new.isChecked = view.download_new.isChecked =
preferences.downloadNew().get() && view.download_new.isChecked preferences.downloadNew().get() && view.download_new.isChecked
setCheckbox( setCheckbox(
@ -132,9 +133,9 @@ class ManageCategoryDialog(bundle: Bundle? = null) :
} }
private fun setCheckbox( private fun setCheckbox(
box: CompoundButton, box: CompoundButton,
categories: Preference<Set<String>>, categories: Preference<Set<String>>,
shouldShow: Boolean shouldShow: Boolean
) { ) {
val updateCategories = categories.get() val updateCategories = categories.get()
box.visibleIf(updateCategories.isNotEmpty() && shouldShow) box.visibleIf(updateCategories.isNotEmpty() && shouldShow)

View File

@ -202,8 +202,9 @@ class DownloadBottomSheet @JvmOverloads constructor(
val adapter = adapter ?: return false val adapter = adapter ?: return false
val items = adapter.currentItems.sortedBy { it.download.chapter.date_upload } val items = adapter.currentItems.sortedBy { it.download.chapter.date_upload }
.toMutableList() .toMutableList()
if (item.itemId == R.id.newest) if (item.itemId == R.id.newest) {
items.reverse() items.reverse()
}
adapter.updateDataSet(items) adapter.updateDataSet(items)
val downloads = items.mapNotNull { it.download } val downloads = items.mapNotNull { it.download }
presenter.reorder(downloads) presenter.reorder(downloads)
@ -266,10 +267,11 @@ class DownloadBottomSheet @JvmOverloads constructor(
val items = adapter?.currentItems?.toMutableList() ?: return val items = adapter?.currentItems?.toMutableList() ?: return
val item = items[position] val item = items[position]
items.remove(item) items.remove(item)
if (menuItem.itemId == R.id.move_to_top) if (menuItem.itemId == R.id.move_to_top) {
items.add(0, item) items.add(0, item)
else } else {
items.add(item) items.add(item)
}
adapter?.updateDataSet(items) adapter?.updateDataSet(items)
val downloads = items.mapNotNull { it.download } val downloads = items.mapNotNull { it.download }
presenter.reorder(downloads) presenter.reorder(downloads)

View File

@ -59,8 +59,9 @@ class DownloadButton @JvmOverloads constructor(context: Context, attrs: Attribut
isAnimating = false isAnimating = false
} }
download_icon.setImageDrawable( download_icon.setImageDrawable(
if (state == Download.CHECKED) if (state == Download.CHECKED) {
checkDrawable else downloadDrawable checkDrawable
} else downloadDrawable
) )
when (state) { when (state) {
Download.CHECKED -> { Download.CHECKED -> {

View File

@ -15,7 +15,6 @@ import eu.kanade.tachiyomi.source.SourceManager
import eu.kanade.tachiyomi.ui.migration.MangaItem import eu.kanade.tachiyomi.ui.migration.MangaItem
import eu.kanade.tachiyomi.ui.migration.SelectionHeader import eu.kanade.tachiyomi.ui.migration.SelectionHeader
import eu.kanade.tachiyomi.ui.migration.SourceItem import eu.kanade.tachiyomi.ui.migration.SourceItem
import eu.kanade.tachiyomi.util.lang.combineLatest
import eu.kanade.tachiyomi.util.system.LocaleHelper import eu.kanade.tachiyomi.util.system.LocaleHelper
import eu.kanade.tachiyomi.util.system.executeOnIO import eu.kanade.tachiyomi.util.system.executeOnIO
import kotlinx.coroutines.CoroutineScope import kotlinx.coroutines.CoroutineScope
@ -26,8 +25,6 @@ import kotlinx.coroutines.awaitAll
import kotlinx.coroutines.launch import kotlinx.coroutines.launch
import kotlinx.coroutines.withContext import kotlinx.coroutines.withContext
import rx.Observable import rx.Observable
import rx.android.schedulers.AndroidSchedulers
import rx.schedulers.Schedulers
import uy.kohesive.injekt.Injekt import uy.kohesive.injekt.Injekt
import uy.kohesive.injekt.api.get import uy.kohesive.injekt.api.get
@ -76,14 +73,15 @@ class ExtensionBottomPresenter(
val migrationJob = async { val migrationJob = async {
val favs = db.getFavoriteMangas().executeOnIO() val favs = db.getFavoriteMangas().executeOnIO()
sourceItems = findSourcesWithManga(favs) sourceItems = findSourcesWithManga(favs)
mangaItems = HashMap(sourceItems.associate { mangaItems = HashMap(
it.source.id to this@ExtensionBottomPresenter.libraryToMigrationItem(favs, it.source.id) sourceItems.associate {
}) it.source.id to this@ExtensionBottomPresenter.libraryToMigrationItem(favs, it.source.id)
}
)
withContext(Dispatchers.Main) { withContext(Dispatchers.Main) {
if (selectedSource != null) { if (selectedSource != null) {
bottomSheet.setMigrationManga(mangaItems[selectedSource]) bottomSheet.setMigrationManga(mangaItems[selectedSource])
} } else {
else {
bottomSheet.setMigrationSources(sourceItems) bottomSheet.setMigrationSources(sourceItems)
} }
} }
@ -125,14 +123,15 @@ class ExtensionBottomPresenter(
scope.launch { scope.launch {
val favs = db.getFavoriteMangas().executeOnIO() val favs = db.getFavoriteMangas().executeOnIO()
sourceItems = findSourcesWithManga(favs) sourceItems = findSourcesWithManga(favs)
mangaItems = HashMap(sourceItems.associate { mangaItems = HashMap(
it.source.id to this@ExtensionBottomPresenter.libraryToMigrationItem(favs, it.source.id) sourceItems.associate {
}) it.source.id to this@ExtensionBottomPresenter.libraryToMigrationItem(favs, it.source.id)
}
)
withContext(Dispatchers.Main) { withContext(Dispatchers.Main) {
if (selectedSource != null) { if (selectedSource != null) {
bottomSheet.setMigrationManga(mangaItems[selectedSource]) bottomSheet.setMigrationManga(mangaItems[selectedSource])
} } else {
else {
bottomSheet.setMigrationSources(sourceItems) bottomSheet.setMigrationSources(sourceItems)
} }
} }

View File

@ -308,10 +308,12 @@ class ExtensionBottomSheet @JvmOverloads constructor(context: Context, attrs: At
} }
override fun getPageTitle(position: Int): CharSequence { override fun getPageTitle(position: Int): CharSequence {
return context.getString(when (position) { return context.getString(
0 -> R.string.extensions when (position) {
else -> R.string.migration 0 -> R.string.extensions
}) else -> R.string.migration
}
)
} }
} }
} }

View File

@ -38,7 +38,6 @@ data class ExtensionGroupItem(val name: String, val size: Int) : AbstractHeaderI
position: Int, position: Int,
payloads: MutableList<Any?>? payloads: MutableList<Any?>?
) { ) {
holder.bind(this) holder.bind(this)
} }

View File

@ -46,7 +46,6 @@ data class ExtensionItem(
position: Int, position: Int,
payloads: MutableList<Any?>? payloads: MutableList<Any?>?
) { ) {
if (payloads == null || payloads.isEmpty()) { if (payloads == null || payloads.isEmpty()) {
holder.bind(this) holder.bind(this)
} else { } else {

View File

@ -3,7 +3,6 @@ package eu.kanade.tachiyomi.ui.extension
import androidx.preference.PreferenceScreen import androidx.preference.PreferenceScreen
import androidx.preference.SwitchPreference import androidx.preference.SwitchPreference
import eu.kanade.tachiyomi.R import eu.kanade.tachiyomi.R
import eu.kanade.tachiyomi.data.preference.getOrDefault
import eu.kanade.tachiyomi.extension.ExtensionManager import eu.kanade.tachiyomi.extension.ExtensionManager
import eu.kanade.tachiyomi.ui.setting.SettingsController import eu.kanade.tachiyomi.ui.setting.SettingsController
import eu.kanade.tachiyomi.ui.setting.onChange import eu.kanade.tachiyomi.ui.setting.onChange

View File

@ -125,7 +125,8 @@ class ExtensionDetailsController(bundle: Bundle? = null) :
screen.setShouldUseGeneratedIds(true) screen.setShouldUseGeneratedIds(true)
val extHeaderAdapter = ExtensionDetailsHeaderAdapter(presenter) val extHeaderAdapter = ExtensionDetailsHeaderAdapter(presenter)
extHeaderAdapter.setHasStableIds(true) extHeaderAdapter.setHasStableIds(true)
extension_prefs_recycler.adapter = ConcatAdapter(concatAdapterConfig, extension_prefs_recycler.adapter = ConcatAdapter(
concatAdapterConfig,
extHeaderAdapter, extHeaderAdapter,
PreferenceGroupAdapter(screen) PreferenceGroupAdapter(screen)
) )
@ -151,7 +152,6 @@ class ExtensionDetailsController(bundle: Bundle? = null) :
lastOpenPreferencePosition = savedInstanceState.get(LASTOPENPREFERENCE_KEY) as? Int lastOpenPreferencePosition = savedInstanceState.get(LASTOPENPREFERENCE_KEY) as? Int
} }
override fun onCreateOptionsMenu(menu: Menu, inflater: MenuInflater) { override fun onCreateOptionsMenu(menu: Menu, inflater: MenuInflater) {
inflater.inflate(R.menu.extension_details, menu) inflater.inflate(R.menu.extension_details, menu)
@ -208,8 +208,7 @@ class ExtensionDetailsController(bundle: Bundle? = null) :
toggleSource(source, checked) toggleSource(source, checked)
prefs.forEach { it.isVisible = checked } prefs.forEach { it.isVisible = checked }
true true
} } else {
else {
coordinator.snack(context.getString(R.string._must_be_enabled_first, title), Snackbar.LENGTH_LONG) { coordinator.snack(context.getString(R.string._must_be_enabled_first, title), Snackbar.LENGTH_LONG) {
setAction(R.string.enable) { setAction(R.string.enable) {
preferences.enabledLanguages() += source.lang preferences.enabledLanguages() += source.lang
@ -308,7 +307,6 @@ class ExtensionDetailsController(bundle: Bundle? = null) :
return id.toString() !in preferences.hiddenSources().get() && isLangEnabled() return id.toString() !in preferences.hiddenSources().get() && isLangEnabled()
} }
private fun Source.isLangEnabled(langs: Set<String>? = null): Boolean { private fun Source.isLangEnabled(langs: Set<String>? = null): Boolean {
return (lang in langs ?: preferences.enabledLanguages().get()) return (lang in langs ?: preferences.enabledLanguages().get())
} }

View File

@ -45,7 +45,7 @@ class ExtensionDetailsHeaderAdapter(private val presenter: ExtensionDetailsPrese
view.extension_pkg.text = extension.pkgName view.extension_pkg.text = extension.pkgName
view.extension_uninstall_button.setOnClickListener { view.extension_uninstall_button.setOnClickListener {
presenter.uninstallExtension() presenter.uninstallExtension()
} }
if (extension.isObsolete) { if (extension.isObsolete) {

View File

@ -41,7 +41,6 @@ class AddToLibraryCategoriesDialog<T>(bundle: Bundle? = null) :
} }
override fun onCreateDialog(savedViewState: Bundle?): Dialog { override fun onCreateDialog(savedViewState: Bundle?): Dialog {
return MaterialDialog(activity!!).title(R.string.add_to_library).message(R.string.add_to_categories) return MaterialDialog(activity!!).title(R.string.add_to_library).message(R.string.add_to_categories)
.listItemsMultiChoice( .listItemsMultiChoice(
items = categories.map { it.name }, items = categories.map { it.name },

View File

@ -29,6 +29,7 @@ class LibraryCategoryAdapter(val controller: LibraryController) :
init { init {
setDisplayHeadersAtStartUp(true) setDisplayHeadersAtStartUp(true)
} }
/** /**
* The list of manga in this category. * The list of manga in this category.
*/ */

View File

@ -619,13 +619,12 @@ class LibraryController(
(listOfYs.minOrNull() ?: filter_bottom_sheet.y) + (listOfYs.minOrNull() ?: filter_bottom_sheet.y) +
hopperOffset hopperOffset
if (view.height - insetBottom < category_hopper_frame.y) { if (view.height - insetBottom < category_hopper_frame.y) {
jumper_category_text.translationY = -(category_hopper_frame.y - (view.height - insetBottom)) jumper_category_text.translationY = -(category_hopper_frame.y - (view.height - insetBottom))
} else { } else {
jumper_category_text.translationY = 0f jumper_category_text.translationY = 0f
} }
} }
fun resetHopperY() { fun resetHopperY() {
hopperOffset = 0f hopperOffset = 0f
} }
@ -821,10 +820,11 @@ class LibraryController(
) )
} }
adapter.setItems(mangaMap) adapter.setItems(mangaMap)
if (recycler.itemAnimator == null) if (recycler.itemAnimator == null) {
recycler.post { recycler.post {
recycler.itemAnimator = DefaultItemAnimator() recycler.itemAnimator = DefaultItemAnimator()
} }
}
singleCategory = presenter.categories.size <= 1 singleCategory = presenter.categories.size <= 1
showDropdown() showDropdown()
progress.gone() progress.gone()

View File

@ -70,8 +70,9 @@ class LibraryGridHolder(
if (cover_thumbnail.height == 0) { if (cover_thumbnail.height == 0) {
val oldPos = adapterPosition val oldPos = adapterPosition
adapter.recyclerView.post { adapter.recyclerView.post {
if (oldPos == adapterPosition) if (oldPos == adapterPosition) {
setCover(item.manga) setCover(item.manga)
}
} }
} else setCover(item.manga) } else setCover(item.manga)
} }

View File

@ -44,8 +44,9 @@ abstract class LibraryHolder(
} }
fun setReadingButton(item: LibraryItem) { fun setReadingButton(item: LibraryItem) {
play_layout?.visibility = if (item.manga.unread > 0 && item.unreadType > 0 && !item.hideReadingButton) play_layout?.visibility = if (item.manga.unread > 0 && item.unreadType > 0 && !item.hideReadingButton) {
View.VISIBLE else View.GONE View.VISIBLE
} else View.GONE
} }
/** /**

View File

@ -46,10 +46,11 @@ class LibraryItem(
get() = preferences.hideStartReadingButton().getOrDefault() get() = preferences.hideStartReadingButton().getOrDefault()
override fun getLayoutRes(): Int { override fun getLayoutRes(): Int {
return if (libraryLayout == 0 || manga.isBlank()) return if (libraryLayout == 0 || manga.isBlank()) {
R.layout.manga_list_item R.layout.manga_list_item
else } else {
R.layout.manga_grid_item R.layout.manga_grid_item
}
} }
override fun createViewHolder(view: View, adapter: FlexibleAdapter<IFlexible<RecyclerView.ViewHolder>>): LibraryHolder { override fun createViewHolder(view: View, adapter: FlexibleAdapter<IFlexible<RecyclerView.ViewHolder>>): LibraryHolder {
@ -141,11 +142,13 @@ class LibraryItem(
* @return true if the manga should be included, false otherwise. * @return true if the manga should be included, false otherwise.
*/ */
override fun filter(constraint: String): Boolean { override fun filter(constraint: String): Boolean {
if (manga.isBlank() && manga.title.isBlank()) if (manga.isBlank() && manga.title.isBlank()) {
return constraint.isEmpty() return constraint.isEmpty()
}
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.title.contains(constraint, true) || return manga.title.contains(constraint, true) ||
(manga.author?.contains(constraint, true) ?: false) || (manga.author?.contains(constraint, true) ?: false) ||
(manga.artist?.contains(constraint, true) ?: false) || (manga.artist?.contains(constraint, true) ?: false) ||
@ -159,14 +162,15 @@ class LibraryItem(
@SuppressLint("DefaultLocale") @SuppressLint("DefaultLocale")
private fun containsGenre(tag: String, genres: List<String>?): Boolean { private fun containsGenre(tag: String, genres: List<String>?): Boolean {
if (tag.trim().isEmpty()) return true if (tag.trim().isEmpty()) return true
return if (tag.startsWith("-")) return if (tag.startsWith("-")) {
genres?.find { genres?.find {
it.trim().toLowerCase() == tag.substringAfter("-").toLowerCase() it.trim().toLowerCase() == tag.substringAfter("-").toLowerCase()
} == null } == null
else } else {
genres?.find { genres?.find {
it.trim().toLowerCase() == tag.toLowerCase() it.trim().toLowerCase() == tag.toLowerCase()
} != null } != null
}
} }
override fun equals(other: Any?): Boolean { override fun equals(other: Any?): Boolean {

View File

@ -36,7 +36,6 @@ class LibraryListHolder(
* @param item the manga item to bind. * @param item the manga item to bind.
*/ */
override fun onSetValues(item: LibraryItem) { override fun onSetValues(item: LibraryItem) {
title.visible() title.visible()
constraint_layout.minHeight = 56.dpToPx constraint_layout.minHeight = 56.dpToPx
if (item.manga.isBlank()) { if (item.manga.isBlank()) {
@ -47,8 +46,9 @@ class LibraryListHolder(
if (item.manga.status == -1) { if (item.manga.status == -1) {
title.text = null title.text = null
title.gone() title.gone()
} else } else {
title.text = itemView.context.getString(R.string.category_is_empty) title.text = itemView.context.getString(R.string.category_is_empty)
}
title.textAlignment = View.TEXT_ALIGNMENT_CENTER title.textAlignment = View.TEXT_ALIGNMENT_CENTER
card.gone() card.gone()
badge_view.gone() badge_view.gone()

View File

@ -729,8 +729,9 @@ class LibraryPresenter(
db.resetMangaInfo(manga).executeOnIO() db.resetMangaInfo(manga).executeOnIO()
coverCache.deleteFromCache(manga) coverCache.deleteFromCache(manga)
val source = sourceManager.get(manga.source) as? HttpSource val source = sourceManager.get(manga.source) as? HttpSource
if (source != null) if (source != null) {
downloadManager.deleteManga(manga, source) downloadManager.deleteManga(manga, source)
}
} }
} }
} }
@ -825,9 +826,10 @@ class LibraryPresenter(
val mc = ArrayList<MangaCategory>() val mc = ArrayList<MangaCategory>()
val categories = val categories =
if (catId == 0) emptyList() if (catId == 0) emptyList()
else else {
db.getCategoriesForManga(manga).executeOnIO() db.getCategoriesForManga(manga).executeOnIO()
.filter { it.id != oldCatId } + listOf(category) .filter { it.id != oldCatId } + listOf(category)
}
for (cat in categories) { for (cat in categories) {
mc.add(MangaCategory.create(manga, cat)) mc.add(MangaCategory.create(manga, cat))
@ -858,10 +860,11 @@ class LibraryPresenter(
val categoriesHidden = preferences.collapsedCategories().getOrDefault().mapNotNull { val categoriesHidden = preferences.collapsedCategories().getOrDefault().mapNotNull {
it.toIntOrNull() it.toIntOrNull()
}.toMutableSet() }.toMutableSet()
if (categoryId in categoriesHidden) if (categoryId in categoriesHidden) {
categoriesHidden.remove(categoryId) categoriesHidden.remove(categoryId)
else } else {
categoriesHidden.add(categoryId) categoriesHidden.add(categoryId)
}
preferences.collapsedCategories().set(categoriesHidden.map { it.toString() }.toMutableSet()) preferences.collapsedCategories().set(categoriesHidden.map { it.toString() }.toMutableSet())
getLibrary() getLibrary()
} }

View File

@ -47,8 +47,9 @@ class CategoryRecyclerView @JvmOverloads constructor(
} }
) )
fastAdapter.onClickListener = { _, _, item, _ -> fastAdapter.onClickListener = { _, _, item, _ ->
if (item.category.id != -1) if (item.category.id != -1) {
onCategoryClicked(item.category.order) onCategoryClicked(item.category.order)
}
true true
} }
} }

View File

@ -11,7 +11,7 @@ import eu.kanade.tachiyomi.util.view.withFadeTransaction
import eu.kanade.tachiyomi.widget.TabbedBottomSheetDialog import eu.kanade.tachiyomi.widget.TabbedBottomSheetDialog
import kotlinx.android.synthetic.main.tabbed_bottom_sheet.* import kotlinx.android.synthetic.main.tabbed_bottom_sheet.*
open class TabbedLibraryDisplaySheet(controller: LibraryController): open class TabbedLibraryDisplaySheet(controller: LibraryController) :
TabbedBottomSheetDialog(controller.activity!!) { TabbedBottomSheetDialog(controller.activity!!) {
private val displayView: LibraryDisplayView = inflate(controller.activity!!, R.layout.library_display_layout, null) as LibraryDisplayView private val displayView: LibraryDisplayView = inflate(controller.activity!!, R.layout.library_display_layout, null) as LibraryDisplayView
@ -26,10 +26,12 @@ open class TabbedLibraryDisplaySheet(controller: LibraryController):
if (android.os.Build.VERSION.SDK_INT >= android.os.Build.VERSION_CODES.O) { if (android.os.Build.VERSION.SDK_INT >= android.os.Build.VERSION_CODES.O) {
menu.tooltipText = context.getString(R.string.more_library_settings) menu.tooltipText = context.getString(R.string.more_library_settings)
} }
menu.setImageDrawable(ContextCompat.getDrawable( menu.setImageDrawable(
context, ContextCompat.getDrawable(
R.drawable.ic_settings_24dp context,
)) R.drawable.ic_settings_24dp
)
)
menu.setOnClickListener { menu.setOnClickListener {
controller.router.pushController(SettingsLibraryController().withFadeTransaction()) controller.router.pushController(SettingsLibraryController().withFadeTransaction())
dismiss() dismiss()

View File

@ -90,8 +90,9 @@ class FilterBottomSheet @JvmOverloads constructor(context: Context, attrs: Attri
list.add(unread) list.add(unread)
list.add(downloaded) list.add(downloaded)
list.add(completed) list.add(completed)
if (hasTracking) if (hasTracking) {
tracked?.let { list.add(it) } tracked?.let { list.add(it) }
}
list list
} }
@ -152,8 +153,9 @@ class FilterBottomSheet @JvmOverloads constructor(context: Context, attrs: Attri
} }
val activeFilters = hasActiveFiltersFromPref() val activeFilters = hasActiveFiltersFromPref()
if (activeFilters && sheetBehavior.isHidden() && sheetBehavior?.skipCollapsed == false) if (activeFilters && sheetBehavior.isHidden() && sheetBehavior?.skipCollapsed == false) {
sheetBehavior?.collapse() sheetBehavior?.collapse()
}
post { post {
updateRootPadding( updateRootPadding(
@ -218,10 +220,11 @@ class FilterBottomSheet @JvmOverloads constructor(context: Context, attrs: Attri
?: if (sheetBehavior.isExpanded()) 1f else 0f ?: if (sheetBehavior.isExpanded()) 1f else 0f
val percent = (trueProgress * 100).roundToInt() val percent = (trueProgress * 100).roundToInt()
val value = (percent * (maxHeight - minHeight) / 100) + minHeight val value = (percent * (maxHeight - minHeight) / 100) + minHeight
if (trueProgress >= 0) if (trueProgress >= 0) {
libraryRecyler?.updatePaddingRelative(bottom = value + 10.dpToPx + bottomBarHeight) libraryRecyler?.updatePaddingRelative(bottom = value + 10.dpToPx + bottomBarHeight)
else } else {
libraryRecyler?.updatePaddingRelative(bottom = (minHeight * (1 + trueProgress)).toInt() + bottomBarHeight) libraryRecyler?.updatePaddingRelative(bottom = (minHeight * (1 + trueProgress)).toInt() + bottomBarHeight)
}
} }
fun hasActiveFilters() = filterItems.any { it.isActivated } fun hasActiveFilters() = filterItems.any { it.isActivated }
@ -235,7 +238,6 @@ class FilterBottomSheet @JvmOverloads constructor(context: Context, attrs: Attri
} }
private fun createTags() { private fun createTags() {
downloaded = inflate(R.layout.filter_buttons) as FilterTagGroup downloaded = inflate(R.layout.filter_buttons) as FilterTagGroup
downloaded.setup(this, R.string.downloaded, R.string.not_downloaded) downloaded.setup(this, R.string.downloaded, R.string.not_downloaded)
@ -372,8 +374,9 @@ class FilterBottomSheet @JvmOverloads constructor(context: Context, attrs: Attri
fun manageFilterPopup() { fun manageFilterPopup() {
val recycler = RecyclerView(context) val recycler = RecyclerView(context)
if (filterOrder.count() != 6) if (filterOrder.count() != 6) {
filterOrder = "urdcmt" filterOrder = "urdcmt"
}
val adapter = FlexibleAdapter( val adapter = FlexibleAdapter(
filterOrder.toCharArray().map(::ManageFilterItem), filterOrder.toCharArray().map(::ManageFilterItem),
this, this,
@ -493,8 +496,9 @@ class FilterBottomSheet @JvmOverloads constructor(context: Context, attrs: Attri
private fun reSortViews() { private fun reSortViews() {
filter_layout.removeAllViews() filter_layout.removeAllViews()
if (filterItems.any { it.isActivated }) if (filterItems.any { it.isActivated }) {
filter_layout.addView(clearButton) filter_layout.addView(clearButton)
}
filterItems.filter { it.isActivated }.forEach { filterItems.filter { it.isActivated }.forEach {
filter_layout.addView(it) filter_layout.addView(it)
} }

View File

@ -84,8 +84,9 @@ class FilterTagGroup@JvmOverloads constructor(context: Context, attrs: Attribute
private fun toggleButton(index: Int, callBack: Boolean = true) { private fun toggleButton(index: Int, callBack: Boolean = true) {
if (index < 0 || itemCount == 0 || if (index < 0 || itemCount == 0 ||
(isActivated && index != buttons.indexOfFirst { it.isActivated }) (isActivated && index != buttons.indexOfFirst { it.isActivated })
) ) {
return return
}
if (callBack) { if (callBack) {
val transition = androidx.transition.AutoTransition() val transition = androidx.transition.AutoTransition()
transition.duration = 150 transition.duration = 150

View File

@ -268,7 +268,6 @@ open class MainActivity : BaseActivity(), DownloadServiceListener {
container: ViewGroup, container: ViewGroup,
handler: ControllerChangeHandler handler: ControllerChangeHandler
) { ) {
syncActivityViewWithController(to, from, isPush) syncActivityViewWithController(to, from, isPush)
appbar.y = 0f appbar.y = 0f
bottom_nav.translationY = 0f bottom_nav.translationY = 0f
@ -318,9 +317,9 @@ open class MainActivity : BaseActivity(), DownloadServiceListener {
window.navigationBarColor = if (Build.VERSION.SDK_INT < Build.VERSION_CODES.O_MR1) { window.navigationBarColor = if (Build.VERSION.SDK_INT < Build.VERSION_CODES.O_MR1) {
// basically if in landscape on a phone // basically if in landscape on a phone
// For lollipop, draw opaque nav bar // For lollipop, draw opaque nav bar
if (insets.hasSideNavBar()) if (insets.hasSideNavBar()) {
Color.BLACK Color.BLACK
else Color.argb(179, 0, 0, 0) } else Color.argb(179, 0, 0, 0)
} }
// if the android q+ device has gesture nav, transparent nav bar // if the android q+ device has gesture nav, transparent nav bar
// this is here in case some crazy with a notch uses landscape // this is here in case some crazy with a notch uses landscape
@ -515,10 +514,10 @@ open class MainActivity : BaseActivity(), DownloadServiceListener {
else !router.handleBack() else !router.handleBack()
) { ) {
if (preferences.backReturnsToStart().get() && this !is SearchActivity && if (preferences.backReturnsToStart().get() && this !is SearchActivity &&
startingTab() != bottom_nav?.selectedItemId) { startingTab() != bottom_nav?.selectedItemId
) {
goToStartingTab() goToStartingTab()
} } else {
else {
if (!preferences.backReturnsToStart().get() && this !is SearchActivity) { if (!preferences.backReturnsToStart().get() && this !is SearchActivity) {
setStartingTab() setStartingTab()
} }
@ -529,13 +528,17 @@ open class MainActivity : BaseActivity(), DownloadServiceListener {
} }
private fun setStartingTab() { private fun setStartingTab() {
if (bottom_nav?.selectedItemId != R.id.nav_browse if (bottom_nav?.selectedItemId != R.id.nav_browse &&
&& bottom_nav?.selectedItemId != null bottom_nav?.selectedItemId != null &&
&& preferences.startingTab().get() >= 0) preferences.startingTab().get() >= 0
preferences.startingTab().set(when (bottom_nav?.selectedItemId) { ) {
R.id.nav_library -> 0 preferences.startingTab().set(
else -> 1 when (bottom_nav?.selectedItemId) {
}) R.id.nav_library -> 0
else -> 1
}
)
}
} }
@IdRes @IdRes

View File

@ -69,8 +69,9 @@ class EditMangaDialog : DialogController {
val isLocal = manga.source == LocalSource.ID val isLocal = manga.source == LocalSource.ID
if (isLocal) { if (isLocal) {
if (manga.title != manga.url) if (manga.title != manga.url) {
view.title.append(manga.title) view.title.append(manga.title)
}
view.title.hint = "${resources?.getString(R.string.title)}: ${manga.url}" view.title.hint = "${resources?.getString(R.string.title)}: ${manga.url}"
view.manga_author.append(manga.author ?: "") view.manga_author.append(manga.author ?: "")
view.manga_artist.append(manga.artist ?: "") view.manga_artist.append(manga.artist ?: "")

View File

@ -434,8 +434,9 @@ class MangaDetailsController :
setActionBar(true) setActionBar(true)
setStatusBarAndToolbar() setStatusBarAndToolbar()
} else if (type == ControllerChangeType.PUSH_EXIT || type == ControllerChangeType.POP_EXIT) { } else if (type == ControllerChangeType.PUSH_EXIT || type == ControllerChangeType.POP_EXIT) {
if (router.backstack.lastOrNull()?.controller() is DialogController) if (router.backstack.lastOrNull()?.controller() is DialogController) {
return return
}
if (type == ControllerChangeType.POP_EXIT) { if (type == ControllerChangeType.POP_EXIT) {
setActionBar(false) setActionBar(false)
presenter.cancelScope() presenter.cancelScope()
@ -1042,10 +1043,11 @@ class MangaDetailsController :
if (chapter.status != Download.NOT_DOWNLOADED && chapter.status != Download.ERROR) { if (chapter.status != Download.NOT_DOWNLOADED && chapter.status != Download.ERROR) {
presenter.deleteChapter(chapter) presenter.deleteChapter(chapter)
} else { } else {
if (chapter.status == Download.ERROR) if (chapter.status == Download.ERROR) {
DownloadService.start(view.context) DownloadService.start(view.context)
else } else {
downloadChapters(listOf(chapter)) downloadChapters(listOf(chapter))
}
} }
} }
@ -1279,8 +1281,9 @@ class MangaDetailsController :
override fun onPrepareActionMode(mode: ActionMode?, menu: Menu?): Boolean { override fun onPrepareActionMode(mode: ActionMode?, menu: Menu?): Boolean {
mode?.title = view?.context?.getString( mode?.title = view?.context?.getString(
if (startingDLChapterPos == null) if (startingDLChapterPos == null) {
R.string.select_starting_chapter else R.string.select_ending_chapter R.string.select_starting_chapter
} else R.string.select_ending_chapter
) )
return false return false
} }

View File

@ -4,7 +4,6 @@ import android.app.Application
import android.graphics.Bitmap import android.graphics.Bitmap
import android.net.Uri import android.net.Uri
import android.os.Environment import android.os.Environment
import coil.Coil
import eu.kanade.tachiyomi.R import eu.kanade.tachiyomi.R
import eu.kanade.tachiyomi.data.cache.CoverCache import eu.kanade.tachiyomi.data.cache.CoverCache
import eu.kanade.tachiyomi.data.database.DatabaseHelper import eu.kanade.tachiyomi.data.database.DatabaseHelper
@ -88,7 +87,6 @@ class MangaDetailsPresenter(
var headerItem = MangaHeaderItem(manga, controller.fromCatalogue) var headerItem = MangaHeaderItem(manga, controller.fromCatalogue)
fun onCreate() { fun onCreate() {
isLockedFromSearch = SecureActivityDelegate.shouldBeLocked() isLockedFromSearch = SecureActivityDelegate.shouldBeLocked()
headerItem.isLocked = isLockedFromSearch headerItem.isLocked = isLockedFromSearch
downloadManager.addListener(this) downloadManager.addListener(this)
@ -218,8 +216,9 @@ class MangaDetailsPresenter(
* @return an observable of the list of chapters filtered and sorted. * @return an observable of the list of chapters filtered and sorted.
*/ */
private fun applyChapterFilters(chapterList: List<ChapterItem>): List<ChapterItem> { private fun applyChapterFilters(chapterList: List<ChapterItem>): List<ChapterItem> {
if (isLockedFromSearch) if (isLockedFromSearch) {
return chapterList return chapterList
}
val chapters = chapterFilter.filterChapters(chapterList, manga) val chapters = chapterFilter.filterChapters(chapterList, manga)
@ -357,8 +356,8 @@ class MangaDetailsPresenter(
if (newChapters.first.isNotEmpty()) { if (newChapters.first.isNotEmpty()) {
if (manga.shouldDownloadNewChapters(db, preferences)) { if (manga.shouldDownloadNewChapters(db, preferences)) {
downloadChapters( downloadChapters(
newChapters.first.sortedBy { it.chapter_number } newChapters.first.sortedBy { it.chapter_number }
.map { it.toModel() } .map { it.toModel() }
) )
} }
} }
@ -867,8 +866,9 @@ class MangaDetailsPresenter(
fun setStatus(item: TrackItem, index: Int) { fun setStatus(item: TrackItem, index: Int) {
val track = item.track!! val track = item.track!!
track.status = item.service.getStatusList()[index] track.status = item.service.getStatusList()[index]
if (item.service.isCompletedStatus(index) && track.total_chapters > 0) if (item.service.isCompletedStatus(index) && track.total_chapters > 0) {
track.last_chapter_read = track.total_chapters track.last_chapter_read = track.total_chapters
}
updateRemote(track, item.service) updateRemote(track, item.service)
} }

View File

@ -70,8 +70,8 @@ class MangaHeaderHolder(
} }
if (event.actionMasked == MotionEvent.ACTION_UP) { if (event.actionMasked == MotionEvent.ACTION_UP) {
hadSelection = manga_summary.hasSelection() hadSelection = manga_summary.hasSelection()
(adapter.delegate as MangaDetailsController).swipe_refresh.isEnabled = (adapter.delegate as MangaDetailsController).swipe_refresh.isEnabled =
true true
} }
false false
} }
@ -320,9 +320,9 @@ class MangaHeaderHolder(
fun collapse() { fun collapse() {
sub_item_group.gone() sub_item_group.gone()
start_reading_button.gone() start_reading_button.gone()
if (more_button.visibility == View.VISIBLE || more_button.visibility == View.INVISIBLE) if (more_button.visibility == View.VISIBLE || more_button.visibility == View.INVISIBLE) {
more_button_group.invisible() more_button_group.invisible()
else { } else {
less_button.gone() less_button.gone()
manga_genres_tags.gone() manga_genres_tags.gone()
} }

View File

@ -40,10 +40,11 @@ class ChaptersSortBottomSheet(controller: MangaDetailsController) : BottomSheetD
sheetBehavior.addBottomSheetCallback( sheetBehavior.addBottomSheetCallback(
object : BottomSheetBehavior.BottomSheetCallback() { object : BottomSheetBehavior.BottomSheetCallback() {
override fun onSlide(bottomSheet: View, progress: Float) { override fun onSlide(bottomSheet: View, progress: Float) {
if (progress.isNaN()) if (progress.isNaN()) {
pill.alpha = 0f pill.alpha = 0f
else } else {
pill.alpha = (1 - max(0f, progress)) * 0.25f pill.alpha = (1 - max(0f, progress)) * 0.25f
}
} }
override fun onStateChanged(p0: View, state: Int) { override fun onStateChanged(p0: View, state: Int) {
@ -92,14 +93,16 @@ class ChaptersSortBottomSheet(controller: MangaDetailsController) : BottomSheetD
var defPref = presenter.globalSort() var defPref = presenter.globalSort()
sort_group.check( sort_group.check(
if (presenter.manga.sortDescending(defPref)) R.id.sort_newest else if (presenter.manga.sortDescending(defPref)) R.id.sort_newest else {
R.id.sort_oldest R.id.sort_oldest
}
) )
hide_titles.isChecked = presenter.manga.displayMode != Manga.DISPLAY_NAME hide_titles.isChecked = presenter.manga.displayMode != Manga.DISPLAY_NAME
sort_method_group.check( sort_method_group.check(
if (presenter.manga.sorting == Manga.SORTING_SOURCE) R.id.sort_by_source else if (presenter.manga.sorting == Manga.SORTING_SOURCE) R.id.sort_by_source else {
R.id.sort_by_number R.id.sort_by_number
}
) )
set_as_default_sort.visInvisIf( set_as_default_sort.visInvisIf(

View File

@ -70,12 +70,14 @@ class SetTrackReadingDatesDialog<T> : DialogController
listener.setReadingDate(item, dateToUpdate, 0L) listener.setReadingDate(item, dateToUpdate, 0L)
}.apply { }.apply {
getSuggestedDate()?.let { getSuggestedDate()?.let {
message(text = it, message(
applySettings = { text = it,
messageTextView.setOnClickListener { applySettings = {
this@apply.setDate(suggestedDate ?: 0L) messageTextView.setOnClickListener {
this@apply.setDate(suggestedDate ?: 0L)
}
} }
}) )
} }
} }
} }
@ -93,9 +95,11 @@ class SetTrackReadingDatesDialog<T> : DialogController
val suggestedCalendar = Calendar.getInstance() val suggestedCalendar = Calendar.getInstance()
suggestedCalendar.timeInMillis = suggestedDate suggestedCalendar.timeInMillis = suggestedDate
return if (date > suggestedDate && return if (date > suggestedDate &&
(suggestedCalendar.year != calendar.year || (
suggestedCalendar.month != calendar.month || suggestedCalendar.year != calendar.year ||
suggestedCalendar.dayOfMonth != calendar.dayOfMonth) suggestedCalendar.month != calendar.month ||
suggestedCalendar.dayOfMonth != calendar.dayOfMonth
)
) { ) {
activity?.getString( activity?.getString(
R.string.suggested_date_, R.string.suggested_date_,

View File

@ -72,9 +72,9 @@ class TrackHolder(view: View, adapter: TrackAdapter) : BaseViewHolder(view) {
date_group.visibleIf(item.service.supportsReadingDates) date_group.visibleIf(item.service.supportsReadingDates)
if (item.service.supportsReadingDates) { if (item.service.supportsReadingDates) {
track_start_date.text = track_start_date.text =
if (track.started_reading_date != 0L) dateFormat.format(track.started_reading_date) else "-" if (track.started_reading_date != 0L) dateFormat.format(track.started_reading_date) else "-"
track_finish_date.text = track_finish_date.text =
if (track.finished_reading_date != 0L) dateFormat.format(track.finished_reading_date) else "-" if (track.finished_reading_date != 0L) dateFormat.format(track.finished_reading_date) else "-"
} else { } else {
} }
} }

View File

@ -1,8 +1,6 @@
package eu.kanade.tachiyomi.ui.manga.track package eu.kanade.tachiyomi.ui.manga.track
import android.content.Intent import android.content.Intent
import android.graphics.Color
import android.graphics.drawable.ColorDrawable
import android.os.Bundle import android.os.Bundle
import android.view.View import android.view.View
import android.view.ViewGroup import android.view.ViewGroup
@ -190,11 +188,13 @@ class TrackingBottomSheet(private val controller: MangaDetailsController) :
if (item.track == null) return if (item.track == null) return
val suggestedDate = presenter.getSuggestedDate(SetTrackReadingDatesDialog.ReadingDate.Start) val suggestedDate = presenter.getSuggestedDate(SetTrackReadingDatesDialog.ReadingDate.Start)
SetTrackReadingDatesDialog(controller, SetTrackReadingDatesDialog(
controller,
this, this,
SetTrackReadingDatesDialog.ReadingDate.Start, SetTrackReadingDatesDialog.ReadingDate.Start,
item, item,
suggestedDate) suggestedDate
)
.showDialog(controller.router) .showDialog(controller.router)
} }
@ -203,11 +203,13 @@ class TrackingBottomSheet(private val controller: MangaDetailsController) :
if (item.track == null) return if (item.track == null) return
val suggestedDate = presenter.getSuggestedDate(SetTrackReadingDatesDialog.ReadingDate.Finish) val suggestedDate = presenter.getSuggestedDate(SetTrackReadingDatesDialog.ReadingDate.Finish)
SetTrackReadingDatesDialog(controller, SetTrackReadingDatesDialog(
controller,
this, this,
SetTrackReadingDatesDialog.ReadingDate.Finish, SetTrackReadingDatesDialog.ReadingDate.Finish,
item, item,
suggestedDate) suggestedDate
)
.showDialog(controller.router) .showDialog(controller.router)
} }
@ -257,5 +259,4 @@ class TrackingBottomSheet(private val controller: MangaDetailsController) :
private companion object { private companion object {
const val TAG_SEARCH_CONTROLLER = "track_search_controller" const val TAG_SEARCH_CONTROLLER = "track_search_controller"
} }
} }

View File

@ -24,7 +24,6 @@ class MangaItem(val manga: Manga) : AbstractFlexibleItem<MangaHolder>() {
position: Int, position: Int,
payloads: MutableList<Any?>? payloads: MutableList<Any?>?
) { ) {
holder.bind(this) holder.bind(this)
} }

View File

@ -93,7 +93,6 @@ class MigrationPresenter(
manga: Manga, manga: Manga,
replace: Boolean replace: Boolean
) { ) {
val flags = preferences.migrateFlags().getOrDefault() val flags = preferences.migrateFlags().getOrDefault()
val migrateChapters = MigrationFlags.hasChapters(flags) val migrateChapters = MigrationFlags.hasChapters(flags)
val migrateCategories = MigrationFlags.hasCategories(flags) val migrateCategories = MigrationFlags.hasCategories(flags)

View File

@ -42,8 +42,9 @@ class SearchController(
override fun getTitle(): String? { override fun getTitle(): String? {
if (totalProgress > 1) { if (totalProgress > 1) {
return "($progress/$totalProgress) ${super.getTitle()}" return "($progress/$totalProgress) ${super.getTitle()}"
} else } else {
return super.getTitle() return super.getTitle()
}
} }
override fun createPresenter(): GlobalSearchPresenter { override fun createPresenter(): GlobalSearchPresenter {

View File

@ -40,7 +40,6 @@ data class SourceItem(val source: Source, val header: SelectionHeader? = null) :
position: Int, position: Int,
payloads: MutableList<Any?>? payloads: MutableList<Any?>?
) { ) {
holder.bind(this) holder.bind(this)
} }
} }

View File

@ -3,7 +3,6 @@ package eu.kanade.tachiyomi.ui.migration.manga.design
import android.graphics.Paint.STRIKE_THRU_TEXT_FLAG import android.graphics.Paint.STRIKE_THRU_TEXT_FLAG
import android.view.View import android.view.View
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.source.icon import eu.kanade.tachiyomi.source.icon
import eu.kanade.tachiyomi.source.online.HttpSource import eu.kanade.tachiyomi.source.online.HttpSource
import eu.kanade.tachiyomi.ui.base.holder.BaseFlexibleViewHolder import eu.kanade.tachiyomi.ui.base.holder.BaseFlexibleViewHolder

View File

@ -15,7 +15,6 @@ import com.google.android.material.bottomsheet.BottomSheetDialog
import eu.davidea.flexibleadapter.FlexibleAdapter import eu.davidea.flexibleadapter.FlexibleAdapter
import eu.kanade.tachiyomi.R import eu.kanade.tachiyomi.R
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.source.SourceManager import eu.kanade.tachiyomi.source.SourceManager
import eu.kanade.tachiyomi.source.online.HttpSource import eu.kanade.tachiyomi.source.online.HttpSource
import eu.kanade.tachiyomi.ui.base.controller.BaseController import eu.kanade.tachiyomi.ui.base.controller.BaseController

View File

@ -54,7 +54,6 @@ import kotlinx.coroutines.launch
import kotlinx.coroutines.sync.Semaphore import kotlinx.coroutines.sync.Semaphore
import kotlinx.coroutines.sync.withPermit import kotlinx.coroutines.sync.withPermit
import kotlinx.coroutines.withContext import kotlinx.coroutines.withContext
import rx.schedulers.Schedulers
import timber.log.Timber import timber.log.Timber
import uy.kohesive.injekt.injectLazy import uy.kohesive.injekt.injectLazy
import java.util.concurrent.atomic.AtomicInteger import java.util.concurrent.atomic.AtomicInteger
@ -99,7 +98,6 @@ class MigrationListController(bundle: Bundle? = null) :
} }
override fun onViewCreated(view: View) { override fun onViewCreated(view: View) {
super.onViewCreated(view) super.onViewCreated(view)
liftAppbarWith(recycler) liftAppbarWith(recycler)
setTitle() setTitle()
@ -324,7 +322,6 @@ class MigrationListController(bundle: Bundle? = null) :
} }
override fun onMenuItemClick(position: Int, item: MenuItem) { override fun onMenuItemClick(position: Int, item: MenuItem) {
when (item.itemId) { when (item.itemId) {
R.id.action_search_manually -> { R.id.action_search_manually -> {
launchUI { launchUI {
@ -377,7 +374,7 @@ class MigrationListController(bundle: Bundle? = null) :
try { try {
val newManga = val newManga =
sourceManager.getOrStub(result.source).getMangaDetails(result.toMangaInfo()) sourceManager.getOrStub(result.source).getMangaDetails(result.toMangaInfo())
.toSManga() .toSManga()
result.copyFrom(newManga) result.copyFrom(newManga)
db.insertManga(result).executeAsBlocking() db.insertManga(result).executeAsBlocking()

View File

@ -33,7 +33,6 @@ import eu.kanade.tachiyomi.data.database.models.Chapter
import eu.kanade.tachiyomi.data.database.models.Manga import eu.kanade.tachiyomi.data.database.models.Manga
import eu.kanade.tachiyomi.data.preference.PreferencesHelper import eu.kanade.tachiyomi.data.preference.PreferencesHelper
import eu.kanade.tachiyomi.source.model.Page import eu.kanade.tachiyomi.source.model.Page
import eu.kanade.tachiyomi.ui.base.MaterialMenuSheet
import eu.kanade.tachiyomi.ui.base.activity.BaseRxActivity import eu.kanade.tachiyomi.ui.base.activity.BaseRxActivity
import eu.kanade.tachiyomi.ui.main.MainActivity import eu.kanade.tachiyomi.ui.main.MainActivity
import eu.kanade.tachiyomi.ui.main.SearchActivity import eu.kanade.tachiyomi.ui.main.SearchActivity
@ -283,8 +282,10 @@ class ReaderActivity :
override fun onPrepareOptionsMenu(menu: Menu?): Boolean { override fun onPrepareOptionsMenu(menu: Menu?): Boolean {
val detailsItem = menu?.findItem(R.id.action_manga_details) val detailsItem = menu?.findItem(R.id.action_manga_details)
if (presenter.manga?.mangaType(this) != null) { if (presenter.manga?.mangaType(this) != null) {
detailsItem?.title = getString(R.string._details, detailsItem?.title = getString(
presenter.manga?.mangaType(this)?.capitalize(Locale.ROOT) ?: "") R.string._details,
presenter.manga?.mangaType(this)?.capitalize(Locale.ROOT) ?: ""
)
} else { } else {
detailsItem?.title = getString(R.string.details) detailsItem?.title = getString(R.string.details)
} }
@ -798,7 +799,6 @@ class ReaderActivity :
*/ */
private fun setNotchCutoutMode() { private fun setNotchCutoutMode() {
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.P) { if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.P) {
val currentOrientation = resources.configuration.orientation val currentOrientation = resources.configuration.orientation
val params = window.attributes val params = window.attributes
@ -941,10 +941,11 @@ class ReaderActivity :
* Sets the 32-bit color mode according to [enabled]. * Sets the 32-bit color mode according to [enabled].
*/ */
private fun setTrueColor(enabled: Boolean) { private fun setTrueColor(enabled: Boolean) {
if (enabled) if (enabled) {
SubsamplingScaleImageView.setPreferredBitmapConfig(Bitmap.Config.ARGB_8888) SubsamplingScaleImageView.setPreferredBitmapConfig(Bitmap.Config.ARGB_8888)
else } else {
SubsamplingScaleImageView.setPreferredBitmapConfig(Bitmap.Config.RGB_565) SubsamplingScaleImageView.setPreferredBitmapConfig(Bitmap.Config.RGB_565)
}
} }
/** /**

View File

@ -38,7 +38,6 @@ class SaveImageNotifier(private val context: Context) {
* @param file image file containing downloaded page image. * @param file image file containing downloaded page image.
*/ */
fun onComplete(file: File) { fun onComplete(file: File) {
val request = LoadRequest.Builder(context).memoryCachePolicy(CachePolicy.DISABLED).diskCachePolicy(CachePolicy.DISABLED) val request = LoadRequest.Builder(context).memoryCachePolicy(CachePolicy.DISABLED).diskCachePolicy(CachePolicy.DISABLED)
.data(file) .data(file)
.size(720, 1280) .size(720, 1280)
@ -64,8 +63,9 @@ class SaveImageNotifier(private val context: Context) {
setAutoCancel(true) setAutoCancel(true)
color = ContextCompat.getColor(context, R.color.colorAccent) color = ContextCompat.getColor(context, R.color.colorAccent)
// Clear old actions if they exist // Clear old actions if they exist
if (mActions.isNotEmpty()) if (mActions.isNotEmpty()) {
mActions.clear() mActions.clear()
}
setContentIntent(NotificationHandler.openImagePendingActivity(context, file)) setContentIntent(NotificationHandler.openImagePendingActivity(context, file))
// Share action // Share action

View File

@ -192,10 +192,11 @@ class HttpPageLoader(
* @param page the page whose source image has to be downloaded. * @param page the page whose source image has to be downloaded.
*/ */
private fun HttpSource.fetchImageFromCacheThenNet(page: ReaderPage): Observable<ReaderPage> { private fun HttpSource.fetchImageFromCacheThenNet(page: ReaderPage): Observable<ReaderPage> {
return if (page.imageUrl.isNullOrEmpty()) return if (page.imageUrl.isNullOrEmpty()) {
getImageUrl(page).flatMap { getCachedImage(it) } getImageUrl(page).flatMap { getCachedImage(it) }
else } else {
getCachedImage(page) getCachedImage(page)
}
} }
private fun HttpSource.getImageUrl(page: ReaderPage): Observable<ReaderPage> { private fun HttpSource.getImageUrl(page: ReaderPage): Observable<ReaderPage> {

View File

@ -5,9 +5,7 @@ import android.util.AttributeSet
import android.widget.SeekBar import android.widget.SeekBar
import androidx.annotation.ColorInt import androidx.annotation.ColorInt
import eu.kanade.tachiyomi.ui.reader.ReaderActivity import eu.kanade.tachiyomi.ui.reader.ReaderActivity
import eu.kanade.tachiyomi.util.view.RecyclerWindowInsetsListener
import eu.kanade.tachiyomi.widget.BaseReaderSettingsView import eu.kanade.tachiyomi.widget.BaseReaderSettingsView
import eu.kanade.tachiyomi.widget.IgnoreFirstSpinnerListener
import eu.kanade.tachiyomi.widget.SimpleSeekBarListener import eu.kanade.tachiyomi.widget.SimpleSeekBarListener
import kotlinx.android.synthetic.main.reader_color_filter.* import kotlinx.android.synthetic.main.reader_color_filter.*
import kotlinx.android.synthetic.main.reader_color_filter.view.* import kotlinx.android.synthetic.main.reader_color_filter.view.*
@ -115,7 +113,6 @@ class ReaderFilterView @JvmOverloads constructor(context: Context, attrs: Attrib
) )
} }
/** /**
* Set enabled status of seekBars belonging to color filter * Set enabled status of seekBars belonging to color filter
* @param enabled determines if seekBar gets enabled * @param enabled determines if seekBar gets enabled
@ -202,7 +199,7 @@ class ReaderFilterView @JvmOverloads constructor(context: Context, attrs: Attrib
* Sets the color filter overlay of the screen. Determined by HEX of integer * Sets the color filter overlay of the screen. Determined by HEX of integer
* @param color hex of color. * @param color hex of color.
*/ */
private fun setColorFilterValue(@ColorInt color: Int) { private fun setColorFilterValue(@ColorInt color: Int) {
setValues(color) setValues(color)
} }

View File

@ -4,9 +4,7 @@ import android.content.Context
import android.util.AttributeSet import android.util.AttributeSet
import eu.kanade.tachiyomi.ui.reader.ReaderActivity import eu.kanade.tachiyomi.ui.reader.ReaderActivity
import eu.kanade.tachiyomi.util.bindToPreference import eu.kanade.tachiyomi.util.bindToPreference
import eu.kanade.tachiyomi.util.view.RecyclerWindowInsetsListener
import eu.kanade.tachiyomi.widget.BaseReaderSettingsView import eu.kanade.tachiyomi.widget.BaseReaderSettingsView
import eu.kanade.tachiyomi.widget.IgnoreFirstSpinnerListener
import kotlinx.android.synthetic.main.reader_general_layout.view.* import kotlinx.android.synthetic.main.reader_general_layout.view.*
class ReaderGeneralView @JvmOverloads constructor(context: Context, attrs: AttributeSet? = null) : class ReaderGeneralView @JvmOverloads constructor(context: Context, attrs: AttributeSet? = null) :

View File

@ -12,16 +12,14 @@ import com.tfcporciuncula.flow.Preference
import eu.kanade.tachiyomi.R import eu.kanade.tachiyomi.R
import kotlinx.android.synthetic.main.reader_preference.view.* import kotlinx.android.synthetic.main.reader_preference.view.*
class ReaderSpinnerView @JvmOverloads constructor(context: Context, attrs: AttributeSet?) : class ReaderSpinnerView @JvmOverloads constructor(context: Context, attrs: AttributeSet?) :
FrameLayout(context, attrs) { FrameLayout(context, attrs) {
private var entries = emptyList<String>() private var entries = emptyList<String>()
private var selectedPosition = 0 private var selectedPosition = 0
private var pref: Preference<Int>? = null private var pref: Preference<Int>? = null
private var prefOffset = 0 private var prefOffset = 0
private var popup:PopupMenu? = null private var popup: PopupMenu? = null
var onItemSelectedListener: ((Int) -> Unit)? = null var onItemSelectedListener: ((Int) -> Unit)? = null
set(value) { set(value) {
@ -159,7 +157,7 @@ class ReaderSpinnerView @JvmOverloads constructor(context: Context, attrs: Attri
fun popup(): PopupMenu { fun popup(): PopupMenu {
val popup = PopupMenu(context, this, Gravity.END) val popup = PopupMenu(context, this, Gravity.END)
entries.forEachIndexed { index, entry -> entries.forEachIndexed { index, entry ->
popup.menu.add(0, index, 0, entry) popup.menu.add(0, index, 0, entry)
} }
popup.menu[selectedPosition].isCheckable = true popup.menu[selectedPosition].isCheckable = true

View File

@ -1,22 +1,19 @@
package eu.kanade.tachiyomi.ui.reader.settings package eu.kanade.tachiyomi.ui.reader.settings
import android.view.View import android.view.View
import androidx.core.widget.NestedScrollView
import com.google.android.material.tabs.TabLayout import com.google.android.material.tabs.TabLayout
import eu.kanade.tachiyomi.R import eu.kanade.tachiyomi.R
import eu.kanade.tachiyomi.ui.library.display.LibraryBadgesView
import eu.kanade.tachiyomi.ui.reader.ReaderActivity import eu.kanade.tachiyomi.ui.reader.ReaderActivity
import eu.kanade.tachiyomi.util.view.gone import eu.kanade.tachiyomi.util.view.gone
import eu.kanade.tachiyomi.util.view.visInvisIf import eu.kanade.tachiyomi.util.view.visInvisIf
import eu.kanade.tachiyomi.util.view.visible import eu.kanade.tachiyomi.util.view.visible
import eu.kanade.tachiyomi.util.view.visibleIf
import eu.kanade.tachiyomi.widget.TabbedBottomSheetDialog import eu.kanade.tachiyomi.widget.TabbedBottomSheetDialog
import kotlinx.android.synthetic.main.reader_activity.* import kotlinx.android.synthetic.main.reader_activity.*
import kotlinx.android.synthetic.main.reader_color_filter.view.* import kotlinx.android.synthetic.main.reader_color_filter.view.*
import kotlinx.android.synthetic.main.recycler_with_scroller.view.* import kotlinx.android.synthetic.main.recycler_with_scroller.view.*
import kotlinx.android.synthetic.main.tabbed_bottom_sheet.* import kotlinx.android.synthetic.main.tabbed_bottom_sheet.*
class TabbedReaderSettingsSheet(val readerActivity: ReaderActivity): TabbedBottomSheetDialog( class TabbedReaderSettingsSheet(val readerActivity: ReaderActivity) : TabbedBottomSheetDialog(
readerActivity readerActivity
) { ) {
private val generalView: ReaderGeneralView = View.inflate( private val generalView: ReaderGeneralView = View.inflate(

View File

@ -27,7 +27,6 @@ abstract class ViewerConfig(preferences: PreferencesHelper) {
var volumeKeysInverted = false var volumeKeysInverted = false
var alwaysShowChapterTransition = true var alwaysShowChapterTransition = true
var navigationOverlayForNewUser = false var navigationOverlayForNewUser = false
var navigationMode = 0 var navigationMode = 0
protected set protected set

View File

@ -17,8 +17,7 @@ abstract class ViewerNavigation {
fun directionalRegion(LTR: Boolean): NavigationRegion { fun directionalRegion(LTR: Boolean): NavigationRegion {
return if (this === LEFT || this === RIGHT) { return if (this === LEFT || this === RIGHT) {
if (if (LTR) this === LEFT else this === RIGHT) NEXT else PREV if (if (LTR) this === LEFT else this === RIGHT) NEXT else PREV
} } else this
else this
} }
} }

View File

@ -45,9 +45,12 @@ class PagerConfig(private val viewer: PagerViewer, preferences: PreferencesHelpe
.register({ navigationMode = it }, { updateNavigation(navigationMode) }) .register({ navigationMode = it }, { updateNavigation(navigationMode) })
preferences.pagerNavInverted() preferences.pagerNavInverted()
.register({ tappingInverted = it }, { .register(
navigator.invertMode = it { tappingInverted = it },
}) {
navigator.invertMode = it
}
)
preferences.pagerNavInverted().asFlow() preferences.pagerNavInverted().asFlow()
.drop(1) .drop(1)

View File

@ -340,7 +340,6 @@ class PagerPageHolder(
@SuppressLint("PrivateResource") @SuppressLint("PrivateResource")
private fun createProgressBar(): ReaderProgressBar { private fun createProgressBar(): ReaderProgressBar {
return ReaderProgressBar(context, null).apply { return ReaderProgressBar(context, null).apply {
val size = 48.dpToPx val size = 48.dpToPx
layoutParams = LayoutParams(size, size).apply { layoutParams = LayoutParams(size, size).apply {
gravity = Gravity.CENTER gravity = Gravity.CENTER

View File

@ -24,6 +24,7 @@ class PagerViewerAdapter(private val viewer: PagerViewer) : ViewPagerAdapter() {
private set private set
var currentChapter: ReaderChapter? = null var currentChapter: ReaderChapter? = null
/** /**
* Updates this adapter with the given [chapters]. It handles setting a few pages of the * Updates this adapter with the given [chapters]. It handles setting a few pages of the
* next/previous chapter to allow seamless transitions and inverting the pages if the viewer * next/previous chapter to allow seamless transitions and inverting the pages if the viewer

View File

@ -22,6 +22,7 @@ class WebtoonAdapter(val viewer: WebtoonViewer) : RecyclerView.Adapter<RecyclerV
private set private set
var currentChapter: ReaderChapter? = null var currentChapter: ReaderChapter? = null
/** /**
* Updates this adapter with the given [chapters]. It handles setting a few pages of the * Updates this adapter with the given [chapters]. It handles setting a few pages of the
* next/previous chapter to allow seamless transitions. * next/previous chapter to allow seamless transitions.

View File

@ -37,9 +37,12 @@ class WebtoonConfig(preferences: PreferencesHelper = Injekt.get()) : ViewerConfi
.register({ navigationMode = it }, { updateNavigation(it) }) .register({ navigationMode = it }, { updateNavigation(it) })
preferences.webtoonNavInverted() preferences.webtoonNavInverted()
.register({ tappingInverted = it }, { .register(
navigator.invertMode = it { tappingInverted = it },
}) {
navigator.invertMode = it
}
)
preferences.webtoonNavInverted().asFlow() preferences.webtoonNavInverted().asFlow()
.drop(1) .drop(1)

View File

@ -42,12 +42,13 @@ class WebtoonLayoutManager(activity: ReaderActivity) : LinearLayoutManager(activ
val fromIndex = childCount - 1 val fromIndex = childCount - 1
val toIndex = -1 val toIndex = -1
val child = if (mOrientation == HORIZONTAL) val child = if (mOrientation == HORIZONTAL) {
mHorizontalBoundCheck mHorizontalBoundCheck
.findOneViewWithinBoundFlags(fromIndex, toIndex, preferredBoundsFlag, 0) .findOneViewWithinBoundFlags(fromIndex, toIndex, preferredBoundsFlag, 0)
else } else {
mVerticalBoundCheck mVerticalBoundCheck
.findOneViewWithinBoundFlags(fromIndex, toIndex, preferredBoundsFlag, 0) .findOneViewWithinBoundFlags(fromIndex, toIndex, preferredBoundsFlag, 0)
}
return if (child == null) NO_POSITION else getPosition(child) return if (child == null) NO_POSITION else getPosition(child)
} }

View File

@ -98,7 +98,7 @@ class WebtoonViewer(val activity: ReaderActivity, val hasMargins: Boolean = fals
} }
} }
) )
recycler.tapListener = f@{ event -> recycler.tapListener = f@{ event ->
if (!config.tappingEnabled) { if (!config.tappingEnabled) {
activity.toggleMenu() activity.toggleMenu()
return@f return@f

View File

@ -44,6 +44,7 @@ class RecentlyReadController(bundle: Bundle? = null) :
init { init {
setHasOptionsMenu(true) setHasOptionsMenu(true)
} }
/** /**
* Adapter containing the recent manga. * Adapter containing the recent manga.
*/ */
@ -85,8 +86,9 @@ class RecentlyReadController(bundle: Bundle? = null) :
resetProgressItem() resetProgressItem()
scrollViewWith(recycler, padBottom = true) scrollViewWith(recycler, padBottom = true)
if (recentItems != null) if (recentItems != null) {
adapter?.updateDataSet(recentItems!!.toList()) adapter?.updateDataSet(recentItems!!.toList())
}
launchUI { launchUI {
val manga = presenter.refresh(query) val manga = presenter.refresh(query)
@ -106,6 +108,7 @@ class RecentlyReadController(bundle: Bundle? = null) :
observeLater = false observeLater = false
} }
} }
/** /**
* Populate adapter with chapters * Populate adapter with chapters
* *
@ -115,8 +118,9 @@ class RecentlyReadController(bundle: Bundle? = null) :
val adapter = adapter ?: return val adapter = adapter ?: return
adapter.updateDataSet(mangaHistory) adapter.updateDataSet(mangaHistory)
adapter.onLoadMoreComplete(null) adapter.onLoadMoreComplete(null)
if (recentItems == null) if (recentItems == null) {
resetProgressItem() resetProgressItem()
}
recentItems = mangaHistory.toMutableList() recentItems = mangaHistory.toMutableList()
} }

View File

@ -24,7 +24,6 @@ class RecentlyReadItem(val mch: MangaChapterHistory) : AbstractFlexibleItem<Rece
position: Int, position: Int,
payloads: MutableList<Any?>? payloads: MutableList<Any?>?
) { ) {
holder.bind(mch) holder.bind(mch)
} }

View File

@ -40,7 +40,6 @@ import eu.kanade.tachiyomi.util.system.dpToPx
import eu.kanade.tachiyomi.util.system.spToPx import eu.kanade.tachiyomi.util.system.spToPx
import eu.kanade.tachiyomi.util.system.toast import eu.kanade.tachiyomi.util.system.toast
import eu.kanade.tachiyomi.util.view.expand import eu.kanade.tachiyomi.util.view.expand
import eu.kanade.tachiyomi.util.view.isCollapsed
import eu.kanade.tachiyomi.util.view.isExpanded import eu.kanade.tachiyomi.util.view.isExpanded
import eu.kanade.tachiyomi.util.view.requestPermissionsSafe import eu.kanade.tachiyomi.util.view.requestPermissionsSafe
import eu.kanade.tachiyomi.util.view.scrollViewWith import eu.kanade.tachiyomi.util.view.scrollViewWith
@ -95,9 +94,9 @@ class RecentsController(bundle: Bundle? = null) :
var headerHeight = 0 var headerHeight = 0
override fun getTitle(): String? { override fun getTitle(): String? {
return if (showingDownloads) return if (showingDownloads) {
resources?.getString(R.string.download_queue) resources?.getString(R.string.download_queue)
else resources?.getString(R.string.recents) } else resources?.getString(R.string.recents)
} }
override fun inflateView(inflater: LayoutInflater, container: ViewGroup): View { override fun inflateView(inflater: LayoutInflater, container: ViewGroup): View {
@ -243,8 +242,9 @@ class RecentsController(bundle: Bundle? = null) :
val pad = bottomBar.translationY - bottomBar.height val pad = bottomBar.translationY - bottomBar.height
val padding = max( val padding = max(
(-pad).toInt(), (-pad).toInt(),
if (dl_bottom_sheet.sheetBehavior.isExpanded()) 0 else if (dl_bottom_sheet.sheetBehavior.isExpanded()) 0 else {
view?.rootWindowInsets?.systemWindowInsetBottom ?: 0 view?.rootWindowInsets?.systemWindowInsetBottom ?: 0
}
) )
shadow2.translationY = pad shadow2.translationY = pad
dl_bottom_sheet.sheetBehavior?.peekHeight = 48.spToPx + padding dl_bottom_sheet.sheetBehavior?.peekHeight = 48.spToPx + padding
@ -303,8 +303,9 @@ class RecentsController(bundle: Bundle? = null) :
swipe_refresh.isRefreshing = LibraryUpdateService.isRunning() swipe_refresh.isRefreshing = LibraryUpdateService.isRunning()
adapter.updateItems(recents) adapter.updateItems(recents)
adapter.removeAllScrollableHeaders() adapter.removeAllScrollableHeaders()
if (presenter.viewType > 0) if (presenter.viewType > 0) {
adapter.addScrollableHeader(presenter.generalHeader) adapter.addScrollableHeader(presenter.generalHeader)
}
if (lastChapterId != null) { if (lastChapterId != null) {
refreshItem(lastChapterId ?: 0L) refreshItem(lastChapterId ?: 0L)
lastChapterId = null lastChapterId = null
@ -380,8 +381,9 @@ class RecentsController(bundle: Bundle? = null) :
val manga = item.mch.manga val manga = item.mch.manga
val history = item.mch.history val history = item.mch.history
val chapter = item.mch.chapter val chapter = item.mch.chapter
if (history.id != null) if (history.id != null) {
RemoveHistoryDialog(this, manga, history, chapter).showDialog(router) RemoveHistoryDialog(this, manga, history, chapter).showDialog(router)
}
} }
override fun removeHistory(manga: Manga, history: History, all: Boolean) { override fun removeHistory(manga: Manga, history: History, all: Boolean) {
@ -476,7 +478,7 @@ class RecentsController(bundle: Bundle? = null) :
setBottomPadding() setBottomPadding()
} }
override fun onChangeEnded(handler: ControllerChangeHandler, type: ControllerChangeType ) { override fun onChangeEnded(handler: ControllerChangeHandler, type: ControllerChangeType) {
super.onChangeEnded(handler, type) super.onChangeEnded(handler, type)
if (type == ControllerChangeType.POP_ENTER) setBottomPadding() if (type == ControllerChangeType.POP_ENTER) setBottomPadding()
} }
@ -484,8 +486,9 @@ class RecentsController(bundle: Bundle? = null) :
fun hasQueue() = presenter.downloadManager.hasQueue() fun hasQueue() = presenter.downloadManager.hasQueue()
override fun showSheet() { override fun showSheet() {
if (dl_bottom_sheet.sheetBehavior?.isHideable == false || hasQueue()) if (dl_bottom_sheet.sheetBehavior?.isHideable == false || hasQueue()) {
dl_bottom_sheet.sheetBehavior?.expand() dl_bottom_sheet.sheetBehavior?.expand()
}
} }
override fun toggleSheet() { override fun toggleSheet() {
@ -498,13 +501,15 @@ class RecentsController(bundle: Bundle? = null) :
override fun expandSearch() { override fun expandSearch() {
if (showingDownloads) { if (showingDownloads) {
dl_bottom_sheet.dismiss() dl_bottom_sheet.dismiss()
} else } else {
activity?.toolbar?.menu?.findItem(R.id.action_search)?.expandActionView() activity?.toolbar?.menu?.findItem(R.id.action_search)?.expandActionView()
}
} }
override fun onOptionsItemSelected(item: MenuItem): Boolean { override fun onOptionsItemSelected(item: MenuItem): Boolean {
if (showingDownloads) if (showingDownloads) {
return dl_bottom_sheet.onOptionsItemSelected(item) return dl_bottom_sheet.onOptionsItemSelected(item)
}
when (item.itemId) { when (item.itemId) {
R.id.action_group_all, R.id.action_ungroup_all, R.id.action_only_history, R.id.action_group_all, R.id.action_ungroup_all, R.id.action_only_history,
R.id.action_only_updates -> { R.id.action_only_updates -> {
@ -516,8 +521,9 @@ class RecentsController(bundle: Bundle? = null) :
else -> 0 else -> 0
} }
) )
if (item.itemId == R.id.action_only_history) if (item.itemId == R.id.action_only_history) {
activity?.toast(R.string.press_and_hold_to_reset_history, Toast.LENGTH_LONG) activity?.toast(R.string.press_and_hold_to_reset_history, Toast.LENGTH_LONG)
}
activity?.invalidateOptionsMenu() activity?.invalidateOptionsMenu()
} }
} }

View File

@ -56,8 +56,9 @@ class RecentsPresenter(
downloadManager.addListener(this) downloadManager.addListener(this)
LibraryUpdateService.setListener(this) LibraryUpdateService.setListener(this)
if (lastRecents != null) { if (lastRecents != null) {
if (recentItems.isEmpty()) if (recentItems.isEmpty()) {
recentItems = lastRecents ?: emptyList() recentItems = lastRecents ?: emptyList()
}
lastRecents = null lastRecents = null
} }
getRecents() getRecents()
@ -95,14 +96,15 @@ class RecentsPresenter(
} }
} }
val cReading = if (viewType != 3) val cReading = if (viewType != 3) {
if (query.isEmpty() && viewType != 2) if (query.isEmpty() && viewType != 2) {
db.getRecentsWithUnread(cal.time, query, isUngrouped).executeOnIO() db.getRecentsWithUnread(cal.time, query, isUngrouped).executeOnIO()
else db.getRecentMangaLimit( } else db.getRecentMangaLimit(
cal.time, cal.time,
if (viewType == 2) 200 else 8, if (viewType == 2) 200 else 8,
query query
).executeOnIO() else emptyList() ).executeOnIO()
} else emptyList()
val rUpdates = when { val rUpdates = when {
viewType == 3 -> db.getRecentChapters(calWeek.time).executeOnIO().map { viewType == 3 -> db.getRecentChapters(calWeek.time).executeOnIO().map {
MangaChapterHistory(it.manga, it.chapter, HistoryImpl()) MangaChapterHistory(it.manga, it.chapter, HistoryImpl())
@ -113,8 +115,9 @@ class RecentsPresenter(
rUpdates.forEach { rUpdates.forEach {
it.history.last_read = it.chapter.date_fetch it.history.last_read = it.chapter.date_fetch
} }
val nAdditions = if (viewType < 2) val nAdditions = if (viewType < 2) {
db.getRecentlyAdded(calDay.time, query, isUngrouped).executeOnIO() else emptyList() db.getRecentlyAdded(calDay.time, query, isUngrouped).executeOnIO()
} else emptyList()
nAdditions.forEach { nAdditions.forEach {
it.history.last_read = it.manga.date_added it.history.last_read = it.manga.date_added
} }
@ -144,10 +147,11 @@ class RecentsPresenter(
Comparator<Pair<MangaChapterHistory, Chapter>> { f1, f2 -> Comparator<Pair<MangaChapterHistory, Chapter>> { f1, f2 ->
if (abs(f1.second.date_fetch - f2.second.date_fetch) <= if (abs(f1.second.date_fetch - f2.second.date_fetch) <=
TimeUnit.HOURS.toMillis(12) TimeUnit.HOURS.toMillis(12)
) ) {
f2.second.date_upload.compareTo(f1.second.date_upload) f2.second.date_upload.compareTo(f1.second.date_upload)
else } else {
f2.second.date_fetch.compareTo(f1.second.date_fetch) f2.second.date_fetch.compareTo(f1.second.date_fetch)
}
} }
) )
.take(4).map { .take(4).map {

View File

@ -10,7 +10,6 @@ import com.google.android.gms.oss.licenses.OssLicensesMenuActivity
import eu.kanade.tachiyomi.BuildConfig import eu.kanade.tachiyomi.BuildConfig
import eu.kanade.tachiyomi.R import eu.kanade.tachiyomi.R
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.updater.UpdateChecker import eu.kanade.tachiyomi.data.updater.UpdateChecker
import eu.kanade.tachiyomi.data.updater.UpdateResult import eu.kanade.tachiyomi.data.updater.UpdateResult
import eu.kanade.tachiyomi.data.updater.UpdaterService import eu.kanade.tachiyomi.data.updater.UpdaterService

View File

@ -46,8 +46,8 @@ inline fun PreferenceGroup.editTextPreference(block: (@DSL EditTextPreference).(
inline fun PreferenceGroup.dropDownPreference(block: (@DSL DropDownPreference).() -> Unit): inline fun PreferenceGroup.dropDownPreference(block: (@DSL DropDownPreference).() -> Unit):
DropDownPreference { DropDownPreference {
return initThenAdd(DropDownPreference(context), block).also(::initDialog) return initThenAdd(DropDownPreference(context), block).also(::initDialog)
} }
inline fun PreferenceGroup.listPreference( inline fun PreferenceGroup.listPreference(
activity: Activity?, activity: Activity?,
@ -55,8 +55,8 @@ inline fun PreferenceGroup.listPreference(
-> Unit -> Unit
): ):
ListMatPreference { ListMatPreference {
return initThenAdd(ListMatPreference(activity, context), block) return initThenAdd(ListMatPreference(activity, context), block)
} }
inline fun PreferenceGroup.intListPreference( inline fun PreferenceGroup.intListPreference(
activity: Activity?, activity: Activity?,
@ -66,8 +66,8 @@ inline fun PreferenceGroup.intListPreference(
).() -> Unit ).() -> Unit
): ):
IntListMatPreference { IntListMatPreference {
return initThenAdd(IntListMatPreference(activity, context), block) return initThenAdd(IntListMatPreference(activity, context), block)
} }
inline fun PreferenceGroup.multiSelectListPreferenceMat( inline fun PreferenceGroup.multiSelectListPreferenceMat(
activity: Activity?, activity: Activity?,

View File

@ -186,9 +186,7 @@ class SettingsAdvancedController : SettingsController() {
class CleanupDownloadsDialogController() : DialogController() { class CleanupDownloadsDialogController() : DialogController() {
override fun onCreateDialog(savedViewState: Bundle?): Dialog { override fun onCreateDialog(savedViewState: Bundle?): Dialog {
return MaterialDialog(activity!!).show { return MaterialDialog(activity!!).show {
title(R.string.clean_up_downloaded_chapters) title(R.string.clean_up_downloaded_chapters)
.listItemsMultiChoice(R.array.clean_up_downloads, disabledIndices = intArrayOf(0), initialSelection = intArrayOf(0, 1, 2)) { dialog, selections, items -> .listItemsMultiChoice(R.array.clean_up_downloads, disabledIndices = intArrayOf(0), initialSelection = intArrayOf(0, 1, 2)) { dialog, selections, items ->
val deleteRead = selections.contains(1) val deleteRead = selections.contains(1)

View File

@ -151,7 +151,7 @@ class SettingsBackupController : SettingsController() {
defaultValue = true defaultValue = true
preferences.backupInterval().asImmediateFlow { isVisible = it > 0 } preferences.backupInterval().asImmediateFlow { isVisible = it > 0 }
.launchIn(viewScope) .launchIn(viewScope)
} }
} }
} }

View File

@ -9,7 +9,6 @@ import eu.kanade.tachiyomi.extension.ExtensionUpdateJob
import eu.kanade.tachiyomi.source.SourceManager import eu.kanade.tachiyomi.source.SourceManager
import eu.kanade.tachiyomi.ui.main.MainActivity import eu.kanade.tachiyomi.ui.main.MainActivity
import eu.kanade.tachiyomi.ui.migration.MigrationController import eu.kanade.tachiyomi.ui.migration.MigrationController
import eu.kanade.tachiyomi.util.system.getResourceColor
import eu.kanade.tachiyomi.util.view.snack import eu.kanade.tachiyomi.util.view.snack
import eu.kanade.tachiyomi.util.view.withFadeTransaction import eu.kanade.tachiyomi.util.view.withFadeTransaction
import kotlinx.coroutines.flow.launchIn import kotlinx.coroutines.flow.launchIn

View File

@ -20,7 +20,6 @@ import com.bluelinelabs.conductor.ControllerChangeType
import eu.kanade.tachiyomi.R import eu.kanade.tachiyomi.R
import eu.kanade.tachiyomi.data.preference.PreferencesHelper import eu.kanade.tachiyomi.data.preference.PreferencesHelper
import eu.kanade.tachiyomi.ui.base.controller.BaseController import eu.kanade.tachiyomi.ui.base.controller.BaseController
import eu.kanade.tachiyomi.util.system.getResourceColor
import eu.kanade.tachiyomi.util.view.scrollViewWith import eu.kanade.tachiyomi.util.view.scrollViewWith
import kotlinx.coroutines.MainScope import kotlinx.coroutines.MainScope
import rx.Observable import rx.Observable

View File

@ -97,15 +97,16 @@ class SettingsDownloadController : SettingsController() {
preferences.downloadNew().asImmediateFlow { isVisible = it } preferences.downloadNew().asImmediateFlow { isVisible = it }
preferences.downloadNewCategories().asImmediateFlow { list -> preferences.downloadNewCategories().asImmediateFlow { list ->
val selectedCategories = list val selectedCategories = list
.mapNotNull { id -> dbCategories.find { it.id == id.toInt() } } .mapNotNull { id -> dbCategories.find { it.id == id.toInt() } }
.sortedBy { it.order } .sortedBy { it.order }
customSummary = if (selectedCategories.isEmpty()) customSummary = if (selectedCategories.isEmpty()) {
resources?.getString(R.string.all) resources?.getString(R.string.all)
else } else {
selectedCategories.joinToString { it.name } selectedCategories.joinToString { it.name }
} }
}
} }
preferenceCategory { preferenceCategory {
intListPreference(activity) { intListPreference(activity) {

View File

@ -137,7 +137,7 @@ class SettingsLibraryController : SettingsController() {
preferences.libraryUpdateCategories().asImmediateFlow { list -> preferences.libraryUpdateCategories().asImmediateFlow { list ->
val selectedCategories = val selectedCategories =
list.mapNotNull { id -> dbCategories.find { it.id == id.toInt() } } list.mapNotNull { id -> dbCategories.find { it.id == id.toInt() } }
.sortedBy { it.order } .sortedBy { it.order }
customSummary = customSummary =

Some files were not shown because too many files have changed in this diff Show More