Merge branch 'main' into d/profile-screen

This commit is contained in:
DS Boyce
2026-02-11 09:43:55 -08:00
26 changed files with 299 additions and 324 deletions
+6 -1
View File
@@ -118,7 +118,12 @@ jobs:
fi fi
- name: 🚀 Deploy - name: 🚀 Deploy
run: eas submit -p ios --non-interactive --path ios-build/ios/build/Bluesky.ipa env:
PROFILE: ${{ inputs.profile || 'testflight' }}
run: >
eas submit -p ios --non-interactive
--path ios-build/ios/build/Bluesky.ipa
--what-to-test "$([[ "$PROFILE" == "production" ]] && echo "Production build" || echo "TestFlight build")"
- name: 🪲 Upload dSYM to Sentry - name: 🪲 Upload dSYM to Sentry
run: > run: >
@@ -242,7 +242,7 @@ jobs:
--local --output build.ipa --non-interactive --local --output build.ipa --non-interactive
- name: 🚀 Deploy - name: 🚀 Deploy
run: eas submit -p ios --non-interactive --path build.ipa run: eas submit -p ios --non-interactive --path build.ipa --what-to-test "TestFlight build"
- name: ⬇️ Restore Cache - name: ⬇️ Restore Cache
id: get-base-commit id: get-base-commit
+1 -1
View File
@@ -44,6 +44,6 @@ android {
dependencies { dependencies {
implementation project(':expo-modules-core') implementation project(':expo-modules-core')
implementation 'com.google.android.material:material:1.12.0' implementation 'com.google.android.material:material:1.13.0'
implementation "com.facebook.react:react-native:+" implementation "com.facebook.react:react-native:+"
} }
@@ -5,8 +5,12 @@ import android.util.DisplayMetrics
import android.view.View import android.view.View
import android.view.ViewGroup import android.view.ViewGroup
import android.view.ViewStructure import android.view.ViewStructure
import android.view.Window
import android.view.accessibility.AccessibilityEvent import android.view.accessibility.AccessibilityEvent
import android.widget.FrameLayout import android.widget.FrameLayout
import androidx.core.view.ViewCompat
import androidx.core.view.WindowInsetsCompat
import androidx.core.view.WindowInsetsControllerCompat
import androidx.core.view.allViews import androidx.core.view.allViews
import com.facebook.react.bridge.LifecycleEventListener import com.facebook.react.bridge.LifecycleEventListener
import com.facebook.react.bridge.ReactContext import com.facebook.react.bridge.ReactContext
@@ -15,6 +19,7 @@ import com.facebook.react.uimanager.UIManagerHelper
import com.facebook.react.uimanager.events.EventDispatcher import com.facebook.react.uimanager.events.EventDispatcher
import com.google.android.material.bottomsheet.BottomSheetBehavior import com.google.android.material.bottomsheet.BottomSheetBehavior
import com.google.android.material.bottomsheet.BottomSheetDialog import com.google.android.material.bottomsheet.BottomSheetDialog
import com.google.android.material.internal.EdgeToEdgeUtils
import expo.modules.kotlin.AppContext import expo.modules.kotlin.AppContext
import expo.modules.kotlin.viewevent.EventDispatcher import expo.modules.kotlin.viewevent.EventDispatcher
import expo.modules.kotlin.views.ExpoView import expo.modules.kotlin.views.ExpoView
@@ -29,22 +34,26 @@ class BottomSheetView(
private lateinit var dialogRootViewGroup: DialogRootViewGroup private lateinit var dialogRootViewGroup: DialogRootViewGroup
private var eventDispatcher: EventDispatcher? = null private var eventDispatcher: EventDispatcher? = null
private var isKeyboardVisible: Boolean = false
private val rawScreenHeight = private val screenHeight =
context.resources.displayMetrics.heightPixels context.resources.displayMetrics.heightPixels
.toFloat() .toFloat()
private val safeScreenHeight = (rawScreenHeight - getNavigationBarHeight()).toFloat()
private fun getNavigationBarHeight(): Int { private fun getNavigationBarHeight(): Int {
val resourceId = resources.getIdentifier("navigation_bar_height", "dimen", "android") val resourceId = resources.getIdentifier("navigation_bar_height", "dimen", "android")
return if (resourceId > 0) resources.getDimensionPixelSize(resourceId) else 0 return if (resourceId > 0) resources.getDimensionPixelSize(resourceId) else 0
} }
private fun getStatusBarHeight(): Int {
val resourceId = resources.getIdentifier("status_bar_height", "dimen", "android")
return if (resourceId > 0) resources.getDimensionPixelSize(resourceId) else 0
}
private val onAttemptDismiss by EventDispatcher() private val onAttemptDismiss by EventDispatcher()
private val onSnapPointChange by EventDispatcher() private val onSnapPointChange by EventDispatcher()
private val onStateChange by EventDispatcher() private val onStateChange by EventDispatcher()
// Props
var disableDrag = false var disableDrag = false
set(value) { set(value) {
field = value field = value
@@ -56,48 +65,31 @@ class BottomSheetView(
field = value field = value
this.dialog?.setCancelable(!value) this.dialog?.setCancelable(!value)
} }
var preventExpansion = false var preventExpansion = false
var minHeight = 0f var minHeight = 0f
set(value) { set(value) {
field = field = if (value < 0) 0f else dpToPx(value)
if (value < 0) {
0f
} else {
dpToPx(value)
}
} }
var maxHeight = this.safeScreenHeight var maxHeight = this.screenHeight
set(value) { set(value) {
val px = dpToPx(value) val px = dpToPx(value)
field = field = if (px > this.screenHeight) this.screenHeight else px
if (px > this.safeScreenHeight) {
this.safeScreenHeight
} else {
px
}
} }
private var isOpen: Boolean = false private var isOpen: Boolean = false
set(value) { set(value) {
field = value field = value
onStateChange( onStateChange(mapOf("state" to if (value) "open" else "closed"))
mapOf(
"state" to if (value) "open" else "closed",
),
)
} }
private var isOpening: Boolean = false private var isOpening: Boolean = false
set(value) { set(value) {
field = value field = value
if (value) { if (value) {
onStateChange( onStateChange(mapOf("state" to "opening"))
mapOf(
"state" to "opening",
),
)
} }
} }
@@ -105,33 +97,21 @@ class BottomSheetView(
set(value) { set(value) {
field = value field = value
if (value) { if (value) {
onStateChange( onStateChange(mapOf("state" to "closing"))
mapOf(
"state" to "closing",
),
)
} }
} }
private var selectedSnapPoint = 0 private var selectedSnapPoint = 0
set(value) { set(value) {
if (field == value) return if (field == value) return
field = value field = value
onSnapPointChange( onSnapPointChange(mapOf("snapPoint" to value))
mapOf(
"snapPoint" to value,
),
)
} }
// Lifecycle
init { init {
(appContext.reactContext as? ReactContext)?.let { (appContext.reactContext as? ReactContext)?.let {
it.addLifecycleEventListener(this) it.addLifecycleEventListener(this)
this.eventDispatcher = UIManagerHelper.getEventDispatcherForReactTag(it, this.id) this.eventDispatcher = UIManagerHelper.getEventDispatcherForReactTag(it, this.id)
this.dialogRootViewGroup = DialogRootViewGroup(context) this.dialogRootViewGroup = DialogRootViewGroup(context)
this.dialogRootViewGroup.eventDispatcher = this.eventDispatcher this.dialogRootViewGroup.eventDispatcher = this.eventDispatcher
} }
@@ -161,27 +141,55 @@ class BottomSheetView(
private fun getHalfExpandedRatio(contentHeight: Float): Float = private fun getHalfExpandedRatio(contentHeight: Float): Float =
when { when {
// Full height sheets // Full height sheets
contentHeight >= safeScreenHeight -> 0.99f contentHeight >= screenHeight -> 0.99f
// Medium height sheets (>50% but <100%) else -> this.clampRatio(this.getTargetHeight() / screenHeight)
contentHeight >= safeScreenHeight / 2 ->
this.clampRatio(this.getTargetHeight() / safeScreenHeight)
// Small height sheets (<50%)
else ->
this.clampRatio(this.getTargetHeight() / rawScreenHeight)
} }
private fun present() { private fun present() {
if (this.isOpen || this.isOpening || this.isClosing) return if (this.isOpen || this.isOpening || this.isClosing) return
val contentHeight = this.getContentHeight() val contentHeight = this.getContentHeight()
val dialog = BottomSheetDialog(context)
var activityWindow: Window? = null
var currentContext = context
while (currentContext != null) {
if (currentContext is android.app.Activity) {
activityWindow = currentContext.window
break
}
currentContext = (currentContext as? android.content.ContextWrapper)?.baseContext
}
val originalStatusBarAppearance =
activityWindow?.let { window ->
WindowInsetsControllerCompat(window, window.decorView).isAppearanceLightStatusBars
}
val originalNavBarAppearance =
activityWindow?.let { window ->
WindowInsetsControllerCompat(window, window.decorView).isAppearanceLightNavigationBars
}
val dialog = BottomSheetDialog(context, R.style.EdgeToEdgeBottomSheetDialogTheme)
dialog.setContentView(dialogRootViewGroup) dialog.setContentView(dialogRootViewGroup)
dialog.setCancelable(!preventDismiss) dialog.setCancelable(!preventDismiss)
dialog.setDismissWithAnimation(true)
dialog.setOnDismissListener { dialog.setOnDismissListener {
this.isClosing = true this.isClosing = true
this.destroy() this.destroy()
} }
dialog.setOnShowListener {
dialog.window?.let { window ->
val insetsController = WindowInsetsControllerCompat(window, window.decorView)
if (originalNavBarAppearance != null) {
insetsController.isAppearanceLightNavigationBars = originalNavBarAppearance
}
if (originalStatusBarAppearance != null) {
EdgeToEdgeUtils.setLightStatusBar(window, originalStatusBarAppearance)
}
}
}
val bottomSheet = dialog.findViewById<FrameLayout>(com.google.android.material.R.id.design_bottom_sheet) val bottomSheet = dialog.findViewById<FrameLayout>(com.google.android.material.R.id.design_bottom_sheet)
bottomSheet?.let { bottomSheet?.let {
it.setBackgroundColor(0) it.setBackgroundColor(0)
@@ -194,7 +202,17 @@ class BottomSheetView(
behavior.isDraggable = true behavior.isDraggable = true
behavior.isHideable = true behavior.isHideable = true
if (contentHeight >= this.safeScreenHeight || this.minHeight >= this.safeScreenHeight) { if (preventExpansion) {
behavior.maxHeight = (behavior.halfExpandedRatio * screenHeight).toInt()
} else {
behavior.maxHeight = (screenHeight - getStatusBarHeight()).toInt()
}
val targetHeight = this.getTargetHeight()
val availableHeight = screenHeight - getStatusBarHeight() - getNavigationBarHeight()
val shouldBeExpanded = targetHeight >= availableHeight
if (shouldBeExpanded) {
behavior.state = BottomSheetBehavior.STATE_EXPANDED behavior.state = BottomSheetBehavior.STATE_EXPANDED
this.selectedSnapPoint = 2 this.selectedSnapPoint = 2
} else { } else {
@@ -209,18 +227,10 @@ class BottomSheetView(
newState: Int, newState: Int,
) { ) {
when (newState) { when (newState) {
BottomSheetBehavior.STATE_EXPANDED -> { BottomSheetBehavior.STATE_EXPANDED -> selectedSnapPoint = 2
selectedSnapPoint = 2 BottomSheetBehavior.STATE_COLLAPSED -> selectedSnapPoint = 1
} BottomSheetBehavior.STATE_HALF_EXPANDED -> selectedSnapPoint = 1
BottomSheetBehavior.STATE_COLLAPSED -> { BottomSheetBehavior.STATE_HIDDEN -> selectedSnapPoint = 0
selectedSnapPoint = 1
}
BottomSheetBehavior.STATE_HALF_EXPANDED -> {
selectedSnapPoint = 1
}
BottomSheetBehavior.STATE_HIDDEN -> {
selectedSnapPoint = 0
}
} }
} }
@@ -231,9 +241,26 @@ class BottomSheetView(
}, },
) )
} }
this.isOpening = true this.isOpening = true
dialog.show() dialog.show()
this.dialog = dialog this.dialog = dialog
ViewCompat.setOnApplyWindowInsetsListener(dialogRootViewGroup) { view, insets ->
val imeVisible = insets.isVisible(WindowInsetsCompat.Type.ime())
val bottomSheet = dialog.findViewById<FrameLayout>(com.google.android.material.R.id.design_bottom_sheet)
val behavior = bottomSheet?.let { BottomSheetBehavior.from(it) }
val wasKeyboardVisible = isKeyboardVisible
isKeyboardVisible = imeVisible
if (imeVisible && behavior?.state == BottomSheetBehavior.STATE_HALF_EXPANDED) {
behavior.state = BottomSheetBehavior.STATE_EXPANDED
} else if (!imeVisible && wasKeyboardVisible) {
updateLayout()
}
insets
}
} }
fun updateLayout() { fun updateLayout() {
@@ -246,12 +273,24 @@ class BottomSheetView(
val currentState = behavior.state val currentState = behavior.state
val oldRatio = behavior.halfExpandedRatio val oldRatio = behavior.halfExpandedRatio
var newRatio = getHalfExpandedRatio(contentHeight) val newRatio = getHalfExpandedRatio(contentHeight)
behavior.halfExpandedRatio = newRatio behavior.halfExpandedRatio = newRatio
if (contentHeight > this.safeScreenHeight && behavior.state != BottomSheetBehavior.STATE_EXPANDED) { if (preventExpansion) {
behavior.maxHeight = (behavior.halfExpandedRatio * screenHeight).toInt()
}
val targetHeight = this.getTargetHeight()
val availableHeight = screenHeight - getStatusBarHeight() - getNavigationBarHeight()
val shouldBeExpanded = targetHeight >= availableHeight
if (isKeyboardVisible) {
if (behavior.state != BottomSheetBehavior.STATE_EXPANDED) {
behavior.state = BottomSheetBehavior.STATE_EXPANDED behavior.state = BottomSheetBehavior.STATE_EXPANDED
} else if (contentHeight < this.safeScreenHeight && behavior.state != BottomSheetBehavior.STATE_HALF_EXPANDED) { }
} else if (shouldBeExpanded && behavior.state != BottomSheetBehavior.STATE_EXPANDED && !preventExpansion) {
behavior.state = BottomSheetBehavior.STATE_EXPANDED
} else if (!shouldBeExpanded && behavior.state != BottomSheetBehavior.STATE_HALF_EXPANDED) {
behavior.state = BottomSheetBehavior.STATE_HALF_EXPANDED behavior.state = BottomSheetBehavior.STATE_HALF_EXPANDED
} else if (currentState == BottomSheetBehavior.STATE_HALF_EXPANDED && oldRatio != newRatio) { } else if (currentState == BottomSheetBehavior.STATE_HALF_EXPANDED && oldRatio != newRatio) {
behavior.state = BottomSheetBehavior.STATE_HALF_EXPANDED behavior.state = BottomSheetBehavior.STATE_HALF_EXPANDED
@@ -279,24 +318,18 @@ class BottomSheetView(
private fun getTargetHeight(): Float { private fun getTargetHeight(): Float {
val contentHeight = this.getContentHeight() val contentHeight = this.getContentHeight()
val height = return when {
if (contentHeight > maxHeight) { contentHeight > maxHeight -> maxHeight
maxHeight contentHeight < minHeight -> minHeight
} else if (contentHeight < minHeight) { else -> contentHeight
minHeight
} else {
contentHeight
} }
return height
} }
private fun clampRatio(ratio: Float): Float { private fun clampRatio(ratio: Float): Float =
if (ratio < 0.01) { when {
return 0.01f ratio < 0.01 -> 0.01f
} else if (ratio > 0.99) { ratio > 0.99 -> 0.99f
return 0.99f else -> ratio
}
return ratio
} }
private fun setDraggable(draggable: Boolean) { private fun setDraggable(draggable: Boolean) {
@@ -322,9 +355,7 @@ class BottomSheetView(
// View overrides to pass to DialogRootViewGroup instead // View overrides to pass to DialogRootViewGroup instead
override fun dispatchProvideStructure(structure: ViewStructure?) { override fun dispatchProvideStructure(structure: ViewStructure?) {
if (structure == null) { if (structure == null) return
return
}
dialogRootViewGroup.dispatchProvideStructure(structure) dialogRootViewGroup.dispatchProvideStructure(structure)
} }
@@ -363,7 +394,6 @@ class BottomSheetView(
// https://stackoverflow.com/questions/11862391/getheight-px-or-dpi // https://stackoverflow.com/questions/11862391/getheight-px-or-dpi
fun dpToPx(dp: Float): Float { fun dpToPx(dp: Float): Float {
val displayMetrics = context.resources.displayMetrics val displayMetrics = context.resources.displayMetrics
val px = dp * (displayMetrics.xdpi / DisplayMetrics.DENSITY_DEFAULT) return dp * (displayMetrics.xdpi / DisplayMetrics.DENSITY_DEFAULT)
return px
} }
} }
@@ -52,6 +52,8 @@ class DialogRootViewGroup(
if (ReactFeatureFlags.dispatchPointerEvents) { if (ReactFeatureFlags.dispatchPointerEvents) {
jSPointerDispatcher = JSPointerDispatcher(this) jSPointerDispatcher = JSPointerDispatcher(this)
} }
fitsSystemWindows = false
} }
override fun onSizeChanged( override fun onSizeChanged(
@@ -0,0 +1,20 @@
<?xml version="1.0" encoding="utf-8"?>
<resources>
<style name="EdgeToEdgeBottomSheetDialogTheme" parent="Theme.Material3.DayNight.BottomSheetDialog">
<!-- Enable edge-to-edge -->
<item name="android:navigationBarColor">@android:color/transparent</item>
<item name="android:statusBarColor">@android:color/transparent</item>
<item name="android:windowIsFloating">false</item>
<item name="enableEdgeToEdge">true</item>
<!-- Configure bottom sheet to respect system window insets -->
<item name="bottomSheetStyle">@style/EdgeToEdgeBottomSheet</item>
</style>
<style name="EdgeToEdgeBottomSheet" parent="Widget.Material3.BottomSheet">
<item name="paddingBottomSystemWindowInsets">false</item>
<item name="paddingLeftSystemWindowInsets">true</item>
<item name="paddingRightSystemWindowInsets">true</item>
<item name="paddingTopSystemWindowInsets">false</item>
</style>
</resources>
@@ -175,6 +175,7 @@ function BottomSheetNativeComponentInner({
Platform.OS === 'android' && { Platform.OS === 'android' && {
borderTopLeftRadius: cornerRadius, borderTopLeftRadius: cornerRadius,
borderTopRightRadius: cornerRadius, borderTopRightRadius: cornerRadius,
overflow: 'hidden',
}, },
extraStyles, extraStyles,
]}> ]}>
@@ -34,12 +34,15 @@ class NotificationPrefs(
is Boolean -> { is Boolean -> {
putBoolean(key, value) putBoolean(key, value)
} }
is String -> { is String -> {
putString(key, value) putString(key, value)
} }
is Array<*> -> { is Array<*> -> {
putStringSet(key, value.map { it.toString() }.toSet()) putStringSet(key, value.map { it.toString() }.toSet())
} }
is Map<*, *> -> { is Map<*, *> -> {
putStringSet(key, value.map { it.toString() }.toSet()) putStringSet(key, value.map { it.toString() }.toSet())
} }
@@ -117,7 +117,7 @@ class ExpoReceiveAndroidIntentsModule : Module() {
private fun handleImageIntents( private fun handleImageIntents(
uris: List<Uri>, uris: List<Uri>,
text: String? text: String?,
) { ) {
var allParams = "" var allParams = ""
@@ -145,7 +145,7 @@ class ExpoReceiveAndroidIntentsModule : Module() {
private fun handleVideoIntents( private fun handleVideoIntents(
uris: List<Uri>, uris: List<Uri>,
text: String? text: String?,
) { ) {
val uri = uris[0] val uri = uris[0]
// If there is no extension for the file, substringAfterLast returns the original string - not // If there is no extension for the file, substringAfterLast returns the original string - not
+1 -1
View File
@@ -202,7 +202,7 @@
"react-native-edge-to-edge": "^1.6.0", "react-native-edge-to-edge": "^1.6.0",
"react-native-gesture-handler": "~2.28.0", "react-native-gesture-handler": "~2.28.0",
"react-native-get-random-values": "~1.11.0", "react-native-get-random-values": "~1.11.0",
"react-native-keyboard-controller": "1.18.5", "react-native-keyboard-controller": "^1.20.7",
"react-native-pager-view": "6.8.0", "react-native-pager-view": "6.8.0",
"react-native-progress": "bluesky-social/react-native-progress", "react-native-progress": "bluesky-social/react-native-progress",
"react-native-qrcode-styled": "^0.3.3", "react-native-qrcode-styled": "^0.3.3",
+1 -1
View File
@@ -3,6 +3,7 @@ import '#/view/icons'
import React, {useEffect, useState} from 'react' import React, {useEffect, useState} from 'react'
import {GestureHandlerRootView} from 'react-native-gesture-handler' import {GestureHandlerRootView} from 'react-native-gesture-handler'
import {KeyboardProvider as KeyboardControllerProvider} from 'react-native-keyboard-controller'
import { import {
initialWindowMetrics, initialWindowMetrics,
SafeAreaProvider, SafeAreaProvider,
@@ -14,7 +15,6 @@ import {msg} from '@lingui/macro'
import {useLingui} from '@lingui/react' import {useLingui} from '@lingui/react'
import * as Sentry from '@sentry/react-native' import * as Sentry from '@sentry/react-native'
import {KeyboardControllerProvider} from '#/lib/hooks/useEnableKeyboardController'
import {Provider as HideBottomBarBorderProvider} from '#/lib/hooks/useHideBottomBarBorder' import {Provider as HideBottomBarBorderProvider} from '#/lib/hooks/useHideBottomBarBorder'
import {QueryProvider} from '#/lib/react-query' import {QueryProvider} from '#/lib/react-query'
import {s} from '#/lib/styles' import {s} from '#/lib/styles'
+3 -7
View File
@@ -11,6 +11,7 @@ import {
} from 'react-native' } from 'react-native'
import { import {
KeyboardAwareScrollView, KeyboardAwareScrollView,
type KeyboardAwareScrollViewRef,
useKeyboardHandler, useKeyboardHandler,
useReanimatedKeyboardAnimation, useReanimatedKeyboardAnimation,
} from 'react-native-keyboard-controller' } from 'react-native-keyboard-controller'
@@ -23,7 +24,6 @@ import {useSafeAreaInsets} from 'react-native-safe-area-context'
import {msg} from '@lingui/macro' import {msg} from '@lingui/macro'
import {useLingui} from '@lingui/react' import {useLingui} from '@lingui/react'
import {useEnableKeyboardController} from '#/lib/hooks/useEnableKeyboardController'
import {ScrollProvider} from '#/lib/ScrollContext' import {ScrollProvider} from '#/lib/ScrollContext'
import {logger} from '#/logger' import {logger} from '#/logger'
import {useA11y} from '#/state/a11y' import {useA11y} from '#/state/a11y'
@@ -209,10 +209,9 @@ export const ScrollableInner = React.forwardRef<ScrollView, DialogInnerProps>(
const {nativeSnapPoint, disableDrag, setDisableDrag} = useDialogContext() const {nativeSnapPoint, disableDrag, setDisableDrag} = useDialogContext()
const insets = useSafeAreaInsets() const insets = useSafeAreaInsets()
useEnableKeyboardController(IS_IOS)
const [keyboardHeight, setKeyboardHeight] = React.useState(0) const [keyboardHeight, setKeyboardHeight] = React.useState(0)
// note: iOS-only. keyboard-controller doesn't seem to work inside the sheets on Android
useKeyboardHandler( useKeyboardHandler(
{ {
onEnd: e => { onEnd: e => {
@@ -231,7 +230,6 @@ export const ScrollableInner = React.forwardRef<ScrollView, DialogInnerProps>(
} }
paddingBottom = Math.max(paddingBottom, tokens.space._2xl) paddingBottom = Math.max(paddingBottom, tokens.space._2xl)
} else { } else {
paddingBottom += keyboardHeight
if (nativeSnapPoint === BottomSheetSnapPoint.Full) { if (nativeSnapPoint === BottomSheetSnapPoint.Full) {
paddingBottom += insets.top paddingBottom += insets.top
} }
@@ -259,7 +257,7 @@ export const ScrollableInner = React.forwardRef<ScrollView, DialogInnerProps>(
{paddingBottom}, {paddingBottom},
contentContainerStyle, contentContainerStyle,
]} ]}
ref={ref} ref={ref as React.Ref<KeyboardAwareScrollViewRef>}
showsVerticalScrollIndicator={IS_ANDROID ? false : undefined} showsVerticalScrollIndicator={IS_ANDROID ? false : undefined}
{...props} {...props}
bounces={nativeSnapPoint === BottomSheetSnapPoint.Full} bounces={nativeSnapPoint === BottomSheetSnapPoint.Full}
@@ -289,8 +287,6 @@ export const InnerFlatList = React.forwardRef<
const insets = useSafeAreaInsets() const insets = useSafeAreaInsets()
const {nativeSnapPoint, disableDrag, setDisableDrag} = useDialogContext() const {nativeSnapPoint, disableDrag, setDisableDrag} = useDialogContext()
useEnableKeyboardController(IS_IOS)
const onScroll = (e: ScrollEvent) => { const onScroll = (e: ScrollEvent) => {
'worklet' 'worklet'
if (!IS_ANDROID) { if (!IS_ANDROID) {
@@ -58,7 +58,7 @@ export function VideoEmbedInnerNative({
<BlueskyVideoView <BlueskyVideoView
url={embed.playlist} url={embed.playlist}
autoplay={!autoplayDisabled && !isWithinMessage} autoplay={!autoplayDisabled && !isWithinMessage}
beginMuted={isGif || autoplayDisabled ? false : muted} beginMuted={isGif || (autoplayDisabled ? false : muted)}
style={[a.rounded_sm]} style={[a.rounded_sm]}
onActiveChange={e => { onActiveChange={e => {
setIsActive(e.nativeEvent.isActive) setIsActive(e.nativeEvent.isActive)
@@ -67,7 +67,9 @@ export function VideoEmbedInnerNative({
setIsLoading(e.nativeEvent.isLoading) setIsLoading(e.nativeEvent.isLoading)
}} }}
onMutedChange={e => { onMutedChange={e => {
if (!isGif) {
setMuted(e.nativeEvent.isMuted) setMuted(e.nativeEvent.isMuted)
}
}} }}
onStatusChange={e => { onStatusChange={e => {
setStatus(e.nativeEvent.status) setStatus(e.nativeEvent.status)
@@ -28,7 +28,7 @@ export function VerifierDialog({
verificationState: FullVerificationState verificationState: FullVerificationState
}) { }) {
return ( return (
<Dialog.Outer control={control}> <Dialog.Outer control={control} nativeOptions={{preventExpansion: true}}>
<Dialog.Handle /> <Dialog.Handle />
<Inner <Inner
control={control} control={control}
@@ -123,7 +123,6 @@ function Inner({
}), }),
)} )}
size="small" size="small"
variant="solid"
color="primary" color="primary"
style={[a.justify_center]} style={[a.justify_center]}
onPress={() => { onPress={() => {
@@ -138,7 +137,6 @@ function Inner({
<Button <Button
label={_(msg`Close dialog`)} label={_(msg`Close dialog`)}
size="small" size="small"
variant="solid"
color="secondary" color="secondary"
onPress={() => { onPress={() => {
control.close() control.close()
@@ -1,107 +0,0 @@
import {
createContext,
useCallback,
useContext,
useEffect,
useMemo,
useRef,
} from 'react'
import {
KeyboardProvider,
useKeyboardController,
} from 'react-native-keyboard-controller'
import {useFocusEffect} from '@react-navigation/native'
const KeyboardControllerRefCountContext = createContext<{
incrementRefCount: () => void
decrementRefCount: () => void
}>({
incrementRefCount: () => {},
decrementRefCount: () => {},
})
KeyboardControllerRefCountContext.displayName =
'KeyboardControllerRefCountContext'
export function KeyboardControllerProvider({
children,
}: {
children: React.ReactNode
}) {
return (
<KeyboardProvider enabled={false} preload={false}>
<KeyboardControllerProviderInner>
{children}
</KeyboardControllerProviderInner>
</KeyboardProvider>
)
}
function KeyboardControllerProviderInner({
children,
}: {
children: React.ReactNode
}) {
const {setEnabled} = useKeyboardController()
const refCount = useRef(0)
const value = useMemo(
() => ({
incrementRefCount: () => {
refCount.current++
setEnabled(refCount.current > 0)
},
decrementRefCount: () => {
refCount.current--
setEnabled(refCount.current > 0)
if (__DEV__ && refCount.current < 0) {
console.error('KeyboardController ref count < 0')
}
},
}),
[setEnabled],
)
return (
<KeyboardControllerRefCountContext.Provider value={value}>
{children}
</KeyboardControllerRefCountContext.Provider>
)
}
export function useEnableKeyboardController(shouldEnable: boolean) {
const {incrementRefCount, decrementRefCount} = useContext(
KeyboardControllerRefCountContext,
)
useEffect(() => {
if (!shouldEnable) {
return
}
incrementRefCount()
return () => {
decrementRefCount()
}
}, [shouldEnable, incrementRefCount, decrementRefCount])
}
/**
* Like `useEnableKeyboardController`, but using `useFocusEffect`
*/
export function useEnableKeyboardControllerScreen(shouldEnable: boolean) {
const {incrementRefCount, decrementRefCount} = useContext(
KeyboardControllerRefCountContext,
)
useFocusEffect(
useCallback(() => {
if (!shouldEnable) {
return
}
incrementRefCount()
return () => {
decrementRefCount()
}
}, [shouldEnable, incrementRefCount, decrementRefCount]),
)
}
+64 -64
View File
@@ -129,7 +129,7 @@ msgstr ""
#. Number of users (always at least 25) who have joined Bluesky using a specific starter pack #. Number of users (always at least 25) who have joined Bluesky using a specific starter pack
#: src/screens/StarterPack/StarterPackScreen.tsx:499 #: src/screens/StarterPack/StarterPackScreen.tsx:499
msgid "{0, plural, other {# people have}} used this starter pack!" msgid "{0, plural, other {# people have}} joined Bluesky via this starter pack!"
msgstr "" msgstr ""
#: src/components/dialogs/StarterPackDialog.tsx:361 #: src/components/dialogs/StarterPackDialog.tsx:361
@@ -242,7 +242,7 @@ msgid "{DISPLAY_NAME_MAX_GRAPHEMES, plural, other {Display name is too long. The
msgstr "" msgstr ""
#: src/lib/generate-starterpack.ts:104 #: src/lib/generate-starterpack.ts:104
#: src/screens/StarterPack/Wizard/index.tsx:202 #: src/screens/StarterPack/Wizard/index.tsx:199
msgid "{displayName}'s Starter Pack" msgid "{displayName}'s Starter Pack"
msgstr "" msgstr ""
@@ -475,12 +475,12 @@ msgstr ""
msgid "+{computedTotal}" msgid "+{computedTotal}"
msgstr "" msgstr ""
#: src/screens/StarterPack/Wizard/index.tsx:525 #: src/screens/StarterPack/Wizard/index.tsx:522
msgctxt "profiles" msgctxt "profiles"
msgid "<0>{0}, </0><1>{1}, </1>and {2, plural, one {# other} other {# others}} are included in your starter pack" msgid "<0>{0}, </0><1>{1}, </1>and {2, plural, one {# other} other {# others}} are included in your starter pack"
msgstr "" msgstr ""
#: src/screens/StarterPack/Wizard/index.tsx:578 #: src/screens/StarterPack/Wizard/index.tsx:575
msgctxt "feeds" msgctxt "feeds"
msgid "<0>{0}, </0><1>{1}, </1>and {2, plural, one {# other} other {# others}} are included in your starter pack" msgid "<0>{0}, </0><1>{1}, </1>and {2, plural, one {# other} other {# others}} are included in your starter pack"
msgstr "" msgstr ""
@@ -493,12 +493,12 @@ msgstr ""
msgid "<0>{0}</0> {1, plural, one {following} other {following}}" msgid "<0>{0}</0> {1, plural, one {following} other {following}}"
msgstr "" msgstr ""
#: src/screens/StarterPack/Wizard/index.tsx:512 #: src/screens/StarterPack/Wizard/index.tsx:509
#: src/screens/StarterPack/Wizard/index.tsx:566 #: src/screens/StarterPack/Wizard/index.tsx:563
msgid "<0>{0}</0> and<1> </1><2>{1} </2>are included in your starter pack" msgid "<0>{0}</0> and<1> </1><2>{1} </2>are included in your starter pack"
msgstr "" msgstr ""
#: src/screens/StarterPack/Wizard/index.tsx:559 #: src/screens/StarterPack/Wizard/index.tsx:556
msgid "<0>{0}</0> is included in your starter pack" msgid "<0>{0}</0> is included in your starter pack"
msgstr "" msgstr ""
@@ -515,7 +515,7 @@ msgstr ""
msgid "<0>Sign in</0><1> or </1><2>create an account</2><3> </3><4>to search for news, sports, politics, and everything else happening on Bluesky.</4>" msgid "<0>Sign in</0><1> or </1><2>create an account</2><3> </3><4>to search for news, sports, politics, and everything else happening on Bluesky.</4>"
msgstr "" msgstr ""
#: src/screens/StarterPack/Wizard/index.tsx:503 #: src/screens/StarterPack/Wizard/index.tsx:500
msgid "<0>You</0> and<1> </1><2>{0} </2>are included in your starter pack" msgid "<0>You</0> and<1> </1><2>{0} </2>are included in your starter pack"
msgstr "" msgstr ""
@@ -581,7 +581,7 @@ msgstr ""
#. Contains a post that originally appeared in English. Consider translating the post text if it makes sense in your language, and noting that the post was translated from English. #. Contains a post that originally appeared in English. Consider translating the post text if it makes sense in your language, and noting that the post was translated from English.
#: src/components/dialogs/nuxs/DraftsAnnouncement.tsx:97 #: src/components/dialogs/nuxs/DraftsAnnouncement.tsx:97
msgid "A screenshot of a the post composer with a new button next to the post button that says \"Drafts\", with a rainbow firework effect. Below, the text in the composer reads \"Hey, did you hear the news? Bluesky has drafts now???\"." msgid "A screenshot of the post composer with a new button next to the post button that says \"Drafts\", with a rainbow firework effect. Below, the text in the composer reads \"Hey, did you hear the news? Bluesky has drafts now!!!\"."
msgstr "" msgstr ""
#: src/Navigation.tsx:535 #: src/Navigation.tsx:535
@@ -710,7 +710,7 @@ msgstr ""
msgid "Add" msgid "Add"
msgstr "" msgstr ""
#: src/screens/StarterPack/Wizard/index.tsx:614 #: src/screens/StarterPack/Wizard/index.tsx:611
msgid "Add {0} more to continue" msgid "Add {0} more to continue"
msgstr "" msgstr ""
@@ -742,8 +742,8 @@ msgstr ""
#: src/view/com/composer/GifAltText.tsx:211 #: src/view/com/composer/GifAltText.tsx:211
#: src/view/com/composer/photos/Gallery.tsx:170 #: src/view/com/composer/photos/Gallery.tsx:170
#: src/view/com/composer/photos/Gallery.tsx:217 #: src/view/com/composer/photos/Gallery.tsx:217
#: src/view/com/composer/photos/ImageAltTextDialog.tsx:88
#: src/view/com/composer/photos/ImageAltTextDialog.tsx:93 #: src/view/com/composer/photos/ImageAltTextDialog.tsx:93
#: src/view/com/composer/photos/ImageAltTextDialog.tsx:98
msgid "Add alt text" msgid "Add alt text"
msgstr "" msgstr ""
@@ -819,7 +819,7 @@ msgstr ""
msgid "Add recommended feeds" msgid "Add recommended feeds"
msgstr "" msgstr ""
#: src/screens/StarterPack/Wizard/index.tsx:547 #: src/screens/StarterPack/Wizard/index.tsx:544
msgid "Add some feeds to your starter pack!" msgid "Add some feeds to your starter pack!"
msgstr "" msgstr ""
@@ -1029,7 +1029,7 @@ msgstr ""
#: src/screens/Settings/AccessibilitySettings.tsx:54 #: src/screens/Settings/AccessibilitySettings.tsx:54
#: src/view/com/composer/GifAltText.tsx:154 #: src/view/com/composer/GifAltText.tsx:154
#: src/view/com/composer/photos/ImageAltTextDialog.tsx:117 #: src/view/com/composer/photos/ImageAltTextDialog.tsx:122
#: src/view/com/composer/videos/SubtitleDialog.tsx:40 #: src/view/com/composer/videos/SubtitleDialog.tsx:40
#: src/view/com/composer/videos/SubtitleDialog.tsx:58 #: src/view/com/composer/videos/SubtitleDialog.tsx:58
#: src/view/com/composer/videos/SubtitleDialog.tsx:109 #: src/view/com/composer/videos/SubtitleDialog.tsx:109
@@ -1050,7 +1050,7 @@ msgid "Alt text must be less than {MAX_ALT_TEXT} characters."
msgstr "" msgstr ""
#: src/view/com/composer/GifAltText.tsx:179 #: src/view/com/composer/GifAltText.tsx:179
#: src/view/com/composer/photos/ImageAltTextDialog.tsx:138 #: src/view/com/composer/photos/ImageAltTextDialog.tsx:143
msgid "Alt text will be truncated. {MAX_ALT_TEXT, plural, other {Limit: {0} characters.}}" msgid "Alt text will be truncated. {MAX_ALT_TEXT, plural, other {Limit: {0} characters.}}"
msgstr "" msgstr ""
@@ -1277,12 +1277,12 @@ msgctxt "toast"
msgid "Appeal submitted" msgid "Appeal submitted"
msgstr "" msgstr ""
#: src/screens/Takendown.tsx:114 #: src/screens/Takendown.tsx:113
#: src/screens/Takendown.tsx:142 #: src/screens/Takendown.tsx:139
msgid "Appeal suspension" msgid "Appeal suspension"
msgstr "" msgstr ""
#: src/screens/Takendown.tsx:117 #: src/screens/Takendown.tsx:116
msgid "Appeal Suspension" msgid "Appeal Suspension"
msgstr "" msgstr ""
@@ -1408,7 +1408,7 @@ msgstr ""
#: src/screens/Settings/components/ChangePasswordDialog.tsx:272 #: src/screens/Settings/components/ChangePasswordDialog.tsx:272
#: src/screens/Settings/components/ChangePasswordDialog.tsx:281 #: src/screens/Settings/components/ChangePasswordDialog.tsx:281
#: src/screens/Signup/BackNextButtons.tsx:41 #: src/screens/Signup/BackNextButtons.tsx:41
#: src/screens/StarterPack/Wizard/index.tsx:324 #: src/screens/StarterPack/Wizard/index.tsx:321
#: src/view/com/composer/drafts/DraftsListDialog.tsx:80 #: src/view/com/composer/drafts/DraftsListDialog.tsx:80
#: src/view/com/composer/drafts/DraftsListDialog.tsx:86 #: src/view/com/composer/drafts/DraftsListDialog.tsx:86
msgid "Back" msgid "Back"
@@ -1453,7 +1453,7 @@ msgstr ""
#: src/components/dms/dialogs/NewChatDialog.tsx:55 #: src/components/dms/dialogs/NewChatDialog.tsx:55
#: src/components/dms/MessageProfileButton.tsx:59 #: src/components/dms/MessageProfileButton.tsx:59
#: src/screens/Messages/ChatList.tsx:371 #: src/screens/Messages/ChatList.tsx:371
#: src/screens/Messages/Conversation.tsx:228 #: src/screens/Messages/Conversation.tsx:225
msgid "Before you can message another user, you must first verify your email." msgid "Before you can message another user, you must first verify your email."
msgstr "" msgstr ""
@@ -1617,7 +1617,7 @@ msgstr ""
msgid "Bluesky is more fun with friends. Do you want to invite some of yours? <0/>" msgid "Bluesky is more fun with friends. Do you want to invite some of yours? <0/>"
msgstr "" msgstr ""
#: src/screens/Takendown.tsx:215 #: src/screens/Takendown.tsx:212
msgid "Bluesky Social Terms of Service" msgid "Bluesky Social Terms of Service"
msgstr "" msgstr ""
@@ -1788,8 +1788,8 @@ msgstr ""
#: src/screens/Settings/components/ChangePasswordDialog.tsx:247 #: src/screens/Settings/components/ChangePasswordDialog.tsx:247
#: src/screens/Settings/components/ChangePasswordDialog.tsx:253 #: src/screens/Settings/components/ChangePasswordDialog.tsx:253
#: src/screens/Settings/Settings.tsx:305 #: src/screens/Settings/Settings.tsx:305
#: src/screens/Takendown.tsx:102 #: src/screens/Takendown.tsx:101
#: src/screens/Takendown.tsx:105 #: src/screens/Takendown.tsx:104
#: src/view/com/composer/Composer.tsx:1449 #: src/view/com/composer/Composer.tsx:1449
#: src/view/com/composer/Composer.tsx:1461 #: src/view/com/composer/Composer.tsx:1461
#: src/view/com/composer/photos/EditImageDialog.web.tsx:43 #: src/view/com/composer/photos/EditImageDialog.web.tsx:43
@@ -1987,7 +1987,7 @@ msgstr ""
msgid "Choose domain verification method" msgid "Choose domain verification method"
msgstr "" msgstr ""
#: src/screens/StarterPack/Wizard/index.tsx:218 #: src/screens/StarterPack/Wizard/index.tsx:215
msgid "Choose Feeds" msgid "Choose Feeds"
msgstr "" msgstr ""
@@ -1995,7 +1995,7 @@ msgstr ""
msgid "Choose for me" msgid "Choose for me"
msgstr "" msgstr ""
#: src/screens/StarterPack/Wizard/index.tsx:214 #: src/screens/StarterPack/Wizard/index.tsx:211
msgid "Choose People" msgid "Choose People"
msgstr "" msgstr ""
@@ -2119,7 +2119,7 @@ msgstr ""
#: src/components/StarterPack/Wizard/WizardEditListDialog.tsx:118 #: src/components/StarterPack/Wizard/WizardEditListDialog.tsx:118
#: src/components/StarterPack/Wizard/WizardEditListDialog.tsx:124 #: src/components/StarterPack/Wizard/WizardEditListDialog.tsx:124
#: src/components/verification/VerificationsDialog.tsx:145 #: src/components/verification/VerificationsDialog.tsx:145
#: src/components/verification/VerifierDialog.tsx:147 #: src/components/verification/VerifierDialog.tsx:145
#: src/components/WhoCanReply.tsx:235 #: src/components/WhoCanReply.tsx:235
#: src/components/WhoCanReply.tsx:242 #: src/components/WhoCanReply.tsx:242
#: src/screens/Settings/components/ChangePasswordDialog.tsx:287 #: src/screens/Settings/components/ChangePasswordDialog.tsx:287
@@ -2147,7 +2147,7 @@ msgstr ""
#: src/components/ageAssurance/AgeAssuranceInitDialog.tsx:228 #: src/components/ageAssurance/AgeAssuranceInitDialog.tsx:228
#: src/components/dialogs/GifSelect.tsx:263 #: src/components/dialogs/GifSelect.tsx:263
#: src/components/verification/VerificationsDialog.tsx:137 #: src/components/verification/VerificationsDialog.tsx:137
#: src/components/verification/VerifierDialog.tsx:139 #: src/components/verification/VerifierDialog.tsx:138
#: src/view/com/composer/select-language/PostLanguageSelectDialog.tsx:204 #: src/view/com/composer/select-language/PostLanguageSelectDialog.tsx:204
#: src/view/com/composer/select-language/PostLanguageSelectDialog.tsx:298 #: src/view/com/composer/select-language/PostLanguageSelectDialog.tsx:298
#: src/view/com/composer/select-language/PostLanguageSelectDialog.tsx:330 #: src/view/com/composer/select-language/PostLanguageSelectDialog.tsx:330
@@ -2433,7 +2433,7 @@ msgstr ""
msgid "Continue to next step" msgid "Continue to next step"
msgstr "" msgstr ""
#: src/screens/Messages/Conversation.tsx:57 #: src/screens/Messages/Conversation.tsx:56
msgid "Conversation" msgid "Conversation"
msgstr "" msgstr ""
@@ -2926,7 +2926,7 @@ msgid "Description"
msgstr "" msgstr ""
#: src/view/com/composer/GifAltText.tsx:150 #: src/view/com/composer/GifAltText.tsx:150
#: src/view/com/composer/photos/ImageAltTextDialog.tsx:113 #: src/view/com/composer/photos/ImageAltTextDialog.tsx:118
msgid "Descriptive alt text" msgid "Descriptive alt text"
msgstr "" msgstr ""
@@ -3040,7 +3040,7 @@ msgstr ""
msgid "Discover New Feeds" msgid "Discover New Feeds"
msgstr "" msgstr ""
#: src/components/Dialog/index.tsx:379 #: src/components/Dialog/index.tsx:375
msgid "Dismiss" msgid "Dismiss"
msgstr "" msgstr ""
@@ -3159,7 +3159,7 @@ msgstr ""
msgid "Double tap or long press the message to add a reaction" msgid "Double tap or long press the message to add a reaction"
msgstr "" msgstr ""
#: src/components/Dialog/index.tsx:380 #: src/components/Dialog/index.tsx:376
msgid "Double tap to close the dialog" msgid "Double tap to close the dialog"
msgstr "" msgstr ""
@@ -3238,8 +3238,8 @@ msgstr ""
#: src/screens/Settings/AccountSettings.tsx:145 #: src/screens/Settings/AccountSettings.tsx:145
#: src/screens/Settings/NotificationSettings/ActivityNotificationSettings.tsx:252 #: src/screens/Settings/NotificationSettings/ActivityNotificationSettings.tsx:252
#: src/screens/StarterPack/StarterPackScreen.tsx:598 #: src/screens/StarterPack/StarterPackScreen.tsx:598
#: src/screens/StarterPack/Wizard/index.tsx:340 #: src/screens/StarterPack/Wizard/index.tsx:337
#: src/screens/StarterPack/Wizard/index.tsx:345 #: src/screens/StarterPack/Wizard/index.tsx:342
msgid "Edit" msgid "Edit"
msgstr "" msgstr ""
@@ -3726,8 +3726,8 @@ msgstr ""
msgid "Failed to create conversation" msgid "Failed to create conversation"
msgstr "" msgstr ""
#: src/screens/StarterPack/Wizard/index.tsx:263 #: src/screens/StarterPack/Wizard/index.tsx:260
#: src/screens/StarterPack/Wizard/index.tsx:271 #: src/screens/StarterPack/Wizard/index.tsx:268
msgid "Failed to create starter pack" msgid "Failed to create starter pack"
msgstr "" msgstr ""
@@ -4098,7 +4098,7 @@ msgstr ""
msgid "Finding friends..." msgid "Finding friends..."
msgstr "" msgstr ""
#: src/screens/StarterPack/Wizard/index.tsx:219 #: src/screens/StarterPack/Wizard/index.tsx:216
msgid "Finish" msgid "Finish"
msgstr "" msgstr ""
@@ -5118,11 +5118,11 @@ msgstr ""
msgid "It's correct" msgid "It's correct"
msgstr "" msgstr ""
#: src/screens/StarterPack/Wizard/index.tsx:492 #: src/screens/StarterPack/Wizard/index.tsx:489
msgid "It's just <0>{0} </0>right now! Add more people to your starter pack by searching above." msgid "It's just <0>{0} </0>right now! Add more people to your starter pack by searching above."
msgstr "" msgstr ""
#: src/screens/StarterPack/Wizard/index.tsx:487 #: src/screens/StarterPack/Wizard/index.tsx:484
msgid "It's just you right now! Add more people to your starter pack by searching above." msgid "It's just you right now! Add more people to your starter pack by searching above."
msgstr "" msgstr ""
@@ -5219,7 +5219,7 @@ msgid "Latest"
msgstr "" msgstr ""
#: src/components/verification/VerificationsDialog.tsx:167 #: src/components/verification/VerificationsDialog.tsx:167
#: src/components/verification/VerifierDialog.tsx:135 #: src/components/verification/VerifierDialog.tsx:134
#: src/screens/Moderation/VerificationSettings.tsx:49 #: src/screens/Moderation/VerificationSettings.tsx:49
#: src/screens/Profile/Header/EditProfileDialog.tsx:349 #: src/screens/Profile/Header/EditProfileDialog.tsx:349
#: src/screens/Settings/components/ChangeHandleDialog.tsx:213 #: src/screens/Settings/components/ChangeHandleDialog.tsx:213
@@ -6140,10 +6140,10 @@ msgstr ""
#: src/screens/Settings/components/AddAppPasswordDialog.tsx:157 #: src/screens/Settings/components/AddAppPasswordDialog.tsx:157
#: src/screens/Settings/components/AddAppPasswordDialog.tsx:165 #: src/screens/Settings/components/AddAppPasswordDialog.tsx:165
#: src/screens/Signup/BackNextButtons.tsx:67 #: src/screens/Signup/BackNextButtons.tsx:67
#: src/screens/StarterPack/Wizard/index.tsx:211 #: src/screens/StarterPack/Wizard/index.tsx:208
#: src/screens/StarterPack/Wizard/index.tsx:215 #: src/screens/StarterPack/Wizard/index.tsx:212
#: src/screens/StarterPack/Wizard/index.tsx:393 #: src/screens/StarterPack/Wizard/index.tsx:390
#: src/screens/StarterPack/Wizard/index.tsx:400 #: src/screens/StarterPack/Wizard/index.tsx:397
msgid "Next" msgid "Next"
msgstr "" msgstr ""
@@ -6355,7 +6355,7 @@ msgstr ""
msgid "None" msgid "None"
msgstr "" msgstr ""
#: src/screens/FindContactsFlowScreen.tsx:70 #: src/screens/FindContactsFlowScreen.tsx:67
#: src/screens/Settings/FindContactsSettings.tsx:103 #: src/screens/Settings/FindContactsSettings.tsx:103
msgid "Not available on this platform." msgid "Not available on this platform."
msgstr "" msgstr ""
@@ -7138,7 +7138,7 @@ msgstr ""
msgid "Please use the native app to import your contacts." msgid "Please use the native app to import your contacts."
msgstr "" msgstr ""
#: src/screens/FindContactsFlowScreen.tsx:71 #: src/screens/FindContactsFlowScreen.tsx:68
msgid "Please use the native app to sync your contacts." msgid "Please use the native app to sync your contacts."
msgstr "" msgstr ""
@@ -7556,8 +7556,8 @@ msgstr ""
msgid "Real people." msgid "Real people."
msgstr "" msgstr ""
#: src/screens/Takendown.tsx:160 #: src/screens/Takendown.tsx:157
#: src/screens/Takendown.tsx:168 #: src/screens/Takendown.tsx:165
msgid "Reason for appeal" msgid "Reason for appeal"
msgstr "" msgstr ""
@@ -8132,7 +8132,7 @@ msgstr ""
msgid "Returns to previous page" msgid "Returns to previous page"
msgstr "" msgstr ""
#: src/screens/StarterPack/Wizard/index.tsx:325 #: src/screens/StarterPack/Wizard/index.tsx:322
msgid "Returns to the previous step" msgid "Returns to the previous step"
msgstr "" msgstr ""
@@ -8152,8 +8152,8 @@ msgstr ""
#: src/view/com/composer/GifAltText.tsx:202 #: src/view/com/composer/GifAltText.tsx:202
#: src/view/com/composer/photos/EditImageDialog.web.tsx:62 #: src/view/com/composer/photos/EditImageDialog.web.tsx:62
#: src/view/com/composer/photos/EditImageDialog.web.tsx:75 #: src/view/com/composer/photos/EditImageDialog.web.tsx:75
#: src/view/com/composer/photos/ImageAltTextDialog.tsx:152 #: src/view/com/composer/photos/ImageAltTextDialog.tsx:157
#: src/view/com/composer/photos/ImageAltTextDialog.tsx:162 #: src/view/com/composer/photos/ImageAltTextDialog.tsx:167
msgid "Save" msgid "Save"
msgstr "" msgstr ""
@@ -8305,7 +8305,7 @@ msgstr ""
msgid "Search for \"{searchText}\"" msgid "Search for \"{searchText}\""
msgstr "" msgstr ""
#: src/screens/StarterPack/Wizard/index.tsx:550 #: src/screens/StarterPack/Wizard/index.tsx:547
msgid "Search for feeds that you want to suggest to others." msgid "Search for feeds that you want to suggest to others."
msgstr "" msgstr ""
@@ -9001,14 +9001,14 @@ msgstr ""
#: src/screens/Settings/Settings.tsx:304 #: src/screens/Settings/Settings.tsx:304
#: src/screens/SignupQueued.tsx:93 #: src/screens/SignupQueued.tsx:93
#: src/screens/SignupQueued.tsx:96 #: src/screens/SignupQueued.tsx:96
#: src/screens/Takendown.tsx:88 #: src/screens/Takendown.tsx:87
#: src/view/shell/desktop/LeftNav.tsx:212 #: src/view/shell/desktop/LeftNav.tsx:212
#: src/view/shell/desktop/LeftNav.tsx:269 #: src/view/shell/desktop/LeftNav.tsx:269
#: src/view/shell/desktop/LeftNav.tsx:272 #: src/view/shell/desktop/LeftNav.tsx:272
msgid "Sign out" msgid "Sign out"
msgstr "" msgstr ""
#: src/screens/Takendown.tsx:91 #: src/screens/Takendown.tsx:90
msgid "Sign Out" msgid "Sign Out"
msgstr "" msgstr ""
@@ -9035,7 +9035,7 @@ msgstr ""
#: src/screens/Onboarding/StepFinished/index.tsx:316 #: src/screens/Onboarding/StepFinished/index.tsx:316
#: src/screens/Onboarding/StepSuggestedAccounts/index.tsx:261 #: src/screens/Onboarding/StepSuggestedAccounts/index.tsx:261
#: src/screens/Onboarding/StepSuggestedStarterpacks/index.tsx:104 #: src/screens/Onboarding/StepSuggestedStarterpacks/index.tsx:104
#: src/screens/StarterPack/Wizard/index.tsx:219 #: src/screens/StarterPack/Wizard/index.tsx:216
msgid "Skip" msgid "Skip"
msgstr "" msgstr ""
@@ -9098,7 +9098,7 @@ msgstr ""
msgid "Something wasn't quite right with the data you're trying to report. Please contact support." msgid "Something wasn't quite right with the data you're trying to report. Please contact support."
msgstr "" msgstr ""
#: src/screens/Messages/Conversation.tsx:144 #: src/screens/Messages/Conversation.tsx:141
msgid "Something went wrong" msgid "Something went wrong"
msgstr "" msgstr ""
@@ -9194,7 +9194,7 @@ msgstr ""
#: src/Navigation.tsx:590 #: src/Navigation.tsx:590
#: src/Navigation.tsx:595 #: src/Navigation.tsx:595
#: src/screens/StarterPack/Wizard/index.tsx:210 #: src/screens/StarterPack/Wizard/index.tsx:207
msgid "Starter Pack" msgid "Starter Pack"
msgstr "" msgstr ""
@@ -9270,11 +9270,11 @@ msgstr ""
msgid "Submit" msgid "Submit"
msgstr "" msgstr ""
#: src/screens/Takendown.tsx:76 #: src/screens/Takendown.tsx:75
msgid "Submit appeal" msgid "Submit appeal"
msgstr "" msgstr ""
#: src/screens/Takendown.tsx:80 #: src/screens/Takendown.tsx:79
msgid "Submit Appeal" msgid "Submit Appeal"
msgstr "" msgstr ""
@@ -9505,8 +9505,8 @@ msgstr ""
#: src/screens/StarterPack/StarterPackScreen.tsx:113 #: src/screens/StarterPack/StarterPackScreen.tsx:113
#: src/screens/StarterPack/StarterPackScreen.tsx:157 #: src/screens/StarterPack/StarterPackScreen.tsx:157
#: src/screens/StarterPack/StarterPackScreen.tsx:158 #: src/screens/StarterPack/StarterPackScreen.tsx:158
#: src/screens/StarterPack/Wizard/index.tsx:117 #: src/screens/StarterPack/Wizard/index.tsx:116
#: src/screens/StarterPack/Wizard/index.tsx:127 #: src/screens/StarterPack/Wizard/index.tsx:126
msgid "That starter pack could not be found." msgid "That starter pack could not be found."
msgstr "" msgstr ""
@@ -10970,7 +10970,7 @@ msgstr ""
msgid "We couldn't find any results for that topic." msgid "We couldn't find any results for that topic."
msgstr "" msgstr ""
#: src/screens/Messages/Conversation.tsx:145 #: src/screens/Messages/Conversation.tsx:142
msgid "We couldn't load this conversation" msgid "We couldn't load this conversation"
msgstr "" msgstr ""
@@ -11191,7 +11191,7 @@ msgstr ""
msgid "Whoops! Trending videos failed to load." msgid "Whoops! Trending videos failed to load."
msgstr "" msgstr ""
#: src/screens/Takendown.tsx:171 #: src/screens/Takendown.tsx:168
msgid "Why are you appealing?" msgid "Why are you appealing?"
msgstr "" msgstr ""
@@ -11751,7 +11751,7 @@ msgstr ""
msgid "Your account has been deleted" msgid "Your account has been deleted"
msgstr "" msgstr ""
#: src/screens/Takendown.tsx:144 #: src/screens/Takendown.tsx:141
msgid "Your account has been suspended" msgid "Your account has been suspended"
msgstr "" msgstr ""
@@ -11763,11 +11763,11 @@ msgstr ""
msgid "Your account repository, containing all public data records, can be downloaded as a \"CAR\" file. This file does not include media embeds, such as images, or your private data, which must be fetched separately." msgid "Your account repository, containing all public data records, can be downloaded as a \"CAR\" file. This file does not include media embeds, such as images, or your private data, which must be fetched separately."
msgstr "" msgstr ""
#: src/screens/Takendown.tsx:212 #: src/screens/Takendown.tsx:209
msgid "Your account was found to be in violation of the <0>Bluesky Social Terms of Service</0>. You have been sent an email outlining the specific violation and suspension period, if applicable. You can appeal this decision if you believe it was made in error." msgid "Your account was found to be in violation of the <0>Bluesky Social Terms of Service</0>. You have been sent an email outlining the specific violation and suspension period, if applicable. You can appeal this decision if you believe it was made in error."
msgstr "" msgstr ""
#: src/screens/Takendown.tsx:152 #: src/screens/Takendown.tsx:149
msgid "Your appeal has been submitted. If your appeal succeeds, you will receive an email." msgid "Your appeal has been submitted. If your appeal succeeds, you will receive an email."
msgstr "" msgstr ""
-3
View File
@@ -4,7 +4,6 @@ import {msg} from '@lingui/macro'
import {useLingui} from '@lingui/react' import {useLingui} from '@lingui/react'
import {usePreventRemove} from '@react-navigation/native' import {usePreventRemove} from '@react-navigation/native'
import {useEnableKeyboardControllerScreen} from '#/lib/hooks/useEnableKeyboardController'
import { import {
type AllNavigatorParams, type AllNavigatorParams,
type NativeStackScreenProps, type NativeStackScreenProps,
@@ -37,8 +36,6 @@ export function FindContactsFlowScreen({navigation}: Props) {
}) })
}) })
useEnableKeyboardControllerScreen(true)
const setMinimalShellMode = useSetMinimalShellMode() const setMinimalShellMode = useSetMinimalShellMode()
const effect = useCallback(() => { const effect = useCallback(() => {
setMinimalShellMode(true) setMinimalShellMode(true)
-3
View File
@@ -15,7 +15,6 @@ import {
} from '@react-navigation/native' } from '@react-navigation/native'
import {type NativeStackScreenProps} from '@react-navigation/native-stack' import {type NativeStackScreenProps} from '@react-navigation/native-stack'
import {useEnableKeyboardControllerScreen} from '#/lib/hooks/useEnableKeyboardController'
import {useNonReactiveCallback} from '#/lib/hooks/useNonReactiveCallback' import {useNonReactiveCallback} from '#/lib/hooks/useNonReactiveCallback'
import { import {
type CommonNavigatorParams, type CommonNavigatorParams,
@@ -68,8 +67,6 @@ export function MessagesConversationScreenInner({route}: Props) {
const convoId = route.params.conversation const convoId = route.params.conversation
const {setCurrentConvoId} = useCurrentConvoId() const {setCurrentConvoId} = useCurrentConvoId()
useEnableKeyboardControllerScreen(true)
useFocusEffect( useFocusEffect(
useCallback(() => { useCallback(() => {
setCurrentConvoId(convoId) setCurrentConvoId(convoId)
-3
View File
@@ -2,7 +2,6 @@ import {useMemo, useReducer} from 'react'
import {View} from 'react-native' import {View} from 'react-native'
import * as bcp47Match from 'bcp-47-match' import * as bcp47Match from 'bcp-47-match'
import {useEnableKeyboardControllerScreen} from '#/lib/hooks/useEnableKeyboardController'
import {useLanguagePrefs} from '#/state/preferences' import {useLanguagePrefs} from '#/state/preferences'
import { import {
Layout, Layout,
@@ -60,8 +59,6 @@ export function Onboarding() {
) )
const [contactsFlowState, contactsFlowDispatch] = useFindContactsFlowState() const [contactsFlowState, contactsFlowDispatch] = useFindContactsFlowState()
useEnableKeyboardControllerScreen(true)
return ( return (
<Portal> <Portal>
<View style={[a.absolute, a.inset_0, t.atoms.bg]}> <View style={[a.absolute, a.inset_0, t.atoms.bg]}>
+19 -4
View File
@@ -1,4 +1,4 @@
import {useCallback, useMemo, useRef} from 'react' import {useCallback, useMemo, useRef, useState} from 'react'
import {View} from 'react-native' import {View} from 'react-native'
import {useAnimatedRef} from 'react-native-reanimated' import {useAnimatedRef} from 'react-native-reanimated'
import { import {
@@ -35,12 +35,13 @@ import {PagerWithHeader} from '#/view/com/pager/PagerWithHeader'
import {FAB} from '#/view/com/util/fab/FAB' import {FAB} from '#/view/com/util/fab/FAB'
import {type ListRef} from '#/view/com/util/List' import {type ListRef} from '#/view/com/util/List'
import {ListHiddenScreen} from '#/screens/List/ListHiddenScreen' import {ListHiddenScreen} from '#/screens/List/ListHiddenScreen'
import {atoms as a, platform} from '#/alf' import {atoms as a, native, platform, useTheme} from '#/alf'
import {useDialogControl} from '#/components/Dialog' import {useDialogControl} from '#/components/Dialog'
import {ListAddRemoveUsersDialog} from '#/components/dialogs/lists/ListAddRemoveUsersDialog' import {ListAddRemoveUsersDialog} from '#/components/dialogs/lists/ListAddRemoveUsersDialog'
import * as Layout from '#/components/Layout' import * as Layout from '#/components/Layout'
import {Loader} from '#/components/Loader' import {Loader} from '#/components/Loader'
import * as Hider from '#/components/moderation/Hider' import * as Hider from '#/components/moderation/Hider'
import {IS_WEB} from '#/env'
import {AboutSection} from './AboutSection' import {AboutSection} from './AboutSection'
import {ErrorScreen} from './components/ErrorScreen' import {ErrorScreen} from './components/ErrorScreen'
import {Header} from './components/Header' import {Header} from './components/Header'
@@ -149,6 +150,7 @@ function ProfileListScreenLoaded({
moderationOpts: ModerationOpts moderationOpts: ModerationOpts
preferences: UsePreferencesQueryResponse preferences: UsePreferencesQueryResponse
}) { }) {
const t = useTheme()
const {_} = useLingui() const {_} = useLingui()
const queryClient = useQueryClient() const queryClient = useQueryClient()
const {openComposer} = useOpenComposer() const {openComposer} = useOpenComposer()
@@ -164,6 +166,8 @@ function ProfileListScreenLoaded({
const scrollElRef = useAnimatedRef() const scrollElRef = useAnimatedRef()
const addUserDialogControl = useDialogControl() const addUserDialogControl = useDialogControl()
const sectionTitlesCurate = [_(msg`Posts`), _(msg`People`)] const sectionTitlesCurate = [_(msg`Posts`), _(msg`People`)]
// modlist only
const [headerHeight, setHeaderHeight] = useState<number | null>(null)
const moderation = useMemo(() => { const moderation = useMemo(() => {
return moderateUserList(list, moderationOpts) return moderateUserList(list, moderationOpts)
@@ -263,13 +267,24 @@ function ProfileListScreenLoaded({
</Hider.Mask> </Hider.Mask>
<Hider.Content> <Hider.Content>
<View style={[a.util_screen_outer]}> <View style={[a.util_screen_outer]}>
<Layout.Center>{renderHeader()}</Layout.Center> <Layout.Center
onLayout={evt => setHeaderHeight(evt.nativeEvent.layout.height)}
style={[
native([a.absolute, a.z_10, t.atoms.bg]),
a.border_b,
t.atoms.border_contrast_low,
]}>
{renderHeader()}
</Layout.Center>
{headerHeight !== null && (
<AboutSection <AboutSection
list={list} list={list}
scrollElRef={scrollElRef as ListRef} scrollElRef={scrollElRef as ListRef}
onPressAddUser={addUserDialogControl.open} onPressAddUser={addUserDialogControl.open}
headerHeight={0} headerHeight={IS_WEB ? 0 : headerHeight}
/> />
)}
<FAB <FAB
testID="composeFAB" testID="composeFAB"
onPress={() => openComposer({logContext: 'Fab'})} onPress={() => openComposer({logContext: 'Fab'})}
-3
View File
@@ -16,7 +16,6 @@ import {useFocusEffect, useNavigation} from '@react-navigation/native'
import {type NativeStackScreenProps} from '@react-navigation/native-stack' import {type NativeStackScreenProps} from '@react-navigation/native-stack'
import {STARTER_PACK_MAX_SIZE} from '#/lib/constants' import {STARTER_PACK_MAX_SIZE} from '#/lib/constants'
import {useEnableKeyboardControllerScreen} from '#/lib/hooks/useEnableKeyboardController'
import {createSanitizedDisplayName} from '#/lib/moderation/create-sanitized-display-name' import {createSanitizedDisplayName} from '#/lib/moderation/create-sanitized-display-name'
import { import {
type CommonNavigatorParams, type CommonNavigatorParams,
@@ -185,8 +184,6 @@ function WizardInner({
}) })
}, [navigation]) }, [navigation])
useEnableKeyboardControllerScreen(true)
useFocusEffect( useFocusEffect(
React.useCallback(() => { React.useCallback(() => {
setMinimalShellMode(true) setMinimalShellMode(true)
-3
View File
@@ -12,7 +12,6 @@ import {
BLUESKY_MOD_SERVICE_HEADERS, BLUESKY_MOD_SERVICE_HEADERS,
MAX_REPORT_REASON_GRAPHEME_LENGTH, MAX_REPORT_REASON_GRAPHEME_LENGTH,
} from '#/lib/constants' } from '#/lib/constants'
import {useEnableKeyboardController} from '#/lib/hooks/useEnableKeyboardController'
import {cleanError} from '#/lib/strings/errors' import {cleanError} from '#/lib/strings/errors'
import {useAgent, useSession, useSessionApi} from '#/state/session' import {useAgent, useSession, useSessionApi} from '#/state/session'
import {CharProgress} from '#/view/com/composer/char-progress/CharProgress' import {CharProgress} from '#/view/com/composer/char-progress/CharProgress'
@@ -121,8 +120,6 @@ export function Takendown() {
const webLayout = IS_WEB && gtMobile const webLayout = IS_WEB && gtMobile
useEnableKeyboardController(true)
return ( return (
<View style={[a.util_screen_outer, a.flex_1]}> <View style={[a.util_screen_outer, a.flex_1]}>
<KeyboardAwareScrollView style={[a.flex_1, t.atoms.bg]} centerContent> <KeyboardAwareScrollView style={[a.flex_1, t.atoms.bg]} centerContent>
+9 -1
View File
@@ -200,7 +200,13 @@ export function useSetFeedViewPreferencesMutation() {
}) })
} }
export function useSetThreadViewPreferencesMutation() { export function useSetThreadViewPreferencesMutation({
onSuccess,
onError,
}: {
onSuccess?: (data: void, variables: Partial<ThreadViewPreferences>) => void
onError?: (error: unknown) => void
}) {
const queryClient = useQueryClient() const queryClient = useQueryClient()
const agent = useAgent() const agent = useAgent()
@@ -212,6 +218,8 @@ export function useSetThreadViewPreferencesMutation() {
queryKey: preferencesQueryKey, queryKey: preferencesQueryKey,
}) })
}, },
onSuccess,
onError,
}) })
} }
@@ -1,5 +1,6 @@
import {useCallback, useMemo, useRef, useState} from 'react' import {useCallback, useMemo, useRef, useState} from 'react'
import {type AppBskyUnspeccedGetPostThreadV2} from '@atproto/api' import {type AppBskyUnspeccedGetPostThreadV2} from '@atproto/api'
import {useFocusEffect} from '@react-navigation/native'
import debounce from 'lodash.debounce' import debounce from 'lodash.debounce'
import {useCallOnce} from '#/lib/once' import {useCallOnce} from '#/lib/once'
@@ -70,26 +71,37 @@ export function useThreadPreferences({
} }
const userUpdatedPrefs = useRef(false) const userUpdatedPrefs = useRef(false)
const [isSaving, setIsSaving] = useState(false) const {mutate, isPending: isSaving} = useSetThreadViewPreferencesMutation({
const {mutateAsync} = useSetThreadViewPreferencesMutation() onSuccess: (_data, prefs) => {
const savePrefs = useMemo(() => {
return debounce(async (prefs: ThreadViewPreferences) => {
try {
setIsSaving(true)
await mutateAsync(prefs)
ax.metric('thread:preferences:update', { ax.metric('thread:preferences:update', {
sort: prefs.sort, sort: prefs.sort,
view: prefs.lab_treeViewEnabled ? 'tree' : 'linear', view: prefs.lab_treeViewEnabled ? 'tree' : 'linear',
}) })
} catch (e) { },
onError: err => {
ax.logger.error('useThreadPreferences failed to save', { ax.logger.error('useThreadPreferences failed to save', {
safeMessage: e, safeMessage: err,
}) })
} finally { },
setIsSaving(false) })
const savePrefs = useMemo(() => {
return debounce(
(prefs: ThreadViewPreferences) => {
mutate(prefs)
},
2e3,
{leading: true, trailing: true},
)
}, [mutate])
// flush on leave screen
useFocusEffect(
useCallback(() => {
return () => {
void savePrefs.flush()
} }
}, 4e3) }, [savePrefs]),
}, [mutateAsync]) )
if (save && userUpdatedPrefs.current) { if (save && userUpdatedPrefs.current) {
savePrefs({ savePrefs({
@@ -5,6 +5,7 @@ import {msg, Plural, Trans} from '@lingui/macro'
import {useLingui} from '@lingui/react' import {useLingui} from '@lingui/react'
import {MAX_ALT_TEXT} from '#/lib/constants' import {MAX_ALT_TEXT} from '#/lib/constants'
import {useIsKeyboardVisible} from '#/lib/hooks/useIsKeyboardVisible'
import {enforceLen} from '#/lib/strings/helpers' import {enforceLen} from '#/lib/strings/helpers'
import {type ComposerImage} from '#/state/gallery' import {type ComposerImage} from '#/state/gallery'
import {AltTextCounterWrapper} from '#/view/com/composer/AltTextCounterWrapper' import {AltTextCounterWrapper} from '#/view/com/composer/AltTextCounterWrapper'
@@ -28,6 +29,7 @@ export const ImageAltTextDialog = ({
image, image,
onChange, onChange,
}: Props): React.ReactNode => { }: Props): React.ReactNode => {
const {height: minHeight} = useWindowDimensions()
const [altText, setAltText] = React.useState(image.alt) const [altText, setAltText] = React.useState(image.alt)
return ( return (
@@ -38,7 +40,8 @@ export const ImageAltTextDialog = ({
...image, ...image,
alt: enforceLen(altText, MAX_ALT_TEXT, true), alt: enforceLen(altText, MAX_ALT_TEXT, true),
}) })
}}> }}
nativeOptions={{minHeight}}>
<Dialog.Handle /> <Dialog.Handle />
<ImageAltTextInner <ImageAltTextInner
control={control} control={control}
@@ -65,6 +68,8 @@ const ImageAltTextInner = ({
const t = useTheme() const t = useTheme()
const windim = useWindowDimensions() const windim = useWindowDimensions()
const [isKeyboardVisible] = useIsKeyboardVisible()
const imageStyle = React.useMemo<ImageStyle>(() => { const imageStyle = React.useMemo<ImageStyle>(() => {
const maxWidth = IS_WEB ? 450 : windim.width const maxWidth = IS_WEB ? 450 : windim.width
const source = image.transformed ?? image.source const source = image.transformed ?? image.source
@@ -165,7 +170,7 @@ const ImageAltTextInner = ({
</AltTextCounterWrapper> </AltTextCounterWrapper>
</View> </View>
{/* Maybe fix this later -h */} {/* Maybe fix this later -h */}
{IS_ANDROID ? <View style={{height: 300}} /> : null} {IS_ANDROID && isKeyboardVisible ? <View style={{height: 300}} /> : null}
</Dialog.ScrollableInner> </Dialog.ScrollableInner>
) )
} }
+4 -4
View File
@@ -17163,10 +17163,10 @@ react-native-is-edge-to-edge@^1.2.1:
resolved "https://registry.yarnpkg.com/react-native-is-edge-to-edge/-/react-native-is-edge-to-edge-1.2.1.tgz#64e10851abd9d176cbf2b40562f751622bde3358" resolved "https://registry.yarnpkg.com/react-native-is-edge-to-edge/-/react-native-is-edge-to-edge-1.2.1.tgz#64e10851abd9d176cbf2b40562f751622bde3358"
integrity sha512-FLbPWl/MyYQWz+KwqOZsSyj2JmLKglHatd3xLZWskXOpRaio4LfEDEz8E/A6uD8QoTHW6Aobw1jbEwK7KMgR7Q== integrity sha512-FLbPWl/MyYQWz+KwqOZsSyj2JmLKglHatd3xLZWskXOpRaio4LfEDEz8E/A6uD8QoTHW6Aobw1jbEwK7KMgR7Q==
react-native-keyboard-controller@1.18.5: react-native-keyboard-controller@^1.20.7:
version "1.18.5" version "1.20.7"
resolved "https://registry.yarnpkg.com/react-native-keyboard-controller/-/react-native-keyboard-controller-1.18.5.tgz#ae12131f2019c574178479d2c55784f55e08bb68" resolved "https://registry.yarnpkg.com/react-native-keyboard-controller/-/react-native-keyboard-controller-1.20.7.tgz#e1be1c15a5eb10b96a40a0812d8472e6e4bd8f29"
integrity sha512-wbYN6Tcu3G5a05dhRYBgjgd74KqoYWuUmroLpigRg9cXy5uYo7prTMIvMgvLtARQtUF7BOtFggUnzgoBOgk0TQ== integrity sha512-G8S5jz1FufPrcL1vPtReATx+jJhT/j+sTqxMIb30b1z7cYEfMlkIzOCyaHgf6IMB2KA9uBmnA5M6ve2A9Ou4kw==
dependencies: dependencies:
react-native-is-edge-to-edge "^1.2.1" react-native-is-edge-to-edge "^1.2.1"