From 321ae1f037564c313c163d11daf16f504ed9462c Mon Sep 17 00:00:00 2001 From: "a.emogurov" Date: Wed, 18 Feb 2026 14:24:04 +0400 Subject: [PATCH 1/4] feature: add about app plugin --- .../noop/plugin/aboutapp/AboutAppInfo.kt | 6 + .../noop/plugin/aboutapp/AboutAppPlugin.kt | 5 + plugins/plugin-about-app/.gitignore | 1 + plugins/plugin-about-app/build.gradle.kts | 11 ++ plugins/plugin-about-app/proguard-rules.pro | 21 ++++ .../debug/plugin/aboutapp/AboutAppPlugin.kt | 33 ++++++ .../aboutapp/AboutAppPluginContainer.kt | 13 ++ .../plugin/aboutapp/model/AboutAppInfo.kt | 6 + .../plugin/aboutapp/ui/AboutAppScreen.kt | 112 ++++++++++++++++++ .../plugin/aboutapp/ui/AboutAppViewModel.kt | 12 ++ .../plugin/aboutapp/ui/AboutAppViewState.kt | 9 ++ .../src/main/res/values/public.xml | 6 + .../src/main/res/values/strings.xml | 2 + sample/build.gradle.kts | 1 + .../debug_data/DebugAboutAppInfoProvider.kt | 28 +++++ .../com/redmadrobot/debug_sample/App.kt | 5 + settings.gradle.kts | 1 + 17 files changed, 272 insertions(+) create mode 100644 panel-no-op/src/main/kotlin/com/redmadrobot/debug/noop/plugin/aboutapp/AboutAppInfo.kt create mode 100644 panel-no-op/src/main/kotlin/com/redmadrobot/debug/noop/plugin/aboutapp/AboutAppPlugin.kt create mode 100644 plugins/plugin-about-app/.gitignore create mode 100644 plugins/plugin-about-app/build.gradle.kts create mode 100644 plugins/plugin-about-app/proguard-rules.pro create mode 100644 plugins/plugin-about-app/src/main/kotlin/com/redmadrobot/debug/plugin/aboutapp/AboutAppPlugin.kt create mode 100644 plugins/plugin-about-app/src/main/kotlin/com/redmadrobot/debug/plugin/aboutapp/AboutAppPluginContainer.kt create mode 100644 plugins/plugin-about-app/src/main/kotlin/com/redmadrobot/debug/plugin/aboutapp/model/AboutAppInfo.kt create mode 100644 plugins/plugin-about-app/src/main/kotlin/com/redmadrobot/debug/plugin/aboutapp/ui/AboutAppScreen.kt create mode 100644 plugins/plugin-about-app/src/main/kotlin/com/redmadrobot/debug/plugin/aboutapp/ui/AboutAppViewModel.kt create mode 100644 plugins/plugin-about-app/src/main/kotlin/com/redmadrobot/debug/plugin/aboutapp/ui/AboutAppViewState.kt create mode 100644 plugins/plugin-about-app/src/main/res/values/public.xml create mode 100644 plugins/plugin-about-app/src/main/res/values/strings.xml create mode 100644 sample/src/debug/kotlin/com/redmadrobot/debug_sample/debug_data/DebugAboutAppInfoProvider.kt diff --git a/panel-no-op/src/main/kotlin/com/redmadrobot/debug/noop/plugin/aboutapp/AboutAppInfo.kt b/panel-no-op/src/main/kotlin/com/redmadrobot/debug/noop/plugin/aboutapp/AboutAppInfo.kt new file mode 100644 index 00000000..c2c1824d --- /dev/null +++ b/panel-no-op/src/main/kotlin/com/redmadrobot/debug/noop/plugin/aboutapp/AboutAppInfo.kt @@ -0,0 +1,6 @@ +package com.redmadrobot.debug.noop.plugin.aboutapp + +data class AboutAppInfo( + val title: String, + val content: String +) diff --git a/panel-no-op/src/main/kotlin/com/redmadrobot/debug/noop/plugin/aboutapp/AboutAppPlugin.kt b/panel-no-op/src/main/kotlin/com/redmadrobot/debug/noop/plugin/aboutapp/AboutAppPlugin.kt new file mode 100644 index 00000000..ba570b04 --- /dev/null +++ b/panel-no-op/src/main/kotlin/com/redmadrobot/debug/noop/plugin/aboutapp/AboutAppPlugin.kt @@ -0,0 +1,5 @@ +package com.redmadrobot.debug.noop.plugin.aboutapp + +class AboutAppPlugin( + private val aboutAppInfo: List = emptyList() +) diff --git a/plugins/plugin-about-app/.gitignore b/plugins/plugin-about-app/.gitignore new file mode 100644 index 00000000..796b96d1 --- /dev/null +++ b/plugins/plugin-about-app/.gitignore @@ -0,0 +1 @@ +/build diff --git a/plugins/plugin-about-app/build.gradle.kts b/plugins/plugin-about-app/build.gradle.kts new file mode 100644 index 00000000..32c8d2e0 --- /dev/null +++ b/plugins/plugin-about-app/build.gradle.kts @@ -0,0 +1,11 @@ +plugins { + id("convention.debug.panel.plugin") + alias(stack.plugins.ksp) + alias(stack.plugins.kotlin.compose) +} + +description = "Plugin for showing about app information" + +android { + namespace = "com.redmadrobot.debug.plugin.aboutapp" +} diff --git a/plugins/plugin-about-app/proguard-rules.pro b/plugins/plugin-about-app/proguard-rules.pro new file mode 100644 index 00000000..4a7e6dc8 --- /dev/null +++ b/plugins/plugin-about-app/proguard-rules.pro @@ -0,0 +1,21 @@ +# Add project specific ProGuard rules here. +# You can control the set of applied configuration files using the +# proguardFiles setting in build.gradle.kts.kts.kts.kts.kts.kts. +# +# For more details, see +# http://developer.android.com/guide/developing/tools/proguard.html + +# If your project uses WebView with JS, uncomment the following +# and specify the fully qualified class name to the JavaScript interface +# class: +#-keepclassmembers class fqcn.of.javascript.interface.for.webview { +# public *; +#} + +# Uncomment this to preserve the line number information for +# debugging stack traces. +#-keepattributes SourceFile,LineNumberTable + +# If you keep the line number information, uncomment this to +# hide the original source file name. +#-renamesourcefileattribute SourceFile diff --git a/plugins/plugin-about-app/src/main/kotlin/com/redmadrobot/debug/plugin/aboutapp/AboutAppPlugin.kt b/plugins/plugin-about-app/src/main/kotlin/com/redmadrobot/debug/plugin/aboutapp/AboutAppPlugin.kt new file mode 100644 index 00000000..384ddb97 --- /dev/null +++ b/plugins/plugin-about-app/src/main/kotlin/com/redmadrobot/debug/plugin/aboutapp/AboutAppPlugin.kt @@ -0,0 +1,33 @@ +package com.redmadrobot.debug.plugin.aboutapp + +import androidx.compose.runtime.Composable +import com.redmadrobot.debug.core.internal.CommonContainer +import com.redmadrobot.debug.core.internal.EditablePlugin +import com.redmadrobot.debug.core.internal.PluginDependencyContainer +import com.redmadrobot.debug.core.plugin.Plugin +import com.redmadrobot.debug.plugin.aboutapp.model.AboutAppInfo +import com.redmadrobot.debug.plugin.aboutapp.ui.AboutAppScreen + +public class AboutAppPlugin( + private val aboutAppInfo: List +) : Plugin(), EditablePlugin { + init { + aboutAppInfo.firstOrNull() + ?: error("AboutAppPlugin can't be initialized. At least one information block must be set.") + } + + internal companion object { + internal const val NAME = "ABOUT APP" + } + + override fun getPluginContainer(commonContainer: CommonContainer): PluginDependencyContainer { + return AboutAppPluginContainer(aboutAppInfo = aboutAppInfo) + } + + override fun getName(): String = NAME + + @Composable + override fun content() { + AboutAppScreen() + } +} diff --git a/plugins/plugin-about-app/src/main/kotlin/com/redmadrobot/debug/plugin/aboutapp/AboutAppPluginContainer.kt b/plugins/plugin-about-app/src/main/kotlin/com/redmadrobot/debug/plugin/aboutapp/AboutAppPluginContainer.kt new file mode 100644 index 00000000..1de22b23 --- /dev/null +++ b/plugins/plugin-about-app/src/main/kotlin/com/redmadrobot/debug/plugin/aboutapp/AboutAppPluginContainer.kt @@ -0,0 +1,13 @@ +package com.redmadrobot.debug.plugin.aboutapp + +import com.redmadrobot.debug.core.internal.PluginDependencyContainer +import com.redmadrobot.debug.plugin.aboutapp.model.AboutAppInfo +import com.redmadrobot.debug.plugin.aboutapp.ui.AboutAppViewModel + +internal class AboutAppPluginContainer( + private val aboutAppInfo: List +) : PluginDependencyContainer { + fun createAboutAppViewModel(): AboutAppViewModel { + return AboutAppViewModel(aboutAppInfo = aboutAppInfo) + } +} diff --git a/plugins/plugin-about-app/src/main/kotlin/com/redmadrobot/debug/plugin/aboutapp/model/AboutAppInfo.kt b/plugins/plugin-about-app/src/main/kotlin/com/redmadrobot/debug/plugin/aboutapp/model/AboutAppInfo.kt new file mode 100644 index 00000000..8ac86c8b --- /dev/null +++ b/plugins/plugin-about-app/src/main/kotlin/com/redmadrobot/debug/plugin/aboutapp/model/AboutAppInfo.kt @@ -0,0 +1,6 @@ +package com.redmadrobot.debug.plugin.aboutapp.model + +public data class AboutAppInfo( + val title: String, + val content: String +) diff --git a/plugins/plugin-about-app/src/main/kotlin/com/redmadrobot/debug/plugin/aboutapp/ui/AboutAppScreen.kt b/plugins/plugin-about-app/src/main/kotlin/com/redmadrobot/debug/plugin/aboutapp/ui/AboutAppScreen.kt new file mode 100644 index 00000000..de9f29ed --- /dev/null +++ b/plugins/plugin-about-app/src/main/kotlin/com/redmadrobot/debug/plugin/aboutapp/ui/AboutAppScreen.kt @@ -0,0 +1,112 @@ +package com.redmadrobot.debug.plugin.aboutapp.ui + +import androidx.compose.foundation.layout.Arrangement +import androidx.compose.foundation.layout.Column +import androidx.compose.foundation.layout.PaddingValues +import androidx.compose.foundation.layout.defaultMinSize +import androidx.compose.foundation.layout.fillMaxSize +import androidx.compose.foundation.layout.fillMaxWidth +import androidx.compose.foundation.layout.padding +import androidx.compose.foundation.lazy.LazyColumn +import androidx.compose.foundation.lazy.items +import androidx.compose.material.Card +import androidx.compose.material.MaterialTheme +import androidx.compose.material.Text +import androidx.compose.runtime.Composable +import androidx.compose.runtime.collectAsState +import androidx.compose.runtime.getValue +import androidx.compose.runtime.remember +import androidx.compose.ui.Modifier +import androidx.compose.ui.text.font.FontWeight +import androidx.compose.ui.text.style.TextOverflow +import androidx.compose.ui.tooling.preview.Preview +import androidx.compose.ui.unit.dp +import com.redmadrobot.debug.core.extension.getPlugin +import com.redmadrobot.debug.core.extension.provideViewModel +import com.redmadrobot.debug.plugin.aboutapp.AboutAppPlugin +import com.redmadrobot.debug.plugin.aboutapp.AboutAppPluginContainer +import com.redmadrobot.debug.plugin.aboutapp.model.AboutAppInfo + +@Composable +internal fun AboutAppScreen( + viewModel: AboutAppViewModel = provideViewModel { + getPlugin() + .getContainer() + .createAboutAppViewModel() + } +) { + val state by viewModel.state.collectAsState() + + AboutAppLayout(state = state) +} + +@Composable +private fun AboutAppLayout(state: AboutAppViewState) { + LazyColumn( + modifier = Modifier.fillMaxSize(), + verticalArrangement = Arrangement.spacedBy(8.dp), + contentPadding = PaddingValues(horizontal = 16.dp, vertical = 16.dp), + ) { + items(items = state.aboutAppInfo, key = { it.title }) { item -> + AboutAppItem(item = item) + } + } +} + +@Composable +private fun AboutAppItem(item: AboutAppInfo, modifier: Modifier = Modifier) { + Card( + modifier = modifier + .fillMaxWidth() + .defaultMinSize(minHeight = 56.dp), + elevation = 4.dp + ) { + Column( + modifier = Modifier + .fillMaxWidth() + .padding(all = 16.dp), + verticalArrangement = Arrangement.spacedBy(space = 4.dp), + ) { + Text( + text = item.title, + style = MaterialTheme.typography.caption, + fontWeight = FontWeight.SemiBold, + color = MaterialTheme.colors.primary, + ) + Text( + text = item.content, + style = MaterialTheme.typography.body1, + color = MaterialTheme.colors.onSurface, + maxLines = 2, + overflow = TextOverflow.Ellipsis, + ) + } + } +} + +@Preview(showBackground = true) +@Composable +private fun Preview() { + val state = remember { + AboutAppViewState( + aboutAppInfo = listOf( + AboutAppInfo(title = "Версия", content = "3,14"), + AboutAppInfo( + title = "Номер билда", + content = "fgkdfjgkdfgjdfkgjdfkjgkdfjgkdfjgkdfjgkdjgskdjgkdgfjdsfgjdsfgdsfgjdsfgdskjfgdsjkfgdjfgdsfg" + ), + AboutAppInfo(title = "Версия1", content = "3,14"), + AboutAppInfo(title = "Версия2", content = "3,14"), + AboutAppInfo(title = "Версия3", content = "3,14"), + AboutAppInfo(title = "Версия4", content = "3,14"), + AboutAppInfo(title = "Версия5", content = "3,14"), + AboutAppInfo(title = "Версия6", content = "3,14"), + AboutAppInfo(title = "Версия7", content = "3,14"), + ) + ) + } + + MaterialTheme { + AboutAppLayout(state = state) + } +} diff --git a/plugins/plugin-about-app/src/main/kotlin/com/redmadrobot/debug/plugin/aboutapp/ui/AboutAppViewModel.kt b/plugins/plugin-about-app/src/main/kotlin/com/redmadrobot/debug/plugin/aboutapp/ui/AboutAppViewModel.kt new file mode 100644 index 00000000..270e7b82 --- /dev/null +++ b/plugins/plugin-about-app/src/main/kotlin/com/redmadrobot/debug/plugin/aboutapp/ui/AboutAppViewModel.kt @@ -0,0 +1,12 @@ +package com.redmadrobot.debug.plugin.aboutapp.ui + +import com.redmadrobot.debug.core.internal.PluginViewModel +import com.redmadrobot.debug.plugin.aboutapp.model.AboutAppInfo +import kotlinx.coroutines.flow.MutableStateFlow +import kotlinx.coroutines.flow.StateFlow +import kotlinx.coroutines.flow.asStateFlow + +internal class AboutAppViewModel(aboutAppInfo: List) : PluginViewModel() { + private val _state = MutableStateFlow(value = AboutAppViewState(aboutAppInfo = aboutAppInfo)) + val state: StateFlow = _state.asStateFlow() +} \ No newline at end of file diff --git a/plugins/plugin-about-app/src/main/kotlin/com/redmadrobot/debug/plugin/aboutapp/ui/AboutAppViewState.kt b/plugins/plugin-about-app/src/main/kotlin/com/redmadrobot/debug/plugin/aboutapp/ui/AboutAppViewState.kt new file mode 100644 index 00000000..74cdbfca --- /dev/null +++ b/plugins/plugin-about-app/src/main/kotlin/com/redmadrobot/debug/plugin/aboutapp/ui/AboutAppViewState.kt @@ -0,0 +1,9 @@ +package com.redmadrobot.debug.plugin.aboutapp.ui + +import androidx.compose.runtime.Immutable +import com.redmadrobot.debug.plugin.aboutapp.model.AboutAppInfo + +@Immutable +internal data class AboutAppViewState( + val aboutAppInfo: List +) diff --git a/plugins/plugin-about-app/src/main/res/values/public.xml b/plugins/plugin-about-app/src/main/res/values/public.xml new file mode 100644 index 00000000..2b0d6805 --- /dev/null +++ b/plugins/plugin-about-app/src/main/res/values/public.xml @@ -0,0 +1,6 @@ + + + + + diff --git a/plugins/plugin-about-app/src/main/res/values/strings.xml b/plugins/plugin-about-app/src/main/res/values/strings.xml new file mode 100644 index 00000000..545704f2 --- /dev/null +++ b/plugins/plugin-about-app/src/main/res/values/strings.xml @@ -0,0 +1,2 @@ + + diff --git a/sample/build.gradle.kts b/sample/build.gradle.kts index dc825623..1f8d7be6 100644 --- a/sample/build.gradle.kts +++ b/sample/build.gradle.kts @@ -48,6 +48,7 @@ dependencies { debugImplementation(project(":plugins:plugin-servers")) debugImplementation(project(":plugins:plugin-accounts")) debugImplementation(project(":plugins:plugin-app-settings")) + debugImplementation(project(":plugins:plugin-about-app")) // Debug panel dependencies debugImplementation(project(":plugins:plugin-flipper")) diff --git a/sample/src/debug/kotlin/com/redmadrobot/debug_sample/debug_data/DebugAboutAppInfoProvider.kt b/sample/src/debug/kotlin/com/redmadrobot/debug_sample/debug_data/DebugAboutAppInfoProvider.kt new file mode 100644 index 00000000..92a22e02 --- /dev/null +++ b/sample/src/debug/kotlin/com/redmadrobot/debug_sample/debug_data/DebugAboutAppInfoProvider.kt @@ -0,0 +1,28 @@ +package com.redmadrobot.debug_sample.debug_data + +import com.redmadrobot.debug.plugin.aboutapp.model.AboutAppInfo + +class DebugAboutAppInfoProvider { + companion object { + fun provideData(): List { + return listOf( + AboutAppInfo( + title = "Версия", + content = "3.14" + ), + AboutAppInfo( + title = "Номер билда", + content = "101" + ), + AboutAppInfo( + title = "Номер билда1", + content = "fgkdfjgkdfgjdfkgjdfkjgkdfjgkdfjgkdfjgkdjgskdjgkdgfjdsfgjdsfgdsfgjdsfgdskjfgdsjkfgdjfgdsfg" + ), + AboutAppInfo( + title = "Версия2", + content = "3,14" + ), + ) + } + } +} \ No newline at end of file diff --git a/sample/src/main/kotlin/com/redmadrobot/debug_sample/App.kt b/sample/src/main/kotlin/com/redmadrobot/debug_sample/App.kt index 2e68dc46..16443d52 100644 --- a/sample/src/main/kotlin/com/redmadrobot/debug_sample/App.kt +++ b/sample/src/main/kotlin/com/redmadrobot/debug_sample/App.kt @@ -3,6 +3,7 @@ package com.redmadrobot.debug_sample import android.app.Application import com.redmadrobot.debug.core.DebugPanel import com.redmadrobot.debug.core.DebugPanelConfig +import com.redmadrobot.debug.plugin.aboutapp.AboutAppPlugin import com.redmadrobot.debug.plugin.accounts.AccountsPlugin import com.redmadrobot.debug.plugin.appsettings.AppSettingsPlugin import com.redmadrobot.debug.plugin.flipper.FlipperPlugin @@ -10,6 +11,7 @@ import com.redmadrobot.debug.plugin.konfeature.KonfeatureDebugPanelInterceptor import com.redmadrobot.debug.plugin.konfeature.KonfeaturePlugin import com.redmadrobot.debug.plugin.servers.ServersPlugin import com.redmadrobot.debug_sample.account.DebugUserAuthenticator +import com.redmadrobot.debug_sample.debug_data.DebugAboutAppInfoProvider import com.redmadrobot.debug_sample.debug_data.DebugAccountsProvider import com.redmadrobot.debug_sample.debug_data.DebugFlipperFeaturesProvider import com.redmadrobot.debug_sample.debug_data.DebugServersProvider @@ -47,6 +49,9 @@ class App : Application() { debugPanelInterceptor = debugPanelInterceptor, konfeature = TestKonfeatureProvider.create(debugPanelInterceptor), ), + AboutAppPlugin( + aboutAppInfo = DebugAboutAppInfoProvider.provideData() + ) ) ) } diff --git a/settings.gradle.kts b/settings.gradle.kts index 485a9e30..d2a96b64 100644 --- a/settings.gradle.kts +++ b/settings.gradle.kts @@ -58,6 +58,7 @@ include( ":plugins:plugin-app-settings", ":plugins:plugin-flipper", ":plugins:plugin-konfeature", + ":plugins:plugin-about-app", ) include(":sample") From 6cb3edc510550e8ddeed80bd7b3e6c5987d1d6c3 Mon Sep 17 00:00:00 2001 From: "a.emogurov" Date: Wed, 18 Feb 2026 14:43:30 +0400 Subject: [PATCH 2/4] feature: minor bottom sheet improves --- .../core/inapp/compose/DebugBottomSheet.kt | 45 +++++++++---------- 1 file changed, 22 insertions(+), 23 deletions(-) diff --git a/panel-core/src/main/kotlin/com/redmadrobot/debug/core/inapp/compose/DebugBottomSheet.kt b/panel-core/src/main/kotlin/com/redmadrobot/debug/core/inapp/compose/DebugBottomSheet.kt index 222335b6..f60d27b2 100644 --- a/panel-core/src/main/kotlin/com/redmadrobot/debug/core/inapp/compose/DebugBottomSheet.kt +++ b/panel-core/src/main/kotlin/com/redmadrobot/debug/core/inapp/compose/DebugBottomSheet.kt @@ -3,17 +3,16 @@ package com.redmadrobot.debug.core.inapp.compose import androidx.compose.foundation.ExperimentalFoundationApi -import androidx.compose.foundation.background -import androidx.compose.foundation.layout.Box import androidx.compose.foundation.layout.Column -import androidx.compose.foundation.layout.Spacer import androidx.compose.foundation.layout.fillMaxSize -import androidx.compose.foundation.layout.height +import androidx.compose.foundation.layout.padding +import androidx.compose.foundation.layout.statusBarsPadding import androidx.compose.foundation.layout.width import androidx.compose.foundation.pager.HorizontalPager import androidx.compose.foundation.pager.PagerState import androidx.compose.foundation.pager.rememberPagerState -import androidx.compose.foundation.shape.CircleShape +import androidx.compose.foundation.shape.RoundedCornerShape +import androidx.compose.material.Divider import androidx.compose.material.MaterialTheme import androidx.compose.material.ModalBottomSheetLayout import androidx.compose.material.ModalBottomSheetValue @@ -28,7 +27,6 @@ import androidx.compose.runtime.remember import androidx.compose.runtime.rememberCoroutineScope import androidx.compose.ui.Alignment import androidx.compose.ui.Modifier -import androidx.compose.ui.draw.clip import androidx.compose.ui.graphics.Color import androidx.compose.ui.unit.dp import com.redmadrobot.debug.core.extension.getAllPlugins @@ -38,7 +36,7 @@ import kotlinx.coroutines.launch @Composable public fun DebugBottomSheet(onClose: () -> Unit) { val state = rememberModalBottomSheetState( - initialValue = ModalBottomSheetValue.HalfExpanded, + initialValue = ModalBottomSheetValue.Expanded, confirmValueChange = { sheetState -> if (sheetState == ModalBottomSheetValue.Hidden) onClose() true @@ -47,9 +45,11 @@ public fun DebugBottomSheet(onClose: () -> Unit) { ) ModalBottomSheetLayout( + modifier = Modifier.statusBarsPadding(), sheetContent = { BottomSheetContent() }, sheetState = state, scrimColor = Color.Transparent, + sheetShape = RoundedCornerShape(size = 16.dp), content = {}, ) } @@ -59,35 +59,34 @@ private fun BottomSheetContent() { val plugins = remember { getAllPlugins() } val pluginsName = remember { plugins.map { it.getName() } } val pagerState = rememberPagerState(initialPage = 0, pageCount = { plugins.size }) - Column(modifier = Modifier.fillMaxSize()) { - Spacer(modifier = Modifier.height(8.dp)) - Box( + Column(modifier = Modifier.fillMaxSize()) { + Divider( modifier = Modifier - .height(4.dp) - .width(50.dp) - .clip(CircleShape) - .background(Color.Gray) - .align(Alignment.CenterHorizontally) + .width(width = 50.dp) + .padding(vertical = 8.dp) + .align(alignment = Alignment.CenterHorizontally), + color = Color.Gray, + thickness = 4.dp ) - - Spacer(modifier = Modifier.height(8.dp)) - - PluginsTabLayout(pluginsName, pagerState = pagerState) - - PluginsPager(plugins, pagerState = pagerState) + PluginsTabLayout(pluginsName = pluginsName, pagerState = pagerState) + PluginsPager(plugins = plugins, pagerState = pagerState) } } @Composable private fun PluginsTabLayout(pluginsName: List, pagerState: PagerState) { val scope = rememberCoroutineScope() + ScrollableTabRow( selectedTabIndex = pagerState.currentPage, backgroundColor = MaterialTheme.colors.background, + edgePadding = 16.dp, indicator = { tabPositions -> TabRowDefaults.Indicator( - modifier = Modifier.tabIndicatorOffset(tabPositions[pagerState.currentPage]), + modifier = Modifier.tabIndicatorOffset( + currentTabPosition = tabPositions[pagerState.currentPage] + ), height = 2.dp, color = MaterialTheme.colors.secondary ) @@ -95,7 +94,7 @@ private fun PluginsTabLayout(pluginsName: List, pagerState: PagerState) ) { pluginsName.forEachIndexed { index, _ -> Tab( - text = { Text(pluginsName[index]) }, + text = { Text(text = pluginsName[index]) }, selected = pagerState.currentPage == index, onClick = { scope.launch { pagerState.animateScrollToPage(index) } From 8e7eac678af4648851bb7f3565d71c60d56d1ead Mon Sep 17 00:00:00 2001 From: "a.emogurov" Date: Wed, 18 Feb 2026 14:52:23 +0400 Subject: [PATCH 3/4] feature: update readme with about app plugin --- README.md | 28 ++++++++++++++++++++++++++++ 1 file changed, 28 insertions(+) diff --git a/README.md b/README.md index 9374aca2..d6d011a9 100644 --- a/README.md +++ b/README.md @@ -62,6 +62,9 @@ dependencies { debugImplementation 'com.redmadrobot.debug:plugin-konfeature:${debug_panel_version}' //Так же необходимо подключить саму библиотеку konfeature debugImplementation "com.redmadrobot.konfeature:konfeature:${konfeature_version}" + + //Плагин для отображения информации о приложении + debugImplementation 'com.redmadrobot.debug:plugin-about-app:${debug_panel_version}' } ``` @@ -328,6 +331,31 @@ KonfeaturePlugin( - настроить работу с remote config через реализацию интерфейса `FeatureSource` - `addSource(featureSource)` - настроить логирование - `setLogger(logger)` +### AboutApp Plugin + +Используется для отображения информации о приложении: версии, номера билда и других произвольных данных. + +Для подключения плагина необходимо передать список `AboutAppInfo`. Требуется хотя бы один элемент: + +```kotlin +AboutAppPlugin( + aboutAppInfo = listOf( + AboutAppInfo( + title = "Версия", + content = BuildConfig.VERSION_NAME + ), + AboutAppInfo( + title = "Номер билда", + content = BuildConfig.VERSION_CODE.toString() + ) + ) +) +``` + +Каждый `AboutAppInfo` содержит: +- `title` — название поля (например, «Версия») +- `content` — значение поля (например, «1.0.0») + # Безопасность! Для того чтобы тестовые данные не попали в релизные сборки рекомендуется не задавать их явно в Application классе, а использовать реализации DebugDataProvider, которые можно разнести по разным buildType. Для release версии следует сделать пустую реализацию. From d4eb65e4b8ab680b02809e94237c9e22879145bf Mon Sep 17 00:00:00 2001 From: "a.emogurov" Date: Tue, 24 Feb 2026 16:46:31 +0400 Subject: [PATCH 4/4] review: review fixes --- README.md | 6 ++-- .../noop/plugin/aboutapp/AboutAppInfo.kt | 4 +-- .../noop/plugin/aboutapp/AboutAppPlugin.kt | 4 +-- .../debug/plugin/aboutapp/AboutAppPlugin.kt | 6 ++-- .../aboutapp/AboutAppPluginContainer.kt | 4 +-- .../plugin/aboutapp/model/AboutAppInfo.kt | 8 ++++-- .../plugin/aboutapp/ui/AboutAppScreen.kt | 28 +++++++++---------- .../plugin/aboutapp/ui/AboutAppViewModel.kt | 4 +-- .../plugin/aboutapp/ui/AboutAppViewState.kt | 2 +- .../debug_data/DebugAboutAppInfoProvider.kt | 12 ++++---- .../com/redmadrobot/debug_sample/App.kt | 2 +- .../debug_data/DebugAboutAppInfoProvider.kt | 11 ++++++++ 12 files changed, 53 insertions(+), 38 deletions(-) create mode 100644 sample/src/release/kotlin/com/redmadrobot/debug_sample/debug_data/DebugAboutAppInfoProvider.kt diff --git a/README.md b/README.md index d6d011a9..aef6f354 100644 --- a/README.md +++ b/README.md @@ -342,11 +342,11 @@ AboutAppPlugin( aboutAppInfo = listOf( AboutAppInfo( title = "Версия", - content = BuildConfig.VERSION_NAME + value = BuildConfig.VERSION_NAME ), AboutAppInfo( title = "Номер билда", - content = BuildConfig.VERSION_CODE.toString() + value = BuildConfig.VERSION_CODE.toString() ) ) ) @@ -354,7 +354,7 @@ AboutAppPlugin( Каждый `AboutAppInfo` содержит: - `title` — название поля (например, «Версия») -- `content` — значение поля (например, «1.0.0») +- `value` — значение поля (например, «1.0.0») # Безопасность! Для того чтобы тестовые данные не попали в релизные сборки рекомендуется не задавать их явно в Application классе, а использовать реализации DebugDataProvider, которые можно разнести по разным buildType. Для release версии следует сделать пустую реализацию. diff --git a/panel-no-op/src/main/kotlin/com/redmadrobot/debug/noop/plugin/aboutapp/AboutAppInfo.kt b/panel-no-op/src/main/kotlin/com/redmadrobot/debug/noop/plugin/aboutapp/AboutAppInfo.kt index c2c1824d..9cab84ac 100644 --- a/panel-no-op/src/main/kotlin/com/redmadrobot/debug/noop/plugin/aboutapp/AboutAppInfo.kt +++ b/panel-no-op/src/main/kotlin/com/redmadrobot/debug/noop/plugin/aboutapp/AboutAppInfo.kt @@ -1,6 +1,6 @@ -package com.redmadrobot.debug.noop.plugin.aboutapp +package com.redmadrobot.debug.plugin.aboutapp data class AboutAppInfo( val title: String, - val content: String + val value: String ) diff --git a/panel-no-op/src/main/kotlin/com/redmadrobot/debug/noop/plugin/aboutapp/AboutAppPlugin.kt b/panel-no-op/src/main/kotlin/com/redmadrobot/debug/noop/plugin/aboutapp/AboutAppPlugin.kt index ba570b04..01b073ff 100644 --- a/panel-no-op/src/main/kotlin/com/redmadrobot/debug/noop/plugin/aboutapp/AboutAppPlugin.kt +++ b/panel-no-op/src/main/kotlin/com/redmadrobot/debug/noop/plugin/aboutapp/AboutAppPlugin.kt @@ -1,5 +1,5 @@ -package com.redmadrobot.debug.noop.plugin.aboutapp +package com.redmadrobot.debug.plugin.aboutapp class AboutAppPlugin( - private val aboutAppInfo: List = emptyList() + private val appInfoList: List = emptyList() ) diff --git a/plugins/plugin-about-app/src/main/kotlin/com/redmadrobot/debug/plugin/aboutapp/AboutAppPlugin.kt b/plugins/plugin-about-app/src/main/kotlin/com/redmadrobot/debug/plugin/aboutapp/AboutAppPlugin.kt index 384ddb97..d2e66abe 100644 --- a/plugins/plugin-about-app/src/main/kotlin/com/redmadrobot/debug/plugin/aboutapp/AboutAppPlugin.kt +++ b/plugins/plugin-about-app/src/main/kotlin/com/redmadrobot/debug/plugin/aboutapp/AboutAppPlugin.kt @@ -9,10 +9,10 @@ import com.redmadrobot.debug.plugin.aboutapp.model.AboutAppInfo import com.redmadrobot.debug.plugin.aboutapp.ui.AboutAppScreen public class AboutAppPlugin( - private val aboutAppInfo: List + private val appInfoList: List ) : Plugin(), EditablePlugin { init { - aboutAppInfo.firstOrNull() + appInfoList.firstOrNull() ?: error("AboutAppPlugin can't be initialized. At least one information block must be set.") } @@ -21,7 +21,7 @@ public class AboutAppPlugin( } override fun getPluginContainer(commonContainer: CommonContainer): PluginDependencyContainer { - return AboutAppPluginContainer(aboutAppInfo = aboutAppInfo) + return AboutAppPluginContainer(appInfoList = appInfoList) } override fun getName(): String = NAME diff --git a/plugins/plugin-about-app/src/main/kotlin/com/redmadrobot/debug/plugin/aboutapp/AboutAppPluginContainer.kt b/plugins/plugin-about-app/src/main/kotlin/com/redmadrobot/debug/plugin/aboutapp/AboutAppPluginContainer.kt index 1de22b23..5c726e1d 100644 --- a/plugins/plugin-about-app/src/main/kotlin/com/redmadrobot/debug/plugin/aboutapp/AboutAppPluginContainer.kt +++ b/plugins/plugin-about-app/src/main/kotlin/com/redmadrobot/debug/plugin/aboutapp/AboutAppPluginContainer.kt @@ -5,9 +5,9 @@ import com.redmadrobot.debug.plugin.aboutapp.model.AboutAppInfo import com.redmadrobot.debug.plugin.aboutapp.ui.AboutAppViewModel internal class AboutAppPluginContainer( - private val aboutAppInfo: List + private val appInfoList: List ) : PluginDependencyContainer { fun createAboutAppViewModel(): AboutAppViewModel { - return AboutAppViewModel(aboutAppInfo = aboutAppInfo) + return AboutAppViewModel(appInfoList = appInfoList) } } diff --git a/plugins/plugin-about-app/src/main/kotlin/com/redmadrobot/debug/plugin/aboutapp/model/AboutAppInfo.kt b/plugins/plugin-about-app/src/main/kotlin/com/redmadrobot/debug/plugin/aboutapp/model/AboutAppInfo.kt index 8ac86c8b..dfee542f 100644 --- a/plugins/plugin-about-app/src/main/kotlin/com/redmadrobot/debug/plugin/aboutapp/model/AboutAppInfo.kt +++ b/plugins/plugin-about-app/src/main/kotlin/com/redmadrobot/debug/plugin/aboutapp/model/AboutAppInfo.kt @@ -1,6 +1,10 @@ package com.redmadrobot.debug.plugin.aboutapp.model +import java.util.UUID + public data class AboutAppInfo( val title: String, - val content: String -) + val value: String, +) { + val id: String = UUID.randomUUID().toString() +} diff --git a/plugins/plugin-about-app/src/main/kotlin/com/redmadrobot/debug/plugin/aboutapp/ui/AboutAppScreen.kt b/plugins/plugin-about-app/src/main/kotlin/com/redmadrobot/debug/plugin/aboutapp/ui/AboutAppScreen.kt index de9f29ed..96abe05b 100644 --- a/plugins/plugin-about-app/src/main/kotlin/com/redmadrobot/debug/plugin/aboutapp/ui/AboutAppScreen.kt +++ b/plugins/plugin-about-app/src/main/kotlin/com/redmadrobot/debug/plugin/aboutapp/ui/AboutAppScreen.kt @@ -44,10 +44,10 @@ internal fun AboutAppScreen( private fun AboutAppLayout(state: AboutAppViewState) { LazyColumn( modifier = Modifier.fillMaxSize(), - verticalArrangement = Arrangement.spacedBy(8.dp), - contentPadding = PaddingValues(horizontal = 16.dp, vertical = 16.dp), + verticalArrangement = Arrangement.spacedBy(space = 8.dp), + contentPadding = PaddingValues(all = 16.dp), ) { - items(items = state.aboutAppInfo, key = { it.title }) { item -> + items(items = state.appInfoList, key = { it.id }) { item -> AboutAppItem(item = item) } } @@ -74,7 +74,7 @@ private fun AboutAppItem(item: AboutAppInfo, modifier: Modifier = Modifier) { color = MaterialTheme.colors.primary, ) Text( - text = item.content, + text = item.value, style = MaterialTheme.typography.body1, color = MaterialTheme.colors.onSurface, maxLines = 2, @@ -89,19 +89,19 @@ private fun AboutAppItem(item: AboutAppInfo, modifier: Modifier = Modifier) { private fun Preview() { val state = remember { AboutAppViewState( - aboutAppInfo = listOf( - AboutAppInfo(title = "Версия", content = "3,14"), + appInfoList = listOf( + AboutAppInfo(title = "Версия", value = "3,14"), AboutAppInfo( title = "Номер билда", - content = "fgkdfjgkdfgjdfkgjdfkjgkdfjgkdfjgkdfjgkdjgskdjgkdgfjdsfgjdsfgdsfgjdsfgdskjfgdsjkfgdjfgdsfg" + value = "fgkdfjgkdfgjdfkgjdfkjgkdfjgkdfjgkdfjgkdjgskdjgkdgfjdsfgjdsfgdsfgjdsfgdskjfgdsjkfgdjfgdsfg" ), - AboutAppInfo(title = "Версия1", content = "3,14"), - AboutAppInfo(title = "Версия2", content = "3,14"), - AboutAppInfo(title = "Версия3", content = "3,14"), - AboutAppInfo(title = "Версия4", content = "3,14"), - AboutAppInfo(title = "Версия5", content = "3,14"), - AboutAppInfo(title = "Версия6", content = "3,14"), - AboutAppInfo(title = "Версия7", content = "3,14"), + AboutAppInfo(title = "Версия", value = "3,14"), + AboutAppInfo(title = "Версия", value = "3,14"), + AboutAppInfo(title = "Версия", value = "3,14"), + AboutAppInfo(title = "Версия", value = "3,14"), + AboutAppInfo(title = "Версия", value = "3,14"), + AboutAppInfo(title = "Версия", value = "3,14"), + AboutAppInfo(title = "Версия", value = "3,14"), ) ) } diff --git a/plugins/plugin-about-app/src/main/kotlin/com/redmadrobot/debug/plugin/aboutapp/ui/AboutAppViewModel.kt b/plugins/plugin-about-app/src/main/kotlin/com/redmadrobot/debug/plugin/aboutapp/ui/AboutAppViewModel.kt index 270e7b82..38dbf548 100644 --- a/plugins/plugin-about-app/src/main/kotlin/com/redmadrobot/debug/plugin/aboutapp/ui/AboutAppViewModel.kt +++ b/plugins/plugin-about-app/src/main/kotlin/com/redmadrobot/debug/plugin/aboutapp/ui/AboutAppViewModel.kt @@ -6,7 +6,7 @@ import kotlinx.coroutines.flow.MutableStateFlow import kotlinx.coroutines.flow.StateFlow import kotlinx.coroutines.flow.asStateFlow -internal class AboutAppViewModel(aboutAppInfo: List) : PluginViewModel() { - private val _state = MutableStateFlow(value = AboutAppViewState(aboutAppInfo = aboutAppInfo)) +internal class AboutAppViewModel(appInfoList: List) : PluginViewModel() { + private val _state = MutableStateFlow(value = AboutAppViewState(appInfoList = appInfoList)) val state: StateFlow = _state.asStateFlow() } \ No newline at end of file diff --git a/plugins/plugin-about-app/src/main/kotlin/com/redmadrobot/debug/plugin/aboutapp/ui/AboutAppViewState.kt b/plugins/plugin-about-app/src/main/kotlin/com/redmadrobot/debug/plugin/aboutapp/ui/AboutAppViewState.kt index 74cdbfca..163fbce3 100644 --- a/plugins/plugin-about-app/src/main/kotlin/com/redmadrobot/debug/plugin/aboutapp/ui/AboutAppViewState.kt +++ b/plugins/plugin-about-app/src/main/kotlin/com/redmadrobot/debug/plugin/aboutapp/ui/AboutAppViewState.kt @@ -5,5 +5,5 @@ import com.redmadrobot.debug.plugin.aboutapp.model.AboutAppInfo @Immutable internal data class AboutAppViewState( - val aboutAppInfo: List + val appInfoList: List ) diff --git a/sample/src/debug/kotlin/com/redmadrobot/debug_sample/debug_data/DebugAboutAppInfoProvider.kt b/sample/src/debug/kotlin/com/redmadrobot/debug_sample/debug_data/DebugAboutAppInfoProvider.kt index 92a22e02..64087c71 100644 --- a/sample/src/debug/kotlin/com/redmadrobot/debug_sample/debug_data/DebugAboutAppInfoProvider.kt +++ b/sample/src/debug/kotlin/com/redmadrobot/debug_sample/debug_data/DebugAboutAppInfoProvider.kt @@ -8,19 +8,19 @@ class DebugAboutAppInfoProvider { return listOf( AboutAppInfo( title = "Версия", - content = "3.14" + value = "3.14" ), AboutAppInfo( title = "Номер билда", - content = "101" + value = "101" ), AboutAppInfo( - title = "Номер билда1", - content = "fgkdfjgkdfgjdfkgjdfkjgkdfjgkdfjgkdfjgkdjgskdjgkdgfjdsfgjdsfgdsfgjdsfgdskjfgdsjkfgdjfgdsfg" + title = "Номер билда", + value = "fgkdfjgkdfgjdfkgjdfkjgkdfjgkdfjgkdfjgkdjgskdjgkdgfjdsfgjdsfgdsfgjdsfgdskjfgdsjkfgdjfgdsfg" ), AboutAppInfo( - title = "Версия2", - content = "3,14" + title = "Версия", + value = "3,145" ), ) } diff --git a/sample/src/main/kotlin/com/redmadrobot/debug_sample/App.kt b/sample/src/main/kotlin/com/redmadrobot/debug_sample/App.kt index 16443d52..65c05741 100644 --- a/sample/src/main/kotlin/com/redmadrobot/debug_sample/App.kt +++ b/sample/src/main/kotlin/com/redmadrobot/debug_sample/App.kt @@ -50,7 +50,7 @@ class App : Application() { konfeature = TestKonfeatureProvider.create(debugPanelInterceptor), ), AboutAppPlugin( - aboutAppInfo = DebugAboutAppInfoProvider.provideData() + appInfoList = DebugAboutAppInfoProvider.provideData() ) ) ) diff --git a/sample/src/release/kotlin/com/redmadrobot/debug_sample/debug_data/DebugAboutAppInfoProvider.kt b/sample/src/release/kotlin/com/redmadrobot/debug_sample/debug_data/DebugAboutAppInfoProvider.kt new file mode 100644 index 00000000..a6258ec1 --- /dev/null +++ b/sample/src/release/kotlin/com/redmadrobot/debug_sample/debug_data/DebugAboutAppInfoProvider.kt @@ -0,0 +1,11 @@ +package com.redmadrobot.debug_sample.debug_data + +import com.redmadrobot.debug.plugin.aboutapp.AboutAppInfo + +class DebugAboutAppInfoProvider { + companion object { + fun provideData(): List { + return emptyList() + } + } +} \ No newline at end of file