expo-dev-launcher 6.0.6 → 6.0.8-canary-20250830-81bb199

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 (127) hide show
  1. package/CHANGELOG.md +4 -0
  2. package/android/build.gradle +2 -2
  3. package/android/src/debug/java/expo/modules/devlauncher/compose/BindingView.kt +3 -5
  4. package/android/src/debug/java/expo/modules/devlauncher/compose/DevLauncherBottomTabsNavigator.kt +2 -33
  5. package/android/src/debug/java/expo/modules/devlauncher/compose/primitives/Accordion.kt +9 -13
  6. package/android/src/debug/java/expo/modules/devlauncher/compose/primitives/{Asyncimage.kt → AsyncImage.kt} +17 -8
  7. package/android/src/debug/java/expo/modules/devlauncher/compose/primitives/CircularProgressBar.kt +5 -13
  8. package/android/src/debug/java/expo/modules/devlauncher/compose/primitives/DefaultScaffold.kt +4 -2
  9. package/android/src/debug/java/expo/modules/devlauncher/compose/routes/CrashReport.kt +1 -1
  10. package/android/src/debug/java/expo/modules/devlauncher/compose/routes/DevelopmentServers.kt +3 -1
  11. package/android/src/debug/java/expo/modules/devlauncher/compose/routes/Home.kt +1 -1
  12. package/android/src/debug/java/expo/modules/devlauncher/compose/routes/Profile.kt +90 -85
  13. package/android/src/debug/java/expo/modules/devlauncher/compose/routes/Routes.kt +3 -0
  14. package/android/src/debug/java/expo/modules/devlauncher/compose/routes/Settings.kt +1 -1
  15. package/android/src/debug/java/expo/modules/devlauncher/compose/routes/Updates.kt +54 -44
  16. package/android/src/debug/java/expo/modules/devlauncher/compose/screens/BranchScreen.kt +12 -25
  17. package/android/src/debug/java/expo/modules/devlauncher/compose/screens/BranchesScreen.kt +18 -26
  18. package/android/src/debug/java/expo/modules/devlauncher/compose/screens/CrashReportScreen.kt +28 -130
  19. package/android/src/debug/java/expo/modules/devlauncher/compose/screens/ErrorScreen.kt +30 -18
  20. package/android/src/debug/java/expo/modules/devlauncher/compose/screens/HomeScreen.kt +87 -106
  21. package/android/src/debug/java/expo/modules/devlauncher/compose/screens/NoUpdatesScreen.kt +1 -1
  22. package/android/src/debug/java/expo/modules/devlauncher/compose/screens/SettingsScreen.kt +44 -143
  23. package/android/src/debug/java/expo/modules/devlauncher/compose/ui/AccountAvatar.kt +2 -6
  24. package/android/src/debug/java/expo/modules/devlauncher/compose/ui/AccountSelector.kt +3 -9
  25. package/android/src/debug/java/expo/modules/devlauncher/compose/ui/ActionButton.kt +0 -29
  26. package/android/src/debug/java/expo/modules/devlauncher/compose/ui/AppHeader.kt +9 -21
  27. package/android/src/debug/java/expo/modules/devlauncher/compose/ui/AppLoadingErrorDialog.kt +51 -21
  28. package/android/src/debug/java/expo/modules/devlauncher/compose/ui/BottomSheet.kt +4 -1
  29. package/android/src/debug/java/expo/modules/devlauncher/compose/ui/BottomTabBar.kt +30 -29
  30. package/android/src/debug/java/expo/modules/devlauncher/compose/ui/BottomTabButton.kt +7 -11
  31. package/android/src/debug/java/expo/modules/devlauncher/compose/ui/DefaultScreenContainer.kt +23 -0
  32. package/android/src/debug/java/expo/modules/devlauncher/compose/ui/FetchDevelopmentServersButton.kt +17 -17
  33. package/android/src/debug/java/expo/modules/devlauncher/compose/ui/LauncherIcons.kt +220 -0
  34. package/android/src/debug/java/expo/modules/devlauncher/compose/ui/RunningAppCard.kt +4 -12
  35. package/android/src/debug/java/expo/modules/devlauncher/compose/ui/ScanQRCodeButton.kt +5 -12
  36. package/android/src/debug/java/expo/modules/devlauncher/compose/ui/ServerUrlInput.kt +1 -10
  37. package/android/src/debug/java/expo/modules/devlauncher/compose/ui/StackTrace.kt +50 -0
  38. package/android/src/debug/java/expo/modules/devlauncher/compose/utils/Scrollbar.kt +65 -0
  39. package/android/src/debug/java/expo/modules/devlauncher/compose/utils/UrlUtils.kt +12 -0
  40. package/android/src/main/res/values/colors.xml +0 -3
  41. package/ios/SwiftUI/GraphQL/APIClient.swift +0 -4
  42. package/ios/SwiftUI/UpdatesTab/UpdateRow.swift +3 -1
  43. package/ios/SwiftUI/UpdatesTab/UpdatesListView.swift +37 -38
  44. package/ios/SwiftUI/UpdatesTab/UpdatesTabView.swift +9 -7
  45. package/package.json +5 -6
  46. package/android/src/debug/assets/Inter-Black.otf +0 -0
  47. package/android/src/debug/assets/Inter-Bold.otf +0 -0
  48. package/android/src/debug/assets/Inter-ExtraBold.otf +0 -0
  49. package/android/src/debug/assets/Inter-ExtraLight.otf +0 -0
  50. package/android/src/debug/assets/Inter-Light.otf +0 -0
  51. package/android/src/debug/assets/Inter-Medium.otf +0 -0
  52. package/android/src/debug/assets/Inter-Regular.otf +0 -0
  53. package/android/src/debug/assets/Inter-SemiBold.otf +0 -0
  54. package/android/src/debug/assets/Inter-Thin.otf +0 -0
  55. package/android/src/debug/java/expo/modules/devlauncher/compose/ui/ProfileLayout.kt +0 -53
  56. package/android/src/debug/java/expo/modules/devlauncher/compose/ui/ScreenHeaderContainer.kt +0 -25
  57. package/android/src/debug/java/expo/modules/devlauncher/compose/ui/SectionHeader.kt +0 -20
  58. package/android/src/debug/java/expo/modules/devlauncher/launcher/errors/DevLauncherStackAdapter.kt +0 -39
  59. package/android/src/debug/res/drawable-mdpi/building_icon.png +0 -0
  60. package/android/src/debug/res/drawable-mdpi/check_icon.png +0 -0
  61. package/android/src/debug/res/drawable-mdpi/chevron_right_icon.png +0 -0
  62. package/android/src/debug/res/drawable-mdpi/home_icon.png +0 -0
  63. package/android/src/debug/res/drawable-mdpi/info_icon.png +0 -0
  64. package/android/src/debug/res/drawable-mdpi/qr_code.png +0 -0
  65. package/android/src/debug/res/drawable-mdpi/settings_icon.png +0 -0
  66. package/android/src/debug/res/drawable-mdpi/shake_device_icon.png +0 -0
  67. package/android/src/debug/res/drawable-mdpi/show_menu_at_launch_icon.png +0 -0
  68. package/android/src/debug/res/drawable-mdpi/terminal_icon.png +0 -0
  69. package/android/src/debug/res/drawable-mdpi/three_finger_long_press_icon.png +0 -0
  70. package/android/src/debug/res/drawable-mdpi/user_icon.png +0 -0
  71. package/android/src/debug/res/drawable-mdpi/x_icon.png +0 -0
  72. package/android/src/debug/res/drawable-night-mdpi/qr_code.png +0 -0
  73. package/android/src/debug/res/drawable-night-mdpi/shake_device_icon.png +0 -0
  74. package/android/src/debug/res/drawable-night-xhdpi/qr_code.png +0 -0
  75. package/android/src/debug/res/drawable-night-xhdpi/shake_device_icon.png +0 -0
  76. package/android/src/debug/res/drawable-night-xxhdpi/qr_code.png +0 -0
  77. package/android/src/debug/res/drawable-night-xxhdpi/shake_device_icon.png +0 -0
  78. package/android/src/debug/res/drawable-xhdpi/building_icon.png +0 -0
  79. package/android/src/debug/res/drawable-xhdpi/check_icon.png +0 -0
  80. package/android/src/debug/res/drawable-xhdpi/chevron_right_icon.png +0 -0
  81. package/android/src/debug/res/drawable-xhdpi/home_icon.png +0 -0
  82. package/android/src/debug/res/drawable-xhdpi/info_icon.png +0 -0
  83. package/android/src/debug/res/drawable-xhdpi/qr_code.png +0 -0
  84. package/android/src/debug/res/drawable-xhdpi/settings_icon.png +0 -0
  85. package/android/src/debug/res/drawable-xhdpi/shake_device_icon.png +0 -0
  86. package/android/src/debug/res/drawable-xhdpi/show_menu_at_launch_icon.png +0 -0
  87. package/android/src/debug/res/drawable-xhdpi/terminal_icon.png +0 -0
  88. package/android/src/debug/res/drawable-xhdpi/three_finger_long_press_icon.png +0 -0
  89. package/android/src/debug/res/drawable-xhdpi/user_icon.png +0 -0
  90. package/android/src/debug/res/drawable-xhdpi/x_icon.png +0 -0
  91. package/android/src/debug/res/drawable-xxhdpi/building_icon.png +0 -0
  92. package/android/src/debug/res/drawable-xxhdpi/check_icon.png +0 -0
  93. package/android/src/debug/res/drawable-xxhdpi/chevron_right_icon.png +0 -0
  94. package/android/src/debug/res/drawable-xxhdpi/home_icon.png +0 -0
  95. package/android/src/debug/res/drawable-xxhdpi/info_icon.png +0 -0
  96. package/android/src/debug/res/drawable-xxhdpi/qr_code.png +0 -0
  97. package/android/src/debug/res/drawable-xxhdpi/settings_icon.png +0 -0
  98. package/android/src/debug/res/drawable-xxhdpi/shake_device_icon.png +0 -0
  99. package/android/src/debug/res/drawable-xxhdpi/show_menu_at_launch_icon.png +0 -0
  100. package/android/src/debug/res/drawable-xxhdpi/terminal_icon.png +0 -0
  101. package/android/src/debug/res/drawable-xxhdpi/three_finger_long_press_icon.png +0 -0
  102. package/android/src/debug/res/drawable-xxhdpi/user_icon.png +0 -0
  103. package/android/src/debug/res/drawable-xxhdpi/x_icon.png +0 -0
  104. package/android/src/main/res/drawable/arrow_right.xml +0 -9
  105. package/android/src/main/res/drawable/copy.xml +0 -13
  106. package/android/src/main/res/drawable/inspect.xml +0 -10
  107. package/android/src/main/res/drawable/pulse.xml +0 -10
  108. package/android/src/main/res/drawable/signal.xml +0 -26
  109. package/android/src/main/res/drawable-hdpi/dev_laucher_ic_home_white_36dp.png +0 -0
  110. package/android/src/main/res/drawable-hdpi/dev_launcher_ic_refresh_white_36dp.png +0 -0
  111. package/android/src/main/res/drawable-mdpi/dev_laucher_ic_home_white_36dp.png +0 -0
  112. package/android/src/main/res/drawable-mdpi/dev_launcher_ic_refresh_white_36dp.png +0 -0
  113. package/android/src/main/res/drawable-mdpi/dev_menu_fab_icon.png +0 -0
  114. package/android/src/main/res/drawable-xhdpi/dev_laucher_ic_home_white_36dp.png +0 -0
  115. package/android/src/main/res/drawable-xhdpi/dev_launcher_ic_refresh_white_36dp.png +0 -0
  116. package/android/src/main/res/drawable-xhdpi/dev_menu_fab_icon.png +0 -0
  117. package/android/src/main/res/drawable-xxhdpi/dev_laucher_ic_home_white_36dp.png +0 -0
  118. package/android/src/main/res/drawable-xxhdpi/dev_launcher_ic_refresh_white_36dp.png +0 -0
  119. package/android/src/main/res/drawable-xxhdpi/dev_menu_fab_icon.png +0 -0
  120. package/android/src/main/res/drawable-xxxhdpi/dev_laucher_ic_home_white_36dp.png +0 -0
  121. package/android/src/main/res/drawable-xxxhdpi/dev_launcher_ic_refresh_white_36dp.png +0 -0
  122. package/android/src/main/res/layout/error_activity_content_view.xml +0 -7
  123. package/android/src/main/res/layout/error_console_fragment.xml +0 -53
  124. package/android/src/main/res/layout/error_console_list_item.xml +0 -23
  125. package/android/src/main/res/layout/error_fragment.xml +0 -102
  126. package/android/src/main/res/values/strings.xml +0 -10
  127. /package/android/src/main/res/drawable/{reload.xml → updates_nav.xml} +0 -0
package/CHANGELOG.md CHANGED
@@ -10,6 +10,10 @@
10
10
 
11
11
  ### 💡 Others
12
12
 
13
+ ## 6.0.7 — 2025-08-28
14
+
15
+ _This version does not introduce any user-facing changes._
16
+
13
17
  ## 6.0.6 — 2025-08-27
14
18
 
15
19
  _This version does not introduce any user-facing changes._
@@ -20,13 +20,13 @@ expoModule {
20
20
  }
21
21
 
22
22
  group = "host.exp.exponent"
23
- version = "6.0.6"
23
+ version = "6.0.8-canary-20250830-81bb199"
24
24
 
25
25
  android {
26
26
  namespace "expo.modules.devlauncher"
27
27
  defaultConfig {
28
28
  versionCode 9
29
- versionName "6.0.6"
29
+ versionName "6.0.8-canary-20250830-81bb199"
30
30
  }
31
31
 
32
32
  buildTypes {
@@ -3,17 +3,15 @@ package expo.modules.devlauncher.compose
3
3
  import android.content.Context
4
4
  import android.widget.LinearLayout
5
5
  import androidx.compose.ui.platform.ComposeView
6
- import expo.modules.devmenu.compose.theme.AppTheme
6
+ import expo.modules.devmenu.compose.newtheme.AppTheme
7
7
 
8
8
  class BindingView(context: Context) : LinearLayout(context) {
9
9
  init {
10
10
  addView(
11
11
  ComposeView(context).apply {
12
12
  setContent {
13
- expo.modules.devmenu.compose.newtheme.AppTheme {
14
- AppTheme {
15
- DevLauncherBottomTabsNavigator()
16
- }
13
+ AppTheme {
14
+ DevLauncherBottomTabsNavigator()
17
15
  }
18
16
  }
19
17
  }
@@ -4,14 +4,8 @@ import androidx.compose.animation.AnimatedContentTransitionScope
4
4
  import androidx.compose.animation.EnterTransition
5
5
  import androidx.compose.animation.ExitTransition
6
6
  import androidx.compose.animation.core.tween
7
- import androidx.compose.foundation.background
8
- import androidx.compose.foundation.layout.Box
9
- import androidx.compose.foundation.layout.fillMaxSize
10
- import androidx.compose.foundation.layout.statusBarsPadding
11
7
  import androidx.compose.runtime.Composable
12
8
  import androidx.compose.runtime.remember
13
- import androidx.compose.ui.Modifier
14
- import androidx.compose.ui.graphics.painter.Painter
15
9
  import androidx.navigation.compose.NavHost
16
10
  import androidx.navigation.compose.composable
17
11
  import androidx.navigation.compose.rememberNavController
@@ -27,31 +21,6 @@ import expo.modules.devlauncher.compose.routes.UpdatesRoute
27
21
  import expo.modules.devlauncher.compose.ui.BottomTabBar
28
22
  import expo.modules.devlauncher.compose.ui.Full
29
23
  import expo.modules.devlauncher.compose.ui.rememberBottomSheetState
30
- import expo.modules.devmenu.compose.newtheme.NewAppTheme
31
- import kotlinx.serialization.Serializable
32
-
33
- @Composable
34
- fun DefaultScreenContainer(
35
- content: @Composable () -> Unit
36
- ) {
37
- Box(
38
- modifier = Modifier
39
- .fillMaxSize()
40
- .background(NewAppTheme.colors.background.default)
41
- .statusBarsPadding()
42
- ) {
43
- content()
44
- }
45
- }
46
-
47
- data class Tab(
48
- val label: String,
49
- val icon: Painter,
50
- val screen: Any
51
- )
52
-
53
- @Serializable
54
- object Main
55
24
 
56
25
  @Composable
57
26
  fun DevLauncherBottomTabsNavigator() {
@@ -70,9 +39,9 @@ fun DevLauncherBottomTabsNavigator() {
70
39
 
71
40
  NavHost(
72
41
  navController = mainNavController,
73
- startDestination = Main
42
+ startDestination = Routes.Main
74
43
  ) {
75
- composable<Main>(
44
+ composable<Routes.Main>(
76
45
  enterTransition = {
77
46
  slideIntoContainer(
78
47
  AnimatedContentTransitionScope.SlideDirection.Right,
@@ -11,7 +11,6 @@ import androidx.compose.foundation.layout.Column
11
11
  import androidx.compose.foundation.layout.Row
12
12
  import androidx.compose.foundation.layout.fillMaxWidth
13
13
  import androidx.compose.foundation.layout.padding
14
- import androidx.compose.foundation.layout.size
15
14
  import androidx.compose.runtime.Composable
16
15
  import androidx.compose.runtime.getValue
17
16
  import androidx.compose.runtime.mutableStateOf
@@ -19,16 +18,14 @@ import androidx.compose.runtime.remember
19
18
  import androidx.compose.runtime.setValue
20
19
  import androidx.compose.ui.Alignment
21
20
  import androidx.compose.ui.Modifier
22
- import androidx.compose.ui.res.painterResource
21
+ import androidx.compose.ui.semantics.Role
23
22
  import androidx.compose.ui.tooling.preview.Preview
24
23
  import androidx.compose.ui.unit.dp
25
- import com.composeunstyled.Icon
26
- import expo.modules.devlauncher.R
24
+ import expo.modules.devlauncher.compose.ui.LauncherIcons
27
25
  import expo.modules.devmenu.compose.newtheme.NewAppTheme
28
26
  import expo.modules.devmenu.compose.primitives.NewText
29
27
  import expo.modules.devmenu.compose.primitives.RoundedSurface
30
28
  import expo.modules.devmenu.compose.primitives.Spacer
31
- import expo.modules.devmenu.compose.primitives.Text
32
29
 
33
30
  @Composable
34
31
  fun Accordion(
@@ -46,7 +43,9 @@ fun Accordion(
46
43
  Column(
47
44
  modifier = Modifier
48
45
  .fillMaxWidth()
49
- .clickable { expanded = !expanded }
46
+ .clickable(
47
+ role = Role.Button
48
+ ) { expanded = !expanded }
50
49
  .padding(NewAppTheme.spacing.`3`)
51
50
  ) {
52
51
  Box {
@@ -55,12 +54,9 @@ fun Accordion(
55
54
  verticalAlignment = Alignment.CenterVertically,
56
55
  modifier = modifier
57
56
  ) {
58
- Icon(
59
- painter = painterResource(R.drawable.plus),
60
- contentDescription = "Accordion Arrow",
61
- tint = NewAppTheme.colors.text.link,
62
- modifier = Modifier
63
- .size(16.dp)
57
+ LauncherIcons.Plus(
58
+ size = 16.dp,
59
+ tint = NewAppTheme.colors.text.link
64
60
  )
65
61
 
66
62
  NewText(
@@ -95,6 +91,6 @@ fun Accordion(
95
91
  @Preview(showBackground = true, heightDp = 200, widthDp = 300)
96
92
  fun AccordionVariantPreview() {
97
93
  Accordion(text = "Enter URL manually") {
98
- Text("Lorem ipsum dolor sit amet, consectetur adipiscing elit. Sed ac nisl interdum, mattis purus a, consequat ipsum. Aliquam sem mauris, egestas a elit a, lacinia efficitur nisi. Maecenas scelerisque erat nisi, ac interdum mauris volutpat vel. Proin sed lectus at purus interdum porta. Ut mollis feugiat dignissim.")
94
+ NewText("Lorem ipsum dolor sit amet, consectetur adipiscing elit. Sed ac nisl interdum, mattis purus a, consequat ipsum. Aliquam sem mauris, egestas a elit a, lacinia efficitur nisi. Maecenas scelerisque erat nisi, ac interdum mauris volutpat vel. Proin sed lectus at purus interdum porta. Ut mollis feugiat dignissim.")
99
95
  }
100
96
  }
@@ -8,15 +8,14 @@ import androidx.compose.runtime.mutableStateOf
8
8
  import androidx.compose.runtime.remember
9
9
  import androidx.compose.runtime.rememberCoroutineScope
10
10
  import androidx.compose.runtime.setValue
11
+ import androidx.compose.ui.graphics.ImageBitmap
11
12
  import androidx.compose.ui.graphics.asImageBitmap
12
13
  import expo.modules.devlauncher.services.ImageLoaderService
13
14
  import expo.modules.devlauncher.services.inject
14
15
  import kotlinx.coroutines.launch
15
16
 
16
17
  @Composable
17
- fun AsyncImage(
18
- url: String
19
- ) {
18
+ private fun rememberImageBitmap(url: String): ImageBitmap? {
20
19
  val imageLoaderService = inject<ImageLoaderService>()
21
20
  val scope = rememberCoroutineScope()
22
21
  var imageBitmap by remember { mutableStateOf(imageLoaderService.loadFromMemory(url)?.asImageBitmap()) }
@@ -30,10 +29,20 @@ fun AsyncImage(
30
29
  }
31
30
  }
32
31
 
33
- imageBitmap?.let {
34
- Image(
35
- bitmap = it,
36
- contentDescription = url
37
- )
32
+ return imageBitmap
33
+ }
34
+
35
+ @Composable
36
+ fun AsyncImage(
37
+ url: String
38
+ ) {
39
+ val imageBitmap = rememberImageBitmap(url)
40
+ if (imageBitmap == null) {
41
+ return
38
42
  }
43
+
44
+ Image(
45
+ bitmap = imageBitmap,
46
+ contentDescription = url
47
+ )
39
48
  }
@@ -17,8 +17,9 @@ import androidx.compose.ui.graphics.drawscope.withTransform
17
17
  import androidx.compose.ui.tooling.preview.Preview
18
18
  import androidx.compose.ui.unit.Dp
19
19
  import androidx.compose.ui.unit.dp
20
- import expo.modules.devmenu.compose.theme.Pallet
21
- import expo.modules.devmenu.compose.theme.Theme
20
+ import expo.modules.devmenu.compose.newtheme.NewAppTheme
21
+ import io.github.lukmccall.colors.blue
22
+ import io.github.lukmccall.colors.gray
22
23
  import kotlin.time.Duration
23
24
  import kotlin.time.Duration.Companion.seconds
24
25
 
@@ -29,17 +30,8 @@ fun CircularProgressBar(
29
30
  strokeWidth: Dp = size / 8,
30
31
  duration: Duration = 1.seconds
31
32
  ) {
32
- val backgroundColor = if (Theme.isDarkTheme) {
33
- Pallet.Dark.Gray.gray300
34
- } else {
35
- Pallet.Light.Gray.gray300
36
- }
37
-
38
- val progressColor = if (Theme.isDarkTheme) {
39
- Pallet.Dark.Blue.blue500
40
- } else {
41
- Pallet.Light.Blue.blue500
42
- }
33
+ val backgroundColor = NewAppTheme.pallet.gray.`3`
34
+ val progressColor = NewAppTheme.pallet.blue.`5`
43
35
 
44
36
  val transition = rememberInfiniteTransition(label = "infiniteSpinningTransition")
45
37
 
@@ -13,9 +13,11 @@ fun DefaultScaffold(
13
13
  val maxWidth = constraints.maxWidth
14
14
  val maxHeight = constraints.maxHeight
15
15
 
16
- val bottomTabPlaceables = subcompose("bottomTab", bottomTab).map { it.measure(constraints) }
16
+ val bottomTabPlaceables = subcompose("bottomTab", bottomTab)
17
+ .map { it.measure(constraints) }
17
18
  val bottomTabsHeight = bottomTabPlaceables.fastMaxBy { it.height }?.height ?: 0
18
- val contentPlaceables = subcompose("content", content).map { it.measure(constraints.copy(maxHeight = maxHeight - bottomTabsHeight)) }
19
+ val contentPlaceables = subcompose("content", content)
20
+ .map { it.measure(constraints.copy(maxHeight = maxHeight - bottomTabsHeight)) }
19
21
 
20
22
  layout(maxWidth, maxHeight) {
21
23
  contentPlaceables.forEach { it.place(0, 0) }
@@ -2,7 +2,7 @@ package expo.modules.devlauncher.compose.routes
2
2
 
3
3
  import androidx.compose.runtime.Composable
4
4
  import androidx.lifecycle.viewmodel.compose.viewModel
5
- import expo.modules.devlauncher.compose.DefaultScreenContainer
5
+ import expo.modules.devlauncher.compose.ui.DefaultScreenContainer
6
6
  import expo.modules.devlauncher.compose.models.CrashReportModel
7
7
  import expo.modules.devlauncher.compose.screens.CrashReportScreen
8
8
  import expo.modules.devlauncher.launcher.errors.DevLauncherErrorInstance
@@ -28,7 +28,9 @@ fun DevelopmentServersRoute(
28
28
  fontWeight = FontWeight.SemiBold,
29
29
  textAlign = TextAlign.Center
30
30
  ),
31
- modifier = Modifier.padding(vertical = NewAppTheme.spacing.`4`).fillMaxWidth()
31
+ modifier = Modifier
32
+ .padding(vertical = NewAppTheme.spacing.`4`)
33
+ .fillMaxWidth()
32
34
  )
33
35
 
34
36
  Spacer(NewAppTheme.spacing.`3`)
@@ -5,7 +5,7 @@ import androidx.compose.runtime.Composable
5
5
  import androidx.compose.ui.platform.LocalContext
6
6
  import androidx.lifecycle.viewmodel.compose.viewModel
7
7
  import androidx.navigation.NavController
8
- import expo.modules.devlauncher.compose.DefaultScreenContainer
8
+ import expo.modules.devlauncher.compose.ui.DefaultScreenContainer
9
9
  import expo.modules.devlauncher.compose.models.HomeAction
10
10
  import expo.modules.devlauncher.compose.models.HomeViewModel
11
11
  import expo.modules.devlauncher.compose.screens.HomeScreen
@@ -1,5 +1,6 @@
1
1
  package expo.modules.devlauncher.compose.routes
2
2
 
3
+ import androidx.activity.compose.ManagedActivityResultLauncher
3
4
  import androidx.activity.compose.rememberLauncherForActivityResult
4
5
  import androidx.compose.foundation.background
5
6
  import androidx.compose.foundation.layout.Arrangement
@@ -17,7 +18,6 @@ import androidx.compose.ui.Modifier
17
18
  import androidx.compose.ui.draw.dropShadow
18
19
  import androidx.compose.ui.graphics.Color
19
20
  import androidx.compose.ui.graphics.shadow.Shadow
20
- import androidx.compose.ui.res.painterResource
21
21
  import androidx.compose.ui.text.style.TextAlign
22
22
  import androidx.compose.ui.unit.DpOffset
23
23
  import androidx.compose.ui.unit.dp
@@ -25,8 +25,6 @@ import androidx.compose.ui.unit.sp
25
25
  import androidx.lifecycle.compose.collectAsStateWithLifecycle
26
26
  import androidx.lifecycle.viewmodel.compose.viewModel
27
27
  import com.composables.core.ModalBottomSheetState
28
- import com.composeunstyled.Icon
29
- import expo.modules.devlauncher.R
30
28
  import expo.modules.devlauncher.compose.AuthActivity
31
29
  import expo.modules.devlauncher.compose.AuthRequestType
32
30
  import expo.modules.devlauncher.compose.AuthResult
@@ -35,6 +33,7 @@ import expo.modules.devlauncher.compose.models.ProfileViewModel
35
33
  import expo.modules.devlauncher.compose.primitives.CircularProgressBar
36
34
  import expo.modules.devlauncher.compose.ui.AccountSelector
37
35
  import expo.modules.devlauncher.compose.ui.BottomSheet
36
+ import expo.modules.devlauncher.compose.ui.LauncherIcons
38
37
  import expo.modules.devlauncher.compose.ui.SignUp
39
38
  import expo.modules.devmenu.compose.newtheme.NewAppTheme
40
39
  import expo.modules.devmenu.compose.primitives.NewText
@@ -56,95 +55,101 @@ fun ProfileRoute(
56
55
  }
57
56
 
58
57
  BottomSheet(bottomSheetState) {
58
+ val state = state // capture state for when statement
59
59
  when (state) {
60
- is ProfileState.LoggedIn -> {
61
- val state = state as ProfileState.LoggedIn
62
- AccountSelector(
63
- accounts = state.accounts,
64
- onSignOut = {
65
- viewModel.onAction(ProfileViewModel.Action.SignOut)
66
- },
67
- onClick = { account ->
68
- viewModel.onAction(ProfileViewModel.Action.SwitchAccount(account))
69
- }
70
- )
71
- }
60
+ is ProfileState.LoggedIn -> LoggedIn(state, viewModel)
61
+ ProfileState.LoggedOut -> LoggedOut(authLauncher)
62
+ ProfileState.Fetching -> Loading()
63
+ }
64
+ }
65
+ }
72
66
 
73
- ProfileState.LoggedOut -> {
74
- Column(
75
- verticalArrangement = Arrangement.spacedBy(NewAppTheme.spacing.`4`)
76
- ) {
77
- Row(
78
- horizontalArrangement = Arrangement.Center,
79
- modifier = Modifier
80
- .fillMaxWidth()
81
- ) {
82
- Box(
83
- modifier = Modifier
84
- .size(44.dp)
85
- .dropShadow(
86
- shape = RoundedCornerShape(NewAppTheme.borderRadius.md),
87
- shadow = Shadow(
88
- radius = 10.dp,
89
- offset = DpOffset(0.dp, 5.dp),
90
- color = Color.Black.copy(alpha = 0.05f)
91
- )
92
- )
93
- .dropShadow(
94
- shape = RoundedCornerShape(NewAppTheme.borderRadius.md),
95
- shadow = Shadow(
96
- radius = 25.dp,
97
- offset = DpOffset(0.dp, 15.dp),
98
- color = Color.Black.copy(alpha = 0.12f)
99
- )
100
- )
101
- .background(
102
- Color.White,
103
- shape = RoundedCornerShape(NewAppTheme.borderRadius.md)
104
- )
105
- ) {
106
- Icon(
107
- painter = painterResource(R.drawable.expo_logo),
108
- contentDescription = "Expo logo",
109
- tint = Color.Black,
110
- modifier = Modifier
111
- .size(24.dp)
112
- .align(Alignment.Center)
113
- )
114
- }
115
- }
67
+ @Composable
68
+ private fun Loading() {
69
+ Box(
70
+ contentAlignment = Alignment.Center,
71
+ modifier = Modifier
72
+ .fillMaxWidth()
73
+ .height(300.dp)
74
+ ) {
75
+ CircularProgressBar(size = 72.dp)
76
+ }
77
+ }
116
78
 
117
- NewText(
118
- "Login or create an account to view local\ndevelopment servers and more",
119
- style = NewAppTheme.font.sm.merge(
120
- lineHeight = 19.sp,
121
- textAlign = TextAlign.Center
122
- ),
123
- color = NewAppTheme.colors.text.secondary,
124
- modifier = Modifier.fillMaxWidth()
125
- )
79
+ @Composable
80
+ private fun LoggedOut(authLauncher: ManagedActivityResultLauncher<AuthRequestType, AuthResult>) {
81
+ Column(
82
+ verticalArrangement = Arrangement.spacedBy(NewAppTheme.spacing.`4`)
83
+ ) {
84
+ Row(
85
+ horizontalArrangement = Arrangement.Center,
86
+ modifier = Modifier
87
+ .fillMaxWidth()
88
+ ) {
89
+ val shape = RoundedCornerShape(NewAppTheme.borderRadius.md)
126
90
 
127
- SignUp(
128
- onLogIn = {
129
- authLauncher.launch(AuthRequestType.LOGIN)
130
- },
131
- onSignUp = {
132
- authLauncher.launch(AuthRequestType.SIGNUP)
133
- }
91
+ Box(
92
+ modifier = Modifier
93
+ .size(44.dp)
94
+ .dropShadow(
95
+ shape = shape,
96
+ shadow = Shadow(
97
+ radius = 10.dp,
98
+ offset = DpOffset(0.dp, 5.dp),
99
+ color = Color.Black.copy(alpha = 0.05f)
100
+ )
134
101
  )
135
- }
102
+ .dropShadow(
103
+ shape = shape,
104
+ shadow = Shadow(
105
+ radius = 25.dp,
106
+ offset = DpOffset(0.dp, 15.dp),
107
+ color = Color.Black.copy(alpha = 0.12f)
108
+ )
109
+ )
110
+ .background(
111
+ Color.White,
112
+ shape = shape
113
+ )
114
+ ) {
115
+ LauncherIcons.ExpoLogo(
116
+ size = 24.dp,
117
+ tint = Color.Black,
118
+ modifier = Modifier.align(Alignment.Center)
119
+ )
136
120
  }
121
+ }
122
+
123
+ NewText(
124
+ "Login or create an account to view local\ndevelopment servers and more",
125
+ style = NewAppTheme.font.sm.merge(
126
+ lineHeight = 19.sp,
127
+ textAlign = TextAlign.Center
128
+ ),
129
+ color = NewAppTheme.colors.text.secondary,
130
+ modifier = Modifier.fillMaxWidth()
131
+ )
137
132
 
138
- ProfileState.Fetching -> {
139
- Box(
140
- contentAlignment = Alignment.Center,
141
- modifier = Modifier
142
- .fillMaxWidth()
143
- .height(300.dp)
144
- ) {
145
- CircularProgressBar(size = 72.dp)
146
- }
133
+ SignUp(
134
+ onLogIn = {
135
+ authLauncher.launch(AuthRequestType.LOGIN)
136
+ },
137
+ onSignUp = {
138
+ authLauncher.launch(AuthRequestType.SIGNUP)
147
139
  }
148
- }
140
+ )
149
141
  }
150
142
  }
143
+
144
+ @Composable
145
+ private fun LoggedIn(state: ProfileState.LoggedIn, viewModel: ProfileViewModel) {
146
+ AccountSelector(
147
+ accounts = state.accounts,
148
+ onSignOut = {
149
+ viewModel.onAction(ProfileViewModel.Action.SignOut)
150
+ },
151
+ onClick = { account ->
152
+ viewModel.onAction(ProfileViewModel.Action.SwitchAccount(account))
153
+ }
154
+ )
155
+ }
@@ -3,6 +3,9 @@ package expo.modules.devlauncher.compose.routes
3
3
  import kotlinx.serialization.Serializable
4
4
 
5
5
  object Routes {
6
+ @Serializable
7
+ object Main
8
+
6
9
  @Serializable
7
10
  object Home
8
11
 
@@ -2,7 +2,7 @@ package expo.modules.devlauncher.compose.routes
2
2
 
3
3
  import androidx.compose.runtime.Composable
4
4
  import androidx.lifecycle.viewmodel.compose.viewModel
5
- import expo.modules.devlauncher.compose.DefaultScreenContainer
5
+ import expo.modules.devlauncher.compose.ui.DefaultScreenContainer
6
6
  import expo.modules.devlauncher.compose.models.SettingsViewModel
7
7
  import expo.modules.devlauncher.compose.screens.SettingsScreen
8
8
 
@@ -6,11 +6,12 @@ import androidx.compose.runtime.Composable
6
6
  import androidx.compose.runtime.getValue
7
7
  import androidx.lifecycle.compose.collectAsStateWithLifecycle
8
8
  import androidx.lifecycle.viewmodel.compose.viewModel
9
+ import androidx.navigation.NavHostController
9
10
  import androidx.navigation.compose.NavHost
10
11
  import androidx.navigation.compose.composable
11
12
  import androidx.navigation.compose.rememberNavController
12
13
  import androidx.navigation.toRoute
13
- import expo.modules.devlauncher.compose.DefaultScreenContainer
14
+ import expo.modules.devlauncher.compose.ui.DefaultScreenContainer
14
15
  import expo.modules.devlauncher.compose.models.BranchViewModel
15
16
  import expo.modules.devlauncher.compose.models.BranchesAction
16
17
  import expo.modules.devlauncher.compose.models.BranchesViewModel
@@ -42,56 +43,65 @@ fun UpdatesRoute(
42
43
  }
43
44
  ) {
44
45
  composable<Routes.Updates.Branches> {
45
- val viewModel = viewModel<BranchesViewModel>()
46
-
47
- val state by viewModel.state.collectAsStateWithLifecycle()
48
-
49
- if (viewModel.areUpdatesConfigured) {
50
- BranchesScreen(
51
- branches = state.branches,
52
- isLoading = state.isLoading,
53
- needToSignIn = state.needToSignIn,
54
- onProfileClick = onProfileClick,
55
- onAction = { action ->
56
- when (action) {
57
- is BranchesAction.OpenBranch -> {
58
- updatesNavController.navigate(
59
- Routes.Updates.Branch(action.branchName)
60
- )
61
- }
62
-
63
- else -> {
64
- viewModel.onAction(action)
65
- }
66
- }
67
- }
68
- )
69
- } else {
70
- NoUpdatesScreen(
71
- onProfileClick = onProfileClick
72
- )
73
- }
46
+ Branches(onProfileClick, updatesNavController)
74
47
  }
75
48
 
76
49
  composable<Routes.Updates.Branch> { navBackStackEntry ->
77
50
  val route = navBackStackEntry.toRoute<Routes.Updates.Branch>()
51
+ Branch(route, updatesNavController)
52
+ }
53
+ }
54
+ }
55
+ }
78
56
 
79
- val viewModel = viewModel {
80
- BranchViewModel(
81
- branchName = route.name
82
- )
83
- }
57
+ @Composable
58
+ private fun Branch(route: Routes.Updates.Branch, updatesNavController: NavHostController) {
59
+ val viewModel = viewModel {
60
+ BranchViewModel(
61
+ branchName = route.name
62
+ )
63
+ }
84
64
 
85
- val state by viewModel.state.collectAsStateWithLifecycle()
65
+ val state by viewModel.state.collectAsStateWithLifecycle()
86
66
 
87
- BranchScreen(
88
- branchName = route.name,
89
- updates = state.updates,
90
- isLoading = state.isLoading,
91
- goBack = { updatesNavController.navigateUp() },
92
- onAction = viewModel::onAction
93
- )
67
+ BranchScreen(
68
+ branchName = route.name,
69
+ updates = state.updates,
70
+ isLoading = state.isLoading,
71
+ goBack = { updatesNavController.navigateUp() },
72
+ onAction = viewModel::onAction
73
+ )
74
+ }
75
+
76
+ @Composable
77
+ private fun Branches(onProfileClick: () -> Unit, updatesNavController: NavHostController) {
78
+ val viewModel = viewModel<BranchesViewModel>()
79
+
80
+ val state by viewModel.state.collectAsStateWithLifecycle()
81
+
82
+ if (viewModel.areUpdatesConfigured) {
83
+ BranchesScreen(
84
+ branches = state.branches,
85
+ isLoading = state.isLoading,
86
+ needToSignIn = state.needToSignIn,
87
+ onProfileClick = onProfileClick,
88
+ onAction = { action ->
89
+ when (action) {
90
+ is BranchesAction.OpenBranch -> {
91
+ updatesNavController.navigate(
92
+ Routes.Updates.Branch(action.branchName)
93
+ )
94
+ }
95
+
96
+ else -> {
97
+ viewModel.onAction(action)
98
+ }
99
+ }
94
100
  }
95
- }
101
+ )
102
+ } else {
103
+ NoUpdatesScreen(
104
+ onProfileClick = onProfileClick
105
+ )
96
106
  }
97
107
  }