expo-dev-menu 7.0.5 → 7.0.6

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (39) hide show
  1. package/CHANGELOG.md +4 -0
  2. package/android/build.gradle +3 -3
  3. package/android/src/main/java/expo/modules/devmenu/compose/BindingView.kt +14 -15
  4. package/android/src/main/java/expo/modules/devmenu/compose/DevMenuAction.kt +2 -2
  5. package/android/src/main/java/expo/modules/devmenu/compose/newtheme/Colors.kt +22 -0
  6. package/android/src/main/java/expo/modules/devmenu/compose/primitives/AppIcon.kt +1 -2
  7. package/android/src/main/java/expo/modules/devmenu/compose/primitives/Divider.kt +2 -2
  8. package/android/src/main/java/expo/modules/devmenu/compose/primitives/Spacer.kt +2 -2
  9. package/android/src/main/java/expo/modules/devmenu/compose/primitives/Surface.kt +4 -4
  10. package/android/src/main/java/expo/modules/devmenu/compose/primitives/Text.kt +0 -119
  11. package/android/src/main/java/expo/modules/devmenu/compose/primitives/ToggleSwitch.kt +1 -2
  12. package/android/src/main/java/expo/modules/devmenu/compose/ripple/RippleFactory.kt +1 -1
  13. package/android/src/main/java/expo/modules/devmenu/compose/ui/AppInfo.kt +7 -13
  14. package/android/src/main/java/expo/modules/devmenu/compose/{BottomSheet.kt → ui/BottomSheetScaffold.kt} +11 -5
  15. package/android/src/main/java/expo/modules/devmenu/compose/ui/BundlerInfo.kt +3 -11
  16. package/android/src/main/java/expo/modules/devmenu/compose/ui/DevMenuBottomSheet.kt +78 -0
  17. package/android/src/main/java/expo/modules/devmenu/compose/ui/DevMenuScreen.kt +94 -0
  18. package/android/src/main/java/expo/modules/devmenu/compose/ui/Icons.kt +172 -0
  19. package/android/src/main/java/expo/modules/devmenu/compose/ui/MenuButton.kt +0 -82
  20. package/android/src/main/java/expo/modules/devmenu/compose/ui/Onboarding.kt +21 -16
  21. package/android/src/main/java/expo/modules/devmenu/compose/ui/QuickAction.kt +27 -0
  22. package/android/src/main/java/expo/modules/devmenu/compose/ui/Section.kt +39 -0
  23. package/android/src/main/java/expo/modules/devmenu/compose/ui/SystemSection.kt +93 -0
  24. package/android/src/main/java/expo/modules/devmenu/compose/ui/ToolsSection.kt +137 -0
  25. package/android/src/main/java/expo/modules/devmenu/compose/ui/Warning.kt +5 -10
  26. package/android/src/main/java/expo/modules/devmenu/compose/utils/IsRunningInPreview.kt +5 -0
  27. package/android/src/main/java/expo/modules/devmenu/fab/FloatingActionButtonContent.kt +13 -10
  28. package/package.json +3 -3
  29. package/android/src/main/java/expo/modules/devmenu/compose/DevMenuScreen.kt +0 -432
  30. package/android/src/main/java/expo/modules/devmenu/compose/primitives/DayNightIcon.kt +0 -36
  31. package/android/src/main/java/expo/modules/devmenu/compose/primitives/RowLayout.kt +0 -34
  32. package/android/src/main/java/expo/modules/devmenu/compose/theme/Colors.kt +0 -283
  33. package/android/src/main/java/expo/modules/devmenu/compose/theme/Pallet.kt +0 -250
  34. package/android/src/main/java/expo/modules/devmenu/compose/theme/Sizing.kt +0 -37
  35. package/android/src/main/java/expo/modules/devmenu/compose/theme/Spacing.kt +0 -58
  36. package/android/src/main/java/expo/modules/devmenu/compose/theme/Theme.kt +0 -72
  37. package/android/src/main/java/expo/modules/devmenu/compose/theme/Typography.kt +0 -73
  38. package/android/src/main/java/expo/modules/devmenu/compose/ui/MenuInfo.kt +0 -38
  39. package/android/src/main/java/expo/modules/devmenu/compose/ui/MenuSwitch.kt +0 -105
package/CHANGELOG.md CHANGED
@@ -10,6 +10,10 @@
10
10
 
11
11
  ### 💡 Others
12
12
 
13
+ ## 7.0.6 — 2025-08-28
14
+
15
+ _This version does not introduce any user-facing changes._
16
+
13
17
  ## 7.0.5 — 2025-08-27
14
18
 
15
19
  _This version does not introduce any user-facing changes._
@@ -12,7 +12,7 @@ apply plugin: 'expo-module-gradle-plugin'
12
12
  apply plugin: 'org.jetbrains.kotlin.plugin.compose'
13
13
 
14
14
  group = 'host.exp.exponent'
15
- version = '7.0.5'
15
+ version = '7.0.6'
16
16
 
17
17
  expoModule {
18
18
  canBePublished false
@@ -22,7 +22,7 @@ android {
22
22
  namespace "expo.modules.devmenu"
23
23
  defaultConfig {
24
24
  versionCode 10
25
- versionName '7.0.5'
25
+ versionName '7.0.6'
26
26
  }
27
27
  buildFeatures {
28
28
  compose true
@@ -77,7 +77,7 @@ dependencies {
77
77
 
78
78
  implementation("com.composables:core:1.37.0")
79
79
 
80
- implementation 'io.github.lukmccall:radix-ui-colors:1.0.1'
80
+ api 'io.github.lukmccall:radix-ui-colors:1.0.1'
81
81
 
82
82
  // Needed by gesture handler
83
83
  implementation "androidx.core:core-ktx:1.6.0"
@@ -6,7 +6,8 @@ import android.content.Context
6
6
  import android.widget.LinearLayout
7
7
  import androidx.compose.ui.platform.ComposeView
8
8
  import expo.modules.devmenu.DevMenuManager
9
- import expo.modules.devmenu.compose.theme.AppTheme
9
+ import expo.modules.devmenu.compose.newtheme.AppTheme
10
+ import expo.modules.devmenu.compose.ui.DevMenuBottomSheet
10
11
  import expo.modules.devmenu.fab.MovableFloatingActionButton
11
12
 
12
13
  @SuppressLint("ViewConstructor")
@@ -18,20 +19,18 @@ class BindingView(context: Context, lazyViewModel: Lazy<DevMenuViewModel>) : Lin
18
19
  addView(
19
20
  ComposeView(context).apply {
20
21
  setContent {
21
- expo.modules.devmenu.compose.newtheme.AppTheme {
22
- AppTheme {
23
- DevMenuScreen(viewModel.state, viewModel::onAction)
24
- MovableFloatingActionButton(
25
- state = viewModel.state,
26
- onRefreshPress = {
27
- lazyViewModel.value.onAction(DevMenuAction.Reload)
28
- },
29
- onOpenMenuPress = {
30
- // TODO: @behenate For some reason doing onAction(DevMenuAction.Open) only works after a first refresh / opening the menu for the first time
31
- DevMenuManager.openMenu(context as Activity)
32
- }
33
- )
34
- }
22
+ AppTheme {
23
+ DevMenuBottomSheet(viewModel.state, viewModel::onAction)
24
+ MovableFloatingActionButton(
25
+ state = viewModel.state,
26
+ onRefreshPress = {
27
+ lazyViewModel.value.onAction(DevMenuAction.Reload)
28
+ },
29
+ onOpenMenuPress = {
30
+ // TODO: @behenate For some reason doing onAction(DevMenuAction.Open) only works after a first refresh / opening the menu for the first time
31
+ DevMenuManager.openMenu(context as Activity)
32
+ }
33
+ )
35
34
  }
36
35
  }
37
36
  }
@@ -7,9 +7,9 @@ sealed class DevMenuAction(val shouldCloseMenu: Boolean = false) {
7
7
  object GoHome : DevMenuAction(shouldCloseMenu = true)
8
8
  object TogglePerformanceMonitor : DevMenuAction(shouldCloseMenu = true)
9
9
  object ToggleElementInspector : DevMenuAction(shouldCloseMenu = true)
10
- object ToggleFab : DevMenuAction(shouldCloseMenu = true)
10
+ object ToggleFab : DevMenuAction(shouldCloseMenu = false)
11
11
  object OpenJSDebugger : DevMenuAction(shouldCloseMenu = true)
12
- data class ToggleFastRefresh(val newValue: Boolean) : DevMenuAction(shouldCloseMenu = true)
12
+ data class ToggleFastRefresh(val newValue: Boolean) : DevMenuAction(shouldCloseMenu = false)
13
13
  object OpenReactNativeDevMenu : DevMenuAction(shouldCloseMenu = true)
14
14
  object FinishOnboarding : DevMenuAction(shouldCloseMenu = false)
15
15
  }
@@ -61,6 +61,28 @@ class Colors(private val pallet: RadixPallet<Color>) {
61
61
  pallet.blue.`10`
62
62
  }
63
63
  )
64
+
65
+ val secondary = Button(
66
+ foreground = if (pallet.isDark) {
67
+ Color.White
68
+ } else {
69
+ pallet.gray.`12`
70
+ },
71
+ background = if (pallet.isDark) {
72
+ pallet.gray.`3`
73
+ } else {
74
+ Color.White
75
+ }
76
+ )
77
+
78
+ val tertiary = Button(
79
+ foreground = if (pallet.isDark) {
80
+ pallet.blue.`11`
81
+ } else {
82
+ pallet.blue.`10`
83
+ },
84
+ background = Color.Transparent
85
+ )
64
86
  }
65
87
 
66
88
  val text = Text()
@@ -20,8 +20,7 @@ import androidx.compose.ui.unit.Dp
20
20
  import androidx.compose.ui.unit.dp
21
21
  import androidx.core.graphics.drawable.toBitmap
22
22
  import expo.modules.devmenu.compose.newtheme.NewAppTheme
23
-
24
- private val IsRunningInPreview = Build.DEVICE == "layoutlib"
23
+ import expo.modules.devmenu.compose.utils.IsRunningInPreview
25
24
 
26
25
  @Composable
27
26
  fun AppIcon(
@@ -8,12 +8,12 @@ import androidx.compose.ui.Modifier
8
8
  import androidx.compose.ui.geometry.Offset
9
9
  import androidx.compose.ui.graphics.Color
10
10
  import androidx.compose.ui.unit.Dp
11
- import expo.modules.devmenu.compose.theme.Theme
11
+ import expo.modules.devmenu.compose.newtheme.NewAppTheme
12
12
 
13
13
  @Composable
14
14
  fun Divider(
15
15
  thickness: Dp = Dp.Hairline,
16
- color: Color = Theme.colors.border.default
16
+ color: Color = NewAppTheme.colors.border.default
17
17
  ) {
18
18
  Canvas(Modifier.fillMaxWidth().height(thickness)) {
19
19
  drawLine(
@@ -4,11 +4,11 @@ import androidx.compose.foundation.layout.size
4
4
  import androidx.compose.runtime.Composable
5
5
  import androidx.compose.ui.Modifier
6
6
  import androidx.compose.ui.unit.Dp
7
- import expo.modules.devmenu.compose.theme.Theme
7
+ import expo.modules.devmenu.compose.newtheme.NewAppTheme
8
8
 
9
9
  @Composable
10
10
  fun Spacer(
11
- height: Dp = Theme.spacing.medium,
11
+ height: Dp = NewAppTheme.spacing.`2`,
12
12
  modifier: Modifier? = null
13
13
  ) {
14
14
  androidx.compose.foundation.layout.Spacer(
@@ -12,13 +12,13 @@ import androidx.compose.ui.graphics.Color
12
12
  import androidx.compose.ui.graphics.RectangleShape
13
13
  import androidx.compose.ui.graphics.Shape
14
14
  import androidx.compose.ui.unit.Dp
15
- import expo.modules.devmenu.compose.theme.Theme
15
+ import expo.modules.devmenu.compose.newtheme.NewAppTheme
16
16
 
17
17
  @Composable
18
18
  fun Surface(
19
19
  modifier: Modifier = Modifier,
20
20
  shape: Shape = RectangleShape,
21
- color: Color = Theme.colors.background.default,
21
+ color: Color = NewAppTheme.colors.background.default,
22
22
  border: BorderStroke? = null,
23
23
  content: @Composable () -> Unit
24
24
  ) {
@@ -42,8 +42,8 @@ fun Surface(
42
42
  @Composable
43
43
  fun RoundedSurface(
44
44
  modifier: Modifier = Modifier,
45
- borderRadius: Dp = Theme.sizing.borderRadius.large,
46
- color: Color = Theme.colors.background.default,
45
+ borderRadius: Dp = NewAppTheme.borderRadius.xl,
46
+ color: Color = NewAppTheme.colors.background.default,
47
47
  border: BorderStroke? = null,
48
48
  content: @Composable () -> Unit
49
49
  ) {
@@ -1,6 +1,5 @@
1
1
  package expo.modules.devmenu.compose.primitives
2
2
 
3
- import androidx.compose.foundation.layout.Column
4
3
  import androidx.compose.foundation.text.BasicText
5
4
  import androidx.compose.runtime.Composable
6
5
  import androidx.compose.ui.Modifier
@@ -8,12 +7,8 @@ import androidx.compose.ui.graphics.Color
8
7
  import androidx.compose.ui.text.AnnotatedString
9
8
  import androidx.compose.ui.text.TextStyle
10
9
  import androidx.compose.ui.text.font.FontWeight
11
- import androidx.compose.ui.text.style.TextAlign
12
10
  import androidx.compose.ui.text.style.TextOverflow
13
- import androidx.compose.ui.tooling.preview.Preview
14
11
  import expo.modules.devmenu.compose.newtheme.NewAppTheme
15
- import expo.modules.devmenu.compose.theme.FontSize
16
- import expo.modules.devmenu.compose.theme.Theme
17
12
 
18
13
  @Composable
19
14
  fun NewText(
@@ -62,117 +57,3 @@ fun NewText(
62
57
  modifier = modifier
63
58
  )
64
59
  }
65
-
66
- @Composable
67
- fun Text(
68
- text: String,
69
- fontSize: FontSize = Theme.typography.medium,
70
- fontWeight: FontWeight = FontWeight.Normal,
71
- color: Color? = null,
72
- maxLines: Int = Int.MAX_VALUE,
73
- softWrap: Boolean = true,
74
- textAlign: TextAlign = TextAlign.Start,
75
- modifier: Modifier = Modifier
76
- ) {
77
- BasicText(
78
- text,
79
- maxLines = maxLines,
80
- softWrap = softWrap,
81
- style = fontSize.font.merge(
82
- color = color ?: Theme.colors.text.default,
83
- fontFamily = Theme.typography.inter,
84
- fontWeight = fontWeight,
85
- textAlign = textAlign
86
- ),
87
- overflow = TextOverflow.Visible,
88
- modifier = modifier
89
- )
90
- }
91
-
92
- @Composable
93
- fun Text(
94
- text: AnnotatedString,
95
- fontSize: FontSize = Theme.typography.medium,
96
- fontWeight: FontWeight = FontWeight.Normal,
97
- color: Color? = null,
98
- maxLines: Int = Int.MAX_VALUE,
99
- softWrap: Boolean = true,
100
- textAlign: TextAlign = TextAlign.Start,
101
- modifier: Modifier = Modifier
102
- ) {
103
- BasicText(
104
- text,
105
- maxLines = maxLines,
106
- softWrap = softWrap,
107
- style = fontSize.font.merge(
108
- color = color ?: Theme.colors.text.default,
109
- fontFamily = Theme.typography.inter,
110
- fontWeight = fontWeight,
111
- textAlign = textAlign
112
- ),
113
- overflow = TextOverflow.Visible,
114
- modifier = modifier
115
- )
116
- }
117
-
118
- @Composable
119
- fun Heading(
120
- text: String,
121
- fontSize: FontSize = Theme.typography.large,
122
- color: Color = Theme.colors.text.default,
123
- maxLines: Int = Int.MAX_VALUE,
124
- overflow: TextOverflow = TextOverflow.Clip,
125
- modifier: Modifier = Modifier
126
- ) {
127
- BasicText(
128
- text,
129
- maxLines = maxLines,
130
- overflow = overflow,
131
- style = fontSize.font.merge(
132
- color = color,
133
- fontWeight = FontWeight.SemiBold,
134
- fontFamily = Theme.typography.inter
135
- ),
136
- modifier = modifier
137
- )
138
- }
139
-
140
- @Composable
141
- fun Mono(
142
- text: String,
143
- fontSize: FontSize = Theme.typography.medium,
144
- color: Color? = null,
145
- maxLines: Int = Int.MAX_VALUE,
146
- modifier: Modifier = Modifier
147
- ) {
148
- BasicText(
149
- text,
150
- maxLines = maxLines,
151
- style = fontSize.font.merge(
152
- color = color ?: Theme.colors.text.default,
153
- fontFamily = Theme.typography.mono
154
- ),
155
- modifier = modifier
156
- )
157
- }
158
-
159
- @Composable
160
- @Preview(showBackground = true)
161
- fun TextPreview() {
162
- Column {
163
- Text("Hello, World!")
164
- Text("Hello, World!", fontSize = Theme.typography.size25)
165
- }
166
- }
167
-
168
- @Composable
169
- @Preview(showBackground = true)
170
- fun HeadingPreview() {
171
- Heading("Hello, World!")
172
- }
173
-
174
- @Composable
175
- @Preview(showBackground = true)
176
- fun MonoPreview() {
177
- Mono("Hello, World!")
178
- }
@@ -16,7 +16,6 @@ import androidx.compose.ui.graphics.Color
16
16
  import androidx.compose.ui.unit.dp
17
17
  import com.composeunstyled.ToggleSwitch
18
18
  import expo.modules.devmenu.compose.newtheme.NewAppTheme
19
- import expo.modules.devmenu.compose.theme.Theme
20
19
 
21
20
  @Composable
22
21
  fun ToggleSwitch(
@@ -38,7 +37,7 @@ fun ToggleSwitch(
38
37
  ToggleSwitch(
39
38
  toggled = isToggled,
40
39
  onToggled = onToggled,
41
- shape = RoundedCornerShape(Theme.sizing.borderRadius.full),
40
+ shape = RoundedCornerShape(NewAppTheme.borderRadius.full),
42
41
  backgroundColor = animatedBackgroundColor,
43
42
  modifier = Modifier.width(52.dp),
44
43
  thumb = {
@@ -37,7 +37,7 @@ import androidx.compose.ui.node.currentValueOf
37
37
  import androidx.compose.ui.node.observeReads
38
38
  import androidx.compose.ui.unit.Dp
39
39
  import com.composeunstyled.LocalContentColor
40
- import expo.modules.devmenu.compose.theme.LocalIsDarkTheme
40
+ import expo.modules.devmenu.compose.newtheme.LocalIsDarkTheme
41
41
 
42
42
  /**
43
43
  * Creates a Ripple using the provided values and values inferred from the theme.
@@ -8,13 +8,10 @@ import androidx.compose.foundation.shape.RoundedCornerShape
8
8
  import androidx.compose.runtime.Composable
9
9
  import androidx.compose.ui.Alignment
10
10
  import androidx.compose.ui.Modifier
11
- import androidx.compose.ui.res.painterResource
12
11
  import androidx.compose.ui.text.font.FontWeight
13
12
  import androidx.compose.ui.tooling.preview.Preview
14
13
  import androidx.compose.ui.unit.dp
15
14
  import com.composeunstyled.Button
16
- import com.composeunstyled.Icon
17
- import expo.modules.devmenu.R
18
15
  import expo.modules.devmenu.compose.DevMenuAction
19
16
  import expo.modules.devmenu.compose.DevMenuActionHandler
20
17
  import expo.modules.devmenu.compose.newtheme.NewAppTheme
@@ -35,25 +32,25 @@ fun AppInfo(
35
32
  horizontalArrangement = Arrangement.Center,
36
33
  modifier = modifier
37
34
  ) {
38
- AppIcon(size = 44.dp)
35
+ AppIcon()
39
36
 
40
37
  Spacer(NewAppTheme.spacing.`3`)
41
38
 
42
- Column {
39
+ Column(
40
+ verticalArrangement = Arrangement.spacedBy(NewAppTheme.spacing.`1`)
41
+ ) {
43
42
  NewText(
44
43
  appName,
45
44
  style = NewAppTheme.font.lg.merge(fontWeight = FontWeight.SemiBold)
46
45
  )
47
46
 
48
47
  if (runtimeVersion != null) {
49
- Spacer(NewAppTheme.spacing.`1`)
50
48
  NewText(
51
49
  "Runtime version: $runtimeVersion",
52
50
  style = NewAppTheme.font.md,
53
51
  color = NewAppTheme.colors.text.secondary
54
52
  )
55
53
  } else if (sdkVersion != null) {
56
- Spacer(NewAppTheme.spacing.`1`)
57
54
  NewText(
58
55
  "SDK version: $sdkVersion",
59
56
  style = NewAppTheme.font.md,
@@ -74,12 +71,9 @@ fun AppInfo(
74
71
  .align(Alignment.CenterVertically)
75
72
  .size(36.dp)
76
73
  ) {
77
- Icon(
78
- painter = painterResource(R.drawable.x_close),
79
- contentDescription = "Close",
80
- tint = NewAppTheme.colors.icon.tertiary,
81
- modifier = Modifier
82
- .size(16.dp)
74
+ Icons.Close(
75
+ size = 16.dp,
76
+ tint = NewAppTheme.colors.icon.tertiary
83
77
  )
84
78
  }
85
79
  }
@@ -1,9 +1,10 @@
1
- package expo.modules.devmenu.compose
1
+ package expo.modules.devmenu.compose.ui
2
2
 
3
3
  import androidx.compose.foundation.background
4
4
  import androidx.compose.foundation.layout.Box
5
5
  import androidx.compose.foundation.layout.Column
6
6
  import androidx.compose.foundation.layout.fillMaxWidth
7
+ import androidx.compose.foundation.layout.navigationBarsPadding
7
8
  import androidx.compose.foundation.layout.padding
8
9
  import androidx.compose.foundation.rememberScrollState
9
10
  import androidx.compose.foundation.shape.RoundedCornerShape
@@ -37,7 +38,7 @@ fun rememberBottomSheetState() = rememberModalBottomSheetState(
37
38
  )
38
39
 
39
40
  @Composable
40
- fun BottomSheet(
41
+ fun BottomSheetScaffold(
41
42
  state: ModalBottomSheetState,
42
43
  onDismiss: () -> Unit = {},
43
44
  header: @Composable () -> Unit = {},
@@ -62,8 +63,10 @@ fun BottomSheet(
62
63
  .background(NewAppTheme.colors.background.default)
63
64
  ) {
64
65
  Column(
65
- modifier = Modifier.fillMaxWidth(),
66
- horizontalAlignment = Alignment.CenterHorizontally
66
+ horizontalAlignment = Alignment.CenterHorizontally,
67
+ modifier = Modifier
68
+ .fillMaxWidth()
69
+ .navigationBarsPadding()
67
70
  ) {
68
71
  Box(modifier = Modifier.padding(NewAppTheme.spacing.`4`)) {
69
72
  header()
@@ -75,7 +78,10 @@ fun BottomSheet(
75
78
  .fillMaxWidth()
76
79
  .verticalScroll(scrollState)
77
80
  ) {
78
- Box(modifier = Modifier.padding(horizontal = NewAppTheme.spacing.`4`)) {
81
+ Box(
82
+ modifier = Modifier
83
+ .padding(horizontal = NewAppTheme.spacing.`4`)
84
+ ) {
79
85
  content()
80
86
  }
81
87
  }
@@ -2,16 +2,11 @@ package expo.modules.devmenu.compose.ui
2
2
 
3
3
  import androidx.compose.foundation.layout.Arrangement
4
4
  import androidx.compose.foundation.layout.Column
5
- import androidx.compose.foundation.layout.size
6
5
  import androidx.compose.runtime.Composable
7
- import androidx.compose.ui.Modifier
8
6
  import androidx.compose.ui.platform.LocalContext
9
- import androidx.compose.ui.res.painterResource
10
7
  import androidx.compose.ui.text.font.FontWeight
11
8
  import androidx.compose.ui.tooling.preview.Preview
12
9
  import androidx.compose.ui.unit.dp
13
- import com.composeunstyled.Icon
14
- import expo.modules.devmenu.R
15
10
  import expo.modules.devmenu.compose.newtheme.NewAppTheme
16
11
  import expo.modules.devmenu.compose.primitives.NewText
17
12
  import expo.modules.devmenu.compose.utils.copyToClipboard
@@ -43,12 +38,9 @@ fun BundlerInfo(
43
38
  }
44
39
  },
45
40
  rightComponent = {
46
- Icon(
47
- painter = painterResource(R.drawable.copy),
48
- contentDescription = "Copy Bundler URL",
49
- tint = NewAppTheme.colors.icon.tertiary,
50
- modifier = Modifier
51
- .size(20.dp)
41
+ Icons.Copy(
42
+ size = 20.dp,
43
+ tint = NewAppTheme.colors.icon.tertiary
52
44
  )
53
45
  },
54
46
  onClick = {
@@ -0,0 +1,78 @@
1
+ package expo.modules.devmenu.compose.ui
2
+
3
+ import androidx.compose.runtime.Composable
4
+ import androidx.compose.runtime.LaunchedEffect
5
+ import androidx.compose.runtime.mutableStateOf
6
+ import androidx.compose.runtime.remember
7
+ import com.composables.core.SheetDetent.Companion.Hidden
8
+ import expo.modules.devmenu.compose.DevMenuAction
9
+ import expo.modules.devmenu.compose.DevMenuActionHandler
10
+ import expo.modules.devmenu.compose.DevMenuState
11
+
12
+ @Composable
13
+ fun DevMenuBottomSheet(
14
+ state: DevMenuState,
15
+ onAction: DevMenuActionHandler = {}
16
+ ) {
17
+ val appInfo = state.appInfo ?: return
18
+ val isOpen = state.isOpen
19
+ val shouldShowOnboarding = remember(state.isOnboardingFinished) {
20
+ mutableStateOf(!state.isOnboardingFinished)
21
+ }
22
+ val bottomSheetState = rememberBottomSheetState()
23
+
24
+ LaunchedEffect(isOpen) {
25
+ if (isOpen) {
26
+ bottomSheetState.targetDetent = Peek
27
+ } else {
28
+ if (bottomSheetState.currentDetent != Hidden) {
29
+ bottomSheetState.animateTo(Hidden)
30
+ shouldShowOnboarding.value = false
31
+ }
32
+ }
33
+ }
34
+
35
+ val wrappedOnAction: DevMenuActionHandler = remember {
36
+ ActionHandler@{ action: DevMenuAction ->
37
+ val shouldClose = action.shouldCloseMenu
38
+
39
+ if (action == DevMenuAction.Close) {
40
+ // If the action is to close the menu, we want to start the animation and then close the menu
41
+ bottomSheetState.targetDetent = Hidden
42
+ return@ActionHandler
43
+ }
44
+
45
+ onAction(action)
46
+ if (shouldClose) {
47
+ bottomSheetState.targetDetent = Hidden
48
+ }
49
+ }
50
+ }
51
+
52
+ BottomSheetScaffold(
53
+ state = bottomSheetState,
54
+ onDismiss = {
55
+ if (isOpen) {
56
+ shouldShowOnboarding.value = false
57
+ // If the menu is open, we want to close it
58
+ // and not just hide the bottom sheet.
59
+ onAction(DevMenuAction.Close)
60
+ }
61
+ },
62
+ header = {
63
+ AppInfo(
64
+ appName = appInfo.appName,
65
+ runtimeVersion = appInfo.runtimeVersion,
66
+ sdkVersion = appInfo.sdkVersion,
67
+ onAction = wrappedOnAction
68
+ )
69
+ }
70
+ ) {
71
+ DevMenuScreen(
72
+ appInfo = appInfo,
73
+ devToolsSettings = state.devToolsSettings,
74
+ shouldShowOnboarding = shouldShowOnboarding.value,
75
+ onAction = wrappedOnAction
76
+ )
77
+ }
78
+ }
@@ -0,0 +1,94 @@
1
+ package expo.modules.devmenu.compose.ui
2
+
3
+ import androidx.compose.foundation.background
4
+ import androidx.compose.foundation.layout.Arrangement
5
+ import androidx.compose.foundation.layout.Box
6
+ import androidx.compose.foundation.layout.Column
7
+ import androidx.compose.foundation.layout.Row
8
+ import androidx.compose.foundation.layout.padding
9
+ import androidx.compose.runtime.Composable
10
+ import androidx.compose.ui.Alignment
11
+ import androidx.compose.ui.Modifier
12
+ import androidx.compose.ui.tooling.preview.Preview
13
+ import androidx.compose.ui.unit.dp
14
+ import expo.modules.devmenu.DevToolsSettings
15
+ import expo.modules.devmenu.compose.DevMenuAction
16
+ import expo.modules.devmenu.compose.DevMenuActionHandler
17
+ import expo.modules.devmenu.compose.DevMenuState
18
+ import expo.modules.devmenu.compose.newtheme.NewAppTheme
19
+ import expo.modules.devmenu.compose.primitives.Spacer
20
+
21
+ @Composable
22
+ fun DevMenuScreen(
23
+ appInfo: DevMenuState.AppInfo,
24
+ devToolsSettings: DevToolsSettings,
25
+ shouldShowOnboarding: Boolean = false,
26
+ onAction: DevMenuActionHandler = {}
27
+ ) {
28
+ if (shouldShowOnboarding) {
29
+ Onboarding(
30
+ onOnboardingFinished = {
31
+ onAction(DevMenuAction.FinishOnboarding)
32
+ }
33
+ )
34
+ return
35
+ }
36
+
37
+ Column {
38
+ BundlerInfo(bundlerIp = appInfo.hostUrl)
39
+
40
+ Spacer(NewAppTheme.spacing.`2`)
41
+
42
+ Row(
43
+ horizontalArrangement = Arrangement.spacedBy(NewAppTheme.spacing.`2`),
44
+ verticalAlignment = Alignment.Companion.CenterVertically
45
+ ) {
46
+ QuickAction(
47
+ label = "Reload",
48
+ icon = { Icons.Reload(size = 20.dp, tint = NewAppTheme.colors.icon.default) },
49
+ modifier = Modifier.Companion.weight(1f),
50
+ onClick = { onAction(DevMenuAction.Reload) }
51
+ )
52
+
53
+ QuickAction(
54
+ label = "Go home",
55
+ icon = { Icons.Home(size = 20.dp, tint = NewAppTheme.colors.icon.default) },
56
+ modifier = Modifier.Companion.weight(1f),
57
+ onClick = { onAction(DevMenuAction.GoHome) }
58
+ )
59
+ }
60
+
61
+ Spacer(NewAppTheme.spacing.`5`)
62
+
63
+ ToolsSection(onAction, devToolsSettings)
64
+
65
+ Box(modifier = Modifier.Companion.padding(vertical = NewAppTheme.spacing.`6`)) {
66
+ Warning("Debugging not working? Try manually reloading first")
67
+ }
68
+
69
+ SystemSection(
70
+ appInfo.appVersion,
71
+ appInfo.runtimeVersion,
72
+ fullDataProvider = { appInfo.toJson() }
73
+ )
74
+ }
75
+ }
76
+
77
+ @Composable
78
+ @Preview(showBackground = false)
79
+ fun DevMenuScreenPreview() {
80
+ Box(
81
+ Modifier.Companion
82
+ .background(NewAppTheme.colors.background.default)
83
+ .padding(horizontal = NewAppTheme.spacing.`4`)
84
+ ) {
85
+ DevMenuScreen(
86
+ appInfo = DevMenuState.AppInfo(
87
+ appName = "Expo App",
88
+ runtimeVersion = "1.0.0",
89
+ hostUrl = "http://localhost:19006"
90
+ ),
91
+ devToolsSettings = DevToolsSettings()
92
+ )
93
+ }
94
+ }