Skip to content

Migration to Jetpack Compose #19

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 36 commits into from
Jul 30, 2024
Merged
Show file tree
Hide file tree
Changes from 25 commits
Commits
Show all changes
36 commits
Select commit Hold shift + click to select a range
903e011
Dependencies: Add Jetpack Compose support
Sep 30, 2022
2ae9fe1
Dependencies: fix themeadapter dependency path
EmogurovAnton Jul 18, 2024
79a9e32
Base:Fix Broadcast receiver action name
Dec 6, 2022
9dba5b5
Deps:Update `common` module dependencies
Dec 8, 2022
4176edc
Core:Add 'content' and `settingsContent` composable functions for Plu…
Dec 8, 2022
e8a3d9c
Base: Migrate to view binding from 'synthetics'
Sep 24, 2023
e27f4eb
AppSettings: Add the ability to open `appsettings` plugin from Jetpac…
Dec 8, 2022
73acd38
Flipper:Add the ability to open `flipper` plugin from JetpackCompose
Dec 8, 2022
6154a48
Servers: Add the ability to open `servers` plugin from JetpackCompose
Dec 8, 2022
68a8498
Account:Migrate account plugin to Jetpack Compose
Oct 3, 2022
cfceedb
Account: fix function params
EmogurovAnton Jul 18, 2024
f179ffa
Accounts: Add the ability to open `accounts` plugin from JetpackCompose
Dec 8, 2022
83788a2
Variable:Add the ability to open `variable` plugin from JetpackCompose
Dec 8, 2022
765f9e6
Servers: Add the ability to add a stage with multiple hosts
Jan 12, 2023
e810f08
No-op: update no-op module
Jan 12, 2023
edd8e41
Servers: Migrate to Jetpack Compose UI
Jan 16, 2023
57dabbd
Sample: Update sample project
Jan 16, 2023
9435e32
Servers: Add methods to get the selected stage and the default stage
Jan 16, 2023
3c45a47
AppSettings: Migrate App-settings plugin to the Jetpack Compose
Jan 21, 2023
f45b6aa
Flipper: Migrate Flipper plugin to the Jetpack Compose
Mar 1, 2023
8d11f4d
Core: Add ability to open panel without fragment manager
EmogurovAnton Jul 18, 2024
6d2d038
Core: fix DebugBottomSheet deprecated expand state
EmogurovAnton Jul 18, 2024
dfee5ad
rebase: rebase fixes
EmogurovAnton Jul 22, 2024
6f49672
build: fix lint & compileTask
EmogurovAnton Jul 23, 2024
4cad8cc
ui: fix inflater error & debug bottom sheet state
EmogurovAnton Jul 23, 2024
ce2b6ff
review: review improves
EmogurovAnton Jul 25, 2024
722d8fa
Servers: Refactoring servers screen
Jul 26, 2024
725a1fa
Review: Fix review commits
Jul 26, 2024
9c86d83
refactoring: move bottom sheet to separate activity
EmogurovAnton Jul 26, 2024
c23629e
Accounts: Add settings content
Jul 26, 2024
0f28095
Core: Delete old DebugBottomSheet
Jul 26, 2024
a3d733b
Core: Delete getFragment from Plugin
Jul 26, 2024
f984f49
Accounts: Delete old fragment
Jul 26, 2024
9b1778a
Servers: Delete old fragment
Jul 26, 2024
af8821e
fix: Delete unused view binding
Jul 26, 2024
d9d4e79
review: minor fixes
EmogurovAnton Jul 29, 2024
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
34 changes: 24 additions & 10 deletions common/build.gradle.kts
Original file line number Diff line number Diff line change
Expand Up @@ -44,23 +44,37 @@ android {
}

dependencies {
api(kotlin("stdlib"))
api(androidx.compose.animation)
api(androidx.compose.material)
api(stack.accompanist.themeadapter.core)
api(stack.accompanist.themeadapter.material)
api(androidx.compose.material)
api(androidx.compose.foundation)
api(androidx.compose.ui)
api(androidx.compose.ui.viewbinding)
api(androidx.compose.ui.tooling)
api(androidx.fragment)
api(androidx.constraintlayout.compose)
api(androidx.activity.compose)
api(androidx.compose.ui.tooling.preview)
api(androidx.lifecycle.viewmodel.compose)
api(androidx.room.runtime)
api(androidx.room)
api(androidx.core)
api(stack.okhttp)
api(stack.kotlinx.coroutines.android)
api(stack.timber)
api(rmr.itemsadapter.viewbinding)
api(rmr.flipper)
kapt(androidx.room.compiler)
// legacy
api(androidx.appcompat)
api(stack.material)
api(androidx.constraintlayout)
api(stack.kotlinx.coroutines.android)
api(androidx.lifecycle.viewmodel)
api(androidx.lifecycle.runtime)
api(androidx.lifecycle.livedata)
api(androidx.lifecycle.livedata.core)
api(androidx.lifecycle.viewmodel)
api(androidx.room.runtime)
api(androidx.room)
api(androidx.core)
api(rmr.itemsadapter.viewbinding)
api(rmr.flipper)
api(stack.timber)
kapt(androidx.room.compiler)
}

tasks.register("prepareKotlinBuildScriptModel") {}
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,10 @@ import com.redmadrobot.debug.panel.common.R

public open class PluginFragment(private val layoutId: Int) : Fragment() {

protected val isSettingMode: Boolean by lazy {
activity?.javaClass?.simpleName == "DebugActivity"
}

override fun onCreateView(
inflater: LayoutInflater,
container: ViewGroup?,
Expand Down
2 changes: 1 addition & 1 deletion common/src/main/res/values/colors.xml
Original file line number Diff line number Diff line change
Expand Up @@ -11,5 +11,5 @@
<color name="black">#000000</color>
<color name="red">#EF0000</color>
<color name="green">#009688</color>
<color name="gray">#E1E5EA</color>
<color name="super_light_gray">#E1E5EA</color>
</resources>
1 change: 0 additions & 1 deletion common/src/main/res/values/styles.xml
Original file line number Diff line number Diff line change
Expand Up @@ -10,4 +10,3 @@
<item name="colorOnSurface">@color/colorOnSurface</item>
</style>
</resources>

5 changes: 5 additions & 0 deletions core/build.gradle.kts
Original file line number Diff line number Diff line change
Expand Up @@ -39,6 +39,11 @@ android {

buildFeatures {
viewBinding = true
compose = true
}

composeOptions {
kotlinCompilerExtensionVersion = androidx.versions.compose.compiler.get()
}
namespace = "com.redmadrobot.debug.core"
}
Expand Down
19 changes: 19 additions & 0 deletions core/src/main/kotlin/com/redmadrobot/debug/core/DebugPanel.kt
Original file line number Diff line number Diff line change
@@ -1,11 +1,16 @@
package com.redmadrobot.debug.core

import android.app.Activity
import android.app.Application
import android.view.ViewGroup
import android.widget.FrameLayout
import androidx.compose.ui.platform.ComposeView
import androidx.fragment.app.FragmentManager
import androidx.lifecycle.LifecycleOwner
import androidx.lifecycle.Observer
import com.redmadrobot.debug.core.annotation.DebugPanelInternal
import com.redmadrobot.debug.core.inapp.DebugBottomSheet
import com.redmadrobot.debug.core.inapp.compose.DebugBottomSheet
import com.redmadrobot.debug.core.plugin.Plugin
import com.redmadrobot.debug.core.util.ApplicationLifecycleHandler
import kotlinx.coroutines.flow.Flow
Expand Down Expand Up @@ -41,6 +46,20 @@ public object DebugPanel {
}
}

public fun showPanel(activity: Activity) {
if (isInitialized) {
val contentView = activity.window.decorView
.findViewById<ViewGroup>(android.R.id.content) as FrameLayout

val debugPanelComposeView = ComposeView(contentView.context).apply {
setContent {
DebugBottomSheet(onClose = { contentView.removeView(this) })
}
}
contentView.addView(debugPanelComposeView)
}
}

private fun createDebugPanelInstance(application: Application, plugins: List<Plugin>) {
instance = DebugPanelInstance(application, plugins)
}
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,46 @@
package com.redmadrobot.debug.core.extension

import androidx.compose.runtime.Composable
import androidx.compose.runtime.DisposableEffect
import androidx.compose.runtime.getValue
import androidx.compose.runtime.rememberUpdatedState
import androidx.compose.ui.platform.LocalLifecycleOwner
import androidx.lifecycle.Lifecycle
import androidx.lifecycle.LifecycleEventObserver
import androidx.lifecycle.ViewModel
import androidx.lifecycle.ViewModelProvider
import androidx.lifecycle.viewmodel.compose.viewModel
import com.redmadrobot.debug.core.annotation.DebugPanelInternal

@DebugPanelInternal
@Composable
public inline fun <reified T : ViewModel> provideViewModel(crossinline block: () -> T): T {
return viewModel(
factory = object : ViewModelProvider.Factory {
override fun <T : ViewModel> create(modelClass: Class<T>): T {
@Suppress("UNCHECKED_CAST")
return block() as T
}
}
)
}


@DebugPanelInternal
@Composable
public fun OnLifecycleEvent(onEvent: (event: Lifecycle.Event) -> Unit) {
val eventHandler by rememberUpdatedState(onEvent)
val lifecycleOwner by rememberUpdatedState(LocalLifecycleOwner.current)

DisposableEffect(lifecycleOwner) {
val lifecycle = lifecycleOwner.lifecycle
val observer = LifecycleEventObserver { _, event ->
eventHandler(event)
}

lifecycle.addObserver(observer)
onDispose {
lifecycle.removeObserver(observer)
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -40,7 +40,7 @@ internal class DebugBottomSheet : BottomSheetDialogFragment() {
setBottomSheetSize()
}
dialog.setContentView(binding.root)
setViews(binding)
binding.setViews()
return dialog
}

Expand All @@ -49,12 +49,12 @@ internal class DebugBottomSheet : BottomSheetDialogFragment() {
_binding = null
}

private fun setViews(binding: BottomSheetDebugPanelBinding) {
private fun BottomSheetDebugPanelBinding.setViews() {
val plugins = getAllPlugins()
/*Only Plugins with Fragment*/
.filter { it.getFragment() != null }

binding.debugSheetViewpager.adapter = DebugSheetViewPagerAdapter(
debugSheetViewpager.adapter = DebugSheetViewPagerAdapter(
requireActivity(),
plugins
)
Expand All @@ -64,13 +64,14 @@ internal class DebugBottomSheet : BottomSheetDialogFragment() {
}

TabLayoutMediator(
binding.debugSheetTabLayout,
binding.debugSheetViewpager,
debugSheetTabLayout,
debugSheetViewpager,
tabConfigurationStrategy
).attach()
}

private fun setBottomSheetSize() {
if (_binding == null) return
val dialogContainer = binding.root.parent as? FrameLayout
dialogContainer?.apply {
layoutParams?.height = ViewGroup.LayoutParams.MATCH_PARENT
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,7 @@ internal class ModalLayout @JvmOverloads constructor(
* Paint для отрисовки "ручки" модального окна
*/
private val handlePaint = Paint().apply {
color = ContextCompat.getColor(context, CommonR.color.gray)
color = ContextCompat.getColor(context, CommonR.color.super_light_gray)
style = Paint.Style.FILL
}

Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,119 @@
@file:OptIn(ExperimentalFoundationApi::class)

package com.redmadrobot.debug.core.inapp.compose

import androidx.appcompat.view.ContextThemeWrapper
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.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.material.ExperimentalMaterialApi
import androidx.compose.material.MaterialTheme
import androidx.compose.material.ModalBottomSheetLayout
import androidx.compose.material.ModalBottomSheetValue
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.rememberModalBottomSheetState
import androidx.compose.runtime.Composable
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.platform.LocalContext
import androidx.compose.ui.unit.dp
import com.google.accompanist.themeadapter.material.MdcTheme
import com.redmadrobot.debug.core.extension.getAllPlugins
import com.redmadrobot.debug.core.plugin.Plugin
import kotlinx.coroutines.launch
import com.redmadrobot.debug.panel.common.R as CommonR

@OptIn(ExperimentalMaterialApi::class)
@Composable
public fun DebugBottomSheet(onClose: () -> Unit) {
val state = rememberModalBottomSheetState(
initialValue = ModalBottomSheetValue.HalfExpanded,
confirmValueChange = { sheetState ->
if (sheetState == ModalBottomSheetValue.Hidden) onClose()
true
},
skipHalfExpanded = false
)

MdcTheme(context = ContextThemeWrapper(LocalContext.current, CommonR.style.DebugPanelTheme)) {
ModalBottomSheetLayout(
sheetContent = { BottomSheetContent() },
sheetState = state,
content = {}
)
}
}

@OptIn(ExperimentalFoundationApi::class)
@Composable
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))
// Handle
Box(
modifier = Modifier
.height(4.dp)
.width(50.dp)
.clip(CircleShape)
.background(Color.Gray)
.align(Alignment.CenterHorizontally)
)
Spacer(modifier = Modifier.height(8.dp))
PluginsTabLayout(pluginsName, pagerState = pagerState)
PluginsPager(plugins, pagerState = pagerState)
}
}

@Composable
private fun PluginsTabLayout(pluginsName: List<String>, pagerState: PagerState) {
val scope = rememberCoroutineScope()
ScrollableTabRow(
selectedTabIndex = pagerState.currentPage,
backgroundColor = MaterialTheme.colors.background,
indicator = { tabPositions ->
TabRowDefaults.Indicator(
modifier = Modifier.tabIndicatorOffset(tabPositions[pagerState.currentPage]),
height = 2.dp,
color = MaterialTheme.colors.secondary
)
}
) {
pluginsName.forEachIndexed { index, _ ->
Tab(
text = { Text(pluginsName[index]) },
selected = pagerState.currentPage == index,
onClick = {
scope.launch { pagerState.animateScrollToPage(index) }
}
)
}
}
}

@Composable
private fun PluginsPager(plugins: List<Plugin>, pagerState: PagerState) {
plugins[pagerState.currentPage].content()
HorizontalPager(state = pagerState) {
// no impl. Temporary solution
}
}
18 changes: 18 additions & 0 deletions core/src/main/kotlin/com/redmadrobot/debug/core/plugin/Plugin.kt
Original file line number Diff line number Diff line change
@@ -1,5 +1,7 @@
package com.redmadrobot.debug.core.plugin

import androidx.compose.runtime.Composable
import androidx.compose.ui.viewinterop.AndroidViewBinding
import androidx.fragment.app.Fragment
import com.redmadrobot.debug.core.DebugEvent
import com.redmadrobot.debug.core.DebugPanelInstance
Expand All @@ -21,10 +23,26 @@ public abstract class Plugin {

public fun <T> getContainer(): T = pluginContainer as T

@Deprecated(
"You shouldn't use fragments for you plugins. Please use Jetpack Compose",
ReplaceWith("content()", "com.redmadrobot.debug.core.plugin.Plugin")
)
public open fun getFragment(): Fragment? = null

@Deprecated(
"You shouldn't use fragments for you plugins. Please use Jetpack Compose",
ReplaceWith("content()", "com.redmadrobot.debug.core.plugin.Plugin")
)
public open fun getSettingFragment(): Fragment? = null

@Composable
public open fun content() {
}

@Composable
public open fun settingsContent() {
}

public abstract fun getPluginContainer(commonContainer: CommonContainer): PluginDependencyContainer

public abstract fun getName(): String
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -11,8 +11,7 @@ internal class DebugPanelBroadcastReceiver(
) : BroadcastReceiver() {

companion object {
const val ACTION_OPEN_DEBUG_PANEL =
"com.redmadrobot.debug_panel_core.ACTION_OPEN_DEBUG_PANEL"
const val ACTION_OPEN_DEBUG_PANEL = "com.redmadrobot.debug.core.ACTION_OPEN_DEBUG_PANEL"
}

override fun onReceive(context: Context, intent: Intent) {
Expand Down
Loading
Loading