diff --git a/__mocks__/@notifee/react-native.ts b/__mocks__/@notifee/react-native.ts deleted file mode 100644 index 7e5ccec939..0000000000 --- a/__mocks__/@notifee/react-native.ts +++ /dev/null @@ -1,6 +0,0 @@ -export default { - requestPermission: jest.fn(), - onForegroundEvent: jest.fn(), - setBadgeCount: jest.fn(), - displayNotification: jest.fn(), -} diff --git a/__mocks__/@react-native-camera-roll/camera-roll.js b/__mocks__/@react-native-camera-roll/camera-roll.js deleted file mode 100644 index 8f1aea43bd..0000000000 --- a/__mocks__/@react-native-camera-roll/camera-roll.js +++ /dev/null @@ -1,9 +0,0 @@ -export const CameraRoll = { - getPhotos: jest.fn().mockResolvedValue({ - edges: [ - {node: {image: {uri: 'path/to/image1.jpg'}}}, - {node: {image: {uri: 'path/to/image2.jpg'}}}, - {node: {image: {uri: 'path/to/image3.jpg'}}}, - ], - }), -} diff --git a/__mocks__/react-native-background-fetch.ts b/__mocks__/react-native-background-fetch.ts deleted file mode 100644 index 0cb644c4d9..0000000000 --- a/__mocks__/react-native-background-fetch.ts +++ /dev/null @@ -1,4 +0,0 @@ -export default { - configure: jest.fn().mockResolvedValue(0), - finish: jest.fn(), -} diff --git a/__mocks__/react-native-fs.js b/__mocks__/react-native-fs.js deleted file mode 100644 index b1c6ea436a..0000000000 --- a/__mocks__/react-native-fs.js +++ /dev/null @@ -1 +0,0 @@ -export default {} diff --git a/__mocks__/rn-fetch-blob.js b/__mocks__/rn-fetch-blob.js deleted file mode 100644 index dedfbdf896..0000000000 --- a/__mocks__/rn-fetch-blob.js +++ /dev/null @@ -1,10 +0,0 @@ -jest.mock('rn-fetch-blob', () => { - return { - __esModule: true, - default: { - fs: { - unlink: jest.fn(), - }, - }, - } -}) diff --git a/__mocks__/zeego/dropdown-menu.js b/__mocks__/zeego/dropdown-menu.js deleted file mode 100644 index 1d51addca9..0000000000 --- a/__mocks__/zeego/dropdown-menu.js +++ /dev/null @@ -1,2 +0,0 @@ -export const DropdownMenu = jest.fn().mockImplementation(() => {}) -export const create = jest.fn().mockImplementation(() => {}) diff --git a/app.config.js b/app.config.js index db9a371654..0ed73cf5a7 100644 --- a/app.config.js +++ b/app.config.js @@ -112,7 +112,6 @@ module.exports = function (_config) { 'zh-Hans', 'zh-Hant', ], - UIDesignRequiresCompatibility: true, }, associatedDomains: ASSOCIATED_DOMAINS, entitlements: { diff --git a/modules/bottom-sheet/ios/SheetViewController.swift b/modules/bottom-sheet/ios/SheetViewController.swift index 90d0fed0df..eaf0a7123a 100644 --- a/modules/bottom-sheet/ios/SheetViewController.swift +++ b/modules/bottom-sheet/ios/SheetViewController.swift @@ -27,6 +27,19 @@ class SheetViewController: UIViewController { return } + // On iOS 26, the floaty sheet presentation adds the device bottom safe area + // on top of the custom detent value, creating visible padding inside the pill. + // Subtract it so the pill height matches our actual content. + var bottomSafeAreaAdjustment: CGFloat = 0 + if #available(iOS 26.0, *) { + if let windowScene = UIApplication.shared.connectedScenes.first as? UIWindowScene, + let window = windowScene.windows.first { + bottomSafeAreaAdjustment = window.safeAreaInsets.bottom + } + } + + let adjustedHeight = contentHeight - bottomSafeAreaAdjustment + if #available(iOS 16.0, *) { if contentHeight > screenHeight - 100 { sheet.detents = [ @@ -36,7 +49,7 @@ class SheetViewController: UIViewController { } else { sheet.detents = [ .custom { _ in - return contentHeight + return adjustedHeight } ] if !preventExpansion { diff --git a/modules/bottom-sheet/src/BottomSheetNativeComponent.tsx b/modules/bottom-sheet/src/BottomSheetNativeComponent.tsx index 817d476fbe..0fa4c8aa23 100644 --- a/modules/bottom-sheet/src/BottomSheetNativeComponent.tsx +++ b/modules/bottom-sheet/src/BottomSheetNativeComponent.tsx @@ -5,6 +5,7 @@ import { type NativeSyntheticEvent, Platform, type StyleProp, + useWindowDimensions, View, type ViewStyle, } from 'react-native' @@ -21,8 +22,6 @@ import { Context as PortalContext, } from './BottomSheetPortal' -const screenHeight = Dimensions.get('screen').height - const NativeView: React.ComponentType< BottomSheetViewProps & { ref: React.RefObject @@ -94,6 +93,7 @@ export class BottomSheetNativeComponent extends React.Component< let extraStyles if (IS_IOS15 && this.state.viewHeight) { + const screenHeight = Dimensions.get('screen').height const {viewHeight} = this.state const cornerRadius = this.props.cornerRadius ?? 0 if (viewHeight < screenHeight / 2) { @@ -154,6 +154,7 @@ function BottomSheetNativeComponentInner({ }) { const insets = useSafeAreaInsets() const cornerRadius = rest.cornerRadius ?? 0 + const {height: screenHeight} = useWindowDimensions() const sheetHeight = IS_IOS ? screenHeight - insets.top : screenHeight diff --git a/package.json b/package.json index 9f32500508..cc4305af84 100644 --- a/package.json +++ b/package.json @@ -16,6 +16,13 @@ "expo-image-picker" ] } + }, + "install": { + "exclude": [ + "react-native-reanimated", + "@sentry/react-native", + "react-native-pager-view" + ] } }, "scripts": { diff --git a/src/alf/atoms.ts b/src/alf/atoms.ts index ffac94a5da..da9b997201 100644 --- a/src/alf/atoms.ts +++ b/src/alf/atoms.ts @@ -10,6 +10,10 @@ const EXP_CURVE = 'cubic-bezier(0.16, 1, 0.3, 1)' export const atoms = { ...baseAtoms, + rounded_sheet: { + borderRadius: 40, + }, + h_full_vh: web({ height: '100vh', }), diff --git a/src/components/Dialog/index.tsx b/src/components/Dialog/index.tsx index 1c2cad9e63..cdc3d657bc 100644 --- a/src/components/Dialog/index.tsx +++ b/src/components/Dialog/index.tsx @@ -38,7 +38,7 @@ import { type DialogOuterProps, } from '#/components/Dialog/types' import {createInput} from '#/components/forms/TextField' -import {IS_ANDROID, IS_IOS} from '#/env' +import {IS_ANDROID, IS_IOS, IS_LIQUID_GLASS} from '#/env' import {BottomSheet, BottomSheetSnapPoint} from '../../../modules/bottom-sheet' import { type BottomSheetSnapPointChangeEvent, @@ -166,7 +166,8 @@ export function Outer({ return ( {children} @@ -253,7 +257,7 @@ export const ScrollableInner = React.forwardRef( {renderLeft && ( - {renderLeft()} + + {renderLeft()} + )} {children} {renderRight && ( - {renderRight()} + + {renderRight()} + )} ) diff --git a/src/components/Dialog/sheet-wrapper.ts b/src/components/Dialog/sheet-wrapper.ts index d6ff687859..558851438f 100644 --- a/src/components/Dialog/sheet-wrapper.ts +++ b/src/components/Dialog/sheet-wrapper.ts @@ -1,7 +1,7 @@ import {useCallback} from 'react' import {SystemBars} from 'react-native-edge-to-edge' -import {IS_IOS} from '#/env' +import {IS_IOS, IS_LIQUID_GLASS} from '#/env' /** * If we're calling a system API like the image picker that opens a sheet @@ -9,7 +9,7 @@ import {IS_IOS} from '#/env' */ export function useSheetWrapper() { return useCallback(async (promise: Promise): Promise => { - if (IS_IOS) { + if (IS_IOS && !IS_LIQUID_GLASS) { const entry = SystemBars.pushStackEntry({ style: { statusBar: 'light', diff --git a/src/components/Menu/index.tsx b/src/components/Menu/index.tsx index 8480956715..65d279e196 100644 --- a/src/components/Menu/index.tsx +++ b/src/components/Menu/index.tsx @@ -273,7 +273,8 @@ export function ContainerItem({ a.align_center, a.gap_sm, a.px_md, - a.rounded_md, + a.rounded_lg, + a.curve_continuous, a.border, t.atoms.bg_contrast_25, t.atoms.border_contrast_low, @@ -311,7 +312,8 @@ export function Group({children, style}: GroupProps) { return ( + nativeOptions={{ + minHeight: IS_LIQUID_GLASS ? height : height - insets.top, + }}> = 26 diff --git a/src/env/index.web.ts b/src/env/index.web.ts index 0435569ed6..0a078fdeb0 100644 --- a/src/env/index.web.ts +++ b/src/env/index.web.ts @@ -47,3 +47,4 @@ export const IS_WEB_FIREFOX: boolean = /firefox|fxios/i.test( export const IS_HIGH_DPI: boolean = window.matchMedia( '(min-resolution: 2dppx)', ).matches +export const IS_LIQUID_GLASS: boolean = false diff --git a/src/screens/SignupQueued.tsx b/src/screens/SignupQueued.tsx index 2daa701b00..55878700bf 100644 --- a/src/screens/SignupQueued.tsx +++ b/src/screens/SignupQueued.tsx @@ -14,7 +14,7 @@ import {atoms as a, native, useBreakpoints, useTheme, web} from '#/alf' import {Button, ButtonIcon, ButtonText} from '#/components/Button' import {Loader} from '#/components/Loader' import {P, Text} from '#/components/Typography' -import {IS_IOS, IS_WEB} from '#/env' +import {IS_IOS, IS_LIQUID_GLASS, IS_WEB} from '#/env' const COL_WIDTH = 400 @@ -107,7 +107,9 @@ export function SignupQueued() { animationType={native('slide')} presentationStyle="formSheet" style={[web(a.util_screen_outer)]}> - {IS_IOS && } + {IS_IOS && !IS_LIQUID_GLASS && ( + + )} - +