A customizable debug screen to view and edit flags that can be used for development in Jetpack Compose applications
To include the library add to your app's build.gradle
:
implementation 'com.telefonica:tweaks:{version}'
Or, in case you want to don't add the library in release builds:
debugImplementation 'com.telefonica:tweaks:{version}'
releaseImplementation 'com.telefonica:tweaks-no-op:{version}'
Then initialize the library in your app's onCreate
:
override fun onCreate() {
super.onCreate()
Tweaks.init(context, demoTweakGraph())
}
where demoTweakGraph
is the structure you want to be rendered:
private fun demoTweakGraph() = tweaksGraph {
cover("Tweaks") {
label("Current user ID:") { flowOf("80057182") }
label("Current IP:") { flowOf("192.168.1.127") }
label("Current IP (public):") { flowOf("80.68.1.92") }
label("Timestamp:") { timestampState }
dropDownMenu(
key = "spinner1",
name = "Spinner example",
values = listOf("Monday", "Tuesday", "Wednesday", "Thursday", "Friday", "Saturday", "Sunday"),
defaultValue = flowOf("Monday")
)
}
category("Statistics") {
group("Group 1") {
label(
name = "Current timestamp",
) {
timestampState
}
editableString(
key = "value1",
name = "Value 1",
)
editableBoolean(
key = "value2",
name = "Value 2",
defaultValue = true,
)
editableLong(
key = "value4",
name = "Value 4",
defaultValue = 42L,
)
button(
name = "Demo button"
) {
Toast.makeText(this@TweakDemoApplication, "Demo button", Toast.LENGTH_LONG)
.show()
}
routeButton(
name = "Custom screen button",
route = "custom-screen"
)
customNavigationButton(
name = "Another custom screen button",
navigation = { navController ->
navController.navigate("custom-screen")
}
)
}
}
}
And then, in your NavHost setup, use the extension function NavGraphBuilder.addTweakGraph
to fill the navigation graph with the tweak components:
@Composable
private fun DemoNavHost(
navController: NavHostController,
initialScreen: String,
modifier: Modifier = Modifier,
) {
NavHost(
navController = navController,
startDestination = initialScreen,
modifier = modifier,
) {
addTweakGraph(
navController = navController,
)
}
}
You can use the DSL to create your own graph. Please note that a graph is composed by:
- A main group of tweaks (Optional)
- A list of categories
The categories are separate screens and are composed of groups of tweaks. You can use each category to separate debug elements of your app by feature or key components, for example: (chat, webviews, login, stats, etc...)
The group of tweaks are a shown inside each category screen, they are composed of tweaks and can represent configuration settings that can be grouped together, for example: endpoints of your API.
And finally, the tweaks are the configurable elements. Currently we support these ones:
button(
name: String,
action: () -> Unit
)
Used to display a button that performs an action
fun routeButton(
name: String,
route: String,
)
Similar, but this button navigates directly to a route of the NavHost, check custom screens section for more info
customNavigationButton(
name = "Another custom screen button",
navigation = { navController ->
navController.navigate("custom-screen") {
popUpTo("another-custom-screen") {
inclusive = true
}
}
}
)
Just like routeButton
, but it allows to pass a lambda which receives a NavController
so more complex navigations can be performed.
fun label(
name: String,
value: () -> Flow<String>,
)
A non editable text
fun editableString(
key: String,
name: String,
defaultValue: Flow<String>? = null,
)
fun editableString(
key: String,
name: String,
defaultValue: String,
)
An editable text
fun editableBoolean(
key: String,
name: String,
defaultValue: Flow<Boolean>? = null,
)
fun editableBoolean(
key: String,
name: String,
defaultValue: Boolean,
)
An editable boolean
fun editableInt(
key: String,
name: String,
defaultValue: Flow<Int>? = null,
)
fun editableInt(
key: String,
name: String,
defaultValue: Int,
)
An editable Int
fun editableLong(
key: String,
name: String,
defaultValue: Flow<Long>? = null,
)
fun editableLong(
key: String,
name: String,
defaultValue: Long,
)
An editable Long
fun dropDownMenu(
key: String,
name: String,
values: List<String>,
defaultValue: Flow<String>,
)
A DropDownMenu Please review the app module for configuration examples.
When a group of tweaks is created, only if there is at least one editable tweak, a reset button will be automatically added.
If you do not want the reset button to be added automatically, there is a parameter in group node withClearButton
that can be set.
group(
title = "Group Title",
withClearButton = true
) {
// Your tweaks
}
You can add your custom screens to the TweaksGraph by using the customComposableScreens
parameter of addTweakGraph
function, for example:
addTweakGraph(
navController = navController,
) {
composable(route = "custom-screen") {
Column(
modifier = Modifier
.fillMaxSize()
.padding(16.dp),
verticalArrangement = Arrangement.Center,
horizontalAlignment = Alignment.CenterHorizontally,
) {
Text("Custom screen")
}
}
}
The tweaks can be opened when the user shakes the device. To achieve this, you can either add the following to your navigation controller:
navController.navigateToTweaksOnShake()
or call:
NavigateToTweaksOnShake(onOpenTweaks: () -> Unit)
and handle the navigation action yourself.
And also, optionally
<uses-permission android:name="android.permission.VIBRATE" />
to your AndroidManifest.xml