Replace DebugOverlay library with a custom composable

This commit is contained in:
Jobobby04 2022-12-05 14:57:33 -05:00
parent 0663928b6b
commit 266b4c4dd7
5 changed files with 173 additions and 95 deletions

View File

@ -298,13 +298,6 @@ dependencies {
// Better logging (EH) // Better logging (EH)
implementation(sylibs.xlog) implementation(sylibs.xlog)
// Debug utils (EH)
debugImplementation(sylibs.debugOverlay.standard)
"releaseTestImplementation"(sylibs.debugOverlay.noop)
"benchmarkImplementation"(sylibs.debugOverlay.noop)
releaseImplementation(sylibs.debugOverlay.noop)
testImplementation(sylibs.debugOverlay.noop)
// RatingBar (SY) // RatingBar (SY)
implementation(sylibs.ratingbar) implementation(sylibs.ratingbar)
implementation(sylibs.composeRatingbar) implementation(sylibs.composeRatingbar)

View File

@ -8,7 +8,6 @@ import android.content.BroadcastReceiver
import android.content.Context import android.content.Context
import android.content.Intent import android.content.Intent
import android.content.IntentFilter import android.content.IntentFilter
import android.graphics.Color
import android.os.Build import android.os.Build
import android.os.Environment import android.os.Environment
import android.os.Looper import android.os.Looper
@ -36,8 +35,6 @@ import com.elvishew.xlog.printer.file.clean.FileLastModifiedCleanStrategy
import com.elvishew.xlog.printer.file.naming.DateFileNameGenerator import com.elvishew.xlog.printer.file.naming.DateFileNameGenerator
import com.google.firebase.analytics.ktx.analytics import com.google.firebase.analytics.ktx.analytics
import com.google.firebase.ktx.Firebase import com.google.firebase.ktx.Firebase
import com.ms_square.debugoverlay.DebugOverlay
import com.ms_square.debugoverlay.modules.FpsModule
import eu.kanade.data.DatabaseHandler import eu.kanade.data.DatabaseHandler
import eu.kanade.domain.DomainModule import eu.kanade.domain.DomainModule
import eu.kanade.domain.SYDomainModule import eu.kanade.domain.SYDomainModule
@ -63,14 +60,11 @@ import eu.kanade.tachiyomi.util.system.animatorDurationScale
import eu.kanade.tachiyomi.util.system.isPreviewBuildType import eu.kanade.tachiyomi.util.system.isPreviewBuildType
import eu.kanade.tachiyomi.util.system.logcat import eu.kanade.tachiyomi.util.system.logcat
import eu.kanade.tachiyomi.util.system.notification import eu.kanade.tachiyomi.util.system.notification
import exh.debug.DebugToggles
import exh.log.CrashlyticsPrinter import exh.log.CrashlyticsPrinter
import exh.log.EHDebugModeOverlay
import exh.log.EHLogLevel import exh.log.EHLogLevel
import exh.log.EnhancedFilePrinter import exh.log.EnhancedFilePrinter
import exh.log.XLogLogcatLogger import exh.log.XLogLogcatLogger
import exh.log.xLogD import exh.log.xLogD
import exh.log.xLogE
import exh.syDebugVersion import exh.syDebugVersion
import kotlinx.coroutines.Dispatchers import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.flow.distinctUntilChanged import kotlinx.coroutines.flow.distinctUntilChanged
@ -126,9 +120,6 @@ class App : Application(), DefaultLifecycleObserver, ImageLoaderFactory {
// SY <-- // SY <--
setupNotificationChannels() setupNotificationChannels()
if ((BuildConfig.DEBUG || BuildConfig.BUILD_TYPE == "releaseTest") && DebugToggles.ENABLE_DEBUG_OVERLAY.enabled) {
setupDebugOverlay()
}
ProcessLifecycleOwner.get().lifecycle.addObserver(this) ProcessLifecycleOwner.get().lifecycle.addObserver(this)
@ -327,22 +318,6 @@ class App : Application(), DefaultLifecycleObserver, ImageLoaderFactory {
) )
} }
// EXH
private fun setupDebugOverlay() {
try {
DebugOverlay.Builder(this)
.modules(FpsModule(), EHDebugModeOverlay(this))
.bgColor(Color.parseColor("#7F000000"))
.notification(false)
.allowSystemLayer(false)
.build()
.install()
} catch (e: IllegalStateException) {
// Crashes if app is in background
xLogE("Failed to initialize debug overlay, app in background?", e)
}
}
private inner class DisableIncognitoReceiver : BroadcastReceiver() { private inner class DisableIncognitoReceiver : BroadcastReceiver() {
private var registered = false private var registered = false

View File

@ -65,7 +65,9 @@ import eu.kanade.tachiyomi.util.system.toast
import eu.kanade.tachiyomi.util.view.setComposeContent import eu.kanade.tachiyomi.util.view.setComposeContent
import eu.kanade.tachiyomi.util.view.setNavigationBarTransparentCompat import eu.kanade.tachiyomi.util.view.setNavigationBarTransparentCompat
import exh.EXHMigrations import exh.EXHMigrations
import exh.debug.DebugToggles
import exh.eh.EHentaiUpdateWorker import exh.eh.EHentaiUpdateWorker
import exh.log.DebugModeOverlay
import exh.source.BlacklistedSources import exh.source.BlacklistedSources
import exh.source.EH_SOURCE_ID import exh.source.EH_SOURCE_ID
import exh.source.EXH_SOURCE_ID import exh.source.EXH_SOURCE_ID
@ -162,6 +164,9 @@ class MainActivity : BaseActivity() {
return return
} }
@Suppress("KotlinConstantConditions")
val hasDebugOverlay = (BuildConfig.DEBUG || BuildConfig.BUILD_TYPE == "releaseTest")
// Draw edge-to-edge // Draw edge-to-edge
WindowCompat.setDecorFitsSystemWindows(window, false) WindowCompat.setDecorFitsSystemWindows(window, false)
@ -206,6 +211,15 @@ class MainActivity : BaseActivity() {
CheckForUpdate() CheckForUpdate()
} }
if (hasDebugOverlay) {
val isDebugOverlayEnabled by remember {
DebugToggles.ENABLE_DEBUG_OVERLAY.asPref(lifecycleScope)
}
if (isDebugOverlayEnabled) {
DebugModeOverlay()
}
}
var showChangelog by remember { mutableStateOf(didMigration && !BuildConfig.DEBUG) } var showChangelog by remember { mutableStateOf(didMigration && !BuildConfig.DEBUG) }
if (showChangelog) { if (showChangelog) {
// SY --> // SY -->

View File

@ -1,70 +1,170 @@
package exh.log package exh.log
import android.content.Context import android.content.Context
import android.view.View import android.view.Choreographer
import android.view.ViewGroup import androidx.compose.foundation.background
import android.widget.LinearLayout import androidx.compose.foundation.layout.Box
import android.widget.TextView import androidx.compose.foundation.layout.Column
import androidx.core.text.HtmlCompat import androidx.compose.foundation.layout.WindowInsets
import com.ms_square.debugoverlay.DataObserver import androidx.compose.foundation.layout.WindowInsetsSides
import com.ms_square.debugoverlay.OverlayModule import androidx.compose.foundation.layout.fillMaxSize
import androidx.compose.foundation.layout.navigationBars
import androidx.compose.foundation.layout.only
import androidx.compose.foundation.layout.padding
import androidx.compose.foundation.layout.windowInsetsPadding
import androidx.compose.material3.Text
import androidx.compose.runtime.Composable
import androidx.compose.runtime.MutableState
import androidx.compose.runtime.RememberObserver
import androidx.compose.runtime.getValue
import androidx.compose.runtime.mutableStateOf
import androidx.compose.runtime.remember
import androidx.compose.runtime.rememberCoroutineScope
import androidx.compose.ui.Alignment
import androidx.compose.ui.Modifier
import androidx.compose.ui.graphics.Color
import androidx.compose.ui.platform.LocalContext
import androidx.compose.ui.text.AnnotatedString
import androidx.compose.ui.text.SpanStyle
import androidx.compose.ui.text.buildAnnotatedString
import androidx.compose.ui.text.font.FontFamily
import androidx.compose.ui.text.font.FontWeight
import androidx.compose.ui.text.withStyle
import androidx.compose.ui.unit.dp
import androidx.compose.ui.unit.sp
import eu.kanade.core.prefs.asState
import eu.kanade.domain.source.service.SourcePreferences import eu.kanade.domain.source.service.SourcePreferences
import eu.kanade.tachiyomi.BuildConfig import eu.kanade.tachiyomi.BuildConfig
import eu.kanade.tachiyomi.R import eu.kanade.tachiyomi.R
import eu.kanade.tachiyomi.util.system.dpToPx import uy.kohesive.injekt.Injekt
import uy.kohesive.injekt.injectLazy import uy.kohesive.injekt.api.get
import java.text.DecimalFormat
import java.text.DecimalFormatSymbols
import java.util.Locale import java.util.Locale
import kotlin.time.Duration.Companion.nanoseconds
class EHDebugModeOverlay(private val context: Context) : OverlayModule<String>(null, null) { @Composable
private var textView: TextView? = null fun DebugModeOverlay() {
private val preferences: SourcePreferences by injectLazy() Box(Modifier.fillMaxSize()) {
Column(
override fun start() {} Modifier
override fun stop() {} .windowInsetsPadding(
override fun notifyObservers() {} WindowInsets.navigationBars
override fun addObserver(observer: DataObserver<Any>) { .only(WindowInsetsSides.Bottom.plus(WindowInsetsSides.Start)),
observer.onDataAvailable(buildInfo()) )
} .align(Alignment.BottomStart)
override fun removeObserver(observer: DataObserver<Any>) {} .background(Color(0x7F000000))
override fun onDataAvailable(data: String?) { .padding(4.dp),
textView?.text = HtmlCompat.fromHtml(data.orEmpty(), HtmlCompat.FROM_HTML_MODE_LEGACY) ) {
} FpsDebugModeOverlay()
EHDebugModeOverlay()
override fun createView(root: ViewGroup, textColor: Int, textSize: Float, textAlpha: Float): View {
val view = LinearLayout(root.context).apply {
layoutParams = ViewGroup.LayoutParams(
ViewGroup.LayoutParams.WRAP_CONTENT,
ViewGroup.LayoutParams.WRAP_CONTENT,
)
setPadding(4.dpToPx, 0, 4.dpToPx, 4.dpToPx)
} }
val textView = TextView(view.context).apply {
setTextColor(textColor)
this.textSize = textSize
alpha = textAlpha
text = HtmlCompat.fromHtml(buildInfo(), HtmlCompat.FROM_HTML_MODE_LEGACY)
layoutParams = LinearLayout.LayoutParams(
ViewGroup.LayoutParams.WRAP_CONTENT,
ViewGroup.LayoutParams.WRAP_CONTENT,
)
}
view.addView(textView)
this.textView = textView
return view
} }
}
private fun buildInfo() =
""" @Composable
<font color='green'>===[ ${context.getString(R.string.app_name)} ]===</font><br> private fun FpsDebugModeOverlay() {
<b>Build type:</b> ${BuildConfig.BUILD_TYPE}<br> val fps by remember { FpsState(FpsState.DEFAULT_INTERVAL) }
<b>Debug mode:</b> ${BuildConfig.DEBUG.asEnabledString()}<br> val format = remember {
<b>Version code:</b> ${BuildConfig.VERSION_CODE}<br> DecimalFormat(
<b>Commit SHA:</b> ${BuildConfig.COMMIT_SHA}<br> "'fps:' 0.0",
<b>Log level:</b> ${EHLogLevel.currentLogLevel.name.lowercase(Locale.getDefault())}<br> DecimalFormatSymbols.getInstance(Locale.ENGLISH),
<b>Source blacklist:</b> ${preferences.enableSourceBlacklist().get().asEnabledString()} )
""".trimIndent() }
private fun Boolean.asEnabledString() = if (this) "enabled" else "disabled" Text(
text = remember(fps) {
format.format(fps)
},
color = Color.White,
fontSize = 12.sp,
fontFamily = FontFamily.Monospace,
)
}
@Composable
private fun EHDebugModeOverlay() {
val scope = rememberCoroutineScope()
val enableSourceBlacklist by remember {
Injekt.get<SourcePreferences>().enableSourceBlacklist().asState(scope)
}
val context = LocalContext.current
Text(
text = remember(enableSourceBlacklist) {
buildInfo(context, enableSourceBlacklist)
},
color = Color.White,
fontSize = 12.sp,
lineHeight = 14.sp,
letterSpacing = 0.1f.sp,
)
}
private fun buildInfo(context: Context, sourceBlacklist: Boolean) = buildAnnotatedString {
withStyle(SpanStyle(color = Color.Green)) {
append("===[ ")
append(context.getString(R.string.app_name))
append(" ]===")
}
append('\n')
appendItem("Build type:", BuildConfig.BUILD_TYPE)
appendItem("Debug mode:", BuildConfig.DEBUG.asEnabledString())
appendItem("Version code:", BuildConfig.VERSION_CODE.toString())
appendItem("Commit SHA:", BuildConfig.COMMIT_SHA)
appendItem("Log level:", EHLogLevel.currentLogLevel.name.lowercase(Locale.getDefault()))
appendItem("Source blacklist:", sourceBlacklist.asEnabledString(), newLine = false)
}
fun AnnotatedString.Builder.appendItem(title: String, item: String, newLine: Boolean = true) {
withStyle(SpanStyle(fontWeight = FontWeight.Bold)) {
append(title)
}
append(' ')
append(item)
if (newLine) {
append('\n')
}
}
private fun Boolean.asEnabledString() = if (this) "enabled" else "disabled"
private class FpsState(private val interval: Int) :
Choreographer.FrameCallback,
RememberObserver,
MutableState<Double> by mutableStateOf(0.0) {
private val choreographer = Choreographer.getInstance()
private var startFrameTimeMillis: Long = 0
private var numFramesRendered = 0
override fun onRemembered() {
choreographer.postFrameCallback(this)
}
override fun onAbandoned() {
choreographer.removeFrameCallback(this)
}
override fun onForgotten() {
choreographer.removeFrameCallback(this)
}
override fun doFrame(frameTimeNanos: Long) {
val currentFrameTimeMillis = frameTimeNanos.nanoseconds.inWholeMilliseconds
if (startFrameTimeMillis > 0) {
val duration = currentFrameTimeMillis - startFrameTimeMillis
numFramesRendered++
if (duration > interval) {
value = (numFramesRendered * 1000f / duration).toDouble()
startFrameTimeMillis = currentFrameTimeMillis
numFramesRendered = 0
}
} else {
startFrameTimeMillis = currentFrameTimeMillis
}
choreographer.postFrameCallback(this)
}
companion object {
const val DEFAULT_INTERVAL = 1000
}
} }

View File

@ -1,5 +1,4 @@
[versions] [versions]
debugOverlay = "1.1.3"
[libraries] [libraries]
firebase-analytics = "com.google.firebase:firebase-analytics-ktx:21.0.0" firebase-analytics = "com.google.firebase:firebase-analytics-ktx:21.0.0"
@ -9,8 +8,5 @@ firebase-crashlytics-gradle = "com.google.firebase:firebase-crashlytics-gradle:2
simularity = "info.debatty:java-string-similarity:2.0.0" simularity = "info.debatty:java-string-similarity:2.0.0"
xlog = "com.elvishew:xlog:1.11.0" xlog = "com.elvishew:xlog:1.11.0"
debugOverlay-standard = { module = "com.ms-square:debugoverlay", version.ref = "debugOverlay" }
debugOverlay-noop = { module = "com.ms-square:debugoverlay-no-op", version.ref = "debugOverlay" }
ratingbar = "me.zhanghai.android.materialratingbar:library:1.4.0" ratingbar = "me.zhanghai.android.materialratingbar:library:1.4.0"
composeRatingbar = "com.github.a914-gowtham:compose-ratingbar:1.2.3" composeRatingbar = "com.github.a914-gowtham:compose-ratingbar:1.2.3"