Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 2 additions & 0 deletions panel-core/build.gradle.kts
Original file line number Diff line number Diff line change
Expand Up @@ -58,5 +58,7 @@ dependencies {
implementation(stack.timber)
implementation(stack.material)

implementation(stack.kotlinx.collections.immutable)

api(androidx.lifecycle.viewmodel)
}
Original file line number Diff line number Diff line change
Expand Up @@ -3,102 +3,183 @@
package com.redmadrobot.debug.core.inapp.compose

import androidx.compose.foundation.ExperimentalFoundationApi
import androidx.compose.foundation.background
import androidx.compose.foundation.layout.Column
import androidx.compose.foundation.layout.Row
import androidx.compose.foundation.layout.fillMaxSize
import androidx.compose.foundation.layout.fillMaxWidth
import androidx.compose.foundation.layout.heightIn
import androidx.compose.foundation.layout.padding
import androidx.compose.foundation.layout.size
import androidx.compose.foundation.pager.HorizontalPager
import androidx.compose.foundation.pager.PagerState
import androidx.compose.foundation.pager.rememberPagerState
import androidx.compose.material.Icon
import androidx.compose.material.IconButton
import androidx.compose.material.MaterialTheme
import androidx.compose.material.Scaffold
import androidx.compose.material.ScrollableTabRow
import androidx.compose.material.Tab
import androidx.compose.material.TabRowDefaults
import androidx.compose.material.TabRowDefaults.tabIndicatorOffset
import androidx.compose.material.Text
import androidx.compose.material.TopAppBar
import androidx.compose.material3.ExperimentalMaterial3Api
import androidx.compose.material3.Icon
import androidx.compose.material3.IconButton
import androidx.compose.material3.SecondaryScrollableTabRow
import androidx.compose.material3.Tab
import androidx.compose.material3.TabRowDefaults
import androidx.compose.material3.Text
import androidx.compose.runtime.Composable
import androidx.compose.runtime.key
import androidx.compose.runtime.remember
import androidx.compose.runtime.rememberCoroutineScope
import androidx.compose.ui.Alignment
import androidx.compose.ui.Modifier
import androidx.compose.ui.res.painterResource
import androidx.compose.ui.res.stringResource
import androidx.compose.ui.unit.dp
import com.redmadrobot.debug.core.R
import com.redmadrobot.debug.core.extension.getAllPlugins
import com.redmadrobot.debug.core.plugin.Plugin
import com.redmadrobot.debug.uikit.components.ThemeSwitcher
import com.redmadrobot.debug.uikit.theme.DebugPanelDimensions
import com.redmadrobot.debug.uikit.theme.DebugPanelTheme
import com.redmadrobot.debug.uikit.theme.model.ThemeMode
import kotlinx.collections.immutable.ImmutableList
import kotlinx.collections.immutable.toImmutableList
import kotlinx.coroutines.launch

@Suppress("UnusedParameter")
@Composable
public fun DebugPanelScreen(
themeMode: ThemeMode,
onThemeModeChange: (ThemeMode) -> Unit,
onClose: () -> Unit,
onThemeModeChange: (ThemeMode) -> Unit = {}
) {
val plugins = remember { getAllPlugins() }
val pluginsName = remember { plugins.map { it.getName() } }
val pluginNames = remember { plugins.map { it.getName() } }
val pagerState = rememberPagerState(initialPage = 0, pageCount = { plugins.size })
val scope = rememberCoroutineScope()

Scaffold(
topBar = {
TopAppBar(
title = { Text(text = stringResource(R.string.debug_panel)) },
navigationIcon = {
IconButton(onClick = onClose) {
Icon(
painter = painterResource(id = R.drawable.ic_arrow_back),
contentDescription = null,
)
}
},
backgroundColor = MaterialTheme.colors.background,
elevation = 0.dp,
)
},
) { paddingValues ->
Column(modifier = Modifier.padding(paddingValues)) {
PluginsTabLayout(pluginsName = pluginsName, pagerState = pagerState)
PluginsPager(plugins = plugins, pagerState = pagerState)
Column(
modifier = Modifier
.fillMaxSize()
.background(color = DebugPanelTheme.colors.background.primary),
) {
PanelTopBar(
themeMode = themeMode,
onThemeModeChange = onThemeModeChange,
onClose = onClose,
)
PanelTabRow(
pluginNames = pluginNames.toImmutableList(),
selectedIndex = pagerState.currentPage,
onTabClick = { index -> scope.launch { pagerState.animateScrollToPage(index) } },
)
HorizontalPager(state = pagerState, modifier = Modifier.weight(weight = 1f)) { page ->
plugins[page].content()
}
}
}

@Composable
private fun PluginsTabLayout(pluginsName: List<String>, pagerState: PagerState) {
val scope = rememberCoroutineScope()
private fun PanelTopBar(
themeMode: ThemeMode,
onThemeModeChange: (ThemeMode) -> Unit,
onClose: () -> Unit,
modifier: Modifier = Modifier
) {
Row(
modifier = modifier
.fillMaxWidth()
.heightIn(min = DebugPanelDimensions.topBarHeight)
.padding(horizontal = 8.dp),
verticalAlignment = Alignment.CenterVertically,
) {
Text(
text = stringResource(id = R.string.debug_panel),
style = DebugPanelTheme.typography.titleLarge,
color = DebugPanelTheme.colors.content.primary,
modifier = Modifier
.weight(weight = 1f)
.padding(start = 4.dp),
)
ThemeSwitcher(
currentMode = themeMode,
onModeSelect = onThemeModeChange,
)
IconButton(onClick = onClose) {
Icon(
painter = painterResource(id = R.drawable.ic_arrow_back),
contentDescription = null,
tint = DebugPanelTheme.colors.content.secondary,
modifier = Modifier.size(size = DebugPanelDimensions.iconSizeMedium),
)
}
}
}

ScrollableTabRow(
selectedTabIndex = pagerState.currentPage,
backgroundColor = MaterialTheme.colors.background,
edgePadding = 16.dp,
indicator = { tabPositions ->
TabRowDefaults.Indicator(
@OptIn(ExperimentalMaterial3Api::class)
@Composable
private fun PanelTabRow(
pluginNames: ImmutableList<String>,
selectedIndex: Int,
onTabClick: (Int) -> Unit,
modifier: Modifier = Modifier
) {
SecondaryScrollableTabRow(
selectedTabIndex = selectedIndex,
modifier = modifier
.fillMaxWidth()
.heightIn(min = DebugPanelDimensions.tabRowHeight)
.background(color = DebugPanelTheme.colors.surface.secondary),
edgePadding = 4.dp,
containerColor = DebugPanelTheme.colors.surface.secondary,
contentColor = DebugPanelTheme.colors.content.secondary,
indicator = {
TabRowDefaults.SecondaryIndicator(
modifier = Modifier.tabIndicatorOffset(
currentTabPosition = tabPositions[pagerState.currentPage]
selectedTabIndex = selectedIndex,
matchContentSize = false,
),
height = 2.dp,
color = MaterialTheme.colors.secondary
color = DebugPanelTheme.colors.content.accent,
)
}
},
divider = {},
) {
pluginsName.forEachIndexed { index, _ ->
Tab(
text = { Text(text = pluginsName[index]) },
selected = pagerState.currentPage == index,
onClick = {
scope.launch { pagerState.animateScrollToPage(index) }
}
)
pluginNames.forEachIndexed { index, title ->
key(title) {
PluginTab(
isSelected = selectedIndex == index,
title = title,
onTabClick = { onTabClick(index) }
)
}
}
}
}

@Composable
private fun PluginsPager(plugins: List<Plugin>, pagerState: PagerState) {
HorizontalPager(state = pagerState) { page ->
plugins[page].content()
private fun PluginTab(
title: String,
isSelected: Boolean,
onTabClick: () -> Unit,
modifier: Modifier = Modifier
) {
Tab(
modifier = modifier.padding(horizontal = 4.dp),
selected = isSelected,
onClick = { onTabClick.invoke() },
text = { PluginTabTitle(title = title, isSelected = isSelected) },
)
}

@Composable
private fun PluginTabTitle(
title: String,
isSelected: Boolean,
modifier: Modifier = Modifier
) {
val titleColor = if (isSelected) {
DebugPanelTheme.colors.content.accent
} else {
DebugPanelTheme.colors.content.secondary
}

Text(
modifier = modifier,
text = title,
style = DebugPanelTheme.typography.labelLarge,
color = titleColor,
)
}
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@ import com.redmadrobot.debug.core.DebugPanel
import com.redmadrobot.debug.core.extension.getAllPlugins
import com.redmadrobot.debug.core.internal.EditablePlugin
import com.redmadrobot.debug.uikit.theme.DebugPanelTheme
import kotlinx.collections.immutable.toImmutableList

internal class DebugSettingsActivity : AppCompatActivity() {
override fun onCreate(savedInstanceState: Bundle?) {
Expand All @@ -26,7 +27,7 @@ internal class DebugSettingsActivity : AppCompatActivity() {
val pluginItems = remember { getSettingItems() }
DebugSettingsNavHost(
navController = navController,
pluginItems = pluginItems,
pluginItems = pluginItems.toImmutableList(),
)
}
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -6,17 +6,21 @@ import androidx.navigation.compose.NavHost
import androidx.navigation.compose.composable
import com.redmadrobot.debug.core.extension.getPlugin
import com.redmadrobot.debug.core.internal.EditablePlugin
import kotlinx.collections.immutable.ImmutableList

private const val MAIN_SCREEN_ROUTE = "main"

@Composable
internal fun DebugSettingsNavHost(
navController: NavHostController,
pluginItems: List<PluginSettingsItem>,
pluginItems: ImmutableList<PluginSettingsItem>,
) {
NavHost(navController = navController, startDestination = MAIN_SCREEN_ROUTE) {
composable(MAIN_SCREEN_ROUTE) {
DebugSettingsScreen(pluginItems = pluginItems, navController = navController)
DebugSettingsScreen(
pluginItems = pluginItems,
navController = navController
)
}

pluginItems.forEach { plugin ->
Expand Down
Original file line number Diff line number Diff line change
@@ -1,26 +1,30 @@
package com.redmadrobot.debug.core.ui.settings

import androidx.compose.foundation.background
import androidx.compose.foundation.clickable
import androidx.compose.foundation.layout.fillMaxSize
import androidx.compose.foundation.layout.padding
import androidx.compose.foundation.lazy.LazyColumn
import androidx.compose.foundation.lazy.items
import androidx.compose.material.Text
import androidx.compose.material3.Text
import androidx.compose.runtime.Composable
import androidx.compose.ui.Modifier
import androidx.compose.ui.unit.dp
import androidx.compose.ui.unit.sp
import androidx.navigation.NavController
import com.redmadrobot.debug.uikit.theme.DebugPanelTheme
import kotlinx.collections.immutable.ImmutableList

@Composable
internal fun DebugSettingsScreen(
navController: NavController,
pluginItems: List<PluginSettingsItem>,
pluginItems: ImmutableList<PluginSettingsItem>,
) {
LazyColumn(
modifier = Modifier.fillMaxSize(),
modifier = Modifier
.fillMaxSize()
.background(color = DebugPanelTheme.colors.background.primary),
) {
items(pluginItems) { item ->
items(items = pluginItems, key = { it.pluginName }) { item ->
PluginItem(
pluginName = item.pluginName,
onClick = { navController.navigate(item.pluginClassName) },
Expand All @@ -30,13 +34,14 @@ internal fun DebugSettingsScreen(
}

@Composable
private fun PluginItem(pluginName: String, onClick: () -> Unit) {
private fun PluginItem(pluginName: String, onClick: () -> Unit, modifier: Modifier = Modifier) {
Text(
modifier = Modifier
modifier = modifier
.fillMaxSize()
.clickable { onClick.invoke() }
.padding(horizontal = 16.dp, vertical = 16.dp),
.padding(all = 16.dp),
text = pluginName,
fontSize = 18.sp,
style = DebugPanelTheme.typography.titleMedium,
color = DebugPanelTheme.colors.content.primary,
)
}
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,7 @@ public class AboutAppPlugin(
}

override fun getPluginContainer(commonContainer: CommonContainer): PluginDependencyContainer {
return AboutAppPluginContainer(appInfoList = appInfoList)
return AboutAppPluginContainer(appInfoList = appInfoList, commonContainer = commonContainer)
}

override fun getName(): String = NAME
Expand Down
Original file line number Diff line number Diff line change
@@ -1,13 +1,18 @@
package com.redmadrobot.debug.plugin.aboutapp

import com.redmadrobot.debug.core.internal.CommonContainer
import com.redmadrobot.debug.core.internal.PluginDependencyContainer
import com.redmadrobot.debug.plugin.aboutapp.model.AboutAppInfo
import com.redmadrobot.debug.plugin.aboutapp.ui.AboutAppViewModel
import com.redmadrobot.debug.plugin.aboutapp.utils.ClipboardProvider

internal class AboutAppPluginContainer(
private val appInfoList: List<AboutAppInfo>
private val appInfoList: List<AboutAppInfo>,
private val commonContainer: CommonContainer
) : PluginDependencyContainer {
fun createAboutAppViewModel(): AboutAppViewModel {
return AboutAppViewModel(appInfoList = appInfoList)
val clipboardProvider = ClipboardProvider(context = commonContainer.context)

return AboutAppViewModel(appInfoList = appInfoList, clipboardProvider = clipboardProvider)
}
}
Loading
Loading