add platform and compose debug actions

This commit is contained in:
Ida Delphine
2026-10-17 22:14:17 +02:00
committed by Tobi
parent 7f18496d94
commit 4fc372035a
5 changed files with 171 additions and 0 deletions
@@ -0,0 +1,53 @@
package org.schabi.newpipe.settings
import android.content.Context
import android.content.Intent
import net.newpipe.app.platform.DebugActions
import org.schabi.newpipe.error.ErrorInfo
import org.schabi.newpipe.error.ErrorUtil
import org.schabi.newpipe.error.UserAction
import org.schabi.newpipe.local.feed.notifications.NotificationWorker
/**
* Host-side implementation of the debug actions used by the Compose debug settings screen.
*/
@Suppress("unused")
class ComposeDebugActions(private val context: Context) : DebugActions {
private val leakCanary = loadLeakCanary()
override val isLeakCanaryAvailable: Boolean
get() = leakCanary != null
override fun showMemoryLeaks() {
// The injected context is the application context, so the activity needs its own task.
leakCanary?.newLeakDisplayActivityIntent
?.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK)
?.let(context::startActivity)
}
override fun checkNewStreams() = NotificationWorker.runNow(context)
override fun createErrorNotification() = ErrorUtil.createNotification(context, dummyErrorInfo())
override fun reportDummyError() = ErrorUtil.openActivity(context, dummyErrorInfo())
private fun dummyErrorInfo() = ErrorInfo(RuntimeException(DUMMY), UserAction.UI_ERROR, DUMMY)
/**
* LeakCanary only ships in debug builds, so it is reached through the build-variant dependent
* bridge the legacy debug settings fragment already defines.
*
* TODO: move [DebugSettingsFragment.DebugSettingsBVDLeakCanaryAPI] out of the fragment when
* the legacy debug settings fragment is deleted.
*/
private fun loadLeakCanary(): DebugSettingsFragment.DebugSettingsBVDLeakCanaryAPI? = runCatching {
Class.forName(DebugSettingsFragment.DebugSettingsBVDLeakCanaryAPI.IMPL_CLASS)
.getDeclaredConstructor()
.newInstance() as DebugSettingsFragment.DebugSettingsBVDLeakCanaryAPI
}.getOrNull()
private companion object {
const val DUMMY = "Dummy"
}
}
@@ -0,0 +1,44 @@
/*
* SPDX-FileCopyrightText: 2026 NewPipe e.V. <https://newpipe-ev.de>
* SPDX-License-Identifier: GPL-3.0-or-later
*/
package net.newpipe.app.platform
import android.content.Context
import co.touchlab.kermit.Logger
import org.koin.core.annotation.Singleton
/**
* Forwards every debug action to a bridge supplied by the host app.
*
*/
@Singleton(binds = [DebugActions::class])
class AndroidDebugActions(context: Context) : DebugActions {
private val host: DebugActions = loadHost(context)
override val isLeakCanaryAvailable: Boolean
get() = host.isLeakCanaryAvailable
override fun showMemoryLeaks() = host.showMemoryLeaks()
override fun checkNewStreams() = host.checkNewStreams()
override fun createErrorNotification() = host.createErrorNotification()
override fun reportDummyError() = host.reportDummyError()
private fun loadHost(context: Context): DebugActions = runCatching {
Class.forName(HOST_CLASS)
.getDeclaredConstructor(Context::class.java)
.newInstance(context) as DebugActions
}.getOrElse { error ->
Logger.w(messageString = "No host debug actions found, falling back to no-op", throwable = error)
NoOpDebugActions
}
private companion object {
const val HOST_CLASS = "org.schabi.newpipe.settings.ComposeDebugActions"
}
}
@@ -1,2 +1,47 @@
/*
* SPDX-FileCopyrightText: 2026 NewPipe e.V. <https://newpipe-ev.de>
* SPDX-License-Identifier: GPL-3.0-or-later
*/
package net.newpipe.app.platform
import co.touchlab.kermit.Logger
/**
* Platform-specific actions triggered from the Debug settings screen.
*
*/
interface DebugActions {
/** Whether the running build ships LeakCanary; its two rows are disabled when it does not. */
val isLeakCanaryAvailable: Boolean
/** Opens the LeakCanary leak list. */
fun showMemoryLeaks()
/** Runs the new-stream notification check now, instead of waiting for its schedule. */
fun checkNewStreams()
/** Posts a dummy error notification, to verify error reporting end to end. */
fun createErrorNotification()
/** Opens the error report screen for a dummy error. */
fun reportDummyError()
}
/**
* Fallback for platforms with no debug tooling to drive, and for Android builds that ship without
* the host-side bridge.
*/
internal object NoOpDebugActions : DebugActions {
override val isLeakCanaryAvailable = false
override fun showMemoryLeaks() = logUnsupported("showMemoryLeaks")
override fun checkNewStreams() = logUnsupported("checkNewStreams")
override fun createErrorNotification() = logUnsupported("createErrorNotification")
override fun reportDummyError() = logUnsupported("reportDummyError")
private fun logUnsupported(action: String) = Logger.w(messageString = "Debug action '$action' is unsupported on this platform")
}
@@ -0,0 +1,14 @@
/*
* SPDX-FileCopyrightText: 2026 NewPipe e.V. <https://newpipe-ev.de>
* SPDX-License-Identifier: GPL-3.0-or-later
*/
package net.newpipe.app.platform
import org.koin.core.annotation.Singleton
/**
* iOS has no debug tooling to drive yet, and the Debug category is hidden there anyway
*/
@Singleton(binds = [DebugActions::class])
class IOSDebugActions : DebugActions by NoOpDebugActions
@@ -0,0 +1,15 @@
/*
* SPDX-FileCopyrightText: 2026 NewPipe e.V. <https://newpipe-ev.de>
* SPDX-License-Identifier: GPL-3.0-or-later
*/
package net.newpipe.app.platform
import org.koin.core.annotation.Singleton
/**
* Desktop has no debug tooling to drive yet
*/
@Singleton(binds = [DebugActions::class])
class JVMDebugActions : DebugActions by NoOpDebugActions