expo-dev-menu 58.0.9 → 58.0.10
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.
- package/CHANGELOG.md +6 -0
- package/android/build.gradle +2 -2
- package/android/src/debug/java/expo/modules/devmenu/compose/ripple/Ripple.kt +8 -2
- package/android/src/debug/java/expo/modules/devmenu/compose/ripple/RippleAlpha.kt +18 -6
- package/android/src/debug/java/expo/modules/devmenu/compose/ripple/RippleFactory.kt +35 -11
- package/android/src/debug/java/expo/modules/devmenu/compose/ripple/RippleHostView.kt +10 -2
- package/android/src/debug/java/expo/modules/devmenu/fab/FabState.kt +10 -2
- package/android/src/debug/java/expo/modules/devmenu/fab/FloatingActionButtonContent.kt +15 -3
- package/android/src/debug/java/expo/modules/devmenu/fab/MovableFloatingActionButton.kt +5 -1
- package/android/src/debug/java/expo/modules/devmenu/launch/ExpoLauncherUrl.kt +8 -2
- package/ios/DevMenuViewController.swift +7 -0
- package/ios/SwiftUI/HeaderView.swift +2 -1
- package/package.json +4 -4
package/CHANGELOG.md
CHANGED
|
@@ -1,5 +1,11 @@
|
|
|
1
1
|
# Changelog
|
|
2
2
|
|
|
3
|
+
## 58.0.10
|
|
4
|
+
|
|
5
|
+
### Patch Changes
|
|
6
|
+
|
|
7
|
+
- [iOS] Disable the vertical bar while the dev menu is open so the sheet fills the full width on iPhone Duo. ([#50900](https://github.com/expo/expo/pull/50900) by [@alanjhughes](https://github.com/alanjhughes))
|
|
8
|
+
|
|
3
9
|
## 58.0.9
|
|
4
10
|
|
|
5
11
|
### Patch Changes
|
package/android/build.gradle
CHANGED
|
@@ -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 = '58.0.
|
|
15
|
+
version = '58.0.10'
|
|
16
16
|
|
|
17
17
|
def hasDevLauncher = findProject(":expo-dev-launcher") != null
|
|
18
18
|
def configureInRelease = findProperty("expo.devmenu.configureInRelease") == "true"
|
|
@@ -29,7 +29,7 @@ android {
|
|
|
29
29
|
|
|
30
30
|
defaultConfig {
|
|
31
31
|
versionCode 10
|
|
32
|
-
versionName '58.0.
|
|
32
|
+
versionName '58.0.10'
|
|
33
33
|
}
|
|
34
34
|
|
|
35
35
|
buildTypes {
|
|
@@ -69,7 +69,11 @@ internal class CommonRippleNode(
|
|
|
69
69
|
override fun addRipple(interaction: PressInteraction.Press, size: Size, targetRadius: Float) {
|
|
70
70
|
// Finish existing ripples
|
|
71
71
|
ripples.forEach { _, ripple -> ripple.finish() }
|
|
72
|
-
val origin = if (bounded)
|
|
72
|
+
val origin = if (bounded) {
|
|
73
|
+
interaction.pressPosition
|
|
74
|
+
} else {
|
|
75
|
+
null
|
|
76
|
+
}
|
|
73
77
|
val rippleAnimation =
|
|
74
78
|
RippleAnimation(origin = origin, radius = targetRadius, bounded = bounded)
|
|
75
79
|
ripples[interaction] = rippleAnimation
|
|
@@ -186,7 +190,9 @@ internal class AndroidRippleNode(
|
|
|
186
190
|
}
|
|
187
191
|
|
|
188
192
|
private fun getOrCreateRippleContainer(): RippleContainer {
|
|
189
|
-
if (rippleContainer != null)
|
|
193
|
+
if (rippleContainer != null) {
|
|
194
|
+
return rippleContainer!!
|
|
195
|
+
}
|
|
190
196
|
val view = findNearestViewGroup(currentValueOf(LocalView))
|
|
191
197
|
rippleContainer = createAndAttachRippleContainerIfNeeded(view)
|
|
192
198
|
return rippleContainer!!
|
|
@@ -26,13 +26,25 @@ public class RippleAlpha(
|
|
|
26
26
|
public val pressedAlpha: Float
|
|
27
27
|
) {
|
|
28
28
|
override fun equals(other: Any?): Boolean {
|
|
29
|
-
if (this === other)
|
|
30
|
-
|
|
29
|
+
if (this === other) {
|
|
30
|
+
return true
|
|
31
|
+
}
|
|
32
|
+
if (other !is RippleAlpha) {
|
|
33
|
+
return false
|
|
34
|
+
}
|
|
31
35
|
|
|
32
|
-
if (draggedAlpha != other.draggedAlpha)
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
if (
|
|
36
|
+
if (draggedAlpha != other.draggedAlpha) {
|
|
37
|
+
return false
|
|
38
|
+
}
|
|
39
|
+
if (focusedAlpha != other.focusedAlpha) {
|
|
40
|
+
return false
|
|
41
|
+
}
|
|
42
|
+
if (hoveredAlpha != other.hoveredAlpha) {
|
|
43
|
+
return false
|
|
44
|
+
}
|
|
45
|
+
if (pressedAlpha != other.pressedAlpha) {
|
|
46
|
+
return false
|
|
47
|
+
}
|
|
36
48
|
|
|
37
49
|
return true
|
|
38
50
|
}
|
|
@@ -77,7 +77,11 @@ fun ripple(
|
|
|
77
77
|
color: Color = Color.Unspecified
|
|
78
78
|
): IndicationNodeFactory {
|
|
79
79
|
return if (radius == Dp.Unspecified && color == Color.Unspecified) {
|
|
80
|
-
if (bounded)
|
|
80
|
+
if (bounded) {
|
|
81
|
+
return DefaultBoundedRipple
|
|
82
|
+
} else {
|
|
83
|
+
DefaultUnboundedRipple
|
|
84
|
+
}
|
|
81
85
|
} else {
|
|
82
86
|
RippleNodeFactory(bounded, radius, color)
|
|
83
87
|
}
|
|
@@ -207,11 +211,19 @@ class RippleConfiguration(
|
|
|
207
211
|
val rippleAlpha: RippleAlpha? = null
|
|
208
212
|
) {
|
|
209
213
|
override fun equals(other: Any?): Boolean {
|
|
210
|
-
if (this === other)
|
|
211
|
-
|
|
214
|
+
if (this === other) {
|
|
215
|
+
return true
|
|
216
|
+
}
|
|
217
|
+
if (other !is RippleConfiguration) {
|
|
218
|
+
return false
|
|
219
|
+
}
|
|
212
220
|
|
|
213
|
-
if (color != other.color)
|
|
214
|
-
|
|
221
|
+
if (color != other.color) {
|
|
222
|
+
return false
|
|
223
|
+
}
|
|
224
|
+
if (rippleAlpha != other.rippleAlpha) {
|
|
225
|
+
return false
|
|
226
|
+
}
|
|
215
227
|
|
|
216
228
|
return true
|
|
217
229
|
}
|
|
@@ -249,12 +261,22 @@ private constructor(
|
|
|
249
261
|
}
|
|
250
262
|
|
|
251
263
|
override fun equals(other: Any?): Boolean {
|
|
252
|
-
if (this === other)
|
|
253
|
-
|
|
264
|
+
if (this === other) {
|
|
265
|
+
return true
|
|
266
|
+
}
|
|
267
|
+
if (other !is RippleNodeFactory) {
|
|
268
|
+
return false
|
|
269
|
+
}
|
|
254
270
|
|
|
255
|
-
if (bounded != other.bounded)
|
|
256
|
-
|
|
257
|
-
|
|
271
|
+
if (bounded != other.bounded) {
|
|
272
|
+
return false
|
|
273
|
+
}
|
|
274
|
+
if (radius != other.radius) {
|
|
275
|
+
return false
|
|
276
|
+
}
|
|
277
|
+
if (colorProducer != other.colorProducer) {
|
|
278
|
+
return false
|
|
279
|
+
}
|
|
258
280
|
return color == other.color
|
|
259
281
|
}
|
|
260
282
|
|
|
@@ -294,7 +316,9 @@ private class DelegatingThemeAwareRippleNode(
|
|
|
294
316
|
if (configuration == null) {
|
|
295
317
|
removeRipple()
|
|
296
318
|
} else {
|
|
297
|
-
if (rippleNode == null)
|
|
319
|
+
if (rippleNode == null) {
|
|
320
|
+
attachNewRipple()
|
|
321
|
+
}
|
|
298
322
|
}
|
|
299
323
|
}
|
|
300
324
|
}
|
|
@@ -227,7 +227,11 @@ internal class RippleHostView(context: Context) : View(context) {
|
|
|
227
227
|
}
|
|
228
228
|
postDelayed(resetRippleRunnable, ResetRippleDelayDuration)
|
|
229
229
|
} else {
|
|
230
|
-
val state = if (pressed)
|
|
230
|
+
val state = if (pressed) {
|
|
231
|
+
PressedState
|
|
232
|
+
} else {
|
|
233
|
+
RestingState
|
|
234
|
+
}
|
|
231
235
|
ripple?.state = state
|
|
232
236
|
}
|
|
233
237
|
lastRippleStateChangeTimeMillis = currentTime
|
|
@@ -276,7 +280,11 @@ private class UnprojectedRipple(private val bounded: Boolean) :
|
|
|
276
280
|
// The color of the mask here doesn't matter - we just need a mask to draw the bounded
|
|
277
281
|
// ripple
|
|
278
282
|
// against
|
|
279
|
-
/* mask */ if (bounded)
|
|
283
|
+
/* mask */ if (bounded) {
|
|
284
|
+
ColorDrawable(android.graphics.Color.WHITE)
|
|
285
|
+
} else {
|
|
286
|
+
null
|
|
287
|
+
}
|
|
280
288
|
) {
|
|
281
289
|
/**
|
|
282
290
|
* Store the ripple color so we can compare it later, as there is no way to get the currently
|
|
@@ -41,8 +41,16 @@ class FabState(
|
|
|
41
41
|
|
|
42
42
|
fun savePosition(offset: Offset) {
|
|
43
43
|
// Store position as 0–1 ratios within the safe area so it survives screen size changes
|
|
44
|
-
val normalizedX = if (fabAreaBounds.x > 0f)
|
|
45
|
-
|
|
44
|
+
val normalizedX = if (fabAreaBounds.x > 0f) {
|
|
45
|
+
offset.x / fabAreaBounds.x
|
|
46
|
+
} else {
|
|
47
|
+
0f
|
|
48
|
+
}
|
|
49
|
+
val normalizedY = if (fabAreaBounds.y > 0f) {
|
|
50
|
+
offset.y / fabAreaBounds.y
|
|
51
|
+
} else {
|
|
52
|
+
0f
|
|
53
|
+
}
|
|
46
54
|
|
|
47
55
|
prefs.edit {
|
|
48
56
|
putFloat(FAB_POSITION_X, normalizedX)
|
|
@@ -42,17 +42,29 @@ fun FloatingActionButtonContent(
|
|
|
42
42
|
showLabel: Boolean = true
|
|
43
43
|
) {
|
|
44
44
|
val scale by animateFloatAsState(
|
|
45
|
-
targetValue = if (isPressed && !isDragging)
|
|
45
|
+
targetValue = if (isPressed && !isDragging) {
|
|
46
|
+
0.9f
|
|
47
|
+
} else {
|
|
48
|
+
1f
|
|
49
|
+
},
|
|
46
50
|
label = "pressScale"
|
|
47
51
|
)
|
|
48
52
|
|
|
49
53
|
val idleAlpha by animateFloatAsState(
|
|
50
|
-
targetValue = if (isIdle)
|
|
54
|
+
targetValue = if (isIdle) {
|
|
55
|
+
0.5f
|
|
56
|
+
} else {
|
|
57
|
+
1f
|
|
58
|
+
},
|
|
51
59
|
label = "idleAlpha"
|
|
52
60
|
)
|
|
53
61
|
|
|
54
62
|
val idleSaturation by animateFloatAsState(
|
|
55
|
-
targetValue = if (isIdle)
|
|
63
|
+
targetValue = if (isIdle) {
|
|
64
|
+
0f
|
|
65
|
+
} else {
|
|
66
|
+
1f
|
|
67
|
+
},
|
|
56
68
|
label = "idleSaturation"
|
|
57
69
|
)
|
|
58
70
|
|
|
@@ -109,7 +109,11 @@ fun MovableFloatingActionButton(
|
|
|
109
109
|
if (state.isOpen) {
|
|
110
110
|
fab.restingOffset = fab.animatedOffset.value
|
|
111
111
|
val isOnLeftSide = fab.animatedOffset.value.x < fab.fabAreaBounds.x / 2f
|
|
112
|
-
val offScreenX = if (isOnLeftSide)
|
|
112
|
+
val offScreenX = if (isOnLeftSide) {
|
|
113
|
+
-totalFabSizePx.x
|
|
114
|
+
} else {
|
|
115
|
+
constraints.maxWidth.toFloat()
|
|
116
|
+
}
|
|
113
117
|
fab.animatedOffset.animateTo(
|
|
114
118
|
targetValue = Offset(offScreenX, fab.animatedOffset.value.y),
|
|
115
119
|
animationSpec = tween(durationMillis = 500)
|
|
@@ -8,7 +8,11 @@ import android.net.Uri
|
|
|
8
8
|
* Keep in sync with `packages/expo-dev-menu/ios/Launch/ExpoLauncherURL.swift`.
|
|
9
9
|
*/
|
|
10
10
|
class ExpoLauncherUrl(val url: Uri) {
|
|
11
|
-
private val paramNames: Set<String> = if (url.isHierarchical)
|
|
11
|
+
private val paramNames: Set<String> = if (url.isHierarchical) {
|
|
12
|
+
url.queryParameterNames
|
|
13
|
+
} else {
|
|
14
|
+
emptySet()
|
|
15
|
+
}
|
|
12
16
|
private val hasReservedParams = paramNames.any { it.startsWith(RESERVED_PREFIX) }
|
|
13
17
|
|
|
14
18
|
val isLegacyHost = url.host == LEGACY_HOST
|
|
@@ -47,7 +51,9 @@ class ExpoLauncherUrl(val url: Uri) {
|
|
|
47
51
|
|
|
48
52
|
/** `__expo_<name>`, or the [legacy] param next to the legacy host. */
|
|
49
53
|
private fun param(name: String, legacy: String? = null): String? {
|
|
50
|
-
if (!url.isHierarchical)
|
|
54
|
+
if (!url.isHierarchical) {
|
|
55
|
+
return null
|
|
56
|
+
}
|
|
51
57
|
return url.getQueryParameter(RESERVED_PREFIX + name)
|
|
52
58
|
?: legacy?.takeIf { isLegacyHost }?.let(url::getQueryParameter)
|
|
53
59
|
}
|
|
@@ -42,6 +42,13 @@ class DevMenuViewController: UIViewController {
|
|
|
42
42
|
}
|
|
43
43
|
#endif
|
|
44
44
|
|
|
45
|
+
#if canImport(SwiftUICore, _version: 8.0.85) && os(iOS)
|
|
46
|
+
@available(iOS 27.1, *)
|
|
47
|
+
override var preferredVerticalBarBehavior: UIVerticalBarBehavior {
|
|
48
|
+
return .disabled
|
|
49
|
+
}
|
|
50
|
+
#endif
|
|
51
|
+
|
|
45
52
|
private func setupSwiftUIView() {
|
|
46
53
|
let rootView = DevMenuRootView()
|
|
47
54
|
let hostingController = UIHostingController(rootView: rootView)
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "expo-dev-menu",
|
|
3
|
-
"version": "58.0.
|
|
3
|
+
"version": "58.0.10",
|
|
4
4
|
"description": "Expo/React Native module with the developer menu.",
|
|
5
5
|
"keywords": [
|
|
6
6
|
"dev",
|
|
@@ -28,11 +28,11 @@
|
|
|
28
28
|
},
|
|
29
29
|
"devDependencies": {
|
|
30
30
|
"@babel/preset-typescript": "^7.7.4",
|
|
31
|
-
"@testing-library/react-native": "^
|
|
31
|
+
"@testing-library/react-native": "^14.0.1",
|
|
32
32
|
"@types/jest": "^29.2.1",
|
|
33
33
|
"@types/node": "^22.14.0",
|
|
34
|
-
"babel-preset-expo": "58.0.
|
|
35
|
-
"expo-module-scripts": "56.0.
|
|
34
|
+
"babel-preset-expo": "58.0.8",
|
|
35
|
+
"expo-module-scripts": "56.0.5",
|
|
36
36
|
"react": "19.3.0",
|
|
37
37
|
"react-native": "0.88.0-rc.3"
|
|
38
38
|
},
|