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")
// Logging
implementation("com.jakewharton.timber:timber:5.0.1")
implementation("com.squareup.logcat:logcat:0.1")
// Crash reports/analytics
implementation("ch.acra:acra-http:5.8.1")

View File

@ -20,6 +20,7 @@ import coil.ImageLoader
import coil.ImageLoaderFactory
import coil.decode.GifDecoder
import coil.decode.ImageDecoderDecoder
import coil.util.DebugLogger
import eu.kanade.tachiyomi.data.coil.ByteBufferFetcher
import eu.kanade.tachiyomi.data.coil.MangaCoverFetcher
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 kotlinx.coroutines.flow.launchIn
import kotlinx.coroutines.flow.onEach
import logcat.AndroidLogcatLogger
import logcat.LogPriority
import logcat.LogcatLogger
import org.acra.config.httpSender
import org.acra.ktx.initAcra
import org.acra.sender.HttpSender
import org.conscrypt.Conscrypt
import timber.log.Timber
import uy.kohesive.injekt.Injekt
import uy.kohesive.injekt.api.get
import uy.kohesive.injekt.injectLazy
@ -52,7 +55,6 @@ open class App : Application(), DefaultLifecycleObserver, ImageLoaderFactory {
override fun onCreate() {
super<Application>.onCreate()
if (BuildConfig.DEBUG) Timber.plant(Timber.DebugTree())
// TLS 1.3 support for Android < 10
if (Build.VERSION.SDK_INT < Build.VERSION_CODES.Q) {
@ -110,6 +112,10 @@ open class App : Application(), DefaultLifecycleObserver, ImageLoaderFactory {
}
)
}.launchIn(ProcessLifecycleOwner.get().lifecycleScope)
if (!LogcatLogger.isInstalled && preferences.verboseLogging()) {
LogcatLogger.install(AndroidLogcatLogger(LogPriority.VERBOSE))
}
}
override fun newImageLoader(): ImageLoader {
@ -127,6 +133,7 @@ open class App : Application(), DefaultLifecycleObserver, ImageLoaderFactory {
okHttpClient(Injekt.get<NetworkHelper>().coilClient)
crossfade((300 * this@App.animatorDurationScale).toInt())
allowRgb565(getSystemService<ActivityManager>()!!.isLowRamDevice)
if (preferences.verboseLogging()) logger(DebugLogger())
}.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.util.system.acquireWakeLock
import eu.kanade.tachiyomi.util.system.isServiceRunning
import eu.kanade.tachiyomi.util.system.logcat
import kotlinx.coroutines.CoroutineExceptionHandler
import kotlinx.coroutines.CoroutineScope
import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.SupervisorJob
import kotlinx.coroutines.cancel
import kotlinx.coroutines.launch
import timber.log.Timber
import logcat.LogPriority
/**
* Restores backup.
@ -128,7 +129,7 @@ class BackupRestoreService : Service() {
}
val handler = CoroutineExceptionHandler { _, exception ->
Timber.e(exception)
logcat(LogPriority.ERROR, exception)
backupRestore?.writeErrorLog()
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.MangaCategory
import eu.kanade.tachiyomi.data.database.models.Track
import eu.kanade.tachiyomi.util.system.logcat
import kotlinx.serialization.protobuf.ProtoBuf
import logcat.LogPriority
import okio.buffer
import okio.gzip
import okio.sink
import timber.log.Timber
import kotlin.math.max
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) }
return file.uri.toString()
} catch (e: Exception) {
Timber.e(e)
logcat(LogPriority.ERROR, 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.model.Page
import eu.kanade.tachiyomi.util.lang.launchIO
import eu.kanade.tachiyomi.util.system.logcat
import logcat.LogPriority
import rx.Observable
import timber.log.Timber
import uy.kohesive.injekt.Injekt
import uy.kohesive.injekt.api.get
import uy.kohesive.injekt.injectLazy
@ -338,7 +339,7 @@ class DownloadManager(
cache.removeChapter(oldChapter, manga)
cache.addChapter(newName, mangaDir, manga)
} 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.source.Source
import eu.kanade.tachiyomi.util.storage.DiskUtil
import eu.kanade.tachiyomi.util.system.logcat
import kotlinx.coroutines.MainScope
import kotlinx.coroutines.flow.launchIn
import kotlinx.coroutines.flow.onEach
import timber.log.Timber
import logcat.LogPriority
import uy.kohesive.injekt.injectLazy
/**
@ -54,7 +55,7 @@ class DownloadProvider(private val context: Context) {
.createDirectory(getSourceDirName(source))
.createDirectory(getMangaDirName(manga))
} 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))
}
}

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.isOnline
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.toast
import kotlinx.coroutines.CoroutineScope
@ -27,9 +28,9 @@ import kotlinx.coroutines.cancel
import kotlinx.coroutines.flow.catch
import kotlinx.coroutines.flow.launchIn
import kotlinx.coroutines.flow.onEach
import logcat.LogPriority
import ru.beryukhov.reactivenetwork.ReactiveNetwork
import rx.subscriptions.CompositeSubscription
import timber.log.Timber
import uy.kohesive.injekt.injectLazy
/**
@ -143,7 +144,7 @@ class DownloadService : Service() {
}
.catch { error ->
withUIContext {
Timber.e(error)
logcat(LogPriority.ERROR, error)
toast(R.string.download_queue_error)
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.saveTo
import eu.kanade.tachiyomi.util.system.ImageUtil
import eu.kanade.tachiyomi.util.system.logcat
import kotlinx.coroutines.async
import logcat.LogPriority
import okhttp3.Response
import rx.Observable
import rx.android.schedulers.AndroidSchedulers
import rx.schedulers.Schedulers
import rx.subscriptions.CompositeSubscription
import timber.log.Timber
import uy.kohesive.injekt.injectLazy
import java.io.File
@ -209,7 +210,7 @@ class Downloader(
},
{ error ->
DownloadService.stop(context)
Timber.e(error)
logcat(LogPriority.ERROR, error)
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.createFileInCacheDir
import eu.kanade.tachiyomi.util.system.isServiceRunning
import eu.kanade.tachiyomi.util.system.logcat
import kotlinx.coroutines.CoroutineExceptionHandler
import kotlinx.coroutines.CoroutineScope
import kotlinx.coroutines.Dispatchers
@ -50,7 +51,7 @@ import kotlinx.coroutines.launch
import kotlinx.coroutines.supervisorScope
import kotlinx.coroutines.sync.Semaphore
import kotlinx.coroutines.sync.withPermit
import timber.log.Timber
import logcat.LogPriority
import uy.kohesive.injekt.Injekt
import uy.kohesive.injekt.api.get
import java.io.File
@ -212,7 +213,7 @@ class LibraryUpdateService(
// Destroy service when completed or in case of an error.
val handler = CoroutineExceptionHandler { _, exception ->
Timber.e(exception)
logcat(LogPriority.ERROR, exception)
stopSelf(startId)
}
updateJob = ioScope.launch(handler) {
@ -377,7 +378,7 @@ class LibraryUpdateService(
// Update manga details metadata in the background
if (preferences.autoUpdateMetadata()) {
val handler = CoroutineExceptionHandler { _, exception ->
Timber.e(exception)
logcat(LogPriority.ERROR, exception)
}
GlobalScope.launch(Dispatchers.IO + handler) {
val updatedManga = source.getMangaDetails(manga.toMangaInfo())
@ -433,7 +434,7 @@ class LibraryUpdateService(
}
} catch (e: Throwable) {
// Ignore errors and continue
Timber.e(e)
logcat(LogPriority.ERROR, e)
}
}
@ -494,7 +495,7 @@ class LibraryUpdateService(
}
} catch (e: Throwable) {
// 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 verboseLogging = "verbose_logging"
fun trackUsername(syncId: Int) = "pref_mangasync_username_$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
)
fun verboseLogging() = prefs.getBoolean(Keys.verboseLogging, false)
fun setChapterSettingsDefault(manga: Manga) {
prefs.edit {
putInt(Keys.defaultChapterFilterByRead, manga.readFilter)

View File

@ -3,7 +3,8 @@ package eu.kanade.tachiyomi.data.track.job
import android.content.Context
import androidx.core.content.edit
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) {
@ -17,7 +18,7 @@ class DelayedTrackingStore(context: Context) {
val (_, lastChapterRead) = preferences.getString(trackId, "0:0.0")!!.split(":")
if (track.last_chapter_read > lastChapterRead.toFloat()) {
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 {
putString(trackId, value)
}

View File

@ -11,9 +11,10 @@ import androidx.work.WorkManager
import androidx.work.WorkerParameters
import eu.kanade.tachiyomi.data.database.DatabaseHelper
import eu.kanade.tachiyomi.data.track.TrackManager
import eu.kanade.tachiyomi.util.system.logcat
import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.withContext
import timber.log.Timber
import logcat.LogPriority
import uy.kohesive.injekt.Injekt
import uy.kohesive.injekt.api.get
import java.util.concurrent.TimeUnit
@ -44,7 +45,7 @@ class DelayedTrackingUpdateJob(context: Context, workerParams: WorkerParameters)
db.insertTrack(track).executeAsBlocking()
}
} 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.parseAs
import eu.kanade.tachiyomi.util.lang.withIOContext
import eu.kanade.tachiyomi.util.system.logcat
import kotlinx.serialization.encodeToString
import kotlinx.serialization.json.Json
import logcat.LogPriority
import okhttp3.MediaType.Companion.toMediaType
import okhttp3.OkHttpClient
import okhttp3.Request
import okhttp3.RequestBody.Companion.toRequestBody
import timber.log.Timber
import uy.kohesive.injekt.injectLazy
const val READLIST_API = "/api/v1/readlists"
@ -56,7 +57,7 @@ class KomgaApi(private val client: OkHttpClient) {
last_chapter_read = progress.lastReadContinuousNumberSort
}
} catch (e: Exception) {
Timber.w(e, "Could not get item: $url")
logcat(LogPriority.WARN, e) { "Could not get item: $url" }
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.system.acquireWakeLock
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 java.io.File
@ -121,7 +122,7 @@ class UpdaterService : Service() {
}
notifier.onDownloadFinished(apkFile.getUriCompat(this))
} catch (error: Exception) {
Timber.e(error)
logcat(LogPriority.ERROR, error)
notifier.onDownloadError(url)
}
}

View File

@ -11,7 +11,8 @@ import android.os.Build
import eu.kanade.tachiyomi.extension.model.InstallStep
import eu.kanade.tachiyomi.util.lang.use
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) {
@ -23,7 +24,7 @@ class PackageInstallerInstaller(private val service: Service) : Installer(servic
PackageInstaller.STATUS_PENDING_USER_ACTION -> {
val userAction = intent.getParcelableExtra<Intent>(Intent.EXTRA_INTENT)
if (userAction == null) {
Timber.e("Fatal error for $intent")
logcat(LogPriority.ERROR) { "Fatal error for $intent" }
continueQueue(InstallStep.Error)
return
}
@ -74,7 +75,7 @@ class PackageInstallerInstaller(private val service: Service) : Installer(servic
session.commit(intentSender)
}
} 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) ->
packageInstaller.abandonSession(sessionId)
}

View File

@ -6,14 +6,15 @@ import android.os.Build
import eu.kanade.tachiyomi.R
import eu.kanade.tachiyomi.extension.model.InstallStep
import eu.kanade.tachiyomi.util.system.getUriSize
import eu.kanade.tachiyomi.util.system.logcat
import eu.kanade.tachiyomi.util.system.toast
import kotlinx.coroutines.CoroutineScope
import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.SupervisorJob
import kotlinx.coroutines.cancel
import kotlinx.coroutines.launch
import logcat.LogPriority
import rikka.shizuku.Shizuku
import timber.log.Timber
import java.io.BufferedReader
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 shizukuDeadListener = Shizuku.OnBinderDeadListener {
Timber.e("Shizuku was killed prematurely")
logcat { "Shizuku was killed prematurely" }
service.stopSelf()
}
@ -72,7 +73,7 @@ class ShizukuInstaller(private val service: Service) : Installer(service) {
continueQueue(InstallStep.Installed)
}
} 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) {
exec("pm install-abandon $sessionId")
}
@ -115,7 +116,7 @@ class ShizukuInstaller(private val service: Service) : Installer(service) {
false
}
} 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.stopSelf()
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.ShizukuInstaller
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 timber.log.Timber
import logcat.LogPriority
class ExtensionInstallService : Service() {
@ -46,7 +47,7 @@ class ExtensionInstallService : Service() {
PreferenceValues.ExtensionInstaller.PACKAGEINSTALLER -> PackageInstallerInstaller(this)
PreferenceValues.ExtensionInstaller.SHIZUKU -> ShizukuInstaller(this)
else -> {
Timber.e("Not implemented for installer $installerUsed")
logcat(LogPriority.ERROR) { "Not implemented for installer $installerUsed" }
stopSelf()
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.InstallStep
import eu.kanade.tachiyomi.util.storage.getUriCompat
import eu.kanade.tachiyomi.util.system.logcat
import logcat.LogPriority
import rx.Observable
import rx.android.schedulers.AndroidSchedulers
import timber.log.Timber
import uy.kohesive.injekt.Injekt
import uy.kohesive.injekt.api.get
import java.io.File
@ -239,7 +240,7 @@ internal class ExtensionInstaller(private val context: Context) {
// Set next installation step
if (uri == null) {
Timber.e("Couldn't locate downloaded APK")
logcat(LogPriority.ERROR) { "Couldn't locate downloaded APK" }
downloadsRelay.call(id to InstallStep.Error)
return
}

View File

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

View File

@ -2,7 +2,6 @@ package eu.kanade.tachiyomi.network
import android.content.Context
import coil.util.CoilUtils
import eu.kanade.tachiyomi.BuildConfig
import eu.kanade.tachiyomi.data.preference.PreferencesHelper
import eu.kanade.tachiyomi.network.interceptor.CloudflareInterceptor
import eu.kanade.tachiyomi.network.interceptor.UserAgentInterceptor
@ -31,7 +30,7 @@ class NetworkHelper(context: Context) {
.readTimeout(30, TimeUnit.SECONDS)
.addInterceptor(UserAgentInterceptor())
if (BuildConfig.DEBUG) {
if (preferences.verboseLogging()) {
val httpLoggingInterceptor = HttpLoggingInterceptor().apply {
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.EpubFile
import eu.kanade.tachiyomi.util.system.ImageUtil
import eu.kanade.tachiyomi.util.system.logcat
import kotlinx.serialization.json.Json
import kotlinx.serialization.json.JsonObject
import kotlinx.serialization.json.contentOrNull
@ -21,8 +22,8 @@ import kotlinx.serialization.json.decodeFromStream
import kotlinx.serialization.json.intOrNull
import kotlinx.serialization.json.jsonArray
import kotlinx.serialization.json.jsonPrimitive
import logcat.LogPriority
import rx.Observable
import timber.log.Timber
import uy.kohesive.injekt.injectLazy
import java.io.File
import java.io.FileInputStream
@ -147,7 +148,7 @@ class LocalSource(private val context: Context) : CatalogueSource {
val dest = updateCover(chapter, this)
thumbnail_url = dest?.absolutePath
} 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.ControllerChangeHandler
import com.bluelinelabs.conductor.ControllerChangeType
import eu.kanade.tachiyomi.util.system.logcat
import kotlinx.coroutines.CoroutineScope
import kotlinx.coroutines.MainScope
import kotlinx.coroutines.cancel
import timber.log.Timber
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) {
viewScope = MainScope()
Timber.d("Create view for ${controller.instance()}")
logcat { "Create view for ${controller.instance()}" }
}
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) {
Timber.d("Detach view for ${controller.instance()}")
logcat { "Detach view for ${controller.instance()}" }
}
override fun preDestroyView(controller: Controller, view: View) {
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.getPreferenceKey
import eu.kanade.tachiyomi.ui.base.controller.NucleusController
import eu.kanade.tachiyomi.util.system.logcat
import eu.kanade.tachiyomi.widget.TachiyomiTextInputEditText.Companion.setIncognito
import timber.log.Timber
import logcat.LogPriority
@SuppressLint("RestrictedApi")
class SourcePreferencesController(bundle: Bundle? = null) :
@ -77,7 +78,7 @@ class SourcePreferencesController(bundle: Bundle? = null) :
try {
addPreferencesForSource(screen, source)
} 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)

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.webview.WebViewActivity
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.toast
import eu.kanade.tachiyomi.util.view.inflate
@ -54,7 +55,7 @@ import kotlinx.coroutines.Job
import kotlinx.coroutines.flow.drop
import kotlinx.coroutines.flow.launchIn
import kotlinx.coroutines.flow.onEach
import timber.log.Timber
import logcat.LogPriority
import uy.kohesive.injekt.injectLazy
/**
@ -405,7 +406,7 @@ open class BrowseSourceController(bundle: Bundle) :
* @param error the error received.
*/
fun onAddPageError(error: Throwable) {
Timber.e(error)
logcat(LogPriority.ERROR, error)
val adapter = adapter ?: return
adapter.onLoadMoreComplete(null)
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.withUIContext
import eu.kanade.tachiyomi.util.removeCovers
import eu.kanade.tachiyomi.util.system.logcat
import kotlinx.coroutines.Job
import kotlinx.coroutines.flow.asFlow
import kotlinx.coroutines.flow.catch
@ -44,10 +45,10 @@ import kotlinx.coroutines.flow.collect
import kotlinx.coroutines.flow.filter
import kotlinx.coroutines.flow.map
import kotlinx.coroutines.flow.onEach
import logcat.LogPriority
import rx.Subscription
import rx.android.schedulers.AndroidSchedulers
import rx.schedulers.Schedulers
import timber.log.Timber
import uy.kohesive.injekt.Injekt
import uy.kohesive.injekt.api.get
import java.util.Date
@ -155,7 +156,7 @@ open class BrowseSourcePresenter(
view.onAddPage(page, mangas)
},
{ _, error ->
Timber.e(error)
logcat(LogPriority.ERROR, error)
}
)
@ -221,7 +222,7 @@ open class BrowseSourcePresenter(
view?.onMangaInitialized(it)
}
}
.catch { e -> Timber.e(e) }
.catch { e -> logcat(LogPriority.ERROR, e) }
.collect()
}
}
@ -239,7 +240,7 @@ open class BrowseSourcePresenter(
manga.initialized = true
db.insertManga(manga).executeAsBlocking()
} catch (e: Exception) {
Timber.e(e)
logcat(LogPriority.ERROR, e)
}
return manga
}
@ -282,7 +283,7 @@ open class BrowseSourcePresenter(
syncChaptersWithTrackServiceTwoWay(db, db.getChapters(manga).executeAsBlocking(), track, service as TrackService)
}
} 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.browse.source.browse.BrowseSourcePresenter
import eu.kanade.tachiyomi.util.lang.runAsObservable
import eu.kanade.tachiyomi.util.system.logcat
import logcat.LogPriority
import rx.Observable
import rx.Subscription
import rx.android.schedulers.AndroidSchedulers
import rx.schedulers.Schedulers
import rx.subjects.PublishSubject
import timber.log.Timber
import uy.kohesive.injekt.Injekt
import uy.kohesive.injekt.api.get
import uy.kohesive.injekt.injectLazy
@ -198,7 +199,7 @@ open class GlobalSearchPresenter(
view.setItems(manga)
},
{ _, error ->
Timber.e(error)
logcat(LogPriority.ERROR, error)
}
)
}
@ -233,7 +234,7 @@ open class GlobalSearchPresenter(
view?.onMangaInitialized(source, manga)
},
{ 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.DownloadQueue
import eu.kanade.tachiyomi.ui.base.presenter.BasePresenter
import eu.kanade.tachiyomi.util.system.logcat
import logcat.LogPriority
import rx.Observable
import rx.android.schedulers.AndroidSchedulers
import timber.log.Timber
import uy.kohesive.injekt.injectLazy
/**
@ -30,7 +31,7 @@ class DownloadPresenter : BasePresenter<DownloadController>() {
.observeOn(AndroidSchedulers.mainThread())
.map { it.map(::DownloadItem) }
.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.system.dpToPx
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.view.setNavigationBarTransparentCompat
import kotlinx.coroutines.delay
import kotlinx.coroutines.flow.drop
import kotlinx.coroutines.flow.launchIn
import kotlinx.coroutines.flow.onEach
import timber.log.Timber
import logcat.LogPriority
import java.util.Date
import java.util.concurrent.TimeUnit
@ -340,7 +341,7 @@ class MainActivity : BaseViewBindingActivity<MainActivityBinding>() {
NewUpdateDialogController(result).showDialog(router)
}
} catch (e: Exception) {
Timber.e(e)
logcat(LogPriority.ERROR, e)
}
}
}
@ -356,7 +357,7 @@ class MainActivity : BaseViewBindingActivity<MainActivityBinding>() {
val pendingUpdates = ExtensionGithubApi().checkForUpdates(this@MainActivity)
preferences.extensionUpdatesCount().set(pendingUpdates.size)
} 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.launchUI
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.toast
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 kotlinx.coroutines.flow.launchIn
import kotlinx.coroutines.flow.onEach
import logcat.LogPriority
import reactivecircus.flowbinding.recyclerview.scrollStateChanges
import reactivecircus.flowbinding.swiperefreshlayout.refreshes
import timber.log.Timber
import uy.kohesive.injekt.Injekt
import uy.kohesive.injekt.api.get
import uy.kohesive.injekt.injectLazy
@ -595,7 +596,9 @@ class MangaController :
presenter.registerTracking(track, service as TrackService)
}
} 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))
}
} catch (e: Exception) {
Timber.e(e)
logcat(LogPriority.ERROR, e)
activity?.toast(R.string.error_sharing_cover)
}
}
@ -780,7 +783,7 @@ class MangaController :
activity.toast(R.string.cover_saved)
}
} catch (e: Exception) {
Timber.e(e)
logcat(LogPriority.ERROR, e)
activity?.toast(R.string.error_saving_cover)
}
}
@ -836,7 +839,7 @@ class MangaController :
fun onSetCoverError(error: Throwable) {
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) {
Timber.e(error)
logcat(LogPriority.ERROR, error)
}
override fun startDownloadNow(position: Int) {
@ -1231,7 +1234,7 @@ class MangaController :
}
fun onTrackingRefreshError(error: Throwable) {
Timber.e(error)
logcat(LogPriority.ERROR, error)
activity?.toast(error.message)
}
@ -1240,7 +1243,7 @@ class MangaController :
}
fun onTrackingSearchResultsError(error: Throwable) {
Timber.e(error)
logcat(LogPriority.ERROR, error)
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.getTempShareDir
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.updateCoverLastModified
import eu.kanade.tachiyomi.widget.ExtendedNavigationView.Item.TriStateGroup.State
@ -50,11 +51,11 @@ import kotlinx.coroutines.Job
import kotlinx.coroutines.async
import kotlinx.coroutines.awaitAll
import kotlinx.coroutines.supervisorScope
import logcat.LogPriority
import rx.Observable
import rx.Subscription
import rx.android.schedulers.AndroidSchedulers
import rx.schedulers.Schedulers
import timber.log.Timber
import uy.kohesive.injekt.Injekt
import uy.kohesive.injekt.api.get
import java.io.File
@ -128,7 +129,9 @@ class MangaPresenter(
getTrackingObservable()
.observeOn(AndroidSchedulers.mainThread())
.subscribeLatestCache(MangaController::onTrackingCount) { _, error -> Timber.e(error) }
.subscribeLatestCache(MangaController::onTrackingCount) { _, error ->
logcat(LogPriority.ERROR, error)
}
// Prepare the relay.
chaptersRelay.flatMap { applyChapterFilters(it) }
@ -138,7 +141,7 @@ class MangaPresenter(
filteredAndSortedChapters = chapters
view?.onNextChapters(chapters)
},
{ _, error -> Timber.e(error) }
{ _, error -> logcat(LogPriority.ERROR, error) }
)
// Manga info - end
@ -428,7 +431,7 @@ class MangaPresenter(
view.onChapterDownloadUpdate(it)
},
{ _, error ->
Timber.e(error)
logcat(LogPriority.ERROR, error)
}
)
@ -439,7 +442,7 @@ class MangaPresenter(
.filter { download -> download.manga.id == manga.id }
.observeOn(AndroidSchedulers.mainThread())
.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.titleRes
import eu.kanade.tachiyomi.util.system.copyToClipboard
import eu.kanade.tachiyomi.util.system.logcat
import eu.kanade.tachiyomi.util.system.toast
import timber.log.Timber
import logcat.LogPriority
import java.text.DateFormat
import java.text.SimpleDateFormat
import java.util.Locale
@ -112,7 +113,7 @@ class AboutController : SettingsController(), NoAppBarElevationController {
}
} catch (error: Exception) {
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.hasDisplayCutout
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.view.popupMenu
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.onEach
import kotlinx.coroutines.flow.sample
import logcat.LogPriority
import nucleus.factory.RequiresPresenter
import timber.log.Timber
import uy.kohesive.injekt.injectLazy
import java.io.File
import kotlin.math.abs
@ -620,7 +621,7 @@ class ReaderActivity : BaseRxActivity<ReaderActivityBinding, ReaderPresenter>()
readingModeToast?.cancel()
readingModeToast = toast(strings[mode])
} 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.
*/
fun setInitialChapterError(error: Throwable) {
Timber.e(error)
logcat(LogPriority.ERROR, error)
finish()
toast(error.message)
}
@ -822,7 +823,7 @@ class ReaderActivity : BaseRxActivity<ReaderActivityBinding, ReaderPresenter>()
toast(R.string.picture_saved)
}
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.system.ImageUtil
import eu.kanade.tachiyomi.util.system.isOnline
import eu.kanade.tachiyomi.util.system.logcat
import eu.kanade.tachiyomi.util.updateCoverLastModified
import kotlinx.coroutines.async
import kotlinx.coroutines.awaitAll
import logcat.LogPriority
import rx.Observable
import rx.Subscription
import rx.android.schedulers.AndroidSchedulers
import rx.schedulers.Schedulers
import timber.log.Timber
import uy.kohesive.injekt.Injekt
import uy.kohesive.injekt.api.get
import java.io.File
@ -301,7 +302,7 @@ class ReaderPresenter(
private fun loadNewChapter(chapter: ReaderChapter) {
val loader = loader ?: return
Timber.d("Loading ${chapter.chapter.url}")
logcat { "Loading ${chapter.chapter.url}" }
activeChapterSubscription?.unsubscribe()
activeChapterSubscription = getLoadObservable(loader, chapter)
@ -319,7 +320,7 @@ class ReaderPresenter(
private fun loadAdjacent(chapter: ReaderChapter) {
val loader = loader ?: return
Timber.d("Loading adjacent ${chapter.chapter.url}")
logcat { "Loading adjacent ${chapter.chapter.url}" }
activeChapterSubscription?.unsubscribe()
activeChapterSubscription = getLoadObservable(loader, chapter)
@ -344,7 +345,7 @@ class ReaderPresenter(
return
}
Timber.d("Preloading ${chapter.chapter.url}")
logcat { "Preloading ${chapter.chapter.url}" }
val loader = loader ?: return
@ -383,7 +384,7 @@ class ReaderPresenter(
}
if (selectedChapter != currentChapters.currChapter) {
Timber.d("Setting ${selectedChapter.chapter.url} as active")
logcat { "Setting ${selectedChapter.chapter.url} as active" }
onChapterChanged(currentChapters.currChapter)
loadNewChapter(selectedChapter)
}
@ -549,7 +550,7 @@ class ReaderPresenter(
manga.orientationType = rotationType
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())
.subscribeFirst({ view, _ ->
@ -734,7 +735,7 @@ class ReaderPresenter(
}
.awaitAll()
.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.online.HttpSource
import eu.kanade.tachiyomi.ui.reader.model.ReaderChapter
import eu.kanade.tachiyomi.util.system.logcat
import rx.Completable
import rx.Observable
import rx.android.schedulers.AndroidSchedulers
import rx.schedulers.Schedulers
import timber.log.Timber
/**
* Loader used to retrieve the [PageLoader] for a given chapter.
@ -37,7 +37,7 @@ class ChapterLoader(
.doOnNext { chapter.state = ReaderChapter.State.Loading }
.observeOn(Schedulers.io())
.flatMap { readerChapter ->
Timber.d("Loading pages for ${chapter.chapter.name}")
logcat { "Loading pages for ${chapter.chapter.name}" }
val loader = getPageLoader(readerChapter)
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.ReaderPage
import eu.kanade.tachiyomi.util.lang.plusAssign
import eu.kanade.tachiyomi.util.system.logcat
import logcat.LogPriority
import rx.Completable
import rx.Observable
import rx.schedulers.Schedulers
import rx.subjects.PublishSubject
import rx.subjects.SerializedSubject
import rx.subscriptions.CompositeSubscription
import timber.log.Timber
import uy.kohesive.injekt.Injekt
import uy.kohesive.injekt.api.get
import java.util.concurrent.PriorityBlockingQueue
@ -51,7 +52,7 @@ class HttpPageLoader(
},
{ error ->
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 eu.kanade.tachiyomi.data.database.models.Chapter
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) {
@ -36,7 +36,7 @@ data class ReaderChapter(val chapter: Chapter) {
references--
if (references == 0) {
if (pageLoader != null) {
Timber.d("Recycling chapter ${chapter.name}")
logcat { "Recycling chapter ${chapter.name}" }
}
pageLoader?.recycle()
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.viewer.BaseViewer
import eu.kanade.tachiyomi.ui.reader.viewer.ViewerNavigation.NavigationRegion
import eu.kanade.tachiyomi.util.system.logcat
import kotlinx.coroutines.MainScope
import kotlinx.coroutines.cancel
import timber.log.Timber
import kotlin.math.min
/**
@ -194,7 +194,7 @@ abstract class PagerViewer(val activity: ReaderActivity) : BaseViewer {
*/
private fun onReaderPageSelected(page: ReaderPage, allowPreload: Boolean) {
val pages = page.chapter.pages ?: return
Timber.d("onReaderPageSelected: ${page.number}/${pages.size}")
logcat { "onReaderPageSelected: ${page.number}/${pages.size}" }
activity.onPageSelected(page)
// 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
val inPreloadRange = pages.size - page.number < 5
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 {
activity.requestPreloadChapter(it)
}
@ -217,10 +217,10 @@ abstract class PagerViewer(val activity: ReaderActivity) : BaseViewer {
* preload of the destination chapter of the transition.
*/
private fun onTransitionSelected(transition: ChapterTransition) {
Timber.d("onTransitionSelected: $transition")
logcat { "onTransitionSelected: $transition" }
val toChapter = transition.to
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)
} else if (transition is ChapterTransition.Next) {
// 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.
*/
private fun setChaptersInternal(chapters: ViewerChapters) {
Timber.d("setChaptersInternal")
logcat { "setChaptersInternal" }
val forceTransition = config.alwaysShowChapterTransition || adapter.items.getOrNull(pager.currentItem) is ChapterTransition
adapter.setChapters(chapters, forceTransition)
// Layout the pager once a chapter is being set
if (pager.isGone) {
Timber.d("Pager first layout")
logcat { "Pager first layout" }
val pages = chapters.currChapter.pages ?: return
moveToPage(pages[min(chapters.currChapter.requestedPage, pages.lastIndex)])
pager.isVisible = true
@ -261,7 +261,7 @@ abstract class PagerViewer(val activity: ReaderActivity) : BaseViewer {
* Tells this viewer to move to the given [page].
*/
override fun moveToPage(page: ReaderPage) {
Timber.d("moveToPage ${page.number}")
logcat { "moveToPage ${page.number}" }
val position = adapter.items.indexOf(page)
if (position != -1) {
val currentPosition = pager.currentItem
@ -271,7 +271,7 @@ abstract class PagerViewer(val activity: ReaderActivity) : BaseViewer {
onPageChange(position)
}
} 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.viewer.hasMissingChapters
import eu.kanade.tachiyomi.util.system.createReaderThemeContext
import eu.kanade.tachiyomi.util.system.logcat
import eu.kanade.tachiyomi.widget.ViewPagerAdapter
import timber.log.Timber
/**
* 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) {
return position
} else {
Timber.d("Position for ${view.item} not found")
logcat { "Position for ${view.item} not found" }
}
}
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.viewer.BaseViewer
import eu.kanade.tachiyomi.ui.reader.viewer.ViewerNavigation.NavigationRegion
import eu.kanade.tachiyomi.util.system.logcat
import kotlinx.coroutines.MainScope
import kotlinx.coroutines.cancel
import rx.subscriptions.CompositeSubscription
import timber.log.Timber
import uy.kohesive.injekt.Injekt
import uy.kohesive.injekt.api.get
import kotlin.math.max
@ -195,17 +195,17 @@ class WebtoonViewer(val activity: ReaderActivity, val isContinuous: Boolean = tr
*/
private fun onPageSelected(page: ReaderPage, allowPreload: Boolean) {
val pages = page.chapter.pages ?: return
Timber.d("onPageSelected: ${page.number}/${pages.size}")
logcat { "onPageSelected: ${page.number}/${pages.size}" }
activity.onPageSelected(page)
// Preload next chapter once we're within the last 5 pages of the current chapter
val inPreloadRange = pages.size - page.number < 5
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 transitionChapter = (nextItem as? ChapterTransition.Next)?.to ?: (nextItem as?ReaderPage)?.chapter
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)
}
}
@ -216,10 +216,10 @@ class WebtoonViewer(val activity: ReaderActivity, val isContinuous: Boolean = tr
* preload of the destination chapter of the transition.
*/
private fun onTransitionSelected(transition: ChapterTransition) {
Timber.d("onTransitionSelected: $transition")
logcat { "onTransitionSelected: $transition" }
val toChapter = transition.to
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)
} else if (transition is ChapterTransition.Next) {
// 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.
*/
override fun setChapters(chapters: ViewerChapters) {
Timber.d("setChapters")
logcat { "setChapters" }
val forceTransition = config.alwaysShowChapterTransition || currentPage is ChapterTransition
adapter.setChapters(chapters, forceTransition)
if (recycler.isGone) {
Timber.d("Recycler first layout")
logcat { "Recycler first layout" }
val pages = chapters.currChapter.pages ?: return
moveToPage(pages[min(chapters.currChapter.requestedPage, pages.lastIndex)])
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].
*/
override fun moveToPage(page: ReaderPage) {
Timber.d("moveToPage")
logcat { "moveToPage" }
val position = adapter.items.indexOf(page)
if (position != -1) {
recycler.scrollToPosition(position)
@ -255,7 +255,7 @@ class WebtoonViewer(val activity: ReaderActivity, val isContinuous: Boolean = tr
onScrolled(pos = position)
}
} 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.manga.MangaController
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.view.onAnimationsFinished
import kotlinx.coroutines.flow.filter
import kotlinx.coroutines.flow.launchIn
import kotlinx.coroutines.flow.onEach
import logcat.LogPriority
import reactivecircus.flowbinding.appcompat.queryTextChanges
import timber.log.Timber
import uy.kohesive.injekt.injectLazy
/**
@ -123,7 +124,7 @@ class HistoryController :
fun onAddPageError(error: Throwable) {
adapter?.onLoadMoreComplete(null)
adapter?.endlessTargetCount = 1
Timber.e(error)
logcat(LogPriority.ERROR, error)
}
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.chapter.base.BaseChaptersAdapter
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.toast
import eu.kanade.tachiyomi.util.view.onAnimationsFinished
import kotlinx.coroutines.flow.launchIn
import kotlinx.coroutines.flow.onEach
import logcat.LogPriority
import reactivecircus.flowbinding.recyclerview.scrollStateChanges
import reactivecircus.flowbinding.swiperefreshlayout.refreshes
import timber.log.Timber
/**
* Fragment that shows recent chapters.
@ -300,7 +301,7 @@ class UpdatesController :
* @param error error message
*/
fun onChaptersDeletedError(error: Throwable) {
Timber.e(error)
logcat(LogPriority.ERROR, error)
}
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.recent.DateSectionItem
import eu.kanade.tachiyomi.util.lang.toDateKey
import eu.kanade.tachiyomi.util.system.logcat
import logcat.LogPriority
import rx.Observable
import rx.android.schedulers.AndroidSchedulers
import rx.schedulers.Schedulers
import timber.log.Timber
import uy.kohesive.injekt.injectLazy
import java.text.DateFormat
import java.util.Calendar
@ -53,7 +54,7 @@ class UpdatesPresenter : BasePresenter<UpdatesController>() {
view.onChapterDownloadUpdate(it)
},
{ _, error ->
Timber.e(error)
logcat(LogPriority.ERROR, error)
}
)
@ -62,7 +63,7 @@ class UpdatesPresenter : BasePresenter<UpdatesController>() {
.onBackpressureBuffer()
.observeOn(AndroidSchedulers.mainThread())
.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.util.system.AuthenticatorUtil
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
/**
@ -27,7 +28,7 @@ class UnlockActivity : BaseThemedActivity() {
errString: CharSequence
) {
super.onAuthenticationError(activity, errorCode, errString)
Timber.e(errString.toString())
logcat(LogPriority.ERROR) { errString.toString() }
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 {
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.track.TrackService
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
@ -33,7 +34,7 @@ fun syncChaptersWithTrackServiceTwoWay(db: DatabaseHelper, chapters: List<Chapte
service.update(remoteTrack)
db.insertTrack(remoteTrack).executeAsBlocking()
} 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.ui.base.activity.BaseThemedActivity
import eu.kanade.tachiyomi.util.lang.truncateCenter
import timber.log.Timber
import logcat.LogPriority
import uy.kohesive.injekt.Injekt
import uy.kohesive.injekt.api.get
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)))
} catch (e: Throwable) {
Timber.e(e)
logcat(LogPriority.ERROR, e)
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
import android.annotation.SuppressLint
import timber.log.Timber
import logcat.LogPriority
object MiuiUtil {
@ -32,7 +32,7 @@ object MiuiUtil {
.getDeclaredMethod("get", String::class.java)
.invoke(null, key) as String
} catch (e: Exception) {
Timber.w(e, "Unable to use SystemProperties.get")
logcat(LogPriority.WARN, e) { "Unable to use SystemProperties.get()" }
null
}
}

View File

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

View File

@ -8,7 +8,8 @@ import android.view.View
import android.widget.LinearLayout
import androidx.core.widget.doOnTextChanged
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.
@ -71,7 +72,7 @@ class DialogCustomDownloadView @JvmOverloads constructor(context: Context, attrs
amount = getAmount(text.toString().toInt())
} catch (error: NumberFormatException) {
// 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="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_verbose_logging">Verbose logging</string>
<string name="pref_verbose_logging_summary">Print verbose logs to system log (reduces app performance)</string>
<!-- About section -->
<string name="website">Website</string>