mirror of
https://github.com/tachiyomiorg/tachiyomi.git
synced 2024-11-09 05:25:08 +01:00
Running kotlinter
This commit is contained in:
parent
7914b26488
commit
fccd3a0ddb
@ -25,7 +25,6 @@ import uy.kohesive.injekt.api.get
|
||||
class AppModule(val app: Application) : InjektModule {
|
||||
|
||||
override fun InjektRegistrar.registerInjectables() {
|
||||
|
||||
addSingleton(app)
|
||||
|
||||
addSingletonFactory { PreferencesHelper(app) }
|
||||
|
@ -70,8 +70,9 @@ object Migrations {
|
||||
}
|
||||
}
|
||||
}
|
||||
if (oldVersion < 54)
|
||||
if (oldVersion < 54) {
|
||||
DownloadProvider(context).renameChapters()
|
||||
}
|
||||
if (oldVersion < 62) {
|
||||
LibraryPresenter.updateDB()
|
||||
// Restore jobs after migrating from Evernote's job scheduler to WorkManager.
|
||||
|
@ -79,8 +79,9 @@ class ChapterCache(private val context: Context) {
|
||||
*/
|
||||
fun removeFileFromCache(file: String): Boolean {
|
||||
// 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
|
||||
}
|
||||
|
||||
try {
|
||||
// Remove the extension from the file to get the key of the cache
|
||||
|
@ -41,9 +41,9 @@ class CategoryPutResolver : DefaultPutResolver<Category>() {
|
||||
put(COL_NAME, obj.name)
|
||||
put(COL_ORDER, obj.order)
|
||||
put(COL_FLAGS, obj.flags)
|
||||
if (obj.mangaSort != null)
|
||||
if (obj.mangaSort != null) {
|
||||
put(COL_MANGA_ORDER, obj.mangaSort.toString())
|
||||
else {
|
||||
} else {
|
||||
val orderString = obj.mangaOrder.joinToString("/")
|
||||
put(COL_MANGA_ORDER, orderString)
|
||||
}
|
||||
|
@ -105,17 +105,17 @@ interface Manga : SManga {
|
||||
{ tag ->
|
||||
tag == "long strip" || tag == "manhwa" || tag.contains("webtoon")
|
||||
} == true || isWebtoonSource(sourceName)
|
||||
)
|
||||
) {
|
||||
ReaderActivity.WEBTOON
|
||||
else if (currentTags?.any
|
||||
} else if (currentTags?.any
|
||||
{ tag ->
|
||||
tag == "chinese" || tag == "manhua" ||
|
||||
tag.startsWith("english") || tag == "comic"
|
||||
} == true || (isComicSource(sourceName) && !sourceName.contains("tapas", true)) ||
|
||||
sourceName.contains("manhua", true)
|
||||
)
|
||||
) {
|
||||
ReaderActivity.LEFT_TO_RIGHT
|
||||
else 0
|
||||
} else 0
|
||||
}
|
||||
|
||||
fun isMangaTag(tag: String): Boolean {
|
||||
@ -127,7 +127,7 @@ interface Manga : SManga {
|
||||
}
|
||||
|
||||
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 {
|
||||
|
@ -90,7 +90,6 @@ class DownloadCache(
|
||||
checkRenew()
|
||||
|
||||
if (forceCheckFolder) {
|
||||
|
||||
val source = sourceManager.get(manga.source) ?: return 0
|
||||
val mangaDir = provider.findMangaDir(manga, source)
|
||||
|
||||
@ -173,7 +172,6 @@ class DownloadCache(
|
||||
*/
|
||||
@Synchronized
|
||||
fun addChapter(chapterDirName: String, mangaUniFile: UniFile, manga: Manga) {
|
||||
|
||||
val id = manga.id ?: return
|
||||
val files = mangaFiles[id]
|
||||
if (files == null) {
|
||||
|
@ -110,10 +110,11 @@ class DownloadManager(val context: Context) {
|
||||
queue.add(0, download)
|
||||
reorderQueue(queue)
|
||||
if (isPaused()) {
|
||||
if (DownloadService.isRunning(context))
|
||||
if (DownloadService.isRunning(context)) {
|
||||
downloader.start()
|
||||
else
|
||||
} else {
|
||||
DownloadService.start(context)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -55,8 +55,9 @@ internal class DownloadNotifier(private val context: Context) {
|
||||
* Clear old actions if they exist.
|
||||
*/
|
||||
private fun clearActions() = with(notification) {
|
||||
if (!mActions.isEmpty())
|
||||
if (!mActions.isEmpty()) {
|
||||
mActions.clear()
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -201,10 +201,11 @@ class DownloadService : Service() {
|
||||
*/
|
||||
private fun listenDownloaderState() {
|
||||
subscriptions += downloadManager.runningRelay.subscribe { running ->
|
||||
if (running)
|
||||
if (running) {
|
||||
wakeLock.acquireIfNeeded()
|
||||
else
|
||||
} else {
|
||||
wakeLock.releaseIfNeeded()
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -469,7 +469,6 @@ class Downloader(
|
||||
tmpDir: UniFile,
|
||||
dirname: String
|
||||
) {
|
||||
|
||||
// Ensure that the chapter folder has all the images.
|
||||
val downloadedImages = tmpDir.listFiles().orEmpty().filterNot { it.name!!.endsWith(".tmp") }
|
||||
|
||||
|
@ -11,11 +11,14 @@ class Download(val source: HttpSource, val manga: Manga, val chapter: Chapter) {
|
||||
|
||||
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) {
|
||||
field = status
|
||||
statusSubject?.onNext(this)
|
||||
|
@ -37,8 +37,9 @@ class DownloadQueue(
|
||||
store.remove(download)
|
||||
download.setStatusSubject(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
|
||||
}
|
||||
downloadListeners.forEach { it.updateDownload(download) }
|
||||
if (removed) {
|
||||
updatedRelay.call(Unit)
|
||||
@ -65,8 +66,9 @@ class DownloadQueue(
|
||||
queue.forEach { download ->
|
||||
download.setStatusSubject(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
|
||||
}
|
||||
downloadListeners.forEach { it.updateDownload(download) }
|
||||
}
|
||||
queue.clear()
|
||||
@ -85,11 +87,12 @@ class DownloadQueue(
|
||||
|
||||
private fun setPagesFor(download: Download) {
|
||||
if (download.status == Download.DOWNLOADING) {
|
||||
if (download.pages != null)
|
||||
if (download.pages != null) {
|
||||
for (page in download.pages!!)
|
||||
page.setStatusCallback {
|
||||
callListeners(download)
|
||||
}
|
||||
}
|
||||
downloadListeners.forEach { it.updateDownload(download) }
|
||||
} else if (download.status == Download.DOWNLOADED || download.status == Download.ERROR) {
|
||||
setPagesSubject(download.pages, null)
|
||||
|
@ -31,10 +31,11 @@ class LibraryUpdateJob(private val context: Context, workerParams: WorkerParamet
|
||||
if (interval > 0) {
|
||||
val restrictions = preferences.libraryUpdateRestriction()!!
|
||||
val acRestriction = "ac" in restrictions
|
||||
val wifiRestriction = if ("wifi" in restrictions)
|
||||
val wifiRestriction = if ("wifi" in restrictions) {
|
||||
NetworkType.UNMETERED
|
||||
else
|
||||
} else {
|
||||
NetworkType.CONNECTED
|
||||
}
|
||||
|
||||
val constraints = Constraints.Builder()
|
||||
.setRequiredNetworkType(wifiRestriction)
|
||||
|
@ -195,7 +195,6 @@ class LibraryUpdateNotifier(private val context: Context) {
|
||||
}
|
||||
|
||||
NotificationManagerCompat.from(context).apply {
|
||||
|
||||
notify(
|
||||
Notifications.ID_NEW_CHAPTERS,
|
||||
context.notification(Notifications.CHANNEL_NEW_CHAPTERS) {
|
||||
|
@ -114,7 +114,9 @@ class LibraryUpdateService(
|
||||
enum class Target {
|
||||
|
||||
CHAPTERS, // Manga chapters
|
||||
|
||||
DETAILS, // Manga metadata
|
||||
|
||||
TRACKING // Tracking metadata
|
||||
}
|
||||
|
||||
@ -172,8 +174,9 @@ class LibraryUpdateService(
|
||||
*/
|
||||
override fun onDestroy() {
|
||||
job?.cancel()
|
||||
if (instance == this)
|
||||
if (instance == this) {
|
||||
instance = null
|
||||
}
|
||||
if (wakeLock.isHeld) {
|
||||
wakeLock.release()
|
||||
}
|
||||
@ -380,47 +383,47 @@ class LibraryUpdateService(
|
||||
shouldDownload: Boolean
|
||||
):
|
||||
Boolean {
|
||||
try {
|
||||
var hasDownloads = false
|
||||
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")
|
||||
}
|
||||
try {
|
||||
var hasDownloads = false
|
||||
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
|
||||
}
|
||||
}
|
||||
|
||||
private fun downloadChapters(manga: Manga, chapters: List<Chapter>) {
|
||||
// We don't want to start downloading while the library is updating, because websites
|
||||
|
@ -448,19 +448,19 @@ class NotificationReceiver : BroadcastReceiver() {
|
||||
*/
|
||||
internal fun openChapterPendingActivity(context: Context, manga: Manga, groupId: Int):
|
||||
PendingIntent {
|
||||
val newIntent =
|
||||
Intent(context, MainActivity::class.java).setAction(MainActivity.SHORTCUT_MANGA)
|
||||
.addFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP or Intent.FLAG_ACTIVITY_SINGLE_TOP)
|
||||
.putExtra(MangaDetailsController.MANGA_EXTRA, manga.id)
|
||||
.putExtra("notificationId", manga.id.hashCode())
|
||||
.putExtra("groupId", groupId)
|
||||
return PendingIntent.getActivity(
|
||||
context,
|
||||
manga.id.hashCode(),
|
||||
newIntent,
|
||||
PendingIntent.FLAG_UPDATE_CURRENT
|
||||
)
|
||||
}
|
||||
val newIntent =
|
||||
Intent(context, MainActivity::class.java).setAction(MainActivity.SHORTCUT_MANGA)
|
||||
.addFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP or Intent.FLAG_ACTIVITY_SINGLE_TOP)
|
||||
.putExtra(MangaDetailsController.MANGA_EXTRA, manga.id)
|
||||
.putExtra("notificationId", manga.id.hashCode())
|
||||
.putExtra("groupId", groupId)
|
||||
return PendingIntent.getActivity(
|
||||
context,
|
||||
manga.id.hashCode(),
|
||||
newIntent,
|
||||
PendingIntent.FLAG_UPDATE_CURRENT
|
||||
)
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns [PendingIntent] that opens the error log file in an external viewer
|
||||
@ -522,15 +522,15 @@ class NotificationReceiver : BroadcastReceiver() {
|
||||
groupId: Int
|
||||
):
|
||||
PendingIntent {
|
||||
val newIntent = Intent(context, NotificationReceiver::class.java).apply {
|
||||
action = ACTION_MARK_AS_READ
|
||||
putExtra(EXTRA_CHAPTER_URL, chapters.map { it.url }.toTypedArray())
|
||||
putExtra(EXTRA_MANGA_ID, manga.id)
|
||||
putExtra(EXTRA_NOTIFICATION_ID, manga.id.hashCode())
|
||||
putExtra(EXTRA_GROUP_ID, groupId)
|
||||
}
|
||||
return PendingIntent.getBroadcast(context, manga.id.hashCode(), newIntent, PendingIntent.FLAG_UPDATE_CURRENT)
|
||||
val newIntent = Intent(context, NotificationReceiver::class.java).apply {
|
||||
action = ACTION_MARK_AS_READ
|
||||
putExtra(EXTRA_CHAPTER_URL, chapters.map { it.url }.toTypedArray())
|
||||
putExtra(EXTRA_MANGA_ID, manga.id)
|
||||
putExtra(EXTRA_NOTIFICATION_ID, manga.id.hashCode())
|
||||
putExtra(EXTRA_GROUP_ID, groupId)
|
||||
}
|
||||
return PendingIntent.getBroadcast(context, manga.id.hashCode(), newIntent, PendingIntent.FLAG_UPDATE_CURRENT)
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns [PendingIntent] that starts a service which stops the library update
|
||||
|
@ -6,11 +6,9 @@ import androidx.annotation.StringRes
|
||||
import eu.kanade.tachiyomi.data.database.DatabaseHelper
|
||||
import eu.kanade.tachiyomi.data.database.models.Track
|
||||
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.network.NetworkHelper
|
||||
import eu.kanade.tachiyomi.source.model.SManga
|
||||
import eu.kanade.tachiyomi.ui.manga.track.SetTrackReadingDatesDialog
|
||||
import eu.kanade.tachiyomi.util.system.executeOnIO
|
||||
import okhttp3.OkHttpClient
|
||||
import uy.kohesive.injekt.injectLazy
|
||||
|
@ -25,7 +25,6 @@ import okhttp3.RequestBody.Companion.toRequestBody
|
||||
import okhttp3.Response
|
||||
import timber.log.Timber
|
||||
import java.util.Calendar
|
||||
import java.util.Date
|
||||
import java.util.concurrent.TimeUnit
|
||||
|
||||
class AnilistApi(val client: OkHttpClient, interceptor: AnilistInterceptor) {
|
||||
@ -34,7 +33,6 @@ class AnilistApi(val client: OkHttpClient, interceptor: AnilistInterceptor) {
|
||||
|
||||
suspend fun addLibManga(track: Track): Track {
|
||||
return withContext(Dispatchers.IO) {
|
||||
|
||||
val variables = jsonObject(
|
||||
"mangaId" to track.media_id,
|
||||
"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? {
|
||||
|
||||
return withContext(Dispatchers.IO) {
|
||||
val variables = jsonObject(
|
||||
"id" to userid,
|
||||
@ -141,7 +138,6 @@ class AnilistApi(val client: OkHttpClient, interceptor: AnilistInterceptor) {
|
||||
suspend fun remove(track: Track): Boolean {
|
||||
return withContext(Dispatchers.IO) {
|
||||
try {
|
||||
|
||||
val variables = jsonObject(
|
||||
"listId" to track.library_id
|
||||
)
|
||||
|
@ -114,7 +114,6 @@ class Bangumi(private val context: Context, id: Int) : TrackService(id) {
|
||||
|
||||
suspend fun login(code: String): Boolean {
|
||||
try {
|
||||
|
||||
val oauth = api.accessToken(code)
|
||||
interceptor.newAuth(oauth)
|
||||
saveCredentials(oauth.user_id.toString(), oauth.access_token)
|
||||
|
@ -5,14 +5,12 @@ import android.graphics.Color
|
||||
import androidx.annotation.StringRes
|
||||
import eu.kanade.tachiyomi.R
|
||||
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.model.TrackSearch
|
||||
import eu.kanade.tachiyomi.data.track.updateNewTrackInfo
|
||||
import kotlinx.serialization.decodeFromString
|
||||
import kotlinx.serialization.encodeToString
|
||||
import kotlinx.serialization.json.Json
|
||||
import okhttp3.HttpUrl.Companion.toHttpUrlOrNull
|
||||
import timber.log.Timber
|
||||
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
|
||||
add(track)
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
override fun canRemoveFromService(): Boolean = true
|
||||
|
@ -8,17 +8,11 @@ import eu.kanade.tachiyomi.data.track.model.TrackSearch
|
||||
import eu.kanade.tachiyomi.network.GET
|
||||
import eu.kanade.tachiyomi.network.POST
|
||||
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.util.PkceUtil
|
||||
import eu.kanade.tachiyomi.util.selectInt
|
||||
import eu.kanade.tachiyomi.util.selectText
|
||||
import eu.kanade.tachiyomi.util.system.withIOContext
|
||||
import kotlinx.coroutines.Dispatchers
|
||||
import kotlinx.coroutines.async
|
||||
import kotlinx.coroutines.awaitAll
|
||||
import kotlinx.coroutines.withContext
|
||||
import kotlinx.serialization.json.JsonObject
|
||||
import kotlinx.serialization.json.boolean
|
||||
import kotlinx.serialization.json.contentOrNull
|
||||
@ -27,17 +21,9 @@ import kotlinx.serialization.json.jsonArray
|
||||
import kotlinx.serialization.json.jsonObject
|
||||
import kotlinx.serialization.json.jsonPrimitive
|
||||
import okhttp3.FormBody
|
||||
import okhttp3.MediaType.Companion.toMediaTypeOrNull
|
||||
import okhttp3.OkHttpClient
|
||||
import okhttp3.Request
|
||||
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 java.text.SimpleDateFormat
|
||||
import java.util.*
|
||||
@ -49,91 +35,90 @@ class MyAnimeListApi(private val client: OkHttpClient, interceptor: MyAnimeListI
|
||||
suspend fun getAccessToken(authCode: String): OAuth {
|
||||
return withIOContext {
|
||||
val formBody: RequestBody = FormBody.Builder()
|
||||
.add("client_id", clientId)
|
||||
.add("code", authCode)
|
||||
.add("code_verifier", codeVerifier)
|
||||
.add("grant_type", "authorization_code")
|
||||
.build()
|
||||
.add("client_id", clientId)
|
||||
.add("code", authCode)
|
||||
.add("code_verifier", codeVerifier)
|
||||
.add("grant_type", "authorization_code")
|
||||
.build()
|
||||
client.newCall(POST("$baseOAuthUrl/token", body = formBody))
|
||||
.await()
|
||||
.parseAs()
|
||||
.await()
|
||||
.parseAs()
|
||||
}
|
||||
}
|
||||
|
||||
suspend fun getCurrentUser(): String {
|
||||
return withIOContext {
|
||||
val request = Request.Builder()
|
||||
.url("$baseApiUrl/users/@me")
|
||||
.get()
|
||||
.build()
|
||||
.url("$baseApiUrl/users/@me")
|
||||
.get()
|
||||
.build()
|
||||
authClient.newCall(request)
|
||||
.await()
|
||||
.parseAs<JsonObject>()
|
||||
.let { it["name"]!!.jsonPrimitive.content }
|
||||
.await()
|
||||
.parseAs<JsonObject>()
|
||||
.let { it["name"]!!.jsonPrimitive.content }
|
||||
}
|
||||
}
|
||||
|
||||
suspend fun search(query: String): List<TrackSearch> {
|
||||
return withIOContext {
|
||||
val url = "$baseApiUrl/manga".toUri().buildUpon()
|
||||
.appendQueryParameter("q", query)
|
||||
.appendQueryParameter("nsfw", "true")
|
||||
.build()
|
||||
.appendQueryParameter("q", query)
|
||||
.appendQueryParameter("nsfw", "true")
|
||||
.build()
|
||||
authClient.newCall(GET(url.toString()))
|
||||
.await()
|
||||
.parseAs<JsonObject>()
|
||||
.let {
|
||||
it["data"]!!.jsonArray
|
||||
.map { data -> data.jsonObject["node"]!!.jsonObject }
|
||||
.map { node ->
|
||||
val id = node["id"]!!.jsonPrimitive.int
|
||||
async { getMangaDetails(id) }
|
||||
}
|
||||
.awaitAll()
|
||||
.filter { trackSearch -> trackSearch.publishing_type != "novel" }
|
||||
}
|
||||
.await()
|
||||
.parseAs<JsonObject>()
|
||||
.let {
|
||||
it["data"]!!.jsonArray
|
||||
.map { data -> data.jsonObject["node"]!!.jsonObject }
|
||||
.map { node ->
|
||||
val id = node["id"]!!.jsonPrimitive.int
|
||||
async { getMangaDetails(id) }
|
||||
}
|
||||
.awaitAll()
|
||||
.filter { trackSearch -> trackSearch.publishing_type != "novel" }
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
suspend fun getMangaDetails(id: Int): TrackSearch {
|
||||
return withIOContext {
|
||||
val url = "$baseApiUrl/manga".toUri().buildUpon()
|
||||
.appendPath(id.toString())
|
||||
.appendQueryParameter("fields", "id,title,synopsis,num_chapters,main_picture,status,media_type,start_date")
|
||||
.build()
|
||||
.appendPath(id.toString())
|
||||
.appendQueryParameter("fields", "id,title,synopsis,num_chapters,main_picture,status,media_type,start_date")
|
||||
.build()
|
||||
authClient.newCall(GET(url.toString()))
|
||||
.await()
|
||||
.parseAs<JsonObject>()
|
||||
.let {
|
||||
val obj = it.jsonObject
|
||||
TrackSearch.create(TrackManager.MYANIMELIST).apply {
|
||||
media_id = obj["id"]!!.jsonPrimitive.int
|
||||
title = obj["title"]!!.jsonPrimitive.content
|
||||
summary = obj["synopsis"]?.jsonPrimitive?.content ?: ""
|
||||
total_chapters = obj["num_chapters"]!!.jsonPrimitive.int
|
||||
cover_url = obj["main_picture"]?.jsonObject?.get("large")?.jsonPrimitive?.content ?: ""
|
||||
tracking_url = "https://myanimelist.net/manga/$media_id"
|
||||
publishing_status = obj["status"]!!.jsonPrimitive.content.replace("_", " ")
|
||||
publishing_type = obj["media_type"]!!.jsonPrimitive.content.replace("_", " ")
|
||||
start_date = try {
|
||||
val outputDf = SimpleDateFormat("yyyy-MM-dd", Locale.US)
|
||||
outputDf.format(obj["start_date"]!!)
|
||||
} catch (e: Exception) {
|
||||
""
|
||||
}
|
||||
.await()
|
||||
.parseAs<JsonObject>()
|
||||
.let {
|
||||
val obj = it.jsonObject
|
||||
TrackSearch.create(TrackManager.MYANIMELIST).apply {
|
||||
media_id = obj["id"]!!.jsonPrimitive.int
|
||||
title = obj["title"]!!.jsonPrimitive.content
|
||||
summary = obj["synopsis"]?.jsonPrimitive?.content ?: ""
|
||||
total_chapters = obj["num_chapters"]!!.jsonPrimitive.int
|
||||
cover_url = obj["main_picture"]?.jsonObject?.get("large")?.jsonPrimitive?.content ?: ""
|
||||
tracking_url = "https://myanimelist.net/manga/$media_id"
|
||||
publishing_status = obj["status"]!!.jsonPrimitive.content.replace("_", " ")
|
||||
publishing_type = obj["media_type"]!!.jsonPrimitive.content.replace("_", " ")
|
||||
start_date = try {
|
||||
val outputDf = SimpleDateFormat("yyyy-MM-dd", Locale.US)
|
||||
outputDf.format(obj["start_date"]!!)
|
||||
} catch (e: Exception) {
|
||||
""
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
suspend fun updateItem(track: Track): Track {
|
||||
return withIOContext {
|
||||
val formBodyBuilder = FormBody.Builder()
|
||||
.add("status", track.toMyAnimeListStatus() ?: "reading")
|
||||
.add("is_rereading", (track.status == MyAnimeList.REREADING).toString())
|
||||
.add("score", track.score.toString())
|
||||
.add("num_chapters_read", track.last_chapter_read.toString())
|
||||
.add("status", track.toMyAnimeListStatus() ?: "reading")
|
||||
.add("is_rereading", (track.status == MyAnimeList.REREADING).toString())
|
||||
.add("score", track.score.toString())
|
||||
.add("num_chapters_read", track.last_chapter_read.toString())
|
||||
convertToIsoDate(track.started_reading_date)?.let {
|
||||
formBodyBuilder.add("start_date", it)
|
||||
}
|
||||
@ -142,32 +127,31 @@ class MyAnimeListApi(private val client: OkHttpClient, interceptor: MyAnimeListI
|
||||
}
|
||||
|
||||
val request = Request.Builder()
|
||||
.url(mangaUrl(track.media_id).toString())
|
||||
.put(formBodyBuilder.build())
|
||||
.build()
|
||||
.url(mangaUrl(track.media_id).toString())
|
||||
.put(formBodyBuilder.build())
|
||||
.build()
|
||||
authClient.newCall(request)
|
||||
.await()
|
||||
.parseAs<JsonObject>()
|
||||
.let { parseMangaItem(it, track) }
|
||||
.await()
|
||||
.parseAs<JsonObject>()
|
||||
.let { parseMangaItem(it, track) }
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
suspend fun findListItem(track: Track): Track? {
|
||||
return withIOContext {
|
||||
val uri = "$baseApiUrl/manga".toUri().buildUpon()
|
||||
.appendPath(track.media_id.toString())
|
||||
.appendQueryParameter("fields", "num_chapters,my_list_status{start_date,finish_date}")
|
||||
.build()
|
||||
.appendPath(track.media_id.toString())
|
||||
.appendQueryParameter("fields", "num_chapters,my_list_status{start_date,finish_date}")
|
||||
.build()
|
||||
authClient.newCall(GET(uri.toString()))
|
||||
.await()
|
||||
.parseAs<JsonObject>()
|
||||
.let { obj ->
|
||||
track.total_chapters = obj["num_chapters"]!!.jsonPrimitive.int
|
||||
obj.jsonObject["my_list_status"]?.jsonObject?.let {
|
||||
parseMangaItem(it, track)
|
||||
}
|
||||
.await()
|
||||
.parseAs<JsonObject>()
|
||||
.let { obj ->
|
||||
track.total_chapters = obj["num_chapters"]!!.jsonPrimitive.int
|
||||
obj.jsonObject["my_list_status"]?.jsonObject?.let {
|
||||
parseMangaItem(it, track)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@ -177,17 +161,17 @@ class MyAnimeListApi(private val client: OkHttpClient, interceptor: MyAnimeListI
|
||||
val obj = json.jsonObject
|
||||
|
||||
val matches = obj["data"]!!.jsonArray
|
||||
.filter {
|
||||
it.jsonObject["node"]!!.jsonObject["title"]!!.jsonPrimitive.content.contains(
|
||||
query,
|
||||
ignoreCase = true
|
||||
)
|
||||
}
|
||||
.map {
|
||||
val id = it.jsonObject["node"]!!.jsonObject["id"]!!.jsonPrimitive.int
|
||||
async { getMangaDetails(id) }
|
||||
}
|
||||
.awaitAll()
|
||||
.filter {
|
||||
it.jsonObject["node"]!!.jsonObject["title"]!!.jsonPrimitive.content.contains(
|
||||
query,
|
||||
ignoreCase = true
|
||||
)
|
||||
}
|
||||
.map {
|
||||
val id = it.jsonObject["node"]!!.jsonObject["id"]!!.jsonPrimitive.int
|
||||
async { getMangaDetails(id) }
|
||||
}
|
||||
.awaitAll()
|
||||
|
||||
// Check next page if there's more
|
||||
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 {
|
||||
return withIOContext {
|
||||
val urlBuilder = "$baseApiUrl/users/@me/mangalist".toUri().buildUpon()
|
||||
.appendQueryParameter("fields", "list_status{start_date,finish_date}")
|
||||
.appendQueryParameter("limit", listPaginationAmount.toString())
|
||||
.appendQueryParameter("fields", "list_status{start_date,finish_date}")
|
||||
.appendQueryParameter("limit", listPaginationAmount.toString())
|
||||
if (offset > 0) {
|
||||
urlBuilder.appendQueryParameter("offset", offset.toString())
|
||||
}
|
||||
|
||||
val request = Request.Builder()
|
||||
.url(urlBuilder.build().toString())
|
||||
.get()
|
||||
.build()
|
||||
.url(urlBuilder.build().toString())
|
||||
.get()
|
||||
.build()
|
||||
authClient.newCall(request)
|
||||
.await()
|
||||
.parseAs()
|
||||
.await()
|
||||
.parseAs()
|
||||
}
|
||||
}
|
||||
|
||||
@ -251,7 +235,7 @@ class MyAnimeListApi(private val client: OkHttpClient, interceptor: MyAnimeListI
|
||||
|
||||
suspend fun remove(track: Track): Boolean {
|
||||
return withIOContext {
|
||||
try {
|
||||
try {
|
||||
val request = Request.Builder()
|
||||
.url(mangaUrl(track.media_id).toString())
|
||||
.delete()
|
||||
@ -277,22 +261,22 @@ class MyAnimeListApi(private val client: OkHttpClient, interceptor: MyAnimeListI
|
||||
private var codeVerifier: String = ""
|
||||
|
||||
fun authUrl(): Uri = "$baseOAuthUrl/authorize".toUri().buildUpon()
|
||||
.appendQueryParameter("client_id", clientId)
|
||||
.appendQueryParameter("code_challenge", getPkceChallengeCode())
|
||||
.appendQueryParameter("response_type", "code")
|
||||
.build()
|
||||
.appendQueryParameter("client_id", clientId)
|
||||
.appendQueryParameter("code_challenge", getPkceChallengeCode())
|
||||
.appendQueryParameter("response_type", "code")
|
||||
.build()
|
||||
|
||||
fun mangaUrl(id: Int): Uri = "$baseApiUrl/manga".toUri().buildUpon()
|
||||
.appendPath(id.toString())
|
||||
.appendPath("my_list_status")
|
||||
.build()
|
||||
.appendPath(id.toString())
|
||||
.appendPath("my_list_status")
|
||||
.build()
|
||||
|
||||
fun refreshTokenRequest(refreshToken: String): Request {
|
||||
val formBody: RequestBody = FormBody.Builder()
|
||||
.add("client_id", clientId)
|
||||
.add("refresh_token", refreshToken)
|
||||
.add("grant_type", "refresh_token")
|
||||
.build()
|
||||
.add("client_id", clientId)
|
||||
.add("refresh_token", refreshToken)
|
||||
.add("grant_type", "refresh_token")
|
||||
.build()
|
||||
return POST("$baseOAuthUrl/token", body = formBody)
|
||||
}
|
||||
|
||||
|
@ -3,16 +3,10 @@ package eu.kanade.tachiyomi.data.track.myanimelist
|
||||
import kotlinx.coroutines.CoroutineScope
|
||||
import kotlinx.coroutines.Dispatchers
|
||||
import kotlinx.coroutines.Job
|
||||
import kotlinx.coroutines.runBlocking
|
||||
import kotlinx.serialization.decodeFromString
|
||||
import kotlinx.serialization.json.Json
|
||||
import okhttp3.Interceptor
|
||||
import okhttp3.Request
|
||||
import okhttp3.RequestBody
|
||||
import okhttp3.RequestBody.Companion.toRequestBody
|
||||
import okhttp3.Response
|
||||
import okio.Buffer
|
||||
import org.json.JSONObject
|
||||
import uy.kohesive.injekt.injectLazy
|
||||
|
||||
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.
|
||||
val authRequest = originalRequest.newBuilder()
|
||||
.addHeader("Authorization", "Bearer ${oauth!!.access_token}")
|
||||
.build()
|
||||
.addHeader("Authorization", "Bearer ${oauth!!.access_token}")
|
||||
.build()
|
||||
|
||||
return chain.proceed(authRequest)
|
||||
}
|
||||
|
@ -69,8 +69,9 @@ class ExtensionManager(
|
||||
}
|
||||
|
||||
fun removeListener(listener: ExtensionsChangedListener) {
|
||||
if (this.listener == listener)
|
||||
if (this.listener == listener) {
|
||||
this.listener = null
|
||||
}
|
||||
}
|
||||
|
||||
fun getAppIconForSource(source: Source): Drawable? {
|
||||
|
@ -62,17 +62,17 @@ internal class ExtensionGithubApi {
|
||||
libVersion >= ExtensionLoader.LIB_VERSION_MIN && libVersion <= ExtensionLoader.LIB_VERSION_MAX
|
||||
}
|
||||
.map { element ->
|
||||
val name = element.jsonObject["name"]!!.jsonPrimitive.content.substringAfter("Tachiyomi: ")
|
||||
val pkgName = element.jsonObject["pkg"]!!.jsonPrimitive.content
|
||||
val apkName = element.jsonObject["apk"]!!.jsonPrimitive.content
|
||||
val versionName = element.jsonObject["version"]!!.jsonPrimitive.content
|
||||
val versionCode = element.jsonObject["code"]!!.jsonPrimitive.int
|
||||
val lang = element.jsonObject["lang"]!!.jsonPrimitive.content
|
||||
val nsfw = element.jsonObject["nsfw"]!!.jsonPrimitive.int == 1
|
||||
val icon = "${REPO_URL_PREFIX}icon/${apkName.replace(".apk", ".png")}"
|
||||
val name = element.jsonObject["name"]!!.jsonPrimitive.content.substringAfter("Tachiyomi: ")
|
||||
val pkgName = element.jsonObject["pkg"]!!.jsonPrimitive.content
|
||||
val apkName = element.jsonObject["apk"]!!.jsonPrimitive.content
|
||||
val versionName = element.jsonObject["version"]!!.jsonPrimitive.content
|
||||
val versionCode = element.jsonObject["code"]!!.jsonPrimitive.int
|
||||
val lang = element.jsonObject["lang"]!!.jsonPrimitive.content
|
||||
val nsfw = element.jsonObject["nsfw"]!!.jsonPrimitive.int == 1
|
||||
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 {
|
||||
|
@ -144,10 +144,11 @@ internal object ExtensionLoader {
|
||||
.split(";")
|
||||
.map {
|
||||
val sourceClass = it.trim()
|
||||
if (sourceClass.startsWith("."))
|
||||
if (sourceClass.startsWith(".")) {
|
||||
pkgInfo.packageName + sourceClass
|
||||
else
|
||||
} else {
|
||||
sourceClass
|
||||
}
|
||||
}
|
||||
.flatMap {
|
||||
try {
|
||||
|
@ -16,7 +16,6 @@ fun GET(
|
||||
headers: Headers = DEFAULT_HEADERS,
|
||||
cache: CacheControl = DEFAULT_CACHE_CONTROL
|
||||
): Request {
|
||||
|
||||
return Request.Builder()
|
||||
.url(url)
|
||||
.headers(headers)
|
||||
@ -30,7 +29,6 @@ fun POST(
|
||||
body: RequestBody = DEFAULT_BODY,
|
||||
cache: CacheControl = DEFAULT_CACHE_CONTROL
|
||||
): Request {
|
||||
|
||||
return Request.Builder()
|
||||
.url(url)
|
||||
.post(body)
|
||||
|
@ -61,8 +61,9 @@ class SmartSearchEngine(
|
||||
} else title
|
||||
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))
|
||||
}
|
||||
|
||||
searchResults.mangas.map {
|
||||
val normalizedDistance = normalizedLevenshtein.similarity(title, it.title)
|
||||
|
@ -15,14 +15,16 @@ open class Page(
|
||||
val number: Int
|
||||
get() = index + 1
|
||||
|
||||
@Transient @Volatile var status: Int = 0
|
||||
@Transient @Volatile
|
||||
var status: Int = 0
|
||||
set(value) {
|
||||
field = value
|
||||
statusSubject?.onNext(value)
|
||||
statusCallback?.invoke(this)
|
||||
}
|
||||
|
||||
@Transient @Volatile var progress: Int = 0
|
||||
@Transient @Volatile
|
||||
var progress: Int = 0
|
||||
set(value) {
|
||||
field = value
|
||||
statusCallback?.invoke(this)
|
||||
|
@ -36,25 +36,31 @@ interface SManga : Serializable {
|
||||
get() = (this as? MangaImpl)?.ogGenre ?: genre
|
||||
|
||||
fun copyFrom(other: SManga) {
|
||||
if (other.author != null)
|
||||
if (other.author != null) {
|
||||
author = other.originalAuthor
|
||||
}
|
||||
|
||||
if (other.artist != null)
|
||||
if (other.artist != null) {
|
||||
artist = other.originalArtist
|
||||
}
|
||||
|
||||
if (other.description != null)
|
||||
if (other.description != null) {
|
||||
description = other.originalDescription
|
||||
}
|
||||
|
||||
if (other.genre != null)
|
||||
if (other.genre != null) {
|
||||
genre = other.originalGenre
|
||||
}
|
||||
|
||||
if (other.thumbnail_url != null)
|
||||
if (other.thumbnail_url != null) {
|
||||
thumbnail_url = other.thumbnail_url
|
||||
}
|
||||
|
||||
status = other.status
|
||||
|
||||
if (!initialized)
|
||||
if (!initialized) {
|
||||
initialized = other.initialized
|
||||
}
|
||||
}
|
||||
|
||||
companion object {
|
||||
|
@ -29,7 +29,8 @@ abstract class BaseActivity : AppCompatActivity() {
|
||||
|
||||
override fun onResume() {
|
||||
super.onResume()
|
||||
if (this !is BiometricActivity && this !is SearchActivity)
|
||||
if (this !is BiometricActivity && this !is SearchActivity) {
|
||||
SecureActivityDelegate.promptLockIfNeeded(this)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -84,8 +84,9 @@ abstract class BaseController(bundle: Bundle? = null) :
|
||||
parentController = parentController.parentController
|
||||
}
|
||||
|
||||
if (router.backstack.lastOrNull()?.controller() == this)
|
||||
if (router.backstack.lastOrNull()?.controller() == this) {
|
||||
(activity as? AppCompatActivity)?.supportActionBar?.title = getTitle()
|
||||
}
|
||||
}
|
||||
|
||||
private fun Controller.instance(): String {
|
||||
|
@ -43,12 +43,10 @@ abstract class RxController(bundle: Bundle? = null) : BaseController(bundle) {
|
||||
}
|
||||
|
||||
fun <T> Observable<T>.subscribeUntilDetach(): Subscription {
|
||||
|
||||
return subscribe().also { untilDetachSubscriptions.add(it) }
|
||||
}
|
||||
|
||||
fun <T> Observable<T>.subscribeUntilDetach(onNext: (T) -> Unit): Subscription {
|
||||
|
||||
return subscribe(onNext).also { untilDetachSubscriptions.add(it) }
|
||||
}
|
||||
|
||||
@ -56,7 +54,6 @@ abstract class RxController(bundle: Bundle? = null) : BaseController(bundle) {
|
||||
onNext: (T) -> Unit,
|
||||
onError: (Throwable) -> Unit
|
||||
): Subscription {
|
||||
|
||||
return subscribe(onNext, onError).also { untilDetachSubscriptions.add(it) }
|
||||
}
|
||||
|
||||
@ -65,17 +62,14 @@ abstract class RxController(bundle: Bundle? = null) : BaseController(bundle) {
|
||||
onError: (Throwable) -> Unit,
|
||||
onCompleted: () -> Unit
|
||||
): Subscription {
|
||||
|
||||
return subscribe(onNext, onError, onCompleted).also { untilDetachSubscriptions.add(it) }
|
||||
}
|
||||
|
||||
fun <T> Observable<T>.subscribeUntilDestroy(): Subscription {
|
||||
|
||||
return subscribe().also { untilDestroySubscriptions.add(it) }
|
||||
}
|
||||
|
||||
fun <T> Observable<T>.subscribeUntilDestroy(onNext: (T) -> Unit): Subscription {
|
||||
|
||||
return subscribe(onNext).also { untilDestroySubscriptions.add(it) }
|
||||
}
|
||||
|
||||
@ -83,7 +77,6 @@ abstract class RxController(bundle: Bundle? = null) : BaseController(bundle) {
|
||||
onNext: (T) -> Unit,
|
||||
onError: (Throwable) -> Unit
|
||||
): Subscription {
|
||||
|
||||
return subscribe(onNext, onError).also { untilDestroySubscriptions.add(it) }
|
||||
}
|
||||
|
||||
@ -92,7 +85,6 @@ abstract class RxController(bundle: Bundle? = null) : BaseController(bundle) {
|
||||
onError: (Throwable) -> Unit,
|
||||
onCompleted: () -> Unit
|
||||
): Subscription {
|
||||
|
||||
return subscribe(onNext, onError, onCompleted).also { untilDestroySubscriptions.add(it) }
|
||||
}
|
||||
}
|
||||
|
@ -122,8 +122,9 @@ class CategoryController(bundle: Bundle? = null) :
|
||||
|
||||
override fun onCategoryRename(position: Int, newName: String): Boolean {
|
||||
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.renameCategory(category, newName))
|
||||
}
|
||||
|
||||
@ -185,6 +186,7 @@ class CategoryController(bundle: Bundle? = null) :
|
||||
override fun shouldMoveItem(fromPosition: Int, toPosition: Int): Boolean {
|
||||
return toPosition > 0
|
||||
}
|
||||
|
||||
/**
|
||||
* Called from the presenter when a category with the given name already exists.
|
||||
*/
|
||||
|
@ -121,8 +121,9 @@ class CategoryHolder(view: View, val adapter: CategoryAdapter) : BaseFlexibleVie
|
||||
) {
|
||||
isEditing(false)
|
||||
edit_text.inputType = InputType.TYPE_NULL
|
||||
if (!createCategory)
|
||||
if (!createCategory) {
|
||||
title.text = edit_text.text.toString()
|
||||
}
|
||||
}
|
||||
} else {
|
||||
itemView.performClick()
|
||||
|
@ -105,10 +105,11 @@ class ManageCategoryDialog(bundle: Bundle? = null) :
|
||||
preferences.downloadNewCategories(),
|
||||
true
|
||||
)
|
||||
if (downloadNew && preferences.downloadNewCategories().get().isEmpty())
|
||||
if (downloadNew && preferences.downloadNewCategories().get().isEmpty()) {
|
||||
view.download_new.gone()
|
||||
else if (!downloadNew)
|
||||
} else if (!downloadNew) {
|
||||
view.download_new.visible()
|
||||
}
|
||||
view.download_new.isChecked =
|
||||
preferences.downloadNew().get() && view.download_new.isChecked
|
||||
setCheckbox(
|
||||
@ -132,9 +133,9 @@ class ManageCategoryDialog(bundle: Bundle? = null) :
|
||||
}
|
||||
|
||||
private fun setCheckbox(
|
||||
box: CompoundButton,
|
||||
categories: Preference<Set<String>>,
|
||||
shouldShow: Boolean
|
||||
box: CompoundButton,
|
||||
categories: Preference<Set<String>>,
|
||||
shouldShow: Boolean
|
||||
) {
|
||||
val updateCategories = categories.get()
|
||||
box.visibleIf(updateCategories.isNotEmpty() && shouldShow)
|
||||
|
@ -202,8 +202,9 @@ class DownloadBottomSheet @JvmOverloads constructor(
|
||||
val adapter = adapter ?: return false
|
||||
val items = adapter.currentItems.sortedBy { it.download.chapter.date_upload }
|
||||
.toMutableList()
|
||||
if (item.itemId == R.id.newest)
|
||||
if (item.itemId == R.id.newest) {
|
||||
items.reverse()
|
||||
}
|
||||
adapter.updateDataSet(items)
|
||||
val downloads = items.mapNotNull { it.download }
|
||||
presenter.reorder(downloads)
|
||||
@ -266,10 +267,11 @@ class DownloadBottomSheet @JvmOverloads constructor(
|
||||
val items = adapter?.currentItems?.toMutableList() ?: return
|
||||
val item = items[position]
|
||||
items.remove(item)
|
||||
if (menuItem.itemId == R.id.move_to_top)
|
||||
if (menuItem.itemId == R.id.move_to_top) {
|
||||
items.add(0, item)
|
||||
else
|
||||
} else {
|
||||
items.add(item)
|
||||
}
|
||||
adapter?.updateDataSet(items)
|
||||
val downloads = items.mapNotNull { it.download }
|
||||
presenter.reorder(downloads)
|
||||
|
@ -59,8 +59,9 @@ class DownloadButton @JvmOverloads constructor(context: Context, attrs: Attribut
|
||||
isAnimating = false
|
||||
}
|
||||
download_icon.setImageDrawable(
|
||||
if (state == Download.CHECKED)
|
||||
checkDrawable else downloadDrawable
|
||||
if (state == Download.CHECKED) {
|
||||
checkDrawable
|
||||
} else downloadDrawable
|
||||
)
|
||||
when (state) {
|
||||
Download.CHECKED -> {
|
||||
|
@ -15,7 +15,6 @@ import eu.kanade.tachiyomi.source.SourceManager
|
||||
import eu.kanade.tachiyomi.ui.migration.MangaItem
|
||||
import eu.kanade.tachiyomi.ui.migration.SelectionHeader
|
||||
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.executeOnIO
|
||||
import kotlinx.coroutines.CoroutineScope
|
||||
@ -26,8 +25,6 @@ import kotlinx.coroutines.awaitAll
|
||||
import kotlinx.coroutines.launch
|
||||
import kotlinx.coroutines.withContext
|
||||
import rx.Observable
|
||||
import rx.android.schedulers.AndroidSchedulers
|
||||
import rx.schedulers.Schedulers
|
||||
import uy.kohesive.injekt.Injekt
|
||||
import uy.kohesive.injekt.api.get
|
||||
|
||||
@ -76,14 +73,15 @@ class ExtensionBottomPresenter(
|
||||
val migrationJob = async {
|
||||
val favs = db.getFavoriteMangas().executeOnIO()
|
||||
sourceItems = findSourcesWithManga(favs)
|
||||
mangaItems = HashMap(sourceItems.associate {
|
||||
it.source.id to this@ExtensionBottomPresenter.libraryToMigrationItem(favs, it.source.id)
|
||||
})
|
||||
mangaItems = HashMap(
|
||||
sourceItems.associate {
|
||||
it.source.id to this@ExtensionBottomPresenter.libraryToMigrationItem(favs, it.source.id)
|
||||
}
|
||||
)
|
||||
withContext(Dispatchers.Main) {
|
||||
if (selectedSource != null) {
|
||||
bottomSheet.setMigrationManga(mangaItems[selectedSource])
|
||||
}
|
||||
else {
|
||||
} else {
|
||||
bottomSheet.setMigrationSources(sourceItems)
|
||||
}
|
||||
}
|
||||
@ -125,14 +123,15 @@ class ExtensionBottomPresenter(
|
||||
scope.launch {
|
||||
val favs = db.getFavoriteMangas().executeOnIO()
|
||||
sourceItems = findSourcesWithManga(favs)
|
||||
mangaItems = HashMap(sourceItems.associate {
|
||||
it.source.id to this@ExtensionBottomPresenter.libraryToMigrationItem(favs, it.source.id)
|
||||
})
|
||||
mangaItems = HashMap(
|
||||
sourceItems.associate {
|
||||
it.source.id to this@ExtensionBottomPresenter.libraryToMigrationItem(favs, it.source.id)
|
||||
}
|
||||
)
|
||||
withContext(Dispatchers.Main) {
|
||||
if (selectedSource != null) {
|
||||
bottomSheet.setMigrationManga(mangaItems[selectedSource])
|
||||
}
|
||||
else {
|
||||
} else {
|
||||
bottomSheet.setMigrationSources(sourceItems)
|
||||
}
|
||||
}
|
||||
|
@ -308,10 +308,12 @@ class ExtensionBottomSheet @JvmOverloads constructor(context: Context, attrs: At
|
||||
}
|
||||
|
||||
override fun getPageTitle(position: Int): CharSequence {
|
||||
return context.getString(when (position) {
|
||||
0 -> R.string.extensions
|
||||
else -> R.string.migration
|
||||
})
|
||||
return context.getString(
|
||||
when (position) {
|
||||
0 -> R.string.extensions
|
||||
else -> R.string.migration
|
||||
}
|
||||
)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -38,7 +38,6 @@ data class ExtensionGroupItem(val name: String, val size: Int) : AbstractHeaderI
|
||||
position: Int,
|
||||
payloads: MutableList<Any?>?
|
||||
) {
|
||||
|
||||
holder.bind(this)
|
||||
}
|
||||
|
||||
|
@ -46,7 +46,6 @@ data class ExtensionItem(
|
||||
position: Int,
|
||||
payloads: MutableList<Any?>?
|
||||
) {
|
||||
|
||||
if (payloads == null || payloads.isEmpty()) {
|
||||
holder.bind(this)
|
||||
} else {
|
||||
|
@ -3,7 +3,6 @@ package eu.kanade.tachiyomi.ui.extension
|
||||
import androidx.preference.PreferenceScreen
|
||||
import androidx.preference.SwitchPreference
|
||||
import eu.kanade.tachiyomi.R
|
||||
import eu.kanade.tachiyomi.data.preference.getOrDefault
|
||||
import eu.kanade.tachiyomi.extension.ExtensionManager
|
||||
import eu.kanade.tachiyomi.ui.setting.SettingsController
|
||||
import eu.kanade.tachiyomi.ui.setting.onChange
|
||||
|
@ -125,7 +125,8 @@ class ExtensionDetailsController(bundle: Bundle? = null) :
|
||||
screen.setShouldUseGeneratedIds(true)
|
||||
val extHeaderAdapter = ExtensionDetailsHeaderAdapter(presenter)
|
||||
extHeaderAdapter.setHasStableIds(true)
|
||||
extension_prefs_recycler.adapter = ConcatAdapter(concatAdapterConfig,
|
||||
extension_prefs_recycler.adapter = ConcatAdapter(
|
||||
concatAdapterConfig,
|
||||
extHeaderAdapter,
|
||||
PreferenceGroupAdapter(screen)
|
||||
)
|
||||
@ -151,7 +152,6 @@ class ExtensionDetailsController(bundle: Bundle? = null) :
|
||||
lastOpenPreferencePosition = savedInstanceState.get(LASTOPENPREFERENCE_KEY) as? Int
|
||||
}
|
||||
|
||||
|
||||
override fun onCreateOptionsMenu(menu: Menu, inflater: MenuInflater) {
|
||||
inflater.inflate(R.menu.extension_details, menu)
|
||||
|
||||
@ -208,8 +208,7 @@ class ExtensionDetailsController(bundle: Bundle? = null) :
|
||||
toggleSource(source, checked)
|
||||
prefs.forEach { it.isVisible = checked }
|
||||
true
|
||||
}
|
||||
else {
|
||||
} else {
|
||||
coordinator.snack(context.getString(R.string._must_be_enabled_first, title), Snackbar.LENGTH_LONG) {
|
||||
setAction(R.string.enable) {
|
||||
preferences.enabledLanguages() += source.lang
|
||||
@ -308,7 +307,6 @@ class ExtensionDetailsController(bundle: Bundle? = null) :
|
||||
return id.toString() !in preferences.hiddenSources().get() && isLangEnabled()
|
||||
}
|
||||
|
||||
|
||||
private fun Source.isLangEnabled(langs: Set<String>? = null): Boolean {
|
||||
return (lang in langs ?: preferences.enabledLanguages().get())
|
||||
}
|
||||
|
@ -45,7 +45,7 @@ class ExtensionDetailsHeaderAdapter(private val presenter: ExtensionDetailsPrese
|
||||
view.extension_pkg.text = extension.pkgName
|
||||
|
||||
view.extension_uninstall_button.setOnClickListener {
|
||||
presenter.uninstallExtension()
|
||||
presenter.uninstallExtension()
|
||||
}
|
||||
|
||||
if (extension.isObsolete) {
|
||||
|
@ -51,4 +51,4 @@ class ExtensionSettingsDividerItemDecoration(context: Context) : androidx.recycl
|
||||
) {
|
||||
outRect.set(0, 0, 0, divider.intrinsicHeight)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -41,7 +41,6 @@ class AddToLibraryCategoriesDialog<T>(bundle: Bundle? = null) :
|
||||
}
|
||||
|
||||
override fun onCreateDialog(savedViewState: Bundle?): Dialog {
|
||||
|
||||
return MaterialDialog(activity!!).title(R.string.add_to_library).message(R.string.add_to_categories)
|
||||
.listItemsMultiChoice(
|
||||
items = categories.map { it.name },
|
||||
|
@ -29,6 +29,7 @@ class LibraryCategoryAdapter(val controller: LibraryController) :
|
||||
init {
|
||||
setDisplayHeadersAtStartUp(true)
|
||||
}
|
||||
|
||||
/**
|
||||
* The list of manga in this category.
|
||||
*/
|
||||
|
@ -619,13 +619,12 @@ class LibraryController(
|
||||
(listOfYs.minOrNull() ?: filter_bottom_sheet.y) +
|
||||
hopperOffset
|
||||
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 {
|
||||
jumper_category_text.translationY = 0f
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
fun resetHopperY() {
|
||||
hopperOffset = 0f
|
||||
}
|
||||
@ -821,10 +820,11 @@ class LibraryController(
|
||||
)
|
||||
}
|
||||
adapter.setItems(mangaMap)
|
||||
if (recycler.itemAnimator == null)
|
||||
if (recycler.itemAnimator == null) {
|
||||
recycler.post {
|
||||
recycler.itemAnimator = DefaultItemAnimator()
|
||||
}
|
||||
}
|
||||
singleCategory = presenter.categories.size <= 1
|
||||
showDropdown()
|
||||
progress.gone()
|
||||
|
@ -70,8 +70,9 @@ class LibraryGridHolder(
|
||||
if (cover_thumbnail.height == 0) {
|
||||
val oldPos = adapterPosition
|
||||
adapter.recyclerView.post {
|
||||
if (oldPos == adapterPosition)
|
||||
if (oldPos == adapterPosition) {
|
||||
setCover(item.manga)
|
||||
}
|
||||
}
|
||||
} else setCover(item.manga)
|
||||
}
|
||||
|
@ -44,8 +44,9 @@ abstract class LibraryHolder(
|
||||
}
|
||||
|
||||
fun setReadingButton(item: LibraryItem) {
|
||||
play_layout?.visibility = if (item.manga.unread > 0 && item.unreadType > 0 && !item.hideReadingButton)
|
||||
View.VISIBLE else View.GONE
|
||||
play_layout?.visibility = if (item.manga.unread > 0 && item.unreadType > 0 && !item.hideReadingButton) {
|
||||
View.VISIBLE
|
||||
} else View.GONE
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -46,10 +46,11 @@ class LibraryItem(
|
||||
get() = preferences.hideStartReadingButton().getOrDefault()
|
||||
|
||||
override fun getLayoutRes(): Int {
|
||||
return if (libraryLayout == 0 || manga.isBlank())
|
||||
return if (libraryLayout == 0 || manga.isBlank()) {
|
||||
R.layout.manga_list_item
|
||||
else
|
||||
} else {
|
||||
R.layout.manga_grid_item
|
||||
}
|
||||
}
|
||||
|
||||
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.
|
||||
*/
|
||||
override fun filter(constraint: String): Boolean {
|
||||
if (manga.isBlank() && manga.title.isBlank())
|
||||
if (manga.isBlank() && manga.title.isBlank()) {
|
||||
return constraint.isEmpty()
|
||||
}
|
||||
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
|
||||
}
|
||||
return manga.title.contains(constraint, true) ||
|
||||
(manga.author?.contains(constraint, true) ?: false) ||
|
||||
(manga.artist?.contains(constraint, true) ?: false) ||
|
||||
@ -159,14 +162,15 @@ class LibraryItem(
|
||||
@SuppressLint("DefaultLocale")
|
||||
private fun containsGenre(tag: String, genres: List<String>?): Boolean {
|
||||
if (tag.trim().isEmpty()) return true
|
||||
return if (tag.startsWith("-"))
|
||||
return if (tag.startsWith("-")) {
|
||||
genres?.find {
|
||||
it.trim().toLowerCase() == tag.substringAfter("-").toLowerCase()
|
||||
} == null
|
||||
else
|
||||
} else {
|
||||
genres?.find {
|
||||
it.trim().toLowerCase() == tag.toLowerCase()
|
||||
} != null
|
||||
}
|
||||
}
|
||||
|
||||
override fun equals(other: Any?): Boolean {
|
||||
|
@ -36,7 +36,6 @@ class LibraryListHolder(
|
||||
* @param item the manga item to bind.
|
||||
*/
|
||||
override fun onSetValues(item: LibraryItem) {
|
||||
|
||||
title.visible()
|
||||
constraint_layout.minHeight = 56.dpToPx
|
||||
if (item.manga.isBlank()) {
|
||||
@ -47,8 +46,9 @@ class LibraryListHolder(
|
||||
if (item.manga.status == -1) {
|
||||
title.text = null
|
||||
title.gone()
|
||||
} else
|
||||
} else {
|
||||
title.text = itemView.context.getString(R.string.category_is_empty)
|
||||
}
|
||||
title.textAlignment = View.TEXT_ALIGNMENT_CENTER
|
||||
card.gone()
|
||||
badge_view.gone()
|
||||
|
@ -729,8 +729,9 @@ class LibraryPresenter(
|
||||
db.resetMangaInfo(manga).executeOnIO()
|
||||
coverCache.deleteFromCache(manga)
|
||||
val source = sourceManager.get(manga.source) as? HttpSource
|
||||
if (source != null)
|
||||
if (source != null) {
|
||||
downloadManager.deleteManga(manga, source)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -825,9 +826,10 @@ class LibraryPresenter(
|
||||
val mc = ArrayList<MangaCategory>()
|
||||
val categories =
|
||||
if (catId == 0) emptyList()
|
||||
else
|
||||
else {
|
||||
db.getCategoriesForManga(manga).executeOnIO()
|
||||
.filter { it.id != oldCatId } + listOf(category)
|
||||
}
|
||||
|
||||
for (cat in categories) {
|
||||
mc.add(MangaCategory.create(manga, cat))
|
||||
@ -858,10 +860,11 @@ class LibraryPresenter(
|
||||
val categoriesHidden = preferences.collapsedCategories().getOrDefault().mapNotNull {
|
||||
it.toIntOrNull()
|
||||
}.toMutableSet()
|
||||
if (categoryId in categoriesHidden)
|
||||
if (categoryId in categoriesHidden) {
|
||||
categoriesHidden.remove(categoryId)
|
||||
else
|
||||
} else {
|
||||
categoriesHidden.add(categoryId)
|
||||
}
|
||||
preferences.collapsedCategories().set(categoriesHidden.map { it.toString() }.toMutableSet())
|
||||
getLibrary()
|
||||
}
|
||||
|
@ -47,8 +47,9 @@ class CategoryRecyclerView @JvmOverloads constructor(
|
||||
}
|
||||
)
|
||||
fastAdapter.onClickListener = { _, _, item, _ ->
|
||||
if (item.category.id != -1)
|
||||
if (item.category.id != -1) {
|
||||
onCategoryClicked(item.category.order)
|
||||
}
|
||||
true
|
||||
}
|
||||
}
|
||||
|
@ -20,4 +20,4 @@ class LibraryBadgesView @JvmOverloads constructor(context: Context, attrs: Attri
|
||||
controller.presenter.requestDownloadBadgesUpdate()
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -25,4 +25,4 @@ class LibraryCategoryView @JvmOverloads constructor(context: Context, attrs: Att
|
||||
controller.resetHopperY()
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -20,4 +20,4 @@ class LibraryDisplayView @JvmOverloads constructor(context: Context, attrs: Attr
|
||||
controller.reattachAdapter()
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -11,7 +11,7 @@ import eu.kanade.tachiyomi.util.view.withFadeTransaction
|
||||
import eu.kanade.tachiyomi.widget.TabbedBottomSheetDialog
|
||||
import kotlinx.android.synthetic.main.tabbed_bottom_sheet.*
|
||||
|
||||
open class TabbedLibraryDisplaySheet(controller: LibraryController):
|
||||
open class TabbedLibraryDisplaySheet(controller: LibraryController) :
|
||||
TabbedBottomSheetDialog(controller.activity!!) {
|
||||
|
||||
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) {
|
||||
menu.tooltipText = context.getString(R.string.more_library_settings)
|
||||
}
|
||||
menu.setImageDrawable(ContextCompat.getDrawable(
|
||||
context,
|
||||
R.drawable.ic_settings_24dp
|
||||
))
|
||||
menu.setImageDrawable(
|
||||
ContextCompat.getDrawable(
|
||||
context,
|
||||
R.drawable.ic_settings_24dp
|
||||
)
|
||||
)
|
||||
menu.setOnClickListener {
|
||||
controller.router.pushController(SettingsLibraryController().withFadeTransaction())
|
||||
dismiss()
|
||||
@ -47,4 +49,4 @@ open class TabbedLibraryDisplaySheet(controller: LibraryController):
|
||||
R.string.badges,
|
||||
R.string.categories
|
||||
)
|
||||
}
|
||||
}
|
||||
|
@ -90,8 +90,9 @@ class FilterBottomSheet @JvmOverloads constructor(context: Context, attrs: Attri
|
||||
list.add(unread)
|
||||
list.add(downloaded)
|
||||
list.add(completed)
|
||||
if (hasTracking)
|
||||
if (hasTracking) {
|
||||
tracked?.let { list.add(it) }
|
||||
}
|
||||
list
|
||||
}
|
||||
|
||||
@ -152,8 +153,9 @@ class FilterBottomSheet @JvmOverloads constructor(context: Context, attrs: Attri
|
||||
}
|
||||
|
||||
val activeFilters = hasActiveFiltersFromPref()
|
||||
if (activeFilters && sheetBehavior.isHidden() && sheetBehavior?.skipCollapsed == false)
|
||||
if (activeFilters && sheetBehavior.isHidden() && sheetBehavior?.skipCollapsed == false) {
|
||||
sheetBehavior?.collapse()
|
||||
}
|
||||
|
||||
post {
|
||||
updateRootPadding(
|
||||
@ -218,10 +220,11 @@ class FilterBottomSheet @JvmOverloads constructor(context: Context, attrs: Attri
|
||||
?: if (sheetBehavior.isExpanded()) 1f else 0f
|
||||
val percent = (trueProgress * 100).roundToInt()
|
||||
val value = (percent * (maxHeight - minHeight) / 100) + minHeight
|
||||
if (trueProgress >= 0)
|
||||
if (trueProgress >= 0) {
|
||||
libraryRecyler?.updatePaddingRelative(bottom = value + 10.dpToPx + bottomBarHeight)
|
||||
else
|
||||
} else {
|
||||
libraryRecyler?.updatePaddingRelative(bottom = (minHeight * (1 + trueProgress)).toInt() + bottomBarHeight)
|
||||
}
|
||||
}
|
||||
|
||||
fun hasActiveFilters() = filterItems.any { it.isActivated }
|
||||
@ -235,7 +238,6 @@ class FilterBottomSheet @JvmOverloads constructor(context: Context, attrs: Attri
|
||||
}
|
||||
|
||||
private fun createTags() {
|
||||
|
||||
downloaded = inflate(R.layout.filter_buttons) as FilterTagGroup
|
||||
downloaded.setup(this, R.string.downloaded, R.string.not_downloaded)
|
||||
|
||||
@ -372,8 +374,9 @@ class FilterBottomSheet @JvmOverloads constructor(context: Context, attrs: Attri
|
||||
|
||||
fun manageFilterPopup() {
|
||||
val recycler = RecyclerView(context)
|
||||
if (filterOrder.count() != 6)
|
||||
if (filterOrder.count() != 6) {
|
||||
filterOrder = "urdcmt"
|
||||
}
|
||||
val adapter = FlexibleAdapter(
|
||||
filterOrder.toCharArray().map(::ManageFilterItem),
|
||||
this,
|
||||
@ -493,8 +496,9 @@ class FilterBottomSheet @JvmOverloads constructor(context: Context, attrs: Attri
|
||||
|
||||
private fun reSortViews() {
|
||||
filter_layout.removeAllViews()
|
||||
if (filterItems.any { it.isActivated })
|
||||
if (filterItems.any { it.isActivated }) {
|
||||
filter_layout.addView(clearButton)
|
||||
}
|
||||
filterItems.filter { it.isActivated }.forEach {
|
||||
filter_layout.addView(it)
|
||||
}
|
||||
|
@ -84,8 +84,9 @@ class FilterTagGroup@JvmOverloads constructor(context: Context, attrs: Attribute
|
||||
private fun toggleButton(index: Int, callBack: Boolean = true) {
|
||||
if (index < 0 || itemCount == 0 ||
|
||||
(isActivated && index != buttons.indexOfFirst { it.isActivated })
|
||||
)
|
||||
) {
|
||||
return
|
||||
}
|
||||
if (callBack) {
|
||||
val transition = androidx.transition.AutoTransition()
|
||||
transition.duration = 150
|
||||
|
@ -268,7 +268,6 @@ open class MainActivity : BaseActivity(), DownloadServiceListener {
|
||||
container: ViewGroup,
|
||||
handler: ControllerChangeHandler
|
||||
) {
|
||||
|
||||
syncActivityViewWithController(to, from, isPush)
|
||||
appbar.y = 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) {
|
||||
// basically if in landscape on a phone
|
||||
// For lollipop, draw opaque nav bar
|
||||
if (insets.hasSideNavBar())
|
||||
if (insets.hasSideNavBar()) {
|
||||
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
|
||||
// this is here in case some crazy with a notch uses landscape
|
||||
@ -515,10 +514,10 @@ open class MainActivity : BaseActivity(), DownloadServiceListener {
|
||||
else !router.handleBack()
|
||||
) {
|
||||
if (preferences.backReturnsToStart().get() && this !is SearchActivity &&
|
||||
startingTab() != bottom_nav?.selectedItemId) {
|
||||
startingTab() != bottom_nav?.selectedItemId
|
||||
) {
|
||||
goToStartingTab()
|
||||
}
|
||||
else {
|
||||
} else {
|
||||
if (!preferences.backReturnsToStart().get() && this !is SearchActivity) {
|
||||
setStartingTab()
|
||||
}
|
||||
@ -529,13 +528,17 @@ open class MainActivity : BaseActivity(), DownloadServiceListener {
|
||||
}
|
||||
|
||||
private fun setStartingTab() {
|
||||
if (bottom_nav?.selectedItemId != R.id.nav_browse
|
||||
&& bottom_nav?.selectedItemId != null
|
||||
&& preferences.startingTab().get() >= 0)
|
||||
preferences.startingTab().set(when (bottom_nav?.selectedItemId) {
|
||||
R.id.nav_library -> 0
|
||||
else -> 1
|
||||
})
|
||||
if (bottom_nav?.selectedItemId != R.id.nav_browse &&
|
||||
bottom_nav?.selectedItemId != null &&
|
||||
preferences.startingTab().get() >= 0
|
||||
) {
|
||||
preferences.startingTab().set(
|
||||
when (bottom_nav?.selectedItemId) {
|
||||
R.id.nav_library -> 0
|
||||
else -> 1
|
||||
}
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
@IdRes
|
||||
|
@ -69,8 +69,9 @@ class EditMangaDialog : DialogController {
|
||||
val isLocal = manga.source == LocalSource.ID
|
||||
|
||||
if (isLocal) {
|
||||
if (manga.title != manga.url)
|
||||
if (manga.title != manga.url) {
|
||||
view.title.append(manga.title)
|
||||
}
|
||||
view.title.hint = "${resources?.getString(R.string.title)}: ${manga.url}"
|
||||
view.manga_author.append(manga.author ?: "")
|
||||
view.manga_artist.append(manga.artist ?: "")
|
||||
|
@ -434,8 +434,9 @@ class MangaDetailsController :
|
||||
setActionBar(true)
|
||||
setStatusBarAndToolbar()
|
||||
} 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
|
||||
}
|
||||
if (type == ControllerChangeType.POP_EXIT) {
|
||||
setActionBar(false)
|
||||
presenter.cancelScope()
|
||||
@ -1042,10 +1043,11 @@ class MangaDetailsController :
|
||||
if (chapter.status != Download.NOT_DOWNLOADED && chapter.status != Download.ERROR) {
|
||||
presenter.deleteChapter(chapter)
|
||||
} else {
|
||||
if (chapter.status == Download.ERROR)
|
||||
if (chapter.status == Download.ERROR) {
|
||||
DownloadService.start(view.context)
|
||||
else
|
||||
} else {
|
||||
downloadChapters(listOf(chapter))
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@ -1279,8 +1281,9 @@ class MangaDetailsController :
|
||||
|
||||
override fun onPrepareActionMode(mode: ActionMode?, menu: Menu?): Boolean {
|
||||
mode?.title = view?.context?.getString(
|
||||
if (startingDLChapterPos == null)
|
||||
R.string.select_starting_chapter else R.string.select_ending_chapter
|
||||
if (startingDLChapterPos == null) {
|
||||
R.string.select_starting_chapter
|
||||
} else R.string.select_ending_chapter
|
||||
)
|
||||
return false
|
||||
}
|
||||
|
@ -4,7 +4,6 @@ import android.app.Application
|
||||
import android.graphics.Bitmap
|
||||
import android.net.Uri
|
||||
import android.os.Environment
|
||||
import coil.Coil
|
||||
import eu.kanade.tachiyomi.R
|
||||
import eu.kanade.tachiyomi.data.cache.CoverCache
|
||||
import eu.kanade.tachiyomi.data.database.DatabaseHelper
|
||||
@ -88,7 +87,6 @@ class MangaDetailsPresenter(
|
||||
var headerItem = MangaHeaderItem(manga, controller.fromCatalogue)
|
||||
|
||||
fun onCreate() {
|
||||
|
||||
isLockedFromSearch = SecureActivityDelegate.shouldBeLocked()
|
||||
headerItem.isLocked = isLockedFromSearch
|
||||
downloadManager.addListener(this)
|
||||
@ -218,8 +216,9 @@ class MangaDetailsPresenter(
|
||||
* @return an observable of the list of chapters filtered and sorted.
|
||||
*/
|
||||
private fun applyChapterFilters(chapterList: List<ChapterItem>): List<ChapterItem> {
|
||||
if (isLockedFromSearch)
|
||||
if (isLockedFromSearch) {
|
||||
return chapterList
|
||||
}
|
||||
|
||||
val chapters = chapterFilter.filterChapters(chapterList, manga)
|
||||
|
||||
@ -357,8 +356,8 @@ class MangaDetailsPresenter(
|
||||
if (newChapters.first.isNotEmpty()) {
|
||||
if (manga.shouldDownloadNewChapters(db, preferences)) {
|
||||
downloadChapters(
|
||||
newChapters.first.sortedBy { it.chapter_number }
|
||||
.map { it.toModel() }
|
||||
newChapters.first.sortedBy { it.chapter_number }
|
||||
.map { it.toModel() }
|
||||
)
|
||||
}
|
||||
}
|
||||
@ -867,8 +866,9 @@ class MangaDetailsPresenter(
|
||||
fun setStatus(item: TrackItem, index: Int) {
|
||||
val track = item.track!!
|
||||
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
|
||||
}
|
||||
updateRemote(track, item.service)
|
||||
}
|
||||
|
||||
|
@ -70,8 +70,8 @@ class MangaHeaderHolder(
|
||||
}
|
||||
if (event.actionMasked == MotionEvent.ACTION_UP) {
|
||||
hadSelection = manga_summary.hasSelection()
|
||||
(adapter.delegate as MangaDetailsController).swipe_refresh.isEnabled =
|
||||
true
|
||||
(adapter.delegate as MangaDetailsController).swipe_refresh.isEnabled =
|
||||
true
|
||||
}
|
||||
false
|
||||
}
|
||||
@ -320,9 +320,9 @@ class MangaHeaderHolder(
|
||||
fun collapse() {
|
||||
sub_item_group.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()
|
||||
else {
|
||||
} else {
|
||||
less_button.gone()
|
||||
manga_genres_tags.gone()
|
||||
}
|
||||
|
@ -40,10 +40,11 @@ class ChaptersSortBottomSheet(controller: MangaDetailsController) : BottomSheetD
|
||||
sheetBehavior.addBottomSheetCallback(
|
||||
object : BottomSheetBehavior.BottomSheetCallback() {
|
||||
override fun onSlide(bottomSheet: View, progress: Float) {
|
||||
if (progress.isNaN())
|
||||
if (progress.isNaN()) {
|
||||
pill.alpha = 0f
|
||||
else
|
||||
} else {
|
||||
pill.alpha = (1 - max(0f, progress)) * 0.25f
|
||||
}
|
||||
}
|
||||
|
||||
override fun onStateChanged(p0: View, state: Int) {
|
||||
@ -92,14 +93,16 @@ class ChaptersSortBottomSheet(controller: MangaDetailsController) : BottomSheetD
|
||||
|
||||
var defPref = presenter.globalSort()
|
||||
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
|
||||
}
|
||||
)
|
||||
|
||||
hide_titles.isChecked = presenter.manga.displayMode != Manga.DISPLAY_NAME
|
||||
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
|
||||
}
|
||||
)
|
||||
|
||||
set_as_default_sort.visInvisIf(
|
||||
|
@ -70,12 +70,14 @@ class SetTrackReadingDatesDialog<T> : DialogController
|
||||
listener.setReadingDate(item, dateToUpdate, 0L)
|
||||
}.apply {
|
||||
getSuggestedDate()?.let {
|
||||
message(text = it,
|
||||
applySettings = {
|
||||
messageTextView.setOnClickListener {
|
||||
this@apply.setDate(suggestedDate ?: 0L)
|
||||
message(
|
||||
text = it,
|
||||
applySettings = {
|
||||
messageTextView.setOnClickListener {
|
||||
this@apply.setDate(suggestedDate ?: 0L)
|
||||
}
|
||||
}
|
||||
})
|
||||
)
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -93,9 +95,11 @@ class SetTrackReadingDatesDialog<T> : DialogController
|
||||
val suggestedCalendar = Calendar.getInstance()
|
||||
suggestedCalendar.timeInMillis = suggestedDate
|
||||
return if (date > suggestedDate &&
|
||||
(suggestedCalendar.year != calendar.year ||
|
||||
suggestedCalendar.month != calendar.month ||
|
||||
suggestedCalendar.dayOfMonth != calendar.dayOfMonth)
|
||||
(
|
||||
suggestedCalendar.year != calendar.year ||
|
||||
suggestedCalendar.month != calendar.month ||
|
||||
suggestedCalendar.dayOfMonth != calendar.dayOfMonth
|
||||
)
|
||||
) {
|
||||
activity?.getString(
|
||||
R.string.suggested_date_,
|
||||
|
@ -72,9 +72,9 @@ class TrackHolder(view: View, adapter: TrackAdapter) : BaseViewHolder(view) {
|
||||
date_group.visibleIf(item.service.supportsReadingDates)
|
||||
if (item.service.supportsReadingDates) {
|
||||
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 =
|
||||
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 {
|
||||
}
|
||||
}
|
||||
|
@ -1,8 +1,6 @@
|
||||
package eu.kanade.tachiyomi.ui.manga.track
|
||||
|
||||
import android.content.Intent
|
||||
import android.graphics.Color
|
||||
import android.graphics.drawable.ColorDrawable
|
||||
import android.os.Bundle
|
||||
import android.view.View
|
||||
import android.view.ViewGroup
|
||||
@ -190,11 +188,13 @@ class TrackingBottomSheet(private val controller: MangaDetailsController) :
|
||||
if (item.track == null) return
|
||||
|
||||
val suggestedDate = presenter.getSuggestedDate(SetTrackReadingDatesDialog.ReadingDate.Start)
|
||||
SetTrackReadingDatesDialog(controller,
|
||||
SetTrackReadingDatesDialog(
|
||||
controller,
|
||||
this,
|
||||
SetTrackReadingDatesDialog.ReadingDate.Start,
|
||||
item,
|
||||
suggestedDate)
|
||||
suggestedDate
|
||||
)
|
||||
.showDialog(controller.router)
|
||||
}
|
||||
|
||||
@ -203,11 +203,13 @@ class TrackingBottomSheet(private val controller: MangaDetailsController) :
|
||||
if (item.track == null) return
|
||||
|
||||
val suggestedDate = presenter.getSuggestedDate(SetTrackReadingDatesDialog.ReadingDate.Finish)
|
||||
SetTrackReadingDatesDialog(controller,
|
||||
SetTrackReadingDatesDialog(
|
||||
controller,
|
||||
this,
|
||||
SetTrackReadingDatesDialog.ReadingDate.Finish,
|
||||
item,
|
||||
suggestedDate)
|
||||
suggestedDate
|
||||
)
|
||||
.showDialog(controller.router)
|
||||
}
|
||||
|
||||
@ -257,5 +259,4 @@ class TrackingBottomSheet(private val controller: MangaDetailsController) :
|
||||
private companion object {
|
||||
const val TAG_SEARCH_CONTROLLER = "track_search_controller"
|
||||
}
|
||||
|
||||
}
|
||||
|
@ -24,7 +24,6 @@ class MangaItem(val manga: Manga) : AbstractFlexibleItem<MangaHolder>() {
|
||||
position: Int,
|
||||
payloads: MutableList<Any?>?
|
||||
) {
|
||||
|
||||
holder.bind(this)
|
||||
}
|
||||
|
||||
|
@ -93,7 +93,6 @@ class MigrationPresenter(
|
||||
manga: Manga,
|
||||
replace: Boolean
|
||||
) {
|
||||
|
||||
val flags = preferences.migrateFlags().getOrDefault()
|
||||
val migrateChapters = MigrationFlags.hasChapters(flags)
|
||||
val migrateCategories = MigrationFlags.hasCategories(flags)
|
||||
|
@ -42,8 +42,9 @@ class SearchController(
|
||||
override fun getTitle(): String? {
|
||||
if (totalProgress > 1) {
|
||||
return "($progress/$totalProgress) ${super.getTitle()}"
|
||||
} else
|
||||
} else {
|
||||
return super.getTitle()
|
||||
}
|
||||
}
|
||||
|
||||
override fun createPresenter(): GlobalSearchPresenter {
|
||||
|
@ -40,7 +40,6 @@ data class SourceItem(val source: Source, val header: SelectionHeader? = null) :
|
||||
position: Int,
|
||||
payloads: MutableList<Any?>?
|
||||
) {
|
||||
|
||||
holder.bind(this)
|
||||
}
|
||||
}
|
||||
|
@ -3,7 +3,6 @@ package eu.kanade.tachiyomi.ui.migration.manga.design
|
||||
import android.graphics.Paint.STRIKE_THRU_TEXT_FLAG
|
||||
import android.view.View
|
||||
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.online.HttpSource
|
||||
import eu.kanade.tachiyomi.ui.base.holder.BaseFlexibleViewHolder
|
||||
|
@ -15,7 +15,6 @@ import com.google.android.material.bottomsheet.BottomSheetDialog
|
||||
import eu.davidea.flexibleadapter.FlexibleAdapter
|
||||
import eu.kanade.tachiyomi.R
|
||||
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.online.HttpSource
|
||||
import eu.kanade.tachiyomi.ui.base.controller.BaseController
|
||||
|
@ -54,7 +54,6 @@ import kotlinx.coroutines.launch
|
||||
import kotlinx.coroutines.sync.Semaphore
|
||||
import kotlinx.coroutines.sync.withPermit
|
||||
import kotlinx.coroutines.withContext
|
||||
import rx.schedulers.Schedulers
|
||||
import timber.log.Timber
|
||||
import uy.kohesive.injekt.injectLazy
|
||||
import java.util.concurrent.atomic.AtomicInteger
|
||||
@ -99,7 +98,6 @@ class MigrationListController(bundle: Bundle? = null) :
|
||||
}
|
||||
|
||||
override fun onViewCreated(view: View) {
|
||||
|
||||
super.onViewCreated(view)
|
||||
liftAppbarWith(recycler)
|
||||
setTitle()
|
||||
@ -324,7 +322,6 @@ class MigrationListController(bundle: Bundle? = null) :
|
||||
}
|
||||
|
||||
override fun onMenuItemClick(position: Int, item: MenuItem) {
|
||||
|
||||
when (item.itemId) {
|
||||
R.id.action_search_manually -> {
|
||||
launchUI {
|
||||
@ -377,7 +374,7 @@ class MigrationListController(bundle: Bundle? = null) :
|
||||
try {
|
||||
val newManga =
|
||||
sourceManager.getOrStub(result.source).getMangaDetails(result.toMangaInfo())
|
||||
.toSManga()
|
||||
.toSManga()
|
||||
result.copyFrom(newManga)
|
||||
|
||||
db.insertManga(result).executeAsBlocking()
|
||||
|
@ -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.preference.PreferencesHelper
|
||||
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.main.MainActivity
|
||||
import eu.kanade.tachiyomi.ui.main.SearchActivity
|
||||
@ -283,8 +282,10 @@ class ReaderActivity :
|
||||
override fun onPrepareOptionsMenu(menu: Menu?): Boolean {
|
||||
val detailsItem = menu?.findItem(R.id.action_manga_details)
|
||||
if (presenter.manga?.mangaType(this) != null) {
|
||||
detailsItem?.title = getString(R.string._details,
|
||||
presenter.manga?.mangaType(this)?.capitalize(Locale.ROOT) ?: "")
|
||||
detailsItem?.title = getString(
|
||||
R.string._details,
|
||||
presenter.manga?.mangaType(this)?.capitalize(Locale.ROOT) ?: ""
|
||||
)
|
||||
} else {
|
||||
detailsItem?.title = getString(R.string.details)
|
||||
}
|
||||
@ -798,7 +799,6 @@ class ReaderActivity :
|
||||
*/
|
||||
private fun setNotchCutoutMode() {
|
||||
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.P) {
|
||||
|
||||
val currentOrientation = resources.configuration.orientation
|
||||
|
||||
val params = window.attributes
|
||||
@ -941,10 +941,11 @@ class ReaderActivity :
|
||||
* Sets the 32-bit color mode according to [enabled].
|
||||
*/
|
||||
private fun setTrueColor(enabled: Boolean) {
|
||||
if (enabled)
|
||||
if (enabled) {
|
||||
SubsamplingScaleImageView.setPreferredBitmapConfig(Bitmap.Config.ARGB_8888)
|
||||
else
|
||||
} else {
|
||||
SubsamplingScaleImageView.setPreferredBitmapConfig(Bitmap.Config.RGB_565)
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -38,7 +38,6 @@ class SaveImageNotifier(private val context: Context) {
|
||||
* @param file image file containing downloaded page image.
|
||||
*/
|
||||
fun onComplete(file: File) {
|
||||
|
||||
val request = LoadRequest.Builder(context).memoryCachePolicy(CachePolicy.DISABLED).diskCachePolicy(CachePolicy.DISABLED)
|
||||
.data(file)
|
||||
.size(720, 1280)
|
||||
@ -64,8 +63,9 @@ class SaveImageNotifier(private val context: Context) {
|
||||
setAutoCancel(true)
|
||||
color = ContextCompat.getColor(context, R.color.colorAccent)
|
||||
// Clear old actions if they exist
|
||||
if (mActions.isNotEmpty())
|
||||
if (mActions.isNotEmpty()) {
|
||||
mActions.clear()
|
||||
}
|
||||
|
||||
setContentIntent(NotificationHandler.openImagePendingActivity(context, file))
|
||||
// Share action
|
||||
|
@ -192,10 +192,11 @@ class HttpPageLoader(
|
||||
* @param page the page whose source image has to be downloaded.
|
||||
*/
|
||||
private fun HttpSource.fetchImageFromCacheThenNet(page: ReaderPage): Observable<ReaderPage> {
|
||||
return if (page.imageUrl.isNullOrEmpty())
|
||||
return if (page.imageUrl.isNullOrEmpty()) {
|
||||
getImageUrl(page).flatMap { getCachedImage(it) }
|
||||
else
|
||||
} else {
|
||||
getCachedImage(page)
|
||||
}
|
||||
}
|
||||
|
||||
private fun HttpSource.getImageUrl(page: ReaderPage): Observable<ReaderPage> {
|
||||
|
@ -5,9 +5,7 @@ import android.util.AttributeSet
|
||||
import android.widget.SeekBar
|
||||
import androidx.annotation.ColorInt
|
||||
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.IgnoreFirstSpinnerListener
|
||||
import eu.kanade.tachiyomi.widget.SimpleSeekBarListener
|
||||
import kotlinx.android.synthetic.main.reader_color_filter.*
|
||||
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
|
||||
* @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
|
||||
* @param color hex of color.
|
||||
*/
|
||||
private fun setColorFilterValue(@ColorInt color: Int) {
|
||||
private fun setColorFilterValue(@ColorInt color: Int) {
|
||||
setValues(color)
|
||||
}
|
||||
|
||||
@ -267,4 +264,4 @@ class ReaderFilterView @JvmOverloads constructor(context: Context, attrs: Attrib
|
||||
*/
|
||||
fun ReaderFilterView.getGreenFromColor(color: Int): Int {
|
||||
return color shr 8 and 0xFF
|
||||
}
|
||||
}
|
||||
|
@ -4,9 +4,7 @@ import android.content.Context
|
||||
import android.util.AttributeSet
|
||||
import eu.kanade.tachiyomi.ui.reader.ReaderActivity
|
||||
import eu.kanade.tachiyomi.util.bindToPreference
|
||||
import eu.kanade.tachiyomi.util.view.RecyclerWindowInsetsListener
|
||||
import eu.kanade.tachiyomi.widget.BaseReaderSettingsView
|
||||
import eu.kanade.tachiyomi.widget.IgnoreFirstSpinnerListener
|
||||
import kotlinx.android.synthetic.main.reader_general_layout.view.*
|
||||
|
||||
class ReaderGeneralView @JvmOverloads constructor(context: Context, attrs: AttributeSet? = null) :
|
||||
@ -43,4 +41,4 @@ class ReaderGeneralView @JvmOverloads constructor(context: Context, attrs: Attri
|
||||
private fun initPagerPreferences() {
|
||||
sheet.updateTabs(false)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -44,4 +44,4 @@ class ReaderPagedView @JvmOverloads constructor(context: Context, attrs: Attribu
|
||||
listOf(scale_type, zoom_start, crop_borders, page_transitions, pager_nav, pager_invert).forEach { it.visibleIf(show) }
|
||||
listOf(crop_borders_webtoon, webtoon_side_padding, webtoon_enable_zoom_out, webtoon_nav, webtoon_invert).forEach { it.visibleIf(!show) }
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -12,16 +12,14 @@ import com.tfcporciuncula.flow.Preference
|
||||
import eu.kanade.tachiyomi.R
|
||||
import kotlinx.android.synthetic.main.reader_preference.view.*
|
||||
|
||||
|
||||
class ReaderSpinnerView @JvmOverloads constructor(context: Context, attrs: AttributeSet?) :
|
||||
FrameLayout(context, attrs) {
|
||||
|
||||
|
||||
private var entries = emptyList<String>()
|
||||
private var selectedPosition = 0
|
||||
private var pref: Preference<Int>? = null
|
||||
private var prefOffset = 0
|
||||
private var popup:PopupMenu? = null
|
||||
private var popup: PopupMenu? = null
|
||||
|
||||
var onItemSelectedListener: ((Int) -> Unit)? = null
|
||||
set(value) {
|
||||
@ -159,11 +157,11 @@ class ReaderSpinnerView @JvmOverloads constructor(context: Context, attrs: Attri
|
||||
|
||||
fun popup(): PopupMenu {
|
||||
val popup = PopupMenu(context, this, Gravity.END)
|
||||
entries.forEachIndexed { index, entry ->
|
||||
entries.forEachIndexed { index, entry ->
|
||||
popup.menu.add(0, index, 0, entry)
|
||||
}
|
||||
popup.menu[selectedPosition].isCheckable = true
|
||||
popup.menu[selectedPosition].isChecked = true
|
||||
return popup
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -1,22 +1,19 @@
|
||||
package eu.kanade.tachiyomi.ui.reader.settings
|
||||
|
||||
import android.view.View
|
||||
import androidx.core.widget.NestedScrollView
|
||||
import com.google.android.material.tabs.TabLayout
|
||||
import eu.kanade.tachiyomi.R
|
||||
import eu.kanade.tachiyomi.ui.library.display.LibraryBadgesView
|
||||
import eu.kanade.tachiyomi.ui.reader.ReaderActivity
|
||||
import eu.kanade.tachiyomi.util.view.gone
|
||||
import eu.kanade.tachiyomi.util.view.visInvisIf
|
||||
import eu.kanade.tachiyomi.util.view.visible
|
||||
import eu.kanade.tachiyomi.util.view.visibleIf
|
||||
import eu.kanade.tachiyomi.widget.TabbedBottomSheetDialog
|
||||
import kotlinx.android.synthetic.main.reader_activity.*
|
||||
import kotlinx.android.synthetic.main.reader_color_filter.view.*
|
||||
import kotlinx.android.synthetic.main.recycler_with_scroller.view.*
|
||||
import kotlinx.android.synthetic.main.tabbed_bottom_sheet.*
|
||||
|
||||
class TabbedReaderSettingsSheet(val readerActivity: ReaderActivity): TabbedBottomSheetDialog(
|
||||
class TabbedReaderSettingsSheet(val readerActivity: ReaderActivity) : TabbedBottomSheetDialog(
|
||||
readerActivity
|
||||
) {
|
||||
private val generalView: ReaderGeneralView = View.inflate(
|
||||
|
@ -27,7 +27,6 @@ abstract class ViewerConfig(preferences: PreferencesHelper) {
|
||||
var volumeKeysInverted = false
|
||||
var alwaysShowChapterTransition = true
|
||||
|
||||
|
||||
var navigationOverlayForNewUser = false
|
||||
var navigationMode = 0
|
||||
protected set
|
||||
|
@ -17,8 +17,7 @@ abstract class ViewerNavigation {
|
||||
fun directionalRegion(LTR: Boolean): NavigationRegion {
|
||||
return if (this === LEFT || this === RIGHT) {
|
||||
if (if (LTR) this === LEFT else this === RIGHT) NEXT else PREV
|
||||
}
|
||||
else this
|
||||
} else this
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -45,9 +45,12 @@ class PagerConfig(private val viewer: PagerViewer, preferences: PreferencesHelpe
|
||||
.register({ navigationMode = it }, { updateNavigation(navigationMode) })
|
||||
|
||||
preferences.pagerNavInverted()
|
||||
.register({ tappingInverted = it }, {
|
||||
navigator.invertMode = it
|
||||
})
|
||||
.register(
|
||||
{ tappingInverted = it },
|
||||
{
|
||||
navigator.invertMode = it
|
||||
}
|
||||
)
|
||||
|
||||
preferences.pagerNavInverted().asFlow()
|
||||
.drop(1)
|
||||
|
@ -340,7 +340,6 @@ class PagerPageHolder(
|
||||
@SuppressLint("PrivateResource")
|
||||
private fun createProgressBar(): ReaderProgressBar {
|
||||
return ReaderProgressBar(context, null).apply {
|
||||
|
||||
val size = 48.dpToPx
|
||||
layoutParams = LayoutParams(size, size).apply {
|
||||
gravity = Gravity.CENTER
|
||||
|
@ -24,6 +24,7 @@ class PagerViewerAdapter(private val viewer: PagerViewer) : ViewPagerAdapter() {
|
||||
private set
|
||||
|
||||
var currentChapter: ReaderChapter? = null
|
||||
|
||||
/**
|
||||
* 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
|
||||
|
@ -22,6 +22,7 @@ class WebtoonAdapter(val viewer: WebtoonViewer) : RecyclerView.Adapter<RecyclerV
|
||||
private set
|
||||
|
||||
var currentChapter: ReaderChapter? = null
|
||||
|
||||
/**
|
||||
* Updates this adapter with the given [chapters]. It handles setting a few pages of the
|
||||
* next/previous chapter to allow seamless transitions.
|
||||
|
@ -37,9 +37,12 @@ class WebtoonConfig(preferences: PreferencesHelper = Injekt.get()) : ViewerConfi
|
||||
.register({ navigationMode = it }, { updateNavigation(it) })
|
||||
|
||||
preferences.webtoonNavInverted()
|
||||
.register({ tappingInverted = it }, {
|
||||
navigator.invertMode = it
|
||||
})
|
||||
.register(
|
||||
{ tappingInverted = it },
|
||||
{
|
||||
navigator.invertMode = it
|
||||
}
|
||||
)
|
||||
|
||||
preferences.webtoonNavInverted().asFlow()
|
||||
.drop(1)
|
||||
|
@ -42,12 +42,13 @@ class WebtoonLayoutManager(activity: ReaderActivity) : LinearLayoutManager(activ
|
||||
val fromIndex = childCount - 1
|
||||
val toIndex = -1
|
||||
|
||||
val child = if (mOrientation == HORIZONTAL)
|
||||
val child = if (mOrientation == HORIZONTAL) {
|
||||
mHorizontalBoundCheck
|
||||
.findOneViewWithinBoundFlags(fromIndex, toIndex, preferredBoundsFlag, 0)
|
||||
else
|
||||
} else {
|
||||
mVerticalBoundCheck
|
||||
.findOneViewWithinBoundFlags(fromIndex, toIndex, preferredBoundsFlag, 0)
|
||||
}
|
||||
|
||||
return if (child == null) NO_POSITION else getPosition(child)
|
||||
}
|
||||
|
@ -98,7 +98,7 @@ class WebtoonViewer(val activity: ReaderActivity, val hasMargins: Boolean = fals
|
||||
}
|
||||
}
|
||||
)
|
||||
recycler.tapListener = f@{ event ->
|
||||
recycler.tapListener = f@{ event ->
|
||||
if (!config.tappingEnabled) {
|
||||
activity.toggleMenu()
|
||||
return@f
|
||||
|
@ -44,6 +44,7 @@ class RecentlyReadController(bundle: Bundle? = null) :
|
||||
init {
|
||||
setHasOptionsMenu(true)
|
||||
}
|
||||
|
||||
/**
|
||||
* Adapter containing the recent manga.
|
||||
*/
|
||||
@ -85,8 +86,9 @@ class RecentlyReadController(bundle: Bundle? = null) :
|
||||
resetProgressItem()
|
||||
scrollViewWith(recycler, padBottom = true)
|
||||
|
||||
if (recentItems != null)
|
||||
if (recentItems != null) {
|
||||
adapter?.updateDataSet(recentItems!!.toList())
|
||||
}
|
||||
|
||||
launchUI {
|
||||
val manga = presenter.refresh(query)
|
||||
@ -106,6 +108,7 @@ class RecentlyReadController(bundle: Bundle? = null) :
|
||||
observeLater = false
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Populate adapter with chapters
|
||||
*
|
||||
@ -115,8 +118,9 @@ class RecentlyReadController(bundle: Bundle? = null) :
|
||||
val adapter = adapter ?: return
|
||||
adapter.updateDataSet(mangaHistory)
|
||||
adapter.onLoadMoreComplete(null)
|
||||
if (recentItems == null)
|
||||
if (recentItems == null) {
|
||||
resetProgressItem()
|
||||
}
|
||||
recentItems = mangaHistory.toMutableList()
|
||||
}
|
||||
|
||||
|
@ -24,7 +24,6 @@ class RecentlyReadItem(val mch: MangaChapterHistory) : AbstractFlexibleItem<Rece
|
||||
position: Int,
|
||||
payloads: MutableList<Any?>?
|
||||
) {
|
||||
|
||||
holder.bind(mch)
|
||||
}
|
||||
|
||||
|
@ -40,7 +40,6 @@ import eu.kanade.tachiyomi.util.system.dpToPx
|
||||
import eu.kanade.tachiyomi.util.system.spToPx
|
||||
import eu.kanade.tachiyomi.util.system.toast
|
||||
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.requestPermissionsSafe
|
||||
import eu.kanade.tachiyomi.util.view.scrollViewWith
|
||||
@ -95,9 +94,9 @@ class RecentsController(bundle: Bundle? = null) :
|
||||
var headerHeight = 0
|
||||
|
||||
override fun getTitle(): String? {
|
||||
return if (showingDownloads)
|
||||
return if (showingDownloads) {
|
||||
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 {
|
||||
@ -243,8 +242,9 @@ class RecentsController(bundle: Bundle? = null) :
|
||||
val pad = bottomBar.translationY - bottomBar.height
|
||||
val padding = max(
|
||||
(-pad).toInt(),
|
||||
if (dl_bottom_sheet.sheetBehavior.isExpanded()) 0 else
|
||||
if (dl_bottom_sheet.sheetBehavior.isExpanded()) 0 else {
|
||||
view?.rootWindowInsets?.systemWindowInsetBottom ?: 0
|
||||
}
|
||||
)
|
||||
shadow2.translationY = pad
|
||||
dl_bottom_sheet.sheetBehavior?.peekHeight = 48.spToPx + padding
|
||||
@ -303,8 +303,9 @@ class RecentsController(bundle: Bundle? = null) :
|
||||
swipe_refresh.isRefreshing = LibraryUpdateService.isRunning()
|
||||
adapter.updateItems(recents)
|
||||
adapter.removeAllScrollableHeaders()
|
||||
if (presenter.viewType > 0)
|
||||
if (presenter.viewType > 0) {
|
||||
adapter.addScrollableHeader(presenter.generalHeader)
|
||||
}
|
||||
if (lastChapterId != null) {
|
||||
refreshItem(lastChapterId ?: 0L)
|
||||
lastChapterId = null
|
||||
@ -380,8 +381,9 @@ class RecentsController(bundle: Bundle? = null) :
|
||||
val manga = item.mch.manga
|
||||
val history = item.mch.history
|
||||
val chapter = item.mch.chapter
|
||||
if (history.id != null)
|
||||
if (history.id != null) {
|
||||
RemoveHistoryDialog(this, manga, history, chapter).showDialog(router)
|
||||
}
|
||||
}
|
||||
|
||||
override fun removeHistory(manga: Manga, history: History, all: Boolean) {
|
||||
@ -476,7 +478,7 @@ class RecentsController(bundle: Bundle? = null) :
|
||||
setBottomPadding()
|
||||
}
|
||||
|
||||
override fun onChangeEnded(handler: ControllerChangeHandler, type: ControllerChangeType ) {
|
||||
override fun onChangeEnded(handler: ControllerChangeHandler, type: ControllerChangeType) {
|
||||
super.onChangeEnded(handler, type)
|
||||
if (type == ControllerChangeType.POP_ENTER) setBottomPadding()
|
||||
}
|
||||
@ -484,8 +486,9 @@ class RecentsController(bundle: Bundle? = null) :
|
||||
fun hasQueue() = presenter.downloadManager.hasQueue()
|
||||
|
||||
override fun showSheet() {
|
||||
if (dl_bottom_sheet.sheetBehavior?.isHideable == false || hasQueue())
|
||||
if (dl_bottom_sheet.sheetBehavior?.isHideable == false || hasQueue()) {
|
||||
dl_bottom_sheet.sheetBehavior?.expand()
|
||||
}
|
||||
}
|
||||
|
||||
override fun toggleSheet() {
|
||||
@ -498,13 +501,15 @@ class RecentsController(bundle: Bundle? = null) :
|
||||
override fun expandSearch() {
|
||||
if (showingDownloads) {
|
||||
dl_bottom_sheet.dismiss()
|
||||
} else
|
||||
} else {
|
||||
activity?.toolbar?.menu?.findItem(R.id.action_search)?.expandActionView()
|
||||
}
|
||||
}
|
||||
|
||||
override fun onOptionsItemSelected(item: MenuItem): Boolean {
|
||||
if (showingDownloads)
|
||||
if (showingDownloads) {
|
||||
return dl_bottom_sheet.onOptionsItemSelected(item)
|
||||
}
|
||||
when (item.itemId) {
|
||||
R.id.action_group_all, R.id.action_ungroup_all, R.id.action_only_history,
|
||||
R.id.action_only_updates -> {
|
||||
@ -516,8 +521,9 @@ class RecentsController(bundle: Bundle? = null) :
|
||||
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?.invalidateOptionsMenu()
|
||||
}
|
||||
}
|
||||
|
@ -56,8 +56,9 @@ class RecentsPresenter(
|
||||
downloadManager.addListener(this)
|
||||
LibraryUpdateService.setListener(this)
|
||||
if (lastRecents != null) {
|
||||
if (recentItems.isEmpty())
|
||||
if (recentItems.isEmpty()) {
|
||||
recentItems = lastRecents ?: emptyList()
|
||||
}
|
||||
lastRecents = null
|
||||
}
|
||||
getRecents()
|
||||
@ -95,14 +96,15 @@ class RecentsPresenter(
|
||||
}
|
||||
}
|
||||
|
||||
val cReading = if (viewType != 3)
|
||||
if (query.isEmpty() && viewType != 2)
|
||||
val cReading = if (viewType != 3) {
|
||||
if (query.isEmpty() && viewType != 2) {
|
||||
db.getRecentsWithUnread(cal.time, query, isUngrouped).executeOnIO()
|
||||
else db.getRecentMangaLimit(
|
||||
} else db.getRecentMangaLimit(
|
||||
cal.time,
|
||||
if (viewType == 2) 200 else 8,
|
||||
query
|
||||
).executeOnIO() else emptyList()
|
||||
).executeOnIO()
|
||||
} else emptyList()
|
||||
val rUpdates = when {
|
||||
viewType == 3 -> db.getRecentChapters(calWeek.time).executeOnIO().map {
|
||||
MangaChapterHistory(it.manga, it.chapter, HistoryImpl())
|
||||
@ -113,8 +115,9 @@ class RecentsPresenter(
|
||||
rUpdates.forEach {
|
||||
it.history.last_read = it.chapter.date_fetch
|
||||
}
|
||||
val nAdditions = if (viewType < 2)
|
||||
db.getRecentlyAdded(calDay.time, query, isUngrouped).executeOnIO() else emptyList()
|
||||
val nAdditions = if (viewType < 2) {
|
||||
db.getRecentlyAdded(calDay.time, query, isUngrouped).executeOnIO()
|
||||
} else emptyList()
|
||||
nAdditions.forEach {
|
||||
it.history.last_read = it.manga.date_added
|
||||
}
|
||||
@ -144,10 +147,11 @@ class RecentsPresenter(
|
||||
Comparator<Pair<MangaChapterHistory, Chapter>> { f1, f2 ->
|
||||
if (abs(f1.second.date_fetch - f2.second.date_fetch) <=
|
||||
TimeUnit.HOURS.toMillis(12)
|
||||
)
|
||||
) {
|
||||
f2.second.date_upload.compareTo(f1.second.date_upload)
|
||||
else
|
||||
} else {
|
||||
f2.second.date_fetch.compareTo(f1.second.date_fetch)
|
||||
}
|
||||
}
|
||||
)
|
||||
.take(4).map {
|
||||
|
@ -10,7 +10,6 @@ import com.google.android.gms.oss.licenses.OssLicensesMenuActivity
|
||||
import eu.kanade.tachiyomi.BuildConfig
|
||||
import eu.kanade.tachiyomi.R
|
||||
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.UpdateResult
|
||||
import eu.kanade.tachiyomi.data.updater.UpdaterService
|
||||
|
@ -46,8 +46,8 @@ inline fun PreferenceGroup.editTextPreference(block: (@DSL EditTextPreference).(
|
||||
|
||||
inline fun PreferenceGroup.dropDownPreference(block: (@DSL DropDownPreference).() -> Unit):
|
||||
DropDownPreference {
|
||||
return initThenAdd(DropDownPreference(context), block).also(::initDialog)
|
||||
}
|
||||
return initThenAdd(DropDownPreference(context), block).also(::initDialog)
|
||||
}
|
||||
|
||||
inline fun PreferenceGroup.listPreference(
|
||||
activity: Activity?,
|
||||
@ -55,8 +55,8 @@ inline fun PreferenceGroup.listPreference(
|
||||
-> Unit
|
||||
):
|
||||
ListMatPreference {
|
||||
return initThenAdd(ListMatPreference(activity, context), block)
|
||||
}
|
||||
return initThenAdd(ListMatPreference(activity, context), block)
|
||||
}
|
||||
|
||||
inline fun PreferenceGroup.intListPreference(
|
||||
activity: Activity?,
|
||||
@ -66,8 +66,8 @@ inline fun PreferenceGroup.intListPreference(
|
||||
).() -> Unit
|
||||
):
|
||||
IntListMatPreference {
|
||||
return initThenAdd(IntListMatPreference(activity, context), block)
|
||||
}
|
||||
return initThenAdd(IntListMatPreference(activity, context), block)
|
||||
}
|
||||
|
||||
inline fun PreferenceGroup.multiSelectListPreferenceMat(
|
||||
activity: Activity?,
|
||||
|
@ -186,9 +186,7 @@ class SettingsAdvancedController : SettingsController() {
|
||||
|
||||
class CleanupDownloadsDialogController() : DialogController() {
|
||||
override fun onCreateDialog(savedViewState: Bundle?): Dialog {
|
||||
|
||||
return MaterialDialog(activity!!).show {
|
||||
|
||||
title(R.string.clean_up_downloaded_chapters)
|
||||
.listItemsMultiChoice(R.array.clean_up_downloads, disabledIndices = intArrayOf(0), initialSelection = intArrayOf(0, 1, 2)) { dialog, selections, items ->
|
||||
val deleteRead = selections.contains(1)
|
||||
|
Some files were not shown because too many files have changed in this diff Show More
Loading…
Reference in New Issue
Block a user