expo-dev-launcher 5.2.0-canary-20250701-6a945c5 → 5.2.0-canary-20250713-8f814f8

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 (62) hide show
  1. package/CHANGELOG.md +9 -0
  2. package/android/build.gradle +2 -2
  3. package/android/src/debug/java/expo/modules/devlauncher/compose/BindingView.kt +2 -14
  4. package/android/src/debug/java/expo/modules/devlauncher/compose/DevLauncherBottomTabsNavigator.kt +13 -23
  5. package/android/src/debug/java/expo/modules/devlauncher/compose/HomeViewModel.kt +95 -0
  6. package/android/src/debug/java/expo/modules/devlauncher/compose/ProfileViewModel.kt +30 -44
  7. package/android/src/debug/java/expo/modules/devlauncher/compose/primitives/Accordion.kt +1 -1
  8. package/android/src/debug/java/expo/modules/devlauncher/compose/primitives/Asyncimage.kt +40 -0
  9. package/android/src/debug/java/expo/modules/devlauncher/compose/routes/Home.kt +23 -0
  10. package/android/src/debug/java/expo/modules/devlauncher/compose/{screens → routes}/Profile.kt +8 -2
  11. package/android/src/debug/java/expo/modules/devlauncher/compose/routes/Settings.kt +16 -0
  12. package/android/src/debug/java/expo/modules/devlauncher/compose/screens/HomeScreen.kt +225 -0
  13. package/android/src/debug/java/expo/modules/devlauncher/compose/ui/AccountAvatar.kt +37 -0
  14. package/android/src/debug/java/expo/modules/devlauncher/compose/ui/AccountSelector.kt +42 -9
  15. package/android/src/debug/java/expo/modules/devlauncher/compose/ui/AppHeader.kt +26 -18
  16. package/android/src/debug/java/expo/modules/devlauncher/compose/ui/BottomTabBar.kt +3 -3
  17. package/android/src/debug/java/expo/modules/devlauncher/compose/ui/BottomTabButton.kt +1 -1
  18. package/android/src/debug/java/expo/modules/devlauncher/compose/ui/DevelopmentServerHelp.kt +52 -0
  19. package/android/src/debug/java/expo/modules/devlauncher/compose/ui/RunningAppCard.kt +29 -29
  20. package/android/src/debug/java/expo/modules/devlauncher/compose/ui/SectionHeader.kt +6 -16
  21. package/android/src/debug/java/expo/modules/devlauncher/launcher/DevLauncherActivity.kt +36 -51
  22. package/android/src/debug/java/expo/modules/devlauncher/services/ApolloClientService.kt +5 -1
  23. package/android/src/debug/java/expo/modules/devlauncher/services/DependencyInjection.kt +46 -5
  24. package/android/src/debug/java/expo/modules/devlauncher/services/HttpClientService.kt +84 -0
  25. package/android/src/debug/java/expo/modules/devlauncher/services/ImageLoaderService.kt +69 -0
  26. package/android/src/debug/java/expo/modules/devlauncher/services/PackagerService.kt +100 -44
  27. package/android/src/debug/java/expo/modules/devlauncher/services/SessionService.kt +94 -4
  28. package/ios/Assets.xcassets/branch-icon.imageset/Contents.json +56 -0
  29. package/ios/Assets.xcassets/branch-icon.imageset/branch-icon-light.png +0 -0
  30. package/ios/Assets.xcassets/branch-icon.imageset/branch-icon-light@2x.png +0 -0
  31. package/ios/Assets.xcassets/branch-icon.imageset/branch-icon-light@3x.png +0 -0
  32. package/ios/Assets.xcassets/branch-icon.imageset/branch-icon.png +0 -0
  33. package/ios/Assets.xcassets/branch-icon.imageset/branch-icon@2x.png +0 -0
  34. package/ios/Assets.xcassets/branch-icon.imageset/branch-icon@3x.png +0 -0
  35. package/ios/Assets.xcassets/update-icon.imageset/Contents.json +56 -0
  36. package/ios/Assets.xcassets/update-icon.imageset/update-icon-light.png +0 -0
  37. package/ios/Assets.xcassets/update-icon.imageset/update-icon-light@2x.png +0 -0
  38. package/ios/Assets.xcassets/update-icon.imageset/update-icon-light@3x.png +0 -0
  39. package/ios/Assets.xcassets/update-icon.imageset/update-icon.png +0 -0
  40. package/ios/Assets.xcassets/update-icon.imageset/update-icon@2x.png +0 -0
  41. package/ios/Assets.xcassets/update-icon.imageset/update-icon@3x.png +0 -0
  42. package/ios/EXDevLauncherController.m +2 -4
  43. package/ios/SwiftUI/Data.swift +34 -0
  44. package/ios/SwiftUI/DevLauncherViewModel.swift +24 -15
  45. package/ios/SwiftUI/DevLauncherViews.swift +3 -11
  46. package/ios/SwiftUI/GraphQL/APIClient.swift +11 -6
  47. package/ios/SwiftUI/GraphQL/Models.swift +12 -0
  48. package/ios/SwiftUI/GraphQL/Queries.swift +3 -15
  49. package/ios/SwiftUI/HomeTabView.swift +5 -3
  50. package/ios/SwiftUI/SettingsTabView.swift +4 -4
  51. package/ios/SwiftUI/UpdatesTab/NotSignedInView.swift +32 -0
  52. package/ios/SwiftUI/UpdatesTab/NotUsingUpdatesView.swift +38 -0
  53. package/ios/SwiftUI/UpdatesTab/UpdateRow.swift +76 -0
  54. package/ios/SwiftUI/UpdatesTab/UpdateUtils.swift +5 -0
  55. package/ios/SwiftUI/UpdatesTab/UpdatesListView.swift +196 -0
  56. package/ios/SwiftUI/UpdatesTab/UpdatesTabView.swift +37 -0
  57. package/package.json +4 -4
  58. package/android/src/debug/java/expo/modules/devlauncher/compose/DevLauncherAction.kt +0 -7
  59. package/android/src/debug/java/expo/modules/devlauncher/compose/DevLauncherViewModel.kt +0 -43
  60. package/android/src/debug/java/expo/modules/devlauncher/compose/screens/Home.kt +0 -134
  61. package/ios/SwiftUI/ExtensionsTabView.swift +0 -68
  62. /package/android/src/debug/java/expo/modules/devlauncher/compose/screens/{Settings.kt → SettingsScreen.kt} +0 -0
package/CHANGELOG.md CHANGED
@@ -11,6 +11,7 @@
11
11
  ### 🐛 Bug fixes
12
12
 
13
13
  - [iOS] Fix missing CDP headers when using static frameworks. ([#37448](https://github.com/expo/expo/pull/37448) by [@alanjhughes](https://github.com/alanjhughes))
14
+ - [Android] Use same strings in UI as iOS. ([#37786](https://github.com/expo/expo/pull/37786) by [@douglowder](https://github.com/douglowder))
14
15
 
15
16
  ### 💡 Others
16
17
 
@@ -20,6 +21,14 @@
20
21
 
21
22
  - Added support for React Native 0.80.x. ([#37400](https://github.com/expo/expo/pull/37400) by [@gabrieldonadel](https://github.com/gabrieldonadel))
22
23
 
24
+ ## 5.1.16 - 2025-07-03
25
+
26
+ _This version does not introduce any user-facing changes._
27
+
28
+ ## 5.1.15 - 2025-07-02
29
+
30
+ _This version does not introduce any user-facing changes._
31
+
23
32
  ## 5.1.14 - 2025-06-26
24
33
 
25
34
  ### 🐛 Bug fixes
@@ -20,13 +20,13 @@ expoModule {
20
20
  }
21
21
 
22
22
  group = "host.exp.exponent"
23
- version = "5.2.0-canary-20250701-6a945c5"
23
+ version = "5.2.0-canary-20250713-8f814f8"
24
24
 
25
25
  android {
26
26
  namespace "expo.modules.devlauncher"
27
27
  defaultConfig {
28
28
  versionCode 9
29
- versionName "5.2.0-canary-20250701-6a945c5"
29
+ versionName "5.2.0-canary-20250713-8f814f8"
30
30
  }
31
31
 
32
32
  buildTypes {
@@ -2,28 +2,16 @@ package expo.modules.devlauncher.compose
2
2
 
3
3
  import android.content.Context
4
4
  import android.widget.LinearLayout
5
- import androidx.compose.runtime.collectAsState
6
- import androidx.compose.runtime.getValue
7
- import androidx.compose.runtime.remember
8
5
  import androidx.compose.ui.platform.ComposeView
9
- import expo.modules.devmenu.AppInfo
10
6
  import expo.modules.devmenu.compose.theme.AppTheme
11
7
 
12
- class BindingView(context: Context, val viewModel: DevLauncherViewModel) : LinearLayout(context) {
8
+ class BindingView(context: Context) : LinearLayout(context) {
13
9
  init {
14
10
  addView(
15
11
  ComposeView(context).apply {
16
12
  setContent {
17
13
  AppTheme {
18
- val runningPackager by viewModel.packagerService.runningPackagers.collectAsState()
19
- val nativeAppInfo = remember { AppInfo.getNativeAppInfo(context) }
20
- DevLauncherBottomTabsNavigator(
21
- DevLauncherState(
22
- appName = nativeAppInfo.appName,
23
- runningPackagers = runningPackager,
24
- onAction = viewModel::onAction
25
- )
26
- )
14
+ DevLauncherBottomTabsNavigator()
27
15
  }
28
16
  }
29
17
  }
@@ -14,21 +14,15 @@ import androidx.navigation.compose.NavHost
14
14
  import androidx.navigation.compose.composable
15
15
  import androidx.navigation.compose.rememberNavController
16
16
  import expo.modules.devlauncher.compose.primitives.DefaultScaffold
17
- import expo.modules.devlauncher.compose.screens.HomeScreen
18
- import expo.modules.devlauncher.compose.screens.Profile
19
- import expo.modules.devlauncher.compose.screens.SettingsScreen
17
+ import expo.modules.devlauncher.compose.routes.Home
18
+ import expo.modules.devlauncher.compose.routes.HomeRoute
19
+ import expo.modules.devlauncher.compose.routes.ProfileRoute
20
+ import expo.modules.devlauncher.compose.routes.Settings
21
+ import expo.modules.devlauncher.compose.routes.SettingsRoute
20
22
  import expo.modules.devlauncher.compose.ui.BottomTabBar
21
23
  import expo.modules.devlauncher.compose.ui.Full
22
24
  import expo.modules.devlauncher.compose.ui.rememberBottomSheetState
23
- import expo.modules.devlauncher.services.PackagerInfo
24
25
  import expo.modules.devmenu.compose.theme.Theme
25
- import kotlinx.serialization.Serializable
26
-
27
- @Serializable
28
- object Home
29
-
30
- @Serializable
31
- object Settings
32
26
 
33
27
  @Composable
34
28
  fun DefaultScreenContainer(
@@ -52,16 +46,8 @@ data class Tab(
52
46
  val screen: Any
53
47
  )
54
48
 
55
- data class DevLauncherState(
56
- val appName: String = "BareExpo",
57
- val runningPackagers: Set<PackagerInfo> = emptySet<PackagerInfo>(),
58
- val onAction: DevLauncherActionHandler = {}
59
- )
60
-
61
49
  @Composable
62
- fun DevLauncherBottomTabsNavigator(
63
- state: DevLauncherState
64
- ) {
50
+ fun DevLauncherBottomTabsNavigator() {
65
51
  val navController = rememberNavController()
66
52
  val bottomSheetState = rememberBottomSheetState()
67
53
 
@@ -78,10 +64,14 @@ fun DevLauncherBottomTabsNavigator(
78
64
  ExitTransition.None
79
65
  }
80
66
  ) {
81
- composable<Home> { DefaultScreenContainer { HomeScreen(state, onProfileClick = { bottomSheetState.jumpTo(Full) }) } }
82
- composable<Settings> { DefaultScreenContainer { SettingsScreen() } }
67
+ composable<Home> {
68
+ HomeRoute(onProfileClick = { bottomSheetState.jumpTo(Full) })
69
+ }
70
+ composable<Settings> {
71
+ SettingsRoute()
72
+ }
83
73
  }
84
74
  }
85
75
 
86
- Profile(bottomSheetState)
76
+ ProfileRoute(bottomSheetState)
87
77
  }
@@ -0,0 +1,95 @@
1
+ package expo.modules.devlauncher.compose
2
+
3
+ import android.util.Log
4
+ import androidx.compose.runtime.mutableStateOf
5
+ import androidx.core.net.toUri
6
+ import androidx.lifecycle.ViewModel
7
+ import androidx.lifecycle.viewModelScope
8
+ import expo.modules.devlauncher.DevLauncherController
9
+ import expo.modules.devlauncher.MeQuery
10
+ import expo.modules.devlauncher.services.PackagerInfo
11
+ import expo.modules.devlauncher.services.PackagerService
12
+ import expo.modules.devlauncher.services.SessionService
13
+ import expo.modules.devlauncher.services.UserState
14
+ import expo.modules.devlauncher.services.inject
15
+ import kotlinx.coroutines.flow.launchIn
16
+ import kotlinx.coroutines.flow.onEach
17
+ import kotlinx.coroutines.launch
18
+
19
+ sealed interface HomeAction {
20
+ class OpenApp(val url: String) : HomeAction
21
+ object RefetchRunningApps : HomeAction
22
+ }
23
+
24
+ typealias HomeActionHandler = (HomeAction) -> Unit
25
+
26
+ data class HomeState(
27
+ val appName: String = "BareExpo",
28
+ val runningPackagers: Set<PackagerInfo> = emptySet(),
29
+ val isFetchingPackagers: Boolean = false,
30
+ val currentAccount: MeQuery.Account? = null
31
+ )
32
+
33
+ class HomeViewModel() : ViewModel() {
34
+ val devLauncherController = inject<DevLauncherController>()
35
+ val sessionService = inject<SessionService>()
36
+ val packagerService = inject<PackagerService>()
37
+
38
+ private var _state = mutableStateOf(
39
+ HomeState(
40
+ runningPackagers = packagerService.runningPackagers.value,
41
+ currentAccount = when (val userState = sessionService.user.value) {
42
+ UserState.Fetching, UserState.LoggedOut -> null
43
+ is UserState.LoggedIn -> userState.selectedAccount
44
+ }
45
+ )
46
+ )
47
+
48
+ val state
49
+ get() = _state.value
50
+
51
+ init {
52
+ viewModelScope.launch {
53
+ packagerService.refetchedPackager()
54
+ }
55
+
56
+ packagerService.runningPackagers.onEach { newPackagers ->
57
+ _state.value = _state.value.copy(
58
+ runningPackagers = newPackagers
59
+ )
60
+ }.launchIn(viewModelScope)
61
+
62
+ sessionService.user.onEach { newUser ->
63
+ when (newUser) {
64
+ UserState.Fetching, UserState.LoggedOut -> _state.value = _state.value.copy(
65
+ currentAccount = null
66
+ )
67
+
68
+ is UserState.LoggedIn -> _state.value = _state.value.copy(
69
+ currentAccount = newUser.selectedAccount
70
+ )
71
+ }
72
+ }.launchIn(viewModelScope)
73
+
74
+ packagerService.isLoading.onEach { isLoading ->
75
+ _state.value = _state.value.copy(
76
+ isFetchingPackagers = isLoading
77
+ )
78
+ }.launchIn(viewModelScope)
79
+ }
80
+
81
+ fun onAction(action: HomeAction) {
82
+ when (action) {
83
+ is HomeAction.OpenApp ->
84
+ viewModelScope.launch {
85
+ try {
86
+ devLauncherController.loadApp(action.url.toUri(), mainActivity = null)
87
+ } catch (e: Exception) {
88
+ Log.e("DevLauncher", "Failed to open app: ${action.url}", e)
89
+ }
90
+ }
91
+
92
+ HomeAction.RefetchRunningApps -> viewModelScope.launch { packagerService.refetchedPackager() }
93
+ }
94
+ }
95
+ }
@@ -2,39 +2,39 @@ package expo.modules.devlauncher.compose
2
2
 
3
3
  import androidx.lifecycle.ViewModel
4
4
  import androidx.lifecycle.viewModelScope
5
- import expo.modules.devlauncher.services.ApolloClientService
6
5
  import expo.modules.devlauncher.services.SessionService
6
+ import expo.modules.devlauncher.services.UserState
7
7
  import expo.modules.devlauncher.services.inject
8
- import kotlinx.coroutines.Dispatchers
9
8
  import kotlinx.coroutines.flow.MutableStateFlow
10
9
  import kotlinx.coroutines.flow.asStateFlow
11
10
  import kotlinx.coroutines.flow.launchIn
12
11
  import kotlinx.coroutines.flow.onEach
13
12
  import kotlinx.coroutines.flow.update
14
- import kotlinx.coroutines.launch
15
13
 
16
- sealed interface ProfileState {
17
- data class Account(
18
- val name: String,
19
- val avatar: String?
20
- )
14
+ data class Account(
15
+ val id: String,
16
+ val name: String,
17
+ val avatar: String?,
18
+ val isSelected: Boolean = false
19
+ )
21
20
 
21
+ sealed interface ProfileState {
22
22
  class LoggedIn(
23
- val isLoading: Boolean = true,
24
23
  val accounts: List<Account> = emptyList()
25
24
  ) : ProfileState
26
25
 
26
+ object Fetching : ProfileState
27
27
  object LoggedOut : ProfileState
28
28
  }
29
29
 
30
30
  class ProfileViewModel : ViewModel() {
31
31
  sealed interface Action {
32
32
  class LogIn(val sessionSecret: String) : Action
33
+ class SwitchAccount(val account: Account) : Action
33
34
  object SignOut : Action
34
35
  }
35
36
 
36
- val sessionSession = inject<SessionService>()
37
- val apolloClientService = inject<ApolloClientService>()
37
+ val session = inject<SessionService>()
38
38
 
39
39
  private val _state = MutableStateFlow<ProfileState>(ProfileState.LoggedOut)
40
40
 
@@ -42,54 +42,40 @@ class ProfileViewModel : ViewModel() {
42
42
  get() = _state.asStateFlow()
43
43
 
44
44
  init {
45
- sessionSession.session.onEach { newSession ->
46
- if (newSession != null) {
47
- fetchMe()
48
- _state.update {
49
- ProfileState.LoggedIn()
45
+ session.user.onEach { newUserState ->
46
+ when (newUserState) {
47
+ UserState.LoggedOut -> _state.update { ProfileState.LoggedOut }
48
+ UserState.Fetching -> _state.update { ProfileState.Fetching }
49
+ is UserState.LoggedIn -> _state.update {
50
+ ProfileState.LoggedIn(
51
+ accounts = newUserState.data.meUserActor?.accounts?.map { account ->
52
+ Account(
53
+ id = account.id,
54
+ name = account.name,
55
+ avatar = account.ownerUserActor?.profilePhoto,
56
+ isSelected = account.id == newUserState.selectedAccount?.id
57
+ )
58
+ } ?: emptyList()
59
+ )
50
60
  }
51
- } else {
52
- _state.update { ProfileState.LoggedOut }
53
61
  }
54
62
  }
55
63
  .launchIn(viewModelScope)
56
64
  }
57
65
 
58
- private fun fetchMe() {
59
- viewModelScope.launch(Dispatchers.IO) {
60
- val me = apolloClientService.fetchMe()
61
- _state.update { prevState ->
62
- // User logged out in the meantime, we can ignore the result
63
- if (prevState is ProfileState.LoggedOut) {
64
- return@update prevState
65
- }
66
-
67
- val accounts = me.data?.meUserActor?.accounts?.map {
68
- ProfileState.Account(
69
- name = it.name,
70
- avatar = it.ownerUserActor?.profilePhoto
71
- )
72
- } ?: emptyList()
73
-
74
- ProfileState.LoggedIn(
75
- isLoading = false,
76
- accounts = accounts
77
- )
78
- }
79
- }
80
- }
81
-
82
66
  fun onAction(action: Action) {
83
67
  when (action) {
84
68
  is Action.LogIn -> {
85
- sessionSession.setSession(
69
+ session.setSession(
86
70
  Session(action.sessionSecret)
87
71
  )
88
72
  }
89
73
 
90
74
  Action.SignOut -> {
91
- sessionSession.setSession(null)
75
+ session.setSession(null)
92
76
  }
77
+
78
+ is Action.SwitchAccount -> session.switchAccount(action.account.id)
93
79
  }
94
80
  }
95
81
  }
@@ -91,7 +91,7 @@ fun Accordion(
91
91
  @Composable
92
92
  @Preview(showBackground = true, heightDp = 200)
93
93
  fun AccordionVariantPreview() {
94
- Accordion(text = "Enter URL") {
94
+ Accordion(text = "Enter URL manually") {
95
95
  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.")
96
96
  }
97
97
  }
@@ -0,0 +1,40 @@
1
+ package expo.modules.devlauncher.compose.primitives
2
+
3
+ import androidx.compose.foundation.Image
4
+ import androidx.compose.runtime.Composable
5
+ import androidx.compose.runtime.LaunchedEffect
6
+ import androidx.compose.runtime.getValue
7
+ import androidx.compose.runtime.mutableStateOf
8
+ import androidx.compose.runtime.remember
9
+ import androidx.compose.runtime.rememberCoroutineScope
10
+ import androidx.compose.runtime.setValue
11
+ import androidx.compose.ui.graphics.ImageBitmap
12
+ import androidx.compose.ui.graphics.asImageBitmap
13
+ import expo.modules.devlauncher.services.ImageLoaderService
14
+ import expo.modules.devlauncher.services.inject
15
+ import kotlinx.coroutines.launch
16
+
17
+ @Composable
18
+ fun AsyncImage(
19
+ url: String
20
+ ) {
21
+ val imageLoaderService = inject<ImageLoaderService>()
22
+ val scope = rememberCoroutineScope()
23
+ var imageBitmap by remember { mutableStateOf<ImageBitmap?>(null) }
24
+
25
+ LaunchedEffect(url) {
26
+ scope.launch {
27
+ val image = imageLoaderService.loadImage(url)
28
+ if (image != null) {
29
+ imageBitmap = image.asImageBitmap()
30
+ }
31
+ }
32
+ }
33
+
34
+ imageBitmap?.let {
35
+ Image(
36
+ bitmap = it,
37
+ contentDescription = url
38
+ )
39
+ }
40
+ }
@@ -0,0 +1,23 @@
1
+ package expo.modules.devlauncher.compose.routes
2
+
3
+ import androidx.compose.runtime.Composable
4
+ import androidx.lifecycle.viewmodel.compose.viewModel
5
+ import expo.modules.devlauncher.compose.DefaultScreenContainer
6
+ import expo.modules.devlauncher.compose.HomeViewModel
7
+ import expo.modules.devlauncher.compose.screens.HomeScreen
8
+ import kotlinx.serialization.Serializable
9
+
10
+ @Serializable
11
+ object Home
12
+
13
+ @Composable
14
+ fun HomeRoute(onProfileClick: () -> Unit) {
15
+ DefaultScreenContainer {
16
+ val viewModel = viewModel<HomeViewModel>()
17
+ HomeScreen(
18
+ state = viewModel.state,
19
+ onAction = viewModel::onAction,
20
+ onProfileClick = onProfileClick
21
+ )
22
+ }
23
+ }
@@ -1,4 +1,4 @@
1
- package expo.modules.devlauncher.compose.screens
1
+ package expo.modules.devlauncher.compose.routes
2
2
 
3
3
  import androidx.activity.compose.rememberLauncherForActivityResult
4
4
  import androidx.compose.runtime.Composable
@@ -18,7 +18,7 @@ import expo.modules.devlauncher.compose.ui.ProfileLayout
18
18
  import expo.modules.devlauncher.compose.ui.SignUp
19
19
 
20
20
  @Composable
21
- fun Profile(
21
+ fun ProfileRoute(
22
22
  bottomSheetState: ModalBottomSheetState,
23
23
  viewModel: ProfileViewModel = viewModel()
24
24
  ) {
@@ -44,6 +44,9 @@ fun Profile(
44
44
  accounts = state.accounts,
45
45
  onSignOut = {
46
46
  viewModel.onAction(ProfileViewModel.Action.SignOut)
47
+ },
48
+ onClick = { account ->
49
+ viewModel.onAction(ProfileViewModel.Action.SwitchAccount(account))
47
50
  }
48
51
  )
49
52
  }
@@ -58,6 +61,9 @@ fun Profile(
58
61
  }
59
62
  )
60
63
  }
64
+
65
+ ProfileState.Fetching -> {
66
+ }
61
67
  }
62
68
  }
63
69
  }
@@ -0,0 +1,16 @@
1
+ package expo.modules.devlauncher.compose.routes
2
+
3
+ import androidx.compose.runtime.Composable
4
+ import expo.modules.devlauncher.compose.DefaultScreenContainer
5
+ import expo.modules.devlauncher.compose.screens.SettingsScreen
6
+ import kotlinx.serialization.Serializable
7
+
8
+ @Serializable
9
+ object Settings
10
+
11
+ @Composable
12
+ fun SettingsRoute() {
13
+ DefaultScreenContainer {
14
+ SettingsScreen()
15
+ }
16
+ }