Skip to content

Commit

Permalink
[Ui] Debug Screen
Browse files Browse the repository at this point in the history
  • Loading branch information
ajou4095 committed Jul 28, 2024
1 parent 7408657 commit 02830c3
Show file tree
Hide file tree
Showing 10 changed files with 298 additions and 9 deletions.
20 changes: 20 additions & 0 deletions presentation/src/debug/AndroidManifest.xml
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools">

<application>
<activity
android:name=".ui.main.DebugMainActivity"
android:exported="true">
<intent-filter>
<action android:name="android.intent.action.MAIN" />

<category android:name="android.intent.category.LAUNCHER" />
</intent-filter>
</activity>

<activity
android:name=".ui.main.MainActivity"
tools:node="remove" />
</application>
</manifest>
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
package com.ray.template.android.presentation.ui.main

import android.os.Bundle
import androidx.activity.compose.setContent
import androidx.appcompat.app.AppCompatActivity
import dagger.hilt.android.AndroidEntryPoint

@AndroidEntryPoint
class DebugMainActivity : AppCompatActivity() {
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContent {
DebugMainScreen()
}
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,81 @@
package com.ray.template.android.presentation.ui.main

import androidx.compose.foundation.gestures.detectDragGestures
import androidx.compose.foundation.layout.offset
import androidx.compose.foundation.layout.size
import androidx.compose.material3.Icon
import androidx.compose.runtime.Composable
import androidx.compose.runtime.getValue
import androidx.compose.runtime.mutableFloatStateOf
import androidx.compose.runtime.remember
import androidx.compose.runtime.setValue
import androidx.compose.ui.Modifier
import androidx.compose.ui.graphics.Color.Companion.Blue
import androidx.compose.ui.input.pointer.pointerInput
import androidx.compose.ui.res.painterResource
import androidx.compose.ui.unit.IntOffset
import androidx.hilt.navigation.compose.hiltViewModel
import androidx.navigation.NavController
import androidx.navigation.compose.NavHost
import androidx.navigation.compose.rememberNavController
import com.ray.template.android.presentation.R
import com.ray.template.android.presentation.common.theme.Space40
import com.ray.template.android.presentation.common.theme.TemplateTheme
import com.ray.template.android.presentation.common.util.compose.ErrorObserver
import com.ray.template.android.presentation.common.util.compose.safeNavigate
import com.ray.template.android.presentation.common.view.RippleBox
import com.ray.template.android.presentation.ui.main.debug.DebugConstant
import com.ray.template.android.presentation.ui.main.debug.debugDestination
import com.ray.template.android.presentation.ui.main.splash.SplashConstant
import kotlin.math.roundToInt

@Composable
fun DebugMainScreen(
viewModel: MainViewModel = hiltViewModel()
) {
TemplateTheme {
val navController = rememberNavController()

NavHost(
navController = navController,
startDestination = SplashConstant.ROUTE
) {
mainDestination(navController)
debugDestination(navController)
}

ErrorObserver(viewModel)
MainScreenRefreshFailDialog(navController, viewModel.refreshFailEvent)
DebugPopup(navController)
}
}

@Composable
private fun DebugPopup(
navController: NavController
) {
var offsetX by remember { mutableFloatStateOf(0f) }
var offsetY by remember { mutableFloatStateOf(0f) }

RippleBox(
modifier = Modifier
.offset { IntOffset(offsetX.roundToInt(), offsetY.roundToInt()) }
.pointerInput(Unit) {
detectDragGestures { change, dragAmount ->
change.consume()
offsetX += dragAmount.x
offsetY += dragAmount.y
}
},
onClick = {
navController.safeNavigate(DebugConstant.ROUTE)
}
) {
Icon(
modifier = Modifier.size(Space40),
painter = painterResource(R.drawable.ic_more_vertical),
contentDescription = null,
tint = Blue
)
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
package com.ray.template.android.presentation.ui.main.debug

import androidx.compose.runtime.Immutable
import com.ray.template.android.common.util.coroutine.event.EventFlow
import kotlinx.coroutines.CoroutineExceptionHandler

@Immutable
data class DebugArgument(
val state: DebugState,
val event: EventFlow<DebugEvent>,
val intent: (DebugIntent) -> Unit,
val logEvent: (eventName: String, params: Map<String, Any>) -> Unit,
val handler: CoroutineExceptionHandler
)

sealed interface DebugState {
data object Init : DebugState
}


sealed interface DebugEvent

sealed interface DebugIntent
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
package com.ray.template.android.presentation.ui.main.debug

object DebugConstant {
const val ROUTE = "debug"
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,37 @@
package com.ray.template.android.presentation.ui.main.debug

import androidx.compose.runtime.getValue
import androidx.hilt.navigation.compose.hiltViewModel
import androidx.lifecycle.compose.collectAsStateWithLifecycle
import androidx.navigation.NavController
import androidx.navigation.NavGraphBuilder
import androidx.navigation.compose.composable
import com.ray.template.android.presentation.common.util.compose.ErrorObserver

fun NavGraphBuilder.debugDestination(
navController: NavController
) {
composable(
route = DebugConstant.ROUTE
) {
val viewModel: DebugViewModel = hiltViewModel()

val argument: DebugArgument = let {
val state by viewModel.state.collectAsStateWithLifecycle()

DebugArgument(
state = state,
event = viewModel.event,
intent = viewModel::onIntent,
logEvent = viewModel::logEvent,
handler = viewModel.handler
)
}

ErrorObserver(viewModel)
DebugScreen(
navController = navController,
argument = argument
)
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,63 @@
package com.ray.template.android.presentation.ui.main.debug

import androidx.compose.foundation.layout.Arrangement
import androidx.compose.foundation.layout.Column
import androidx.compose.foundation.layout.fillMaxSize
import androidx.compose.material3.Text
import androidx.compose.runtime.Composable
import androidx.compose.runtime.rememberCoroutineScope
import androidx.compose.ui.Alignment
import androidx.compose.ui.Modifier
import androidx.compose.ui.platform.LocalContext
import androidx.compose.ui.tooling.preview.Preview
import androidx.navigation.NavController
import androidx.navigation.compose.rememberNavController
import com.ray.template.android.common.util.coroutine.event.MutableEventFlow
import com.ray.template.android.common.util.coroutine.event.eventObserve
import com.ray.template.android.presentation.common.theme.Gray900
import com.ray.template.android.presentation.common.theme.Headline0
import com.ray.template.android.presentation.common.util.compose.LaunchedEffectWithLifecycle
import kotlinx.coroutines.CoroutineExceptionHandler
import kotlinx.coroutines.plus

@Composable
fun DebugScreen(
navController: NavController,
argument: DebugArgument,
) {
val (state, event, intent, logEvent, handler) = argument
val scope = rememberCoroutineScope() + handler
val context = LocalContext.current

Column(
modifier = Modifier.fillMaxSize(),
horizontalAlignment = Alignment.CenterHorizontally,
verticalArrangement = Arrangement.Center
) {
Text(
text = "Debug Page",
style = Headline0.merge(Gray900)
)
}

LaunchedEffectWithLifecycle(event, handler) {
event.eventObserve { event ->

}
}
}

@Preview
@Composable
private fun DebugScreenPreview() {
DebugScreen(
navController = rememberNavController(),
argument = DebugArgument(
state = DebugState.Init,
event = MutableEventFlow(),
intent = {},
logEvent = { _, _ -> },
handler = CoroutineExceptionHandler { _, _ -> }
)
)
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,34 @@
package com.ray.template.android.presentation.ui.main.debug

import androidx.lifecycle.SavedStateHandle
import com.ray.template.android.common.util.coroutine.event.EventFlow
import com.ray.template.android.common.util.coroutine.event.MutableEventFlow
import com.ray.template.android.common.util.coroutine.event.asEventFlow
import com.ray.template.android.presentation.common.base.BaseViewModel
import dagger.hilt.android.lifecycle.HiltViewModel
import javax.inject.Inject
import kotlinx.coroutines.flow.MutableStateFlow
import kotlinx.coroutines.flow.StateFlow
import kotlinx.coroutines.flow.asStateFlow

@HiltViewModel
class DebugViewModel @Inject constructor(
private val savedStateHandle: SavedStateHandle
) : BaseViewModel() {

private val _state: MutableStateFlow<DebugState> = MutableStateFlow(DebugState.Init)
val state: StateFlow<DebugState> = _state.asStateFlow()

private val _event: MutableEventFlow<DebugEvent> = MutableEventFlow()
val event: EventFlow<DebugEvent> = _event.asEventFlow()

init {
launch {

}
}

fun onIntent(intent: DebugIntent) {

}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
package com.ray.template.android.presentation.ui.main

import androidx.navigation.NavController
import androidx.navigation.NavGraphBuilder
import com.ray.template.android.presentation.ui.main.home.homeDestination
import com.ray.template.android.presentation.ui.main.nonlogin.nonLoginNavGraphNavGraph
import com.ray.template.android.presentation.ui.main.splash.splashDestination

fun NavGraphBuilder.mainDestination(
navController: NavController
) {
splashDestination(navController = navController)
nonLoginNavGraphNavGraph(navController = navController)
homeDestination(navController = navController)
}
Original file line number Diff line number Diff line change
Expand Up @@ -18,10 +18,7 @@ import com.ray.template.android.presentation.common.util.compose.ErrorObserver
import com.ray.template.android.presentation.common.util.compose.LaunchedEffectWithLifecycle
import com.ray.template.android.presentation.common.util.compose.safeNavigate
import com.ray.template.android.presentation.common.view.DialogScreen
import com.ray.template.android.presentation.ui.main.home.homeDestination
import com.ray.template.android.presentation.ui.main.nonlogin.nonLoginNavGraphNavGraph
import com.ray.template.android.presentation.ui.main.splash.SplashConstant
import com.ray.template.android.presentation.ui.main.splash.splashDestination

@Composable
fun MainScreen(
Expand All @@ -30,17 +27,15 @@ fun MainScreen(
TemplateTheme {
val navController = rememberNavController()

ErrorObserver(viewModel)
MainScreenRefreshFailDialog(navController, viewModel.refreshFailEvent)

NavHost(
navController = navController,
startDestination = SplashConstant.ROUTE
) {
splashDestination(navController = navController)
nonLoginNavGraphNavGraph(navController = navController)
homeDestination(navController = navController)
mainDestination(navController)
}

ErrorObserver(viewModel)
MainScreenRefreshFailDialog(navController, viewModel.refreshFailEvent)
}
}

Expand Down

0 comments on commit 02830c3

Please sign in to comment.