Replace Timber with Square Logcat and make logging configurable (#6062)

* Replace Timber with Square Logcat

* Configurable logger
This commit is contained in:
Ivan Iskandar 2021-10-08 09:12:55 +07:00 committed by GitHub
parent 828db19e02
commit 2e127dff1f
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
52 changed files with 223 additions and 142 deletions

View File

@ -252,7 +252,7 @@ dependencies {
implementation("io.github.reactivecircus.flowbinding:flowbinding-viewpager:$flowbindingVersion") implementation("io.github.reactivecircus.flowbinding:flowbinding-viewpager:$flowbindingVersion")
// Logging // Logging
implementation("com.jakewharton.timber:timber:5.0.1") implementation("com.squareup.logcat:logcat:0.1")
// Crash reports/analytics // Crash reports/analytics
implementation("ch.acra:acra-http:5.8.1") implementation("ch.acra:acra-http:5.8.1")

View File

@ -20,6 +20,7 @@ import coil.ImageLoader
import coil.ImageLoaderFactory import coil.ImageLoaderFactory
import coil.decode.GifDecoder import coil.decode.GifDecoder
import coil.decode.ImageDecoderDecoder import coil.decode.ImageDecoderDecoder
import coil.util.DebugLogger
import eu.kanade.tachiyomi.data.coil.ByteBufferFetcher import eu.kanade.tachiyomi.data.coil.ByteBufferFetcher
import eu.kanade.tachiyomi.data.coil.MangaCoverFetcher import eu.kanade.tachiyomi.data.coil.MangaCoverFetcher
import eu.kanade.tachiyomi.data.coil.TachiyomiImageDecoder import eu.kanade.tachiyomi.data.coil.TachiyomiImageDecoder
@ -34,11 +35,13 @@ import eu.kanade.tachiyomi.util.system.animatorDurationScale
import eu.kanade.tachiyomi.util.system.notification import eu.kanade.tachiyomi.util.system.notification
import kotlinx.coroutines.flow.launchIn import kotlinx.coroutines.flow.launchIn
import kotlinx.coroutines.flow.onEach import kotlinx.coroutines.flow.onEach
import logcat.AndroidLogcatLogger
import logcat.LogPriority
import logcat.LogcatLogger
import org.acra.config.httpSender import org.acra.config.httpSender
import org.acra.ktx.initAcra import org.acra.ktx.initAcra
import org.acra.sender.HttpSender import org.acra.sender.HttpSender
import org.conscrypt.Conscrypt import org.conscrypt.Conscrypt
import timber.log.Timber
import uy.kohesive.injekt.Injekt import uy.kohesive.injekt.Injekt
import uy.kohesive.injekt.api.get import uy.kohesive.injekt.api.get
import uy.kohesive.injekt.injectLazy import uy.kohesive.injekt.injectLazy
@ -52,7 +55,6 @@ open class App : Application(), DefaultLifecycleObserver, ImageLoaderFactory {
override fun onCreate() { override fun onCreate() {
super<Application>.onCreate() super<Application>.onCreate()
if (BuildConfig.DEBUG) Timber.plant(Timber.DebugTree())
// TLS 1.3 support for Android < 10 // TLS 1.3 support for Android < 10
if (Build.VERSION.SDK_INT < Build.VERSION_CODES.Q) { if (Build.VERSION.SDK_INT < Build.VERSION_CODES.Q) {
@ -110,6 +112,10 @@ open class App : Application(), DefaultLifecycleObserver, ImageLoaderFactory {
} }
) )
}.launchIn(ProcessLifecycleOwner.get().lifecycleScope) }.launchIn(ProcessLifecycleOwner.get().lifecycleScope)
if (!LogcatLogger.isInstalled && preferences.verboseLogging()) {
LogcatLogger.install(AndroidLogcatLogger(LogPriority.VERBOSE))
}
} }
override fun newImageLoader(): ImageLoader { override fun newImageLoader(): ImageLoader {
@ -127,6 +133,7 @@ open class App : Application(), DefaultLifecycleObserver, ImageLoaderFactory {
okHttpClient(Injekt.get<NetworkHelper>().coilClient) okHttpClient(Injekt.get<NetworkHelper>().coilClient)
crossfade((300 * this@App.animatorDurationScale).toInt()) crossfade((300 * this@App.animatorDurationScale).toInt())
allowRgb565(getSystemService<ActivityManager>()!!.isLowRamDevice) allowRgb565(getSystemService<ActivityManager>()!!.isLowRamDevice)
if (preferences.verboseLogging()) logger(DebugLogger())
}.build() }.build()
} }

View File

@ -13,13 +13,14 @@ import eu.kanade.tachiyomi.data.backup.legacy.LegacyBackupRestore
import eu.kanade.tachiyomi.data.notification.Notifications import eu.kanade.tachiyomi.data.notification.Notifications
import eu.kanade.tachiyomi.util.system.acquireWakeLock import eu.kanade.tachiyomi.util.system.acquireWakeLock
import eu.kanade.tachiyomi.util.system.isServiceRunning import eu.kanade.tachiyomi.util.system.isServiceRunning
import eu.kanade.tachiyomi.util.system.logcat
import kotlinx.coroutines.CoroutineExceptionHandler import kotlinx.coroutines.CoroutineExceptionHandler
import kotlinx.coroutines.CoroutineScope import kotlinx.coroutines.CoroutineScope
import kotlinx.coroutines.Dispatchers import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.SupervisorJob import kotlinx.coroutines.SupervisorJob
import kotlinx.coroutines.cancel import kotlinx.coroutines.cancel
import kotlinx.coroutines.launch import kotlinx.coroutines.launch
import timber.log.Timber import logcat.LogPriority
/** /**
* Restores backup. * Restores backup.
@ -128,7 +129,7 @@ class BackupRestoreService : Service() {
} }
val handler = CoroutineExceptionHandler { _, exception -> val handler = CoroutineExceptionHandler { _, exception ->
Timber.e(exception) logcat(LogPriority.ERROR, exception)
backupRestore?.writeErrorLog() backupRestore?.writeErrorLog()
notifier.showRestoreError(exception.message) notifier.showRestoreError(exception.message)

View File

@ -26,11 +26,12 @@ import eu.kanade.tachiyomi.data.database.models.History
import eu.kanade.tachiyomi.data.database.models.Manga import eu.kanade.tachiyomi.data.database.models.Manga
import eu.kanade.tachiyomi.data.database.models.MangaCategory import eu.kanade.tachiyomi.data.database.models.MangaCategory
import eu.kanade.tachiyomi.data.database.models.Track import eu.kanade.tachiyomi.data.database.models.Track
import eu.kanade.tachiyomi.util.system.logcat
import kotlinx.serialization.protobuf.ProtoBuf import kotlinx.serialization.protobuf.ProtoBuf
import logcat.LogPriority
import okio.buffer import okio.buffer
import okio.gzip import okio.gzip
import okio.sink import okio.sink
import timber.log.Timber
import kotlin.math.max import kotlin.math.max
class FullBackupManager(context: Context) : AbstractBackupManager(context) { class FullBackupManager(context: Context) : AbstractBackupManager(context) {
@ -86,7 +87,7 @@ class FullBackupManager(context: Context) : AbstractBackupManager(context) {
file.openOutputStream().sink().gzip().buffer().use { it.write(byteArray) } file.openOutputStream().sink().gzip().buffer().use { it.write(byteArray) }
return file.uri.toString() return file.uri.toString()
} catch (e: Exception) { } catch (e: Exception) {
Timber.e(e) logcat(LogPriority.ERROR, e)
throw e throw e
} }
} }

View File

@ -14,8 +14,9 @@ import eu.kanade.tachiyomi.source.Source
import eu.kanade.tachiyomi.source.SourceManager import eu.kanade.tachiyomi.source.SourceManager
import eu.kanade.tachiyomi.source.model.Page import eu.kanade.tachiyomi.source.model.Page
import eu.kanade.tachiyomi.util.lang.launchIO import eu.kanade.tachiyomi.util.lang.launchIO
import eu.kanade.tachiyomi.util.system.logcat
import logcat.LogPriority
import rx.Observable import rx.Observable
import timber.log.Timber
import uy.kohesive.injekt.Injekt import uy.kohesive.injekt.Injekt
import uy.kohesive.injekt.api.get import uy.kohesive.injekt.api.get
import uy.kohesive.injekt.injectLazy import uy.kohesive.injekt.injectLazy
@ -338,7 +339,7 @@ class DownloadManager(
cache.removeChapter(oldChapter, manga) cache.removeChapter(oldChapter, manga)
cache.addChapter(newName, mangaDir, manga) cache.addChapter(newName, mangaDir, manga)
} else { } else {
Timber.e("Could not rename downloaded chapter: %s.", oldNames.joinToString()) logcat(LogPriority.ERROR) { "Could not rename downloaded chapter: ${oldNames.joinToString()}." }
} }
} }

View File

@ -9,10 +9,11 @@ import eu.kanade.tachiyomi.data.database.models.Manga
import eu.kanade.tachiyomi.data.preference.PreferencesHelper import eu.kanade.tachiyomi.data.preference.PreferencesHelper
import eu.kanade.tachiyomi.source.Source import eu.kanade.tachiyomi.source.Source
import eu.kanade.tachiyomi.util.storage.DiskUtil import eu.kanade.tachiyomi.util.storage.DiskUtil
import eu.kanade.tachiyomi.util.system.logcat
import kotlinx.coroutines.MainScope import kotlinx.coroutines.MainScope
import kotlinx.coroutines.flow.launchIn import kotlinx.coroutines.flow.launchIn
import kotlinx.coroutines.flow.onEach import kotlinx.coroutines.flow.onEach
import timber.log.Timber import logcat.LogPriority
import uy.kohesive.injekt.injectLazy import uy.kohesive.injekt.injectLazy
/** /**
@ -54,7 +55,7 @@ class DownloadProvider(private val context: Context) {
.createDirectory(getSourceDirName(source)) .createDirectory(getSourceDirName(source))
.createDirectory(getMangaDirName(manga)) .createDirectory(getMangaDirName(manga))
} catch (e: Throwable) { } catch (e: Throwable) {
Timber.e(e, "Invalid download directory") logcat(LogPriority.ERROR, e) { "Invalid download directory" }
throw Exception(context.getString(R.string.invalid_download_dir)) throw Exception(context.getString(R.string.invalid_download_dir))
} }
} }

View File

@ -18,6 +18,7 @@ import eu.kanade.tachiyomi.util.system.acquireWakeLock
import eu.kanade.tachiyomi.util.system.isConnectedToWifi import eu.kanade.tachiyomi.util.system.isConnectedToWifi
import eu.kanade.tachiyomi.util.system.isOnline import eu.kanade.tachiyomi.util.system.isOnline
import eu.kanade.tachiyomi.util.system.isServiceRunning import eu.kanade.tachiyomi.util.system.isServiceRunning
import eu.kanade.tachiyomi.util.system.logcat
import eu.kanade.tachiyomi.util.system.notification import eu.kanade.tachiyomi.util.system.notification
import eu.kanade.tachiyomi.util.system.toast import eu.kanade.tachiyomi.util.system.toast
import kotlinx.coroutines.CoroutineScope import kotlinx.coroutines.CoroutineScope
@ -27,9 +28,9 @@ import kotlinx.coroutines.cancel
import kotlinx.coroutines.flow.catch import kotlinx.coroutines.flow.catch
import kotlinx.coroutines.flow.launchIn import kotlinx.coroutines.flow.launchIn
import kotlinx.coroutines.flow.onEach import kotlinx.coroutines.flow.onEach
import logcat.LogPriority
import ru.beryukhov.reactivenetwork.ReactiveNetwork import ru.beryukhov.reactivenetwork.ReactiveNetwork
import rx.subscriptions.CompositeSubscription import rx.subscriptions.CompositeSubscription
import timber.log.Timber
import uy.kohesive.injekt.injectLazy import uy.kohesive.injekt.injectLazy
/** /**
@ -143,7 +144,7 @@ class DownloadService : Service() {
} }
.catch { error -> .catch { error ->
withUIContext { withUIContext {
Timber.e(error) logcat(LogPriority.ERROR, error)
toast(R.string.download_queue_error) toast(R.string.download_queue_error)
stopSelf() stopSelf()
} }

View File

@ -22,13 +22,14 @@ import eu.kanade.tachiyomi.util.lang.plusAssign
import eu.kanade.tachiyomi.util.storage.DiskUtil import eu.kanade.tachiyomi.util.storage.DiskUtil
import eu.kanade.tachiyomi.util.storage.saveTo import eu.kanade.tachiyomi.util.storage.saveTo
import eu.kanade.tachiyomi.util.system.ImageUtil import eu.kanade.tachiyomi.util.system.ImageUtil
import eu.kanade.tachiyomi.util.system.logcat
import kotlinx.coroutines.async import kotlinx.coroutines.async
import logcat.LogPriority
import okhttp3.Response import okhttp3.Response
import rx.Observable import rx.Observable
import rx.android.schedulers.AndroidSchedulers import rx.android.schedulers.AndroidSchedulers
import rx.schedulers.Schedulers import rx.schedulers.Schedulers
import rx.subscriptions.CompositeSubscription import rx.subscriptions.CompositeSubscription
import timber.log.Timber
import uy.kohesive.injekt.injectLazy import uy.kohesive.injekt.injectLazy
import java.io.File import java.io.File
@ -209,7 +210,7 @@ class Downloader(
}, },
{ error -> { error ->
DownloadService.stop(context) DownloadService.stop(context)
Timber.e(error) logcat(LogPriority.ERROR, error)
notifier.onError(error.message) notifier.onError(error.message)
} }
) )

View File

@ -37,6 +37,7 @@ import eu.kanade.tachiyomi.util.storage.getUriCompat
import eu.kanade.tachiyomi.util.system.acquireWakeLock import eu.kanade.tachiyomi.util.system.acquireWakeLock
import eu.kanade.tachiyomi.util.system.createFileInCacheDir import eu.kanade.tachiyomi.util.system.createFileInCacheDir
import eu.kanade.tachiyomi.util.system.isServiceRunning import eu.kanade.tachiyomi.util.system.isServiceRunning
import eu.kanade.tachiyomi.util.system.logcat
import kotlinx.coroutines.CoroutineExceptionHandler import kotlinx.coroutines.CoroutineExceptionHandler
import kotlinx.coroutines.CoroutineScope import kotlinx.coroutines.CoroutineScope
import kotlinx.coroutines.Dispatchers import kotlinx.coroutines.Dispatchers
@ -50,7 +51,7 @@ import kotlinx.coroutines.launch
import kotlinx.coroutines.supervisorScope import kotlinx.coroutines.supervisorScope
import kotlinx.coroutines.sync.Semaphore import kotlinx.coroutines.sync.Semaphore
import kotlinx.coroutines.sync.withPermit import kotlinx.coroutines.sync.withPermit
import timber.log.Timber import logcat.LogPriority
import uy.kohesive.injekt.Injekt import uy.kohesive.injekt.Injekt
import uy.kohesive.injekt.api.get import uy.kohesive.injekt.api.get
import java.io.File import java.io.File
@ -212,7 +213,7 @@ class LibraryUpdateService(
// Destroy service when completed or in case of an error. // Destroy service when completed or in case of an error.
val handler = CoroutineExceptionHandler { _, exception -> val handler = CoroutineExceptionHandler { _, exception ->
Timber.e(exception) logcat(LogPriority.ERROR, exception)
stopSelf(startId) stopSelf(startId)
} }
updateJob = ioScope.launch(handler) { updateJob = ioScope.launch(handler) {
@ -377,7 +378,7 @@ class LibraryUpdateService(
// Update manga details metadata in the background // Update manga details metadata in the background
if (preferences.autoUpdateMetadata()) { if (preferences.autoUpdateMetadata()) {
val handler = CoroutineExceptionHandler { _, exception -> val handler = CoroutineExceptionHandler { _, exception ->
Timber.e(exception) logcat(LogPriority.ERROR, exception)
} }
GlobalScope.launch(Dispatchers.IO + handler) { GlobalScope.launch(Dispatchers.IO + handler) {
val updatedManga = source.getMangaDetails(manga.toMangaInfo()) val updatedManga = source.getMangaDetails(manga.toMangaInfo())
@ -433,7 +434,7 @@ class LibraryUpdateService(
} }
} catch (e: Throwable) { } catch (e: Throwable) {
// Ignore errors and continue // Ignore errors and continue
Timber.e(e) logcat(LogPriority.ERROR, e)
} }
} }
@ -494,7 +495,7 @@ class LibraryUpdateService(
} }
} catch (e: Throwable) { } catch (e: Throwable) {
// Ignore errors and continue // Ignore errors and continue
Timber.e(e) logcat(LogPriority.ERROR, e)
} }
} }
} }

View File

@ -227,6 +227,8 @@ object PreferenceKeys {
const val extensionInstaller = "extension_installer" const val extensionInstaller = "extension_installer"
const val verboseLogging = "verbose_logging"
fun trackUsername(syncId: Int) = "pref_mangasync_username_$syncId" fun trackUsername(syncId: Int) = "pref_mangasync_username_$syncId"
fun trackPassword(syncId: Int) = "pref_mangasync_password_$syncId" fun trackPassword(syncId: Int) = "pref_mangasync_password_$syncId"

View File

@ -331,6 +331,8 @@ class PreferencesHelper(val context: Context) {
if (MiuiUtil.isMiui()) Values.ExtensionInstaller.LEGACY else Values.ExtensionInstaller.PACKAGEINSTALLER if (MiuiUtil.isMiui()) Values.ExtensionInstaller.LEGACY else Values.ExtensionInstaller.PACKAGEINSTALLER
) )
fun verboseLogging() = prefs.getBoolean(Keys.verboseLogging, false)
fun setChapterSettingsDefault(manga: Manga) { fun setChapterSettingsDefault(manga: Manga) {
prefs.edit { prefs.edit {
putInt(Keys.defaultChapterFilterByRead, manga.readFilter) putInt(Keys.defaultChapterFilterByRead, manga.readFilter)

View File

@ -3,7 +3,8 @@ package eu.kanade.tachiyomi.data.track.job
import android.content.Context import android.content.Context
import androidx.core.content.edit import androidx.core.content.edit
import eu.kanade.tachiyomi.data.database.models.Track import eu.kanade.tachiyomi.data.database.models.Track
import timber.log.Timber import eu.kanade.tachiyomi.util.system.logcat
import logcat.LogPriority
class DelayedTrackingStore(context: Context) { class DelayedTrackingStore(context: Context) {
@ -17,7 +18,7 @@ class DelayedTrackingStore(context: Context) {
val (_, lastChapterRead) = preferences.getString(trackId, "0:0.0")!!.split(":") val (_, lastChapterRead) = preferences.getString(trackId, "0:0.0")!!.split(":")
if (track.last_chapter_read > lastChapterRead.toFloat()) { if (track.last_chapter_read > lastChapterRead.toFloat()) {
val value = "${track.manga_id}:${track.last_chapter_read}" val value = "${track.manga_id}:${track.last_chapter_read}"
Timber.i("Queuing track item: $trackId, $value") logcat(LogPriority.INFO) { "Queuing track item: $trackId, $value" }
preferences.edit { preferences.edit {
putString(trackId, value) putString(trackId, value)
} }

View File

@ -11,9 +11,10 @@ import androidx.work.WorkManager
import androidx.work.WorkerParameters import androidx.work.WorkerParameters
import eu.kanade.tachiyomi.data.database.DatabaseHelper import eu.kanade.tachiyomi.data.database.DatabaseHelper
import eu.kanade.tachiyomi.data.track.TrackManager import eu.kanade.tachiyomi.data.track.TrackManager
import eu.kanade.tachiyomi.util.system.logcat
import kotlinx.coroutines.Dispatchers import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.withContext import kotlinx.coroutines.withContext
import timber.log.Timber import logcat.LogPriority
import uy.kohesive.injekt.Injekt import uy.kohesive.injekt.Injekt
import uy.kohesive.injekt.api.get import uy.kohesive.injekt.api.get
import java.util.concurrent.TimeUnit import java.util.concurrent.TimeUnit
@ -44,7 +45,7 @@ class DelayedTrackingUpdateJob(context: Context, workerParams: WorkerParameters)
db.insertTrack(track).executeAsBlocking() db.insertTrack(track).executeAsBlocking()
} }
} catch (e: Exception) { } catch (e: Exception) {
Timber.e(e) logcat(LogPriority.ERROR, e)
} }
} }

View File

@ -7,13 +7,14 @@ import eu.kanade.tachiyomi.network.GET
import eu.kanade.tachiyomi.network.await import eu.kanade.tachiyomi.network.await
import eu.kanade.tachiyomi.network.parseAs import eu.kanade.tachiyomi.network.parseAs
import eu.kanade.tachiyomi.util.lang.withIOContext import eu.kanade.tachiyomi.util.lang.withIOContext
import eu.kanade.tachiyomi.util.system.logcat
import kotlinx.serialization.encodeToString import kotlinx.serialization.encodeToString
import kotlinx.serialization.json.Json import kotlinx.serialization.json.Json
import logcat.LogPriority
import okhttp3.MediaType.Companion.toMediaType import okhttp3.MediaType.Companion.toMediaType
import okhttp3.OkHttpClient import okhttp3.OkHttpClient
import okhttp3.Request import okhttp3.Request
import okhttp3.RequestBody.Companion.toRequestBody import okhttp3.RequestBody.Companion.toRequestBody
import timber.log.Timber
import uy.kohesive.injekt.injectLazy import uy.kohesive.injekt.injectLazy
const val READLIST_API = "/api/v1/readlists" const val READLIST_API = "/api/v1/readlists"
@ -56,7 +57,7 @@ class KomgaApi(private val client: OkHttpClient) {
last_chapter_read = progress.lastReadContinuousNumberSort last_chapter_read = progress.lastReadContinuousNumberSort
} }
} catch (e: Exception) { } catch (e: Exception) {
Timber.w(e, "Could not get item: $url") logcat(LogPriority.WARN, e) { "Could not get item: $url" }
throw e throw e
} }
} }

View File

@ -20,7 +20,8 @@ import eu.kanade.tachiyomi.util.storage.getUriCompat
import eu.kanade.tachiyomi.util.storage.saveTo import eu.kanade.tachiyomi.util.storage.saveTo
import eu.kanade.tachiyomi.util.system.acquireWakeLock import eu.kanade.tachiyomi.util.system.acquireWakeLock
import eu.kanade.tachiyomi.util.system.isServiceRunning import eu.kanade.tachiyomi.util.system.isServiceRunning
import timber.log.Timber import eu.kanade.tachiyomi.util.system.logcat
import logcat.LogPriority
import uy.kohesive.injekt.injectLazy import uy.kohesive.injekt.injectLazy
import java.io.File import java.io.File
@ -121,7 +122,7 @@ class UpdaterService : Service() {
} }
notifier.onDownloadFinished(apkFile.getUriCompat(this)) notifier.onDownloadFinished(apkFile.getUriCompat(this))
} catch (error: Exception) { } catch (error: Exception) {
Timber.e(error) logcat(LogPriority.ERROR, error)
notifier.onDownloadError(url) notifier.onDownloadError(url)
} }
} }

View File

@ -11,7 +11,8 @@ import android.os.Build
import eu.kanade.tachiyomi.extension.model.InstallStep import eu.kanade.tachiyomi.extension.model.InstallStep
import eu.kanade.tachiyomi.util.lang.use import eu.kanade.tachiyomi.util.lang.use
import eu.kanade.tachiyomi.util.system.getUriSize import eu.kanade.tachiyomi.util.system.getUriSize
import timber.log.Timber import eu.kanade.tachiyomi.util.system.logcat
import logcat.LogPriority
class PackageInstallerInstaller(private val service: Service) : Installer(service) { class PackageInstallerInstaller(private val service: Service) : Installer(service) {
@ -23,7 +24,7 @@ class PackageInstallerInstaller(private val service: Service) : Installer(servic
PackageInstaller.STATUS_PENDING_USER_ACTION -> { PackageInstaller.STATUS_PENDING_USER_ACTION -> {
val userAction = intent.getParcelableExtra<Intent>(Intent.EXTRA_INTENT) val userAction = intent.getParcelableExtra<Intent>(Intent.EXTRA_INTENT)
if (userAction == null) { if (userAction == null) {
Timber.e("Fatal error for $intent") logcat(LogPriority.ERROR) { "Fatal error for $intent" }
continueQueue(InstallStep.Error) continueQueue(InstallStep.Error)
return return
} }
@ -74,7 +75,7 @@ class PackageInstallerInstaller(private val service: Service) : Installer(servic
session.commit(intentSender) session.commit(intentSender)
} }
} catch (e: Exception) { } catch (e: Exception) {
Timber.e(e, "Failed to install extension ${entry.downloadId} ${entry.uri}") logcat(LogPriority.ERROR) { "Failed to install extension ${entry.downloadId} ${entry.uri}" }
activeSession?.let { (_, sessionId) -> activeSession?.let { (_, sessionId) ->
packageInstaller.abandonSession(sessionId) packageInstaller.abandonSession(sessionId)
} }

View File

@ -6,14 +6,15 @@ import android.os.Build
import eu.kanade.tachiyomi.R import eu.kanade.tachiyomi.R
import eu.kanade.tachiyomi.extension.model.InstallStep import eu.kanade.tachiyomi.extension.model.InstallStep
import eu.kanade.tachiyomi.util.system.getUriSize import eu.kanade.tachiyomi.util.system.getUriSize
import eu.kanade.tachiyomi.util.system.logcat
import eu.kanade.tachiyomi.util.system.toast import eu.kanade.tachiyomi.util.system.toast
import kotlinx.coroutines.CoroutineScope import kotlinx.coroutines.CoroutineScope
import kotlinx.coroutines.Dispatchers import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.SupervisorJob import kotlinx.coroutines.SupervisorJob
import kotlinx.coroutines.cancel import kotlinx.coroutines.cancel
import kotlinx.coroutines.launch import kotlinx.coroutines.launch
import logcat.LogPriority
import rikka.shizuku.Shizuku import rikka.shizuku.Shizuku
import timber.log.Timber
import java.io.BufferedReader import java.io.BufferedReader
import java.io.InputStream import java.io.InputStream
@ -22,7 +23,7 @@ class ShizukuInstaller(private val service: Service) : Installer(service) {
private val ioScope = CoroutineScope(SupervisorJob() + Dispatchers.IO) private val ioScope = CoroutineScope(SupervisorJob() + Dispatchers.IO)
private val shizukuDeadListener = Shizuku.OnBinderDeadListener { private val shizukuDeadListener = Shizuku.OnBinderDeadListener {
Timber.e("Shizuku was killed prematurely") logcat { "Shizuku was killed prematurely" }
service.stopSelf() service.stopSelf()
} }
@ -72,7 +73,7 @@ class ShizukuInstaller(private val service: Service) : Installer(service) {
continueQueue(InstallStep.Installed) continueQueue(InstallStep.Installed)
} }
} catch (e: Exception) { } catch (e: Exception) {
Timber.e(e, "Failed to install extension ${entry.downloadId} ${entry.uri}") logcat(LogPriority.ERROR, e) { "Failed to install extension ${entry.downloadId} ${entry.uri}" }
if (sessionId != null) { if (sessionId != null) {
exec("pm install-abandon $sessionId") exec("pm install-abandon $sessionId")
} }
@ -115,7 +116,7 @@ class ShizukuInstaller(private val service: Service) : Installer(service) {
false false
} }
} else { } else {
Timber.e("Shizuku is not ready to use.") logcat(LogPriority.ERROR) { "Shizuku is not ready to use." }
service.toast(R.string.ext_installer_shizuku_stopped) service.toast(R.string.ext_installer_shizuku_stopped)
service.stopSelf() service.stopSelf()
false false

View File

@ -12,8 +12,9 @@ import eu.kanade.tachiyomi.extension.installer.Installer
import eu.kanade.tachiyomi.extension.installer.PackageInstallerInstaller import eu.kanade.tachiyomi.extension.installer.PackageInstallerInstaller
import eu.kanade.tachiyomi.extension.installer.ShizukuInstaller import eu.kanade.tachiyomi.extension.installer.ShizukuInstaller
import eu.kanade.tachiyomi.extension.util.ExtensionInstaller.Companion.EXTRA_DOWNLOAD_ID import eu.kanade.tachiyomi.extension.util.ExtensionInstaller.Companion.EXTRA_DOWNLOAD_ID
import eu.kanade.tachiyomi.util.system.logcat
import eu.kanade.tachiyomi.util.system.notificationBuilder import eu.kanade.tachiyomi.util.system.notificationBuilder
import timber.log.Timber import logcat.LogPriority
class ExtensionInstallService : Service() { class ExtensionInstallService : Service() {
@ -46,7 +47,7 @@ class ExtensionInstallService : Service() {
PreferenceValues.ExtensionInstaller.PACKAGEINSTALLER -> PackageInstallerInstaller(this) PreferenceValues.ExtensionInstaller.PACKAGEINSTALLER -> PackageInstallerInstaller(this)
PreferenceValues.ExtensionInstaller.SHIZUKU -> ShizukuInstaller(this) PreferenceValues.ExtensionInstaller.SHIZUKU -> ShizukuInstaller(this)
else -> { else -> {
Timber.e("Not implemented for installer $installerUsed") logcat(LogPriority.ERROR) { "Not implemented for installer $installerUsed" }
stopSelf() stopSelf()
return START_NOT_STICKY return START_NOT_STICKY
} }

View File

@ -17,9 +17,10 @@ import eu.kanade.tachiyomi.extension.installer.Installer
import eu.kanade.tachiyomi.extension.model.Extension import eu.kanade.tachiyomi.extension.model.Extension
import eu.kanade.tachiyomi.extension.model.InstallStep import eu.kanade.tachiyomi.extension.model.InstallStep
import eu.kanade.tachiyomi.util.storage.getUriCompat import eu.kanade.tachiyomi.util.storage.getUriCompat
import eu.kanade.tachiyomi.util.system.logcat
import logcat.LogPriority
import rx.Observable import rx.Observable
import rx.android.schedulers.AndroidSchedulers import rx.android.schedulers.AndroidSchedulers
import timber.log.Timber
import uy.kohesive.injekt.Injekt import uy.kohesive.injekt.Injekt
import uy.kohesive.injekt.api.get import uy.kohesive.injekt.api.get
import java.io.File import java.io.File
@ -239,7 +240,7 @@ internal class ExtensionInstaller(private val context: Context) {
// Set next installation step // Set next installation step
if (uri == null) { if (uri == null) {
Timber.e("Couldn't locate downloaded APK") logcat(LogPriority.ERROR) { "Couldn't locate downloaded APK" }
downloadsRelay.call(id to InstallStep.Error) downloadsRelay.call(id to InstallStep.Error)
return return
} }

View File

@ -13,9 +13,10 @@ import eu.kanade.tachiyomi.source.CatalogueSource
import eu.kanade.tachiyomi.source.Source import eu.kanade.tachiyomi.source.Source
import eu.kanade.tachiyomi.source.SourceFactory import eu.kanade.tachiyomi.source.SourceFactory
import eu.kanade.tachiyomi.util.lang.Hash import eu.kanade.tachiyomi.util.lang.Hash
import eu.kanade.tachiyomi.util.system.logcat
import kotlinx.coroutines.async import kotlinx.coroutines.async
import kotlinx.coroutines.runBlocking import kotlinx.coroutines.runBlocking
import timber.log.Timber import logcat.LogPriority
import uy.kohesive.injekt.injectLazy import uy.kohesive.injekt.injectLazy
/** /**
@ -107,7 +108,7 @@ internal object ExtensionLoader {
if (versionName.isNullOrEmpty()) { if (versionName.isNullOrEmpty()) {
val exception = Exception("Missing versionName for extension $extName") val exception = Exception("Missing versionName for extension $extName")
Timber.w(exception) logcat(LogPriority.WARN, exception)
return LoadResult.Error(exception) return LoadResult.Error(exception)
} }
@ -118,7 +119,7 @@ internal object ExtensionLoader {
"Lib version is $libVersion, while only versions " + "Lib version is $libVersion, while only versions " +
"$LIB_VERSION_MIN to $LIB_VERSION_MAX are allowed" "$LIB_VERSION_MIN to $LIB_VERSION_MAX are allowed"
) )
Timber.w(exception) logcat(LogPriority.WARN, exception)
return LoadResult.Error(exception) return LoadResult.Error(exception)
} }
@ -128,7 +129,7 @@ internal object ExtensionLoader {
return LoadResult.Error("Package $pkgName isn't signed") return LoadResult.Error("Package $pkgName isn't signed")
} else if (signatureHash !in trustedSignatures) { } else if (signatureHash !in trustedSignatures) {
val extension = Extension.Untrusted(extName, pkgName, versionName, versionCode, signatureHash) val extension = Extension.Untrusted(extName, pkgName, versionName, versionCode, signatureHash)
Timber.w("Extension $pkgName isn't trusted") logcat(LogPriority.WARN) { "Extension $pkgName isn't trusted" }
return LoadResult.Untrusted(extension) return LoadResult.Untrusted(extension)
} }
@ -157,7 +158,7 @@ internal object ExtensionLoader {
else -> throw Exception("Unknown source class type! ${obj.javaClass}") else -> throw Exception("Unknown source class type! ${obj.javaClass}")
} }
} catch (e: Throwable) { } catch (e: Throwable) {
Timber.e(e, "Extension load error: $extName ($it)") logcat(LogPriority.ERROR, e) { "Extension load error: $extName ($it)" }
return LoadResult.Error(e) return LoadResult.Error(e)
} }
} }

View File

@ -2,7 +2,6 @@ package eu.kanade.tachiyomi.network
import android.content.Context import android.content.Context
import coil.util.CoilUtils import coil.util.CoilUtils
import eu.kanade.tachiyomi.BuildConfig
import eu.kanade.tachiyomi.data.preference.PreferencesHelper import eu.kanade.tachiyomi.data.preference.PreferencesHelper
import eu.kanade.tachiyomi.network.interceptor.CloudflareInterceptor import eu.kanade.tachiyomi.network.interceptor.CloudflareInterceptor
import eu.kanade.tachiyomi.network.interceptor.UserAgentInterceptor import eu.kanade.tachiyomi.network.interceptor.UserAgentInterceptor
@ -31,7 +30,7 @@ class NetworkHelper(context: Context) {
.readTimeout(30, TimeUnit.SECONDS) .readTimeout(30, TimeUnit.SECONDS)
.addInterceptor(UserAgentInterceptor()) .addInterceptor(UserAgentInterceptor())
if (BuildConfig.DEBUG) { if (preferences.verboseLogging()) {
val httpLoggingInterceptor = HttpLoggingInterceptor().apply { val httpLoggingInterceptor = HttpLoggingInterceptor().apply {
level = HttpLoggingInterceptor.Level.HEADERS level = HttpLoggingInterceptor.Level.HEADERS
} }

View File

@ -14,6 +14,7 @@ import eu.kanade.tachiyomi.util.lang.compareToCaseInsensitiveNaturalOrder
import eu.kanade.tachiyomi.util.storage.DiskUtil import eu.kanade.tachiyomi.util.storage.DiskUtil
import eu.kanade.tachiyomi.util.storage.EpubFile import eu.kanade.tachiyomi.util.storage.EpubFile
import eu.kanade.tachiyomi.util.system.ImageUtil import eu.kanade.tachiyomi.util.system.ImageUtil
import eu.kanade.tachiyomi.util.system.logcat
import kotlinx.serialization.json.Json import kotlinx.serialization.json.Json
import kotlinx.serialization.json.JsonObject import kotlinx.serialization.json.JsonObject
import kotlinx.serialization.json.contentOrNull import kotlinx.serialization.json.contentOrNull
@ -21,8 +22,8 @@ import kotlinx.serialization.json.decodeFromStream
import kotlinx.serialization.json.intOrNull import kotlinx.serialization.json.intOrNull
import kotlinx.serialization.json.jsonArray import kotlinx.serialization.json.jsonArray
import kotlinx.serialization.json.jsonPrimitive import kotlinx.serialization.json.jsonPrimitive
import logcat.LogPriority
import rx.Observable import rx.Observable
import timber.log.Timber
import uy.kohesive.injekt.injectLazy import uy.kohesive.injekt.injectLazy
import java.io.File import java.io.File
import java.io.FileInputStream import java.io.FileInputStream
@ -147,7 +148,7 @@ class LocalSource(private val context: Context) : CatalogueSource {
val dest = updateCover(chapter, this) val dest = updateCover(chapter, this)
thumbnail_url = dest?.absolutePath thumbnail_url = dest?.absolutePath
} catch (e: Exception) { } catch (e: Exception) {
Timber.e(e) logcat(LogPriority.ERROR, e)
} }
} }
} }

View File

@ -10,10 +10,10 @@ import androidx.viewbinding.ViewBinding
import com.bluelinelabs.conductor.Controller import com.bluelinelabs.conductor.Controller
import com.bluelinelabs.conductor.ControllerChangeHandler import com.bluelinelabs.conductor.ControllerChangeHandler
import com.bluelinelabs.conductor.ControllerChangeType import com.bluelinelabs.conductor.ControllerChangeType
import eu.kanade.tachiyomi.util.system.logcat
import kotlinx.coroutines.CoroutineScope import kotlinx.coroutines.CoroutineScope
import kotlinx.coroutines.MainScope import kotlinx.coroutines.MainScope
import kotlinx.coroutines.cancel import kotlinx.coroutines.cancel
import timber.log.Timber
abstract class BaseController<VB : ViewBinding>(bundle: Bundle? = null) : Controller(bundle) { abstract class BaseController<VB : ViewBinding>(bundle: Bundle? = null) : Controller(bundle) {
@ -31,20 +31,20 @@ abstract class BaseController<VB : ViewBinding>(bundle: Bundle? = null) : Contro
override fun preCreateView(controller: Controller) { override fun preCreateView(controller: Controller) {
viewScope = MainScope() viewScope = MainScope()
Timber.d("Create view for ${controller.instance()}") logcat { "Create view for ${controller.instance()}" }
} }
override fun preAttach(controller: Controller, view: View) { override fun preAttach(controller: Controller, view: View) {
Timber.d("Attach view for ${controller.instance()}") logcat { "Attach view for ${controller.instance()}" }
} }
override fun preDetach(controller: Controller, view: View) { override fun preDetach(controller: Controller, view: View) {
Timber.d("Detach view for ${controller.instance()}") logcat { "Detach view for ${controller.instance()}" }
} }
override fun preDestroyView(controller: Controller, view: View) { override fun preDestroyView(controller: Controller, view: View) {
viewScope.cancel() viewScope.cancel()
Timber.d("Destroy view for ${controller.instance()}") logcat { "Destroy view for ${controller.instance()}" }
} }
} }
) )

View File

@ -27,8 +27,9 @@ import eu.kanade.tachiyomi.source.ConfigurableSource
import eu.kanade.tachiyomi.source.Source import eu.kanade.tachiyomi.source.Source
import eu.kanade.tachiyomi.source.getPreferenceKey import eu.kanade.tachiyomi.source.getPreferenceKey
import eu.kanade.tachiyomi.ui.base.controller.NucleusController import eu.kanade.tachiyomi.ui.base.controller.NucleusController
import eu.kanade.tachiyomi.util.system.logcat
import eu.kanade.tachiyomi.widget.TachiyomiTextInputEditText.Companion.setIncognito import eu.kanade.tachiyomi.widget.TachiyomiTextInputEditText.Companion.setIncognito
import timber.log.Timber import logcat.LogPriority
@SuppressLint("RestrictedApi") @SuppressLint("RestrictedApi")
class SourcePreferencesController(bundle: Bundle? = null) : class SourcePreferencesController(bundle: Bundle? = null) :
@ -77,7 +78,7 @@ class SourcePreferencesController(bundle: Bundle? = null) :
try { try {
addPreferencesForSource(screen, source) addPreferencesForSource(screen, source)
} catch (e: AbstractMethodError) { } catch (e: AbstractMethodError) {
Timber.e("Source did not implement [addPreferencesForSource]: ${source.name}") logcat(LogPriority.ERROR) { "Source did not implement [addPreferencesForSource]: ${source.name}" }
} }
manager.setPreferences(screen) manager.setPreferences(screen)

View File

@ -42,6 +42,7 @@ import eu.kanade.tachiyomi.ui.manga.MangaController
import eu.kanade.tachiyomi.ui.more.MoreController import eu.kanade.tachiyomi.ui.more.MoreController
import eu.kanade.tachiyomi.ui.webview.WebViewActivity import eu.kanade.tachiyomi.ui.webview.WebViewActivity
import eu.kanade.tachiyomi.util.system.connectivityManager import eu.kanade.tachiyomi.util.system.connectivityManager
import eu.kanade.tachiyomi.util.system.logcat
import eu.kanade.tachiyomi.util.system.openInBrowser import eu.kanade.tachiyomi.util.system.openInBrowser
import eu.kanade.tachiyomi.util.system.toast import eu.kanade.tachiyomi.util.system.toast
import eu.kanade.tachiyomi.util.view.inflate import eu.kanade.tachiyomi.util.view.inflate
@ -54,7 +55,7 @@ import kotlinx.coroutines.Job
import kotlinx.coroutines.flow.drop import kotlinx.coroutines.flow.drop
import kotlinx.coroutines.flow.launchIn import kotlinx.coroutines.flow.launchIn
import kotlinx.coroutines.flow.onEach import kotlinx.coroutines.flow.onEach
import timber.log.Timber import logcat.LogPriority
import uy.kohesive.injekt.injectLazy import uy.kohesive.injekt.injectLazy
/** /**
@ -405,7 +406,7 @@ open class BrowseSourceController(bundle: Bundle) :
* @param error the error received. * @param error the error received.
*/ */
fun onAddPageError(error: Throwable) { fun onAddPageError(error: Throwable) {
Timber.e(error) logcat(LogPriority.ERROR, error)
val adapter = adapter ?: return val adapter = adapter ?: return
adapter.onLoadMoreComplete(null) adapter.onLoadMoreComplete(null)
hideProgressBar() hideProgressBar()

View File

@ -37,6 +37,7 @@ import eu.kanade.tachiyomi.util.chapter.syncChaptersWithTrackServiceTwoWay
import eu.kanade.tachiyomi.util.lang.launchIO import eu.kanade.tachiyomi.util.lang.launchIO
import eu.kanade.tachiyomi.util.lang.withUIContext import eu.kanade.tachiyomi.util.lang.withUIContext
import eu.kanade.tachiyomi.util.removeCovers import eu.kanade.tachiyomi.util.removeCovers
import eu.kanade.tachiyomi.util.system.logcat
import kotlinx.coroutines.Job import kotlinx.coroutines.Job
import kotlinx.coroutines.flow.asFlow import kotlinx.coroutines.flow.asFlow
import kotlinx.coroutines.flow.catch import kotlinx.coroutines.flow.catch
@ -44,10 +45,10 @@ import kotlinx.coroutines.flow.collect
import kotlinx.coroutines.flow.filter import kotlinx.coroutines.flow.filter
import kotlinx.coroutines.flow.map import kotlinx.coroutines.flow.map
import kotlinx.coroutines.flow.onEach import kotlinx.coroutines.flow.onEach
import logcat.LogPriority
import rx.Subscription import rx.Subscription
import rx.android.schedulers.AndroidSchedulers import rx.android.schedulers.AndroidSchedulers
import rx.schedulers.Schedulers import rx.schedulers.Schedulers
import timber.log.Timber
import uy.kohesive.injekt.Injekt import uy.kohesive.injekt.Injekt
import uy.kohesive.injekt.api.get import uy.kohesive.injekt.api.get
import java.util.Date import java.util.Date
@ -155,7 +156,7 @@ open class BrowseSourcePresenter(
view.onAddPage(page, mangas) view.onAddPage(page, mangas)
}, },
{ _, error -> { _, error ->
Timber.e(error) logcat(LogPriority.ERROR, error)
} }
) )
@ -221,7 +222,7 @@ open class BrowseSourcePresenter(
view?.onMangaInitialized(it) view?.onMangaInitialized(it)
} }
} }
.catch { e -> Timber.e(e) } .catch { e -> logcat(LogPriority.ERROR, e) }
.collect() .collect()
} }
} }
@ -239,7 +240,7 @@ open class BrowseSourcePresenter(
manga.initialized = true manga.initialized = true
db.insertManga(manga).executeAsBlocking() db.insertManga(manga).executeAsBlocking()
} catch (e: Exception) { } catch (e: Exception) {
Timber.e(e) logcat(LogPriority.ERROR, e)
} }
return manga return manga
} }
@ -282,7 +283,7 @@ open class BrowseSourcePresenter(
syncChaptersWithTrackServiceTwoWay(db, db.getChapters(manga).executeAsBlocking(), track, service as TrackService) syncChaptersWithTrackServiceTwoWay(db, db.getChapters(manga).executeAsBlocking(), track, service as TrackService)
} }
} catch (e: Exception) { } catch (e: Exception) {
Timber.w(e, "Could not match manga: ${manga.title} with service $service") logcat(LogPriority.WARN, e) { "Could not match manga: ${manga.title} with service $service" }
} }
} }
} }

View File

@ -16,12 +16,13 @@ import eu.kanade.tachiyomi.source.model.toSManga
import eu.kanade.tachiyomi.ui.base.presenter.BasePresenter import eu.kanade.tachiyomi.ui.base.presenter.BasePresenter
import eu.kanade.tachiyomi.ui.browse.source.browse.BrowseSourcePresenter import eu.kanade.tachiyomi.ui.browse.source.browse.BrowseSourcePresenter
import eu.kanade.tachiyomi.util.lang.runAsObservable import eu.kanade.tachiyomi.util.lang.runAsObservable
import eu.kanade.tachiyomi.util.system.logcat
import logcat.LogPriority
import rx.Observable import rx.Observable
import rx.Subscription import rx.Subscription
import rx.android.schedulers.AndroidSchedulers import rx.android.schedulers.AndroidSchedulers
import rx.schedulers.Schedulers import rx.schedulers.Schedulers
import rx.subjects.PublishSubject import rx.subjects.PublishSubject
import timber.log.Timber
import uy.kohesive.injekt.Injekt import uy.kohesive.injekt.Injekt
import uy.kohesive.injekt.api.get import uy.kohesive.injekt.api.get
import uy.kohesive.injekt.injectLazy import uy.kohesive.injekt.injectLazy
@ -198,7 +199,7 @@ open class GlobalSearchPresenter(
view.setItems(manga) view.setItems(manga)
}, },
{ _, error -> { _, error ->
Timber.e(error) logcat(LogPriority.ERROR, error)
} }
) )
} }
@ -233,7 +234,7 @@ open class GlobalSearchPresenter(
view?.onMangaInitialized(source, manga) view?.onMangaInitialized(source, manga)
}, },
{ error -> { error ->
Timber.e(error) logcat(LogPriority.ERROR, error)
} }
) )
} }

View File

@ -5,9 +5,10 @@ import eu.kanade.tachiyomi.data.download.DownloadManager
import eu.kanade.tachiyomi.data.download.model.Download import eu.kanade.tachiyomi.data.download.model.Download
import eu.kanade.tachiyomi.data.download.model.DownloadQueue import eu.kanade.tachiyomi.data.download.model.DownloadQueue
import eu.kanade.tachiyomi.ui.base.presenter.BasePresenter import eu.kanade.tachiyomi.ui.base.presenter.BasePresenter
import eu.kanade.tachiyomi.util.system.logcat
import logcat.LogPriority
import rx.Observable import rx.Observable
import rx.android.schedulers.AndroidSchedulers import rx.android.schedulers.AndroidSchedulers
import timber.log.Timber
import uy.kohesive.injekt.injectLazy import uy.kohesive.injekt.injectLazy
/** /**
@ -30,7 +31,7 @@ class DownloadPresenter : BasePresenter<DownloadController>() {
.observeOn(AndroidSchedulers.mainThread()) .observeOn(AndroidSchedulers.mainThread())
.map { it.map(::DownloadItem) } .map { it.map(::DownloadItem) }
.subscribeLatestCache(DownloadController::onNextDownloads) { _, error -> .subscribeLatestCache(DownloadController::onNextDownloads) { _, error ->
Timber.e(error) logcat(LogPriority.ERROR, error)
} }
} }

View File

@ -61,13 +61,14 @@ import eu.kanade.tachiyomi.util.lang.launchIO
import eu.kanade.tachiyomi.util.lang.launchUI import eu.kanade.tachiyomi.util.lang.launchUI
import eu.kanade.tachiyomi.util.system.dpToPx import eu.kanade.tachiyomi.util.system.dpToPx
import eu.kanade.tachiyomi.util.system.isTablet import eu.kanade.tachiyomi.util.system.isTablet
import eu.kanade.tachiyomi.util.system.logcat
import eu.kanade.tachiyomi.util.system.toast import eu.kanade.tachiyomi.util.system.toast
import eu.kanade.tachiyomi.util.view.setNavigationBarTransparentCompat import eu.kanade.tachiyomi.util.view.setNavigationBarTransparentCompat
import kotlinx.coroutines.delay import kotlinx.coroutines.delay
import kotlinx.coroutines.flow.drop import kotlinx.coroutines.flow.drop
import kotlinx.coroutines.flow.launchIn import kotlinx.coroutines.flow.launchIn
import kotlinx.coroutines.flow.onEach import kotlinx.coroutines.flow.onEach
import timber.log.Timber import logcat.LogPriority
import java.util.Date import java.util.Date
import java.util.concurrent.TimeUnit import java.util.concurrent.TimeUnit
@ -340,7 +341,7 @@ class MainActivity : BaseViewBindingActivity<MainActivityBinding>() {
NewUpdateDialogController(result).showDialog(router) NewUpdateDialogController(result).showDialog(router)
} }
} catch (e: Exception) { } catch (e: Exception) {
Timber.e(e) logcat(LogPriority.ERROR, e)
} }
} }
} }
@ -356,7 +357,7 @@ class MainActivity : BaseViewBindingActivity<MainActivityBinding>() {
val pendingUpdates = ExtensionGithubApi().checkForUpdates(this@MainActivity) val pendingUpdates = ExtensionGithubApi().checkForUpdates(this@MainActivity)
preferences.extensionUpdatesCount().set(pendingUpdates.size) preferences.extensionUpdatesCount().set(pendingUpdates.size)
} catch (e: Exception) { } catch (e: Exception) {
Timber.e(e) logcat(LogPriority.ERROR, e)
} }
} }
} }

View File

@ -87,6 +87,7 @@ import eu.kanade.tachiyomi.util.hasCustomCover
import eu.kanade.tachiyomi.util.lang.launchIO import eu.kanade.tachiyomi.util.lang.launchIO
import eu.kanade.tachiyomi.util.lang.launchUI import eu.kanade.tachiyomi.util.lang.launchUI
import eu.kanade.tachiyomi.util.storage.getUriCompat import eu.kanade.tachiyomi.util.storage.getUriCompat
import eu.kanade.tachiyomi.util.system.logcat
import eu.kanade.tachiyomi.util.system.toShareIntent import eu.kanade.tachiyomi.util.system.toShareIntent
import eu.kanade.tachiyomi.util.system.toast import eu.kanade.tachiyomi.util.system.toast
import eu.kanade.tachiyomi.util.view.getCoordinates import eu.kanade.tachiyomi.util.view.getCoordinates
@ -95,9 +96,9 @@ import eu.kanade.tachiyomi.util.view.snack
import eu.kanade.tachiyomi.widget.materialdialogs.QuadStateTextView import eu.kanade.tachiyomi.widget.materialdialogs.QuadStateTextView
import kotlinx.coroutines.flow.launchIn import kotlinx.coroutines.flow.launchIn
import kotlinx.coroutines.flow.onEach import kotlinx.coroutines.flow.onEach
import logcat.LogPriority
import reactivecircus.flowbinding.recyclerview.scrollStateChanges import reactivecircus.flowbinding.recyclerview.scrollStateChanges
import reactivecircus.flowbinding.swiperefreshlayout.refreshes import reactivecircus.flowbinding.swiperefreshlayout.refreshes
import timber.log.Timber
import uy.kohesive.injekt.Injekt import uy.kohesive.injekt.Injekt
import uy.kohesive.injekt.api.get import uy.kohesive.injekt.api.get
import uy.kohesive.injekt.injectLazy import uy.kohesive.injekt.injectLazy
@ -595,7 +596,9 @@ class MangaController :
presenter.registerTracking(track, service as TrackService) presenter.registerTracking(track, service as TrackService)
} }
} catch (e: Exception) { } catch (e: Exception) {
Timber.w(e, "Could not match manga: ${manga.title} with service $service") logcat(LogPriority.WARN, e) {
"Could not match manga: ${manga.title} with service $service"
}
} }
} }
} }
@ -767,7 +770,7 @@ class MangaController :
startActivity(uri.toShareIntent(activity)) startActivity(uri.toShareIntent(activity))
} }
} catch (e: Exception) { } catch (e: Exception) {
Timber.e(e) logcat(LogPriority.ERROR, e)
activity?.toast(R.string.error_sharing_cover) activity?.toast(R.string.error_sharing_cover)
} }
} }
@ -780,7 +783,7 @@ class MangaController :
activity.toast(R.string.cover_saved) activity.toast(R.string.cover_saved)
} }
} catch (e: Exception) { } catch (e: Exception) {
Timber.e(e) logcat(LogPriority.ERROR, e)
activity?.toast(R.string.error_saving_cover) activity?.toast(R.string.error_saving_cover)
} }
} }
@ -836,7 +839,7 @@ class MangaController :
fun onSetCoverError(error: Throwable) { fun onSetCoverError(error: Throwable) {
activity?.toast(R.string.notification_cover_update_failed) activity?.toast(R.string.notification_cover_update_failed)
Timber.e(error) logcat(LogPriority.ERROR, error)
} }
/** /**
@ -1177,7 +1180,7 @@ class MangaController :
} }
fun onChaptersDeletedError(error: Throwable) { fun onChaptersDeletedError(error: Throwable) {
Timber.e(error) logcat(LogPriority.ERROR, error)
} }
override fun startDownloadNow(position: Int) { override fun startDownloadNow(position: Int) {
@ -1231,7 +1234,7 @@ class MangaController :
} }
fun onTrackingRefreshError(error: Throwable) { fun onTrackingRefreshError(error: Throwable) {
Timber.e(error) logcat(LogPriority.ERROR, error)
activity?.toast(error.message) activity?.toast(error.message)
} }
@ -1240,7 +1243,7 @@ class MangaController :
} }
fun onTrackingSearchResultsError(error: Throwable) { fun onTrackingSearchResultsError(error: Throwable) {
Timber.e(error) logcat(LogPriority.ERROR, error)
getTrackingSearchDialog()?.onSearchResultsError(error.message) getTrackingSearchDialog()?.onSearchResultsError(error.message)
} }

View File

@ -43,6 +43,7 @@ import eu.kanade.tachiyomi.util.storage.DiskUtil
import eu.kanade.tachiyomi.util.storage.getPicturesDir import eu.kanade.tachiyomi.util.storage.getPicturesDir
import eu.kanade.tachiyomi.util.storage.getTempShareDir import eu.kanade.tachiyomi.util.storage.getTempShareDir
import eu.kanade.tachiyomi.util.system.ImageUtil import eu.kanade.tachiyomi.util.system.ImageUtil
import eu.kanade.tachiyomi.util.system.logcat
import eu.kanade.tachiyomi.util.system.toast import eu.kanade.tachiyomi.util.system.toast
import eu.kanade.tachiyomi.util.updateCoverLastModified import eu.kanade.tachiyomi.util.updateCoverLastModified
import eu.kanade.tachiyomi.widget.ExtendedNavigationView.Item.TriStateGroup.State import eu.kanade.tachiyomi.widget.ExtendedNavigationView.Item.TriStateGroup.State
@ -50,11 +51,11 @@ import kotlinx.coroutines.Job
import kotlinx.coroutines.async import kotlinx.coroutines.async
import kotlinx.coroutines.awaitAll import kotlinx.coroutines.awaitAll
import kotlinx.coroutines.supervisorScope import kotlinx.coroutines.supervisorScope
import logcat.LogPriority
import rx.Observable import rx.Observable
import rx.Subscription import rx.Subscription
import rx.android.schedulers.AndroidSchedulers import rx.android.schedulers.AndroidSchedulers
import rx.schedulers.Schedulers import rx.schedulers.Schedulers
import timber.log.Timber
import uy.kohesive.injekt.Injekt import uy.kohesive.injekt.Injekt
import uy.kohesive.injekt.api.get import uy.kohesive.injekt.api.get
import java.io.File import java.io.File
@ -128,7 +129,9 @@ class MangaPresenter(
getTrackingObservable() getTrackingObservable()
.observeOn(AndroidSchedulers.mainThread()) .observeOn(AndroidSchedulers.mainThread())
.subscribeLatestCache(MangaController::onTrackingCount) { _, error -> Timber.e(error) } .subscribeLatestCache(MangaController::onTrackingCount) { _, error ->
logcat(LogPriority.ERROR, error)
}
// Prepare the relay. // Prepare the relay.
chaptersRelay.flatMap { applyChapterFilters(it) } chaptersRelay.flatMap { applyChapterFilters(it) }
@ -138,7 +141,7 @@ class MangaPresenter(
filteredAndSortedChapters = chapters filteredAndSortedChapters = chapters
view?.onNextChapters(chapters) view?.onNextChapters(chapters)
}, },
{ _, error -> Timber.e(error) } { _, error -> logcat(LogPriority.ERROR, error) }
) )
// Manga info - end // Manga info - end
@ -428,7 +431,7 @@ class MangaPresenter(
view.onChapterDownloadUpdate(it) view.onChapterDownloadUpdate(it)
}, },
{ _, error -> { _, error ->
Timber.e(error) logcat(LogPriority.ERROR, error)
} }
) )
@ -439,7 +442,7 @@ class MangaPresenter(
.filter { download -> download.manga.id == manga.id } .filter { download -> download.manga.id == manga.id }
.observeOn(AndroidSchedulers.mainThread()) .observeOn(AndroidSchedulers.mainThread())
.subscribeLatestCache(MangaController::onChapterDownloadUpdate) { _, error -> .subscribeLatestCache(MangaController::onChapterDownloadUpdate) { _, error ->
Timber.e(error) logcat(LogPriority.ERROR, error)
} }
} }

View File

@ -18,8 +18,9 @@ import eu.kanade.tachiyomi.util.preference.onClick
import eu.kanade.tachiyomi.util.preference.preference import eu.kanade.tachiyomi.util.preference.preference
import eu.kanade.tachiyomi.util.preference.titleRes import eu.kanade.tachiyomi.util.preference.titleRes
import eu.kanade.tachiyomi.util.system.copyToClipboard import eu.kanade.tachiyomi.util.system.copyToClipboard
import eu.kanade.tachiyomi.util.system.logcat
import eu.kanade.tachiyomi.util.system.toast import eu.kanade.tachiyomi.util.system.toast
import timber.log.Timber import logcat.LogPriority
import java.text.DateFormat import java.text.DateFormat
import java.text.SimpleDateFormat import java.text.SimpleDateFormat
import java.util.Locale import java.util.Locale
@ -112,7 +113,7 @@ class AboutController : SettingsController(), NoAppBarElevationController {
} }
} catch (error: Exception) { } catch (error: Exception) {
activity?.toast(error.message) activity?.toast(error.message)
Timber.e(error) logcat(LogPriority.ERROR, error)
} }
} }
} }

View File

@ -70,6 +70,7 @@ import eu.kanade.tachiyomi.util.system.createReaderThemeContext
import eu.kanade.tachiyomi.util.system.getThemeColor import eu.kanade.tachiyomi.util.system.getThemeColor
import eu.kanade.tachiyomi.util.system.hasDisplayCutout import eu.kanade.tachiyomi.util.system.hasDisplayCutout
import eu.kanade.tachiyomi.util.system.isNightMode import eu.kanade.tachiyomi.util.system.isNightMode
import eu.kanade.tachiyomi.util.system.logcat
import eu.kanade.tachiyomi.util.system.toast import eu.kanade.tachiyomi.util.system.toast
import eu.kanade.tachiyomi.util.view.popupMenu import eu.kanade.tachiyomi.util.view.popupMenu
import eu.kanade.tachiyomi.util.view.setTooltip import eu.kanade.tachiyomi.util.view.setTooltip
@ -79,8 +80,8 @@ import kotlinx.coroutines.flow.launchIn
import kotlinx.coroutines.flow.merge import kotlinx.coroutines.flow.merge
import kotlinx.coroutines.flow.onEach import kotlinx.coroutines.flow.onEach
import kotlinx.coroutines.flow.sample import kotlinx.coroutines.flow.sample
import logcat.LogPriority
import nucleus.factory.RequiresPresenter import nucleus.factory.RequiresPresenter
import timber.log.Timber
import uy.kohesive.injekt.injectLazy import uy.kohesive.injekt.injectLazy
import java.io.File import java.io.File
import kotlin.math.abs import kotlin.math.abs
@ -620,7 +621,7 @@ class ReaderActivity : BaseRxActivity<ReaderActivityBinding, ReaderPresenter>()
readingModeToast?.cancel() readingModeToast?.cancel()
readingModeToast = toast(strings[mode]) readingModeToast = toast(strings[mode])
} catch (e: ArrayIndexOutOfBoundsException) { } catch (e: ArrayIndexOutOfBoundsException) {
Timber.e("Unknown reading mode: $mode") logcat(LogPriority.ERROR) { "Unknown reading mode: $mode" }
} }
} }
@ -660,7 +661,7 @@ class ReaderActivity : BaseRxActivity<ReaderActivityBinding, ReaderPresenter>()
* this case the activity is closed and a toast is shown to the user. * this case the activity is closed and a toast is shown to the user.
*/ */
fun setInitialChapterError(error: Throwable) { fun setInitialChapterError(error: Throwable) {
Timber.e(error) logcat(LogPriority.ERROR, error)
finish() finish()
toast(error.message) toast(error.message)
} }
@ -822,7 +823,7 @@ class ReaderActivity : BaseRxActivity<ReaderActivityBinding, ReaderPresenter>()
toast(R.string.picture_saved) toast(R.string.picture_saved)
} }
is ReaderPresenter.SaveImageResult.Error -> { is ReaderPresenter.SaveImageResult.Error -> {
Timber.e(result.error) logcat(LogPriority.ERROR, result.error)
} }
} }
} }

View File

@ -34,14 +34,15 @@ import eu.kanade.tachiyomi.util.storage.getPicturesDir
import eu.kanade.tachiyomi.util.storage.getTempShareDir import eu.kanade.tachiyomi.util.storage.getTempShareDir
import eu.kanade.tachiyomi.util.system.ImageUtil import eu.kanade.tachiyomi.util.system.ImageUtil
import eu.kanade.tachiyomi.util.system.isOnline import eu.kanade.tachiyomi.util.system.isOnline
import eu.kanade.tachiyomi.util.system.logcat
import eu.kanade.tachiyomi.util.updateCoverLastModified import eu.kanade.tachiyomi.util.updateCoverLastModified
import kotlinx.coroutines.async import kotlinx.coroutines.async
import kotlinx.coroutines.awaitAll import kotlinx.coroutines.awaitAll
import logcat.LogPriority
import rx.Observable import rx.Observable
import rx.Subscription import rx.Subscription
import rx.android.schedulers.AndroidSchedulers import rx.android.schedulers.AndroidSchedulers
import rx.schedulers.Schedulers import rx.schedulers.Schedulers
import timber.log.Timber
import uy.kohesive.injekt.Injekt import uy.kohesive.injekt.Injekt
import uy.kohesive.injekt.api.get import uy.kohesive.injekt.api.get
import java.io.File import java.io.File
@ -301,7 +302,7 @@ class ReaderPresenter(
private fun loadNewChapter(chapter: ReaderChapter) { private fun loadNewChapter(chapter: ReaderChapter) {
val loader = loader ?: return val loader = loader ?: return
Timber.d("Loading ${chapter.chapter.url}") logcat { "Loading ${chapter.chapter.url}" }
activeChapterSubscription?.unsubscribe() activeChapterSubscription?.unsubscribe()
activeChapterSubscription = getLoadObservable(loader, chapter) activeChapterSubscription = getLoadObservable(loader, chapter)
@ -319,7 +320,7 @@ class ReaderPresenter(
private fun loadAdjacent(chapter: ReaderChapter) { private fun loadAdjacent(chapter: ReaderChapter) {
val loader = loader ?: return val loader = loader ?: return
Timber.d("Loading adjacent ${chapter.chapter.url}") logcat { "Loading adjacent ${chapter.chapter.url}" }
activeChapterSubscription?.unsubscribe() activeChapterSubscription?.unsubscribe()
activeChapterSubscription = getLoadObservable(loader, chapter) activeChapterSubscription = getLoadObservable(loader, chapter)
@ -344,7 +345,7 @@ class ReaderPresenter(
return return
} }
Timber.d("Preloading ${chapter.chapter.url}") logcat { "Preloading ${chapter.chapter.url}" }
val loader = loader ?: return val loader = loader ?: return
@ -383,7 +384,7 @@ class ReaderPresenter(
} }
if (selectedChapter != currentChapters.currChapter) { if (selectedChapter != currentChapters.currChapter) {
Timber.d("Setting ${selectedChapter.chapter.url} as active") logcat { "Setting ${selectedChapter.chapter.url} as active" }
onChapterChanged(currentChapters.currChapter) onChapterChanged(currentChapters.currChapter)
loadNewChapter(selectedChapter) loadNewChapter(selectedChapter)
} }
@ -549,7 +550,7 @@ class ReaderPresenter(
manga.orientationType = rotationType manga.orientationType = rotationType
db.updateViewerFlags(manga).executeAsBlocking() db.updateViewerFlags(manga).executeAsBlocking()
Timber.i("Manga orientation is ${manga.orientationType}") logcat(LogPriority.INFO) { "Manga orientation is ${manga.orientationType}" }
Observable.timer(250, TimeUnit.MILLISECONDS, AndroidSchedulers.mainThread()) Observable.timer(250, TimeUnit.MILLISECONDS, AndroidSchedulers.mainThread())
.subscribeFirst({ view, _ -> .subscribeFirst({ view, _ ->
@ -734,7 +735,7 @@ class ReaderPresenter(
} }
.awaitAll() .awaitAll()
.mapNotNull { it.exceptionOrNull() } .mapNotNull { it.exceptionOrNull() }
.forEach { Timber.w(it) } .forEach { logcat(LogPriority.INFO, it) }
} }
} }

View File

@ -8,11 +8,11 @@ import eu.kanade.tachiyomi.source.LocalSource
import eu.kanade.tachiyomi.source.Source import eu.kanade.tachiyomi.source.Source
import eu.kanade.tachiyomi.source.online.HttpSource import eu.kanade.tachiyomi.source.online.HttpSource
import eu.kanade.tachiyomi.ui.reader.model.ReaderChapter import eu.kanade.tachiyomi.ui.reader.model.ReaderChapter
import eu.kanade.tachiyomi.util.system.logcat
import rx.Completable import rx.Completable
import rx.Observable import rx.Observable
import rx.android.schedulers.AndroidSchedulers import rx.android.schedulers.AndroidSchedulers
import rx.schedulers.Schedulers import rx.schedulers.Schedulers
import timber.log.Timber
/** /**
* Loader used to retrieve the [PageLoader] for a given chapter. * Loader used to retrieve the [PageLoader] for a given chapter.
@ -37,7 +37,7 @@ class ChapterLoader(
.doOnNext { chapter.state = ReaderChapter.State.Loading } .doOnNext { chapter.state = ReaderChapter.State.Loading }
.observeOn(Schedulers.io()) .observeOn(Schedulers.io())
.flatMap { readerChapter -> .flatMap { readerChapter ->
Timber.d("Loading pages for ${chapter.chapter.name}") logcat { "Loading pages for ${chapter.chapter.name}" }
val loader = getPageLoader(readerChapter) val loader = getPageLoader(readerChapter)
chapter.pageLoader = loader chapter.pageLoader = loader

View File

@ -6,13 +6,14 @@ import eu.kanade.tachiyomi.source.online.HttpSource
import eu.kanade.tachiyomi.ui.reader.model.ReaderChapter import eu.kanade.tachiyomi.ui.reader.model.ReaderChapter
import eu.kanade.tachiyomi.ui.reader.model.ReaderPage import eu.kanade.tachiyomi.ui.reader.model.ReaderPage
import eu.kanade.tachiyomi.util.lang.plusAssign import eu.kanade.tachiyomi.util.lang.plusAssign
import eu.kanade.tachiyomi.util.system.logcat
import logcat.LogPriority
import rx.Completable import rx.Completable
import rx.Observable import rx.Observable
import rx.schedulers.Schedulers import rx.schedulers.Schedulers
import rx.subjects.PublishSubject import rx.subjects.PublishSubject
import rx.subjects.SerializedSubject import rx.subjects.SerializedSubject
import rx.subscriptions.CompositeSubscription import rx.subscriptions.CompositeSubscription
import timber.log.Timber
import uy.kohesive.injekt.Injekt import uy.kohesive.injekt.Injekt
import uy.kohesive.injekt.api.get import uy.kohesive.injekt.api.get
import java.util.concurrent.PriorityBlockingQueue import java.util.concurrent.PriorityBlockingQueue
@ -51,7 +52,7 @@ class HttpPageLoader(
}, },
{ error -> { error ->
if (error !is InterruptedException) { if (error !is InterruptedException) {
Timber.e(error) logcat(LogPriority.ERROR, error)
} }
} }
) )

View File

@ -3,7 +3,7 @@ package eu.kanade.tachiyomi.ui.reader.model
import com.jakewharton.rxrelay.BehaviorRelay import com.jakewharton.rxrelay.BehaviorRelay
import eu.kanade.tachiyomi.data.database.models.Chapter import eu.kanade.tachiyomi.data.database.models.Chapter
import eu.kanade.tachiyomi.ui.reader.loader.PageLoader import eu.kanade.tachiyomi.ui.reader.loader.PageLoader
import timber.log.Timber import eu.kanade.tachiyomi.util.system.logcat
data class ReaderChapter(val chapter: Chapter) { data class ReaderChapter(val chapter: Chapter) {
@ -36,7 +36,7 @@ data class ReaderChapter(val chapter: Chapter) {
references-- references--
if (references == 0) { if (references == 0) {
if (pageLoader != null) { if (pageLoader != null) {
Timber.d("Recycling chapter ${chapter.name}") logcat { "Recycling chapter ${chapter.name}" }
} }
pageLoader?.recycle() pageLoader?.recycle()
pageLoader = null pageLoader = null

View File

@ -17,9 +17,9 @@ import eu.kanade.tachiyomi.ui.reader.model.ReaderPage
import eu.kanade.tachiyomi.ui.reader.model.ViewerChapters import eu.kanade.tachiyomi.ui.reader.model.ViewerChapters
import eu.kanade.tachiyomi.ui.reader.viewer.BaseViewer import eu.kanade.tachiyomi.ui.reader.viewer.BaseViewer
import eu.kanade.tachiyomi.ui.reader.viewer.ViewerNavigation.NavigationRegion import eu.kanade.tachiyomi.ui.reader.viewer.ViewerNavigation.NavigationRegion
import eu.kanade.tachiyomi.util.system.logcat
import kotlinx.coroutines.MainScope import kotlinx.coroutines.MainScope
import kotlinx.coroutines.cancel import kotlinx.coroutines.cancel
import timber.log.Timber
import kotlin.math.min import kotlin.math.min
/** /**
@ -194,7 +194,7 @@ abstract class PagerViewer(val activity: ReaderActivity) : BaseViewer {
*/ */
private fun onReaderPageSelected(page: ReaderPage, allowPreload: Boolean) { private fun onReaderPageSelected(page: ReaderPage, allowPreload: Boolean) {
val pages = page.chapter.pages ?: return val pages = page.chapter.pages ?: return
Timber.d("onReaderPageSelected: ${page.number}/${pages.size}") logcat { "onReaderPageSelected: ${page.number}/${pages.size}" }
activity.onPageSelected(page) activity.onPageSelected(page)
// Skip preload on inserts it causes unwanted page jumping // Skip preload on inserts it causes unwanted page jumping
@ -205,7 +205,7 @@ abstract class PagerViewer(val activity: ReaderActivity) : BaseViewer {
// Preload next chapter once we're within the last 5 pages of the current chapter // Preload next chapter once we're within the last 5 pages of the current chapter
val inPreloadRange = pages.size - page.number < 5 val inPreloadRange = pages.size - page.number < 5
if (inPreloadRange && allowPreload && page.chapter == adapter.currentChapter) { if (inPreloadRange && allowPreload && page.chapter == adapter.currentChapter) {
Timber.d("Request preload next chapter because we're at page ${page.number} of ${pages.size}") logcat { "Request preload next chapter because we're at page ${page.number} of ${pages.size}" }
adapter.nextTransition?.to?.let { adapter.nextTransition?.to?.let {
activity.requestPreloadChapter(it) activity.requestPreloadChapter(it)
} }
@ -217,10 +217,10 @@ abstract class PagerViewer(val activity: ReaderActivity) : BaseViewer {
* preload of the destination chapter of the transition. * preload of the destination chapter of the transition.
*/ */
private fun onTransitionSelected(transition: ChapterTransition) { private fun onTransitionSelected(transition: ChapterTransition) {
Timber.d("onTransitionSelected: $transition") logcat { "onTransitionSelected: $transition" }
val toChapter = transition.to val toChapter = transition.to
if (toChapter != null) { if (toChapter != null) {
Timber.d("Request preload destination chapter because we're on the transition") logcat { "Request preload destination chapter because we're on the transition" }
activity.requestPreloadChapter(toChapter) activity.requestPreloadChapter(toChapter)
} else if (transition is ChapterTransition.Next) { } else if (transition is ChapterTransition.Next) {
// No more chapters, show menu because the user is probably going to close the reader // No more chapters, show menu because the user is probably going to close the reader
@ -244,13 +244,13 @@ abstract class PagerViewer(val activity: ReaderActivity) : BaseViewer {
* Sets the active [chapters] on this pager. * Sets the active [chapters] on this pager.
*/ */
private fun setChaptersInternal(chapters: ViewerChapters) { private fun setChaptersInternal(chapters: ViewerChapters) {
Timber.d("setChaptersInternal") logcat { "setChaptersInternal" }
val forceTransition = config.alwaysShowChapterTransition || adapter.items.getOrNull(pager.currentItem) is ChapterTransition val forceTransition = config.alwaysShowChapterTransition || adapter.items.getOrNull(pager.currentItem) is ChapterTransition
adapter.setChapters(chapters, forceTransition) adapter.setChapters(chapters, forceTransition)
// Layout the pager once a chapter is being set // Layout the pager once a chapter is being set
if (pager.isGone) { if (pager.isGone) {
Timber.d("Pager first layout") logcat { "Pager first layout" }
val pages = chapters.currChapter.pages ?: return val pages = chapters.currChapter.pages ?: return
moveToPage(pages[min(chapters.currChapter.requestedPage, pages.lastIndex)]) moveToPage(pages[min(chapters.currChapter.requestedPage, pages.lastIndex)])
pager.isVisible = true pager.isVisible = true
@ -261,7 +261,7 @@ abstract class PagerViewer(val activity: ReaderActivity) : BaseViewer {
* Tells this viewer to move to the given [page]. * Tells this viewer to move to the given [page].
*/ */
override fun moveToPage(page: ReaderPage) { override fun moveToPage(page: ReaderPage) {
Timber.d("moveToPage ${page.number}") logcat { "moveToPage ${page.number}" }
val position = adapter.items.indexOf(page) val position = adapter.items.indexOf(page)
if (position != -1) { if (position != -1) {
val currentPosition = pager.currentItem val currentPosition = pager.currentItem
@ -271,7 +271,7 @@ abstract class PagerViewer(val activity: ReaderActivity) : BaseViewer {
onPageChange(position) onPageChange(position)
} }
} else { } else {
Timber.d("Page $page not found in adapter") logcat { "Page $page not found in adapter" }
} }
} }

View File

@ -9,8 +9,8 @@ import eu.kanade.tachiyomi.ui.reader.model.ReaderPage
import eu.kanade.tachiyomi.ui.reader.model.ViewerChapters import eu.kanade.tachiyomi.ui.reader.model.ViewerChapters
import eu.kanade.tachiyomi.ui.reader.viewer.hasMissingChapters import eu.kanade.tachiyomi.ui.reader.viewer.hasMissingChapters
import eu.kanade.tachiyomi.util.system.createReaderThemeContext import eu.kanade.tachiyomi.util.system.createReaderThemeContext
import eu.kanade.tachiyomi.util.system.logcat
import eu.kanade.tachiyomi.widget.ViewPagerAdapter import eu.kanade.tachiyomi.widget.ViewPagerAdapter
import timber.log.Timber
/** /**
* Pager adapter used by this [viewer] to where [ViewerChapters] updates are posted. * Pager adapter used by this [viewer] to where [ViewerChapters] updates are posted.
@ -152,7 +152,7 @@ class PagerViewerAdapter(private val viewer: PagerViewer) : ViewPagerAdapter() {
if (position != -1) { if (position != -1) {
return position return position
} else { } else {
Timber.d("Position for ${view.item} not found") logcat { "Position for ${view.item} not found" }
} }
} }
return POSITION_NONE return POSITION_NONE

View File

@ -18,10 +18,10 @@ import eu.kanade.tachiyomi.ui.reader.model.ReaderPage
import eu.kanade.tachiyomi.ui.reader.model.ViewerChapters import eu.kanade.tachiyomi.ui.reader.model.ViewerChapters
import eu.kanade.tachiyomi.ui.reader.viewer.BaseViewer import eu.kanade.tachiyomi.ui.reader.viewer.BaseViewer
import eu.kanade.tachiyomi.ui.reader.viewer.ViewerNavigation.NavigationRegion import eu.kanade.tachiyomi.ui.reader.viewer.ViewerNavigation.NavigationRegion
import eu.kanade.tachiyomi.util.system.logcat
import kotlinx.coroutines.MainScope import kotlinx.coroutines.MainScope
import kotlinx.coroutines.cancel import kotlinx.coroutines.cancel
import rx.subscriptions.CompositeSubscription import rx.subscriptions.CompositeSubscription
import timber.log.Timber
import uy.kohesive.injekt.Injekt import uy.kohesive.injekt.Injekt
import uy.kohesive.injekt.api.get import uy.kohesive.injekt.api.get
import kotlin.math.max import kotlin.math.max
@ -195,17 +195,17 @@ class WebtoonViewer(val activity: ReaderActivity, val isContinuous: Boolean = tr
*/ */
private fun onPageSelected(page: ReaderPage, allowPreload: Boolean) { private fun onPageSelected(page: ReaderPage, allowPreload: Boolean) {
val pages = page.chapter.pages ?: return val pages = page.chapter.pages ?: return
Timber.d("onPageSelected: ${page.number}/${pages.size}") logcat { "onPageSelected: ${page.number}/${pages.size}" }
activity.onPageSelected(page) activity.onPageSelected(page)
// Preload next chapter once we're within the last 5 pages of the current chapter // Preload next chapter once we're within the last 5 pages of the current chapter
val inPreloadRange = pages.size - page.number < 5 val inPreloadRange = pages.size - page.number < 5
if (inPreloadRange && allowPreload && page.chapter == adapter.currentChapter) { if (inPreloadRange && allowPreload && page.chapter == adapter.currentChapter) {
Timber.d("Request preload next chapter because we're at page ${page.number} of ${pages.size}") logcat { "Request preload next chapter because we're at page ${page.number} of ${pages.size}" }
val nextItem = adapter.items.getOrNull(adapter.items.size - 1) val nextItem = adapter.items.getOrNull(adapter.items.size - 1)
val transitionChapter = (nextItem as? ChapterTransition.Next)?.to ?: (nextItem as?ReaderPage)?.chapter val transitionChapter = (nextItem as? ChapterTransition.Next)?.to ?: (nextItem as?ReaderPage)?.chapter
if (transitionChapter != null) { if (transitionChapter != null) {
Timber.d("Requesting to preload chapter ${transitionChapter.chapter.chapter_number}") logcat { "Requesting to preload chapter ${transitionChapter.chapter.chapter_number}" }
activity.requestPreloadChapter(transitionChapter) activity.requestPreloadChapter(transitionChapter)
} }
} }
@ -216,10 +216,10 @@ class WebtoonViewer(val activity: ReaderActivity, val isContinuous: Boolean = tr
* preload of the destination chapter of the transition. * preload of the destination chapter of the transition.
*/ */
private fun onTransitionSelected(transition: ChapterTransition) { private fun onTransitionSelected(transition: ChapterTransition) {
Timber.d("onTransitionSelected: $transition") logcat { "onTransitionSelected: $transition" }
val toChapter = transition.to val toChapter = transition.to
if (toChapter != null) { if (toChapter != null) {
Timber.d("Request preload destination chapter because we're on the transition") logcat { "Request preload destination chapter because we're on the transition" }
activity.requestPreloadChapter(toChapter) activity.requestPreloadChapter(toChapter)
} else if (transition is ChapterTransition.Next) { } else if (transition is ChapterTransition.Next) {
// No more chapters, show menu because the user is probably going to close the reader // No more chapters, show menu because the user is probably going to close the reader
@ -231,12 +231,12 @@ class WebtoonViewer(val activity: ReaderActivity, val isContinuous: Boolean = tr
* Tells this viewer to set the given [chapters] as active. * Tells this viewer to set the given [chapters] as active.
*/ */
override fun setChapters(chapters: ViewerChapters) { override fun setChapters(chapters: ViewerChapters) {
Timber.d("setChapters") logcat { "setChapters" }
val forceTransition = config.alwaysShowChapterTransition || currentPage is ChapterTransition val forceTransition = config.alwaysShowChapterTransition || currentPage is ChapterTransition
adapter.setChapters(chapters, forceTransition) adapter.setChapters(chapters, forceTransition)
if (recycler.isGone) { if (recycler.isGone) {
Timber.d("Recycler first layout") logcat { "Recycler first layout" }
val pages = chapters.currChapter.pages ?: return val pages = chapters.currChapter.pages ?: return
moveToPage(pages[min(chapters.currChapter.requestedPage, pages.lastIndex)]) moveToPage(pages[min(chapters.currChapter.requestedPage, pages.lastIndex)])
recycler.isVisible = true recycler.isVisible = true
@ -247,7 +247,7 @@ class WebtoonViewer(val activity: ReaderActivity, val isContinuous: Boolean = tr
* Tells this viewer to move to the given [page]. * Tells this viewer to move to the given [page].
*/ */
override fun moveToPage(page: ReaderPage) { override fun moveToPage(page: ReaderPage) {
Timber.d("moveToPage") logcat { "moveToPage" }
val position = adapter.items.indexOf(page) val position = adapter.items.indexOf(page)
if (position != -1) { if (position != -1) {
recycler.scrollToPosition(position) recycler.scrollToPosition(position)
@ -255,7 +255,7 @@ class WebtoonViewer(val activity: ReaderActivity, val isContinuous: Boolean = tr
onScrolled(pos = position) onScrolled(pos = position)
} }
} else { } else {
Timber.d("Page $page not found in adapter") logcat { "Page $page not found in adapter" }
} }
} }

View File

@ -26,13 +26,14 @@ import eu.kanade.tachiyomi.ui.browse.source.browse.ProgressItem
import eu.kanade.tachiyomi.ui.main.MainActivity import eu.kanade.tachiyomi.ui.main.MainActivity
import eu.kanade.tachiyomi.ui.manga.MangaController import eu.kanade.tachiyomi.ui.manga.MangaController
import eu.kanade.tachiyomi.ui.reader.ReaderActivity import eu.kanade.tachiyomi.ui.reader.ReaderActivity
import eu.kanade.tachiyomi.util.system.logcat
import eu.kanade.tachiyomi.util.system.toast import eu.kanade.tachiyomi.util.system.toast
import eu.kanade.tachiyomi.util.view.onAnimationsFinished import eu.kanade.tachiyomi.util.view.onAnimationsFinished
import kotlinx.coroutines.flow.filter import kotlinx.coroutines.flow.filter
import kotlinx.coroutines.flow.launchIn import kotlinx.coroutines.flow.launchIn
import kotlinx.coroutines.flow.onEach import kotlinx.coroutines.flow.onEach
import logcat.LogPriority
import reactivecircus.flowbinding.appcompat.queryTextChanges import reactivecircus.flowbinding.appcompat.queryTextChanges
import timber.log.Timber
import uy.kohesive.injekt.injectLazy import uy.kohesive.injekt.injectLazy
/** /**
@ -123,7 +124,7 @@ class HistoryController :
fun onAddPageError(error: Throwable) { fun onAddPageError(error: Throwable) {
adapter?.onLoadMoreComplete(null) adapter?.onLoadMoreComplete(null)
adapter?.endlessTargetCount = 1 adapter?.endlessTargetCount = 1
Timber.e(error) logcat(LogPriority.ERROR, error)
} }
override fun onUpdateEmptyView(size: Int) { override fun onUpdateEmptyView(size: Int) {

View File

@ -25,14 +25,15 @@ import eu.kanade.tachiyomi.ui.main.MainActivity
import eu.kanade.tachiyomi.ui.manga.MangaController import eu.kanade.tachiyomi.ui.manga.MangaController
import eu.kanade.tachiyomi.ui.manga.chapter.base.BaseChaptersAdapter import eu.kanade.tachiyomi.ui.manga.chapter.base.BaseChaptersAdapter
import eu.kanade.tachiyomi.ui.reader.ReaderActivity import eu.kanade.tachiyomi.ui.reader.ReaderActivity
import eu.kanade.tachiyomi.util.system.logcat
import eu.kanade.tachiyomi.util.system.notificationManager import eu.kanade.tachiyomi.util.system.notificationManager
import eu.kanade.tachiyomi.util.system.toast import eu.kanade.tachiyomi.util.system.toast
import eu.kanade.tachiyomi.util.view.onAnimationsFinished import eu.kanade.tachiyomi.util.view.onAnimationsFinished
import kotlinx.coroutines.flow.launchIn import kotlinx.coroutines.flow.launchIn
import kotlinx.coroutines.flow.onEach import kotlinx.coroutines.flow.onEach
import logcat.LogPriority
import reactivecircus.flowbinding.recyclerview.scrollStateChanges import reactivecircus.flowbinding.recyclerview.scrollStateChanges
import reactivecircus.flowbinding.swiperefreshlayout.refreshes import reactivecircus.flowbinding.swiperefreshlayout.refreshes
import timber.log.Timber
/** /**
* Fragment that shows recent chapters. * Fragment that shows recent chapters.
@ -300,7 +301,7 @@ class UpdatesController :
* @param error error message * @param error error message
*/ */
fun onChaptersDeletedError(error: Throwable) { fun onChaptersDeletedError(error: Throwable) {
Timber.e(error) logcat(LogPriority.ERROR, error)
} }
override fun downloadChapter(position: Int) { override fun downloadChapter(position: Int) {

View File

@ -11,10 +11,11 @@ import eu.kanade.tachiyomi.source.SourceManager
import eu.kanade.tachiyomi.ui.base.presenter.BasePresenter import eu.kanade.tachiyomi.ui.base.presenter.BasePresenter
import eu.kanade.tachiyomi.ui.recent.DateSectionItem import eu.kanade.tachiyomi.ui.recent.DateSectionItem
import eu.kanade.tachiyomi.util.lang.toDateKey import eu.kanade.tachiyomi.util.lang.toDateKey
import eu.kanade.tachiyomi.util.system.logcat
import logcat.LogPriority
import rx.Observable import rx.Observable
import rx.android.schedulers.AndroidSchedulers import rx.android.schedulers.AndroidSchedulers
import rx.schedulers.Schedulers import rx.schedulers.Schedulers
import timber.log.Timber
import uy.kohesive.injekt.injectLazy import uy.kohesive.injekt.injectLazy
import java.text.DateFormat import java.text.DateFormat
import java.util.Calendar import java.util.Calendar
@ -53,7 +54,7 @@ class UpdatesPresenter : BasePresenter<UpdatesController>() {
view.onChapterDownloadUpdate(it) view.onChapterDownloadUpdate(it)
}, },
{ _, error -> { _, error ->
Timber.e(error) logcat(LogPriority.ERROR, error)
} }
) )
@ -62,7 +63,7 @@ class UpdatesPresenter : BasePresenter<UpdatesController>() {
.onBackpressureBuffer() .onBackpressureBuffer()
.observeOn(AndroidSchedulers.mainThread()) .observeOn(AndroidSchedulers.mainThread())
.subscribeLatestCache(UpdatesController::onChapterDownloadUpdate) { _, error -> .subscribeLatestCache(UpdatesController::onChapterDownloadUpdate) { _, error ->
Timber.e(error) logcat(LogPriority.ERROR, error)
} }
} }

View File

@ -7,7 +7,8 @@ import eu.kanade.tachiyomi.R
import eu.kanade.tachiyomi.ui.base.activity.BaseThemedActivity import eu.kanade.tachiyomi.ui.base.activity.BaseThemedActivity
import eu.kanade.tachiyomi.util.system.AuthenticatorUtil import eu.kanade.tachiyomi.util.system.AuthenticatorUtil
import eu.kanade.tachiyomi.util.system.AuthenticatorUtil.startAuthentication import eu.kanade.tachiyomi.util.system.AuthenticatorUtil.startAuthentication
import timber.log.Timber import eu.kanade.tachiyomi.util.system.logcat
import logcat.LogPriority
import java.util.Date import java.util.Date
/** /**
@ -27,7 +28,7 @@ class UnlockActivity : BaseThemedActivity() {
errString: CharSequence errString: CharSequence
) { ) {
super.onAuthenticationError(activity, errorCode, errString) super.onAuthenticationError(activity, errorCode, errString)
Timber.e(errString.toString()) logcat(LogPriority.ERROR) { errString.toString() }
finishAffinity() finishAffinity()
} }

View File

@ -74,6 +74,18 @@ class SettingsAdvancedController : SettingsController() {
} }
} }
switchPreference {
key = Keys.verboseLogging
titleRes = R.string.pref_verbose_logging
summaryRes = R.string.pref_verbose_logging_summary
defaultValue = false
onChange {
activity?.toast(R.string.requires_app_restart)
true
}
}
preferenceCategory { preferenceCategory {
titleRes = R.string.label_background_activity titleRes = R.string.label_background_activity

View File

@ -5,7 +5,8 @@ import eu.kanade.tachiyomi.data.database.models.Chapter
import eu.kanade.tachiyomi.data.database.models.Track import eu.kanade.tachiyomi.data.database.models.Track
import eu.kanade.tachiyomi.data.track.TrackService import eu.kanade.tachiyomi.data.track.TrackService
import eu.kanade.tachiyomi.util.lang.launchIO import eu.kanade.tachiyomi.util.lang.launchIO
import timber.log.Timber import eu.kanade.tachiyomi.util.system.logcat
import logcat.LogPriority
/** /**
* Helper method for syncing a remote track with the local chapters, and back * Helper method for syncing a remote track with the local chapters, and back
@ -33,7 +34,7 @@ fun syncChaptersWithTrackServiceTwoWay(db: DatabaseHelper, chapters: List<Chapte
service.update(remoteTrack) service.update(remoteTrack)
db.insertTrack(remoteTrack).executeAsBlocking() db.insertTrack(remoteTrack).executeAsBlocking()
} catch (e: Throwable) { } catch (e: Throwable) {
Timber.w(e) logcat(LogPriority.WARN, e)
} }
} }
} }

View File

@ -47,7 +47,7 @@ import eu.kanade.tachiyomi.data.preference.PreferenceValues
import eu.kanade.tachiyomi.data.preference.PreferencesHelper import eu.kanade.tachiyomi.data.preference.PreferencesHelper
import eu.kanade.tachiyomi.ui.base.activity.BaseThemedActivity import eu.kanade.tachiyomi.ui.base.activity.BaseThemedActivity
import eu.kanade.tachiyomi.util.lang.truncateCenter import eu.kanade.tachiyomi.util.lang.truncateCenter
import timber.log.Timber import logcat.LogPriority
import uy.kohesive.injekt.Injekt import uy.kohesive.injekt.Injekt
import uy.kohesive.injekt.api.get import uy.kohesive.injekt.api.get
import java.io.File import java.io.File
@ -93,7 +93,7 @@ fun Context.copyToClipboard(label: String, content: String) {
toast(getString(R.string.copied_to_clipboard, content.truncateCenter(50))) toast(getString(R.string.copied_to_clipboard, content.truncateCenter(50)))
} catch (e: Throwable) { } catch (e: Throwable) {
Timber.e(e) logcat(LogPriority.ERROR, e)
toast(R.string.clipboard_copy_error) toast(R.string.clipboard_copy_error)
} }
} }

View File

@ -0,0 +1,18 @@
package eu.kanade.tachiyomi.util.system
import logcat.LogPriority
import logcat.asLog
import logcat.logcat
inline fun Any.logcat(
priority: LogPriority = LogPriority.DEBUG,
throwable: Throwable? = null,
message: () -> String = { "" }
) = logcat(priority = priority) {
var msg = message()
if (throwable != null) {
if (msg.isNotBlank()) msg += "\n"
msg += throwable.asLog()
}
msg
}

View File

@ -1,7 +1,7 @@
package eu.kanade.tachiyomi.util.system package eu.kanade.tachiyomi.util.system
import android.annotation.SuppressLint import android.annotation.SuppressLint
import timber.log.Timber import logcat.LogPriority
object MiuiUtil { object MiuiUtil {
@ -32,7 +32,7 @@ object MiuiUtil {
.getDeclaredMethod("get", String::class.java) .getDeclaredMethod("get", String::class.java)
.invoke(null, key) as String .invoke(null, key) as String
} catch (e: Exception) { } catch (e: Exception) {
Timber.w(e, "Unable to use SystemProperties.get") logcat(LogPriority.WARN, e) { "Unable to use SystemProperties.get()" }
null null
} }
} }

View File

@ -6,7 +6,7 @@ import android.content.pm.PackageManager
import android.webkit.CookieManager import android.webkit.CookieManager
import android.webkit.WebSettings import android.webkit.WebSettings
import android.webkit.WebView import android.webkit.WebView
import timber.log.Timber import logcat.LogPriority
object WebViewUtil { object WebViewUtil {
const val REQUESTED_WITH = "com.android.browser" const val REQUESTED_WITH = "com.android.browser"
@ -19,7 +19,7 @@ object WebViewUtil {
// is not installed // is not installed
CookieManager.getInstance() CookieManager.getInstance()
} catch (e: Throwable) { } catch (e: Throwable) {
Timber.e(e) logcat(LogPriority.ERROR, e)
return false return false
} }

View File

@ -8,7 +8,8 @@ import android.view.View
import android.widget.LinearLayout import android.widget.LinearLayout
import androidx.core.widget.doOnTextChanged import androidx.core.widget.doOnTextChanged
import eu.kanade.tachiyomi.databinding.DownloadCustomAmountBinding import eu.kanade.tachiyomi.databinding.DownloadCustomAmountBinding
import timber.log.Timber import eu.kanade.tachiyomi.util.system.logcat
import logcat.LogPriority
/** /**
* Custom dialog to select how many chapters to download. * Custom dialog to select how many chapters to download.
@ -71,7 +72,7 @@ class DialogCustomDownloadView @JvmOverloads constructor(context: Context, attrs
amount = getAmount(text.toString().toInt()) amount = getAmount(text.toString().toInt())
} catch (error: NumberFormatException) { } catch (error: NumberFormatException) {
// Catch NumberFormatException to prevent parse exception when input is empty. // Catch NumberFormatException to prevent parse exception when input is empty.
Timber.e(error) logcat(LogPriority.ERROR, error)
} }
} }
} }

View File

@ -476,6 +476,8 @@
<string name="battery_optimization_setting_activity_not_found">Couldn\'t open device settings</string> <string name="battery_optimization_setting_activity_not_found">Couldn\'t open device settings</string>
<string name="about_dont_kill_my_app">Some manufacturers have additional app restrictions that kill background services. This website has more info on how to fix it.</string> <string name="about_dont_kill_my_app">Some manufacturers have additional app restrictions that kill background services. This website has more info on how to fix it.</string>
<string name="pref_tablet_ui_mode">Force tablet UI</string> <string name="pref_tablet_ui_mode">Force tablet UI</string>
<string name="pref_verbose_logging">Verbose logging</string>
<string name="pref_verbose_logging_summary">Print verbose logs to system log (reduces app performance)</string>
<!-- About section --> <!-- About section -->
<string name="website">Website</string> <string name="website">Website</string>