Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@ import expo.modules.core.utilities.EmulatorUtilities
import expo.modules.easclient.EASClientID
import expo.modules.updates.UpdatesConfiguration
import expo.modules.updates.UpdatesUtils
import expo.modules.updates.db.DatabaseHolder
import expo.modules.updates.db.UpdatesDatabase
import expo.modules.updates.db.entity.UpdateEntity
import expo.modules.updates.launcher.Launcher
import expo.modules.updates.loader.FileDownloader
Expand Down Expand Up @@ -70,7 +70,7 @@ class ExpoUpdatesAppLoader @JvmOverloads constructor(
lateinit var exponentSharedPreferences: ExponentSharedPreferences

@Inject
lateinit var databaseHolder: DatabaseHolder
lateinit var database: UpdatesDatabase

@Inject
lateinit var kernel: Kernel
Expand Down Expand Up @@ -173,7 +173,7 @@ class ExpoUpdatesAppLoader @JvmOverloads constructor(
EASClientID(context).uuid.toString(),
configuration,
logger,
databaseHolder.database
database
)
loaderScope.launch {
startLoaderTask(configuration, fileDownloader, directory, selectionPolicy, context, logger)
Expand All @@ -192,7 +192,7 @@ class ExpoUpdatesAppLoader @JvmOverloads constructor(
LoaderTask(
context,
configuration,
databaseHolder,
database,
directory,
fileDownloader,
selectionPolicy,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,6 @@ import android.content.Context
import android.os.Handler
import android.os.Looper
import com.facebook.proguard.annotations.DoNotStrip
import expo.modules.updates.db.DatabaseHolder
import expo.modules.updates.db.UpdatesDatabase
import host.exp.exponent.ExpoHandler
import host.exp.exponent.ExponentManifest
Expand Down Expand Up @@ -54,7 +53,7 @@ class NativeModuleDepsProvider(application: Application) {

@Inject
@DoNotStrip
val mUpdatesDatabaseHolder: DatabaseHolder = DatabaseHolder(UpdatesDatabase.getInstance(mContext, Dispatchers.IO))
val mUpdatesDatabase: UpdatesDatabase = UpdatesDatabase.getInstance(mContext, Dispatchers.IO)

private val classToInstanceMap = mutableMapOf<Class<*>, Any>()

Expand Down
1 change: 1 addition & 0 deletions apps/test-suite/TestModules.ts
Original file line number Diff line number Diff line change
Expand Up @@ -86,6 +86,7 @@ export function getTestModules() {
if (['android', 'ios'].includes(Platform.OS)) {
modules.push(require('./tests/ExpoUIMeasurement'));
modules.push(require('./tests/ExpoUIHostSize'));
modules.push(require('./tests/ExpoUIRNHostViewSize'));
modules.push(require('./tests/AppMetrics'));
modules.push(require('./tests/Blob'));
modules.push(require('./tests/FileSystem'));
Expand Down
4 changes: 2 additions & 2 deletions apps/test-suite/components/Suites.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -299,8 +299,8 @@ export default function Suites({
renderItem={({ item }) => (
<SuiteResult suite={item} depth={0} failuresOnly={failuresOnly} />
)}
ListHeaderComponent={header}
ListFooterComponent={footer}
ListHeaderComponent={header ?? undefined}
ListFooterComponent={footer ?? undefined}
stickyHeaderIndices={[0]}
onContentSizeChange={onContentSizeChange}
onLayout={onLayout}
Expand Down
52 changes: 28 additions & 24 deletions apps/test-suite/tests/ExpoUIMeasurement.android.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,10 @@ import { padding, paddingAll, size } from '@expo/ui/jetpack-compose/modifiers';
import React from 'react';
import { ScrollView, View } from 'react-native';

// React Native types `View` as a function component, so the instance type is its ref type.
type ViewRef = React.ComponentRef<typeof View>;
type ScrollViewRef = React.ComponentRef<typeof ScrollView>;

// Tests actual placement of UI matches return returned by RN's measure API.
// UI is placed by Compose and not Yoga, so these tests test that correct placement is reported to RN so Pressability can work correctly.
export const name = 'ExpoUIMeasurement';
Expand All @@ -29,7 +33,7 @@ type Measurement = {
pageY: number;
};

function measureAsync(ref: React.RefObject<View | null>, label = 'view'): Promise<Measurement> {
function measureAsync(ref: React.RefObject<ViewRef | null>, label = 'view'): Promise<Measurement> {
return new Promise((resolve, reject) => {
const node = ref.current;
if (!node) {
Expand All @@ -51,7 +55,7 @@ function delay(ms: number): Promise<void> {
* a row.
*
*/
async function measureWhenSettled<T extends Record<string, React.RefObject<View | null>>>(
async function measureWhenSettled<T extends Record<string, React.RefObject<ViewRef | null>>>(
refs: T,
timeoutMs = 5000
): Promise<Record<keyof T, Measurement>> {
Expand Down Expand Up @@ -109,8 +113,8 @@ export async function test(

describe(name, () => {
it('measures a hosted view where Compose placed it', async () => {
const hostWrapperRef = React.createRef<View>();
const hostedRef = React.createRef<View>();
const hostWrapperRef = React.createRef<ViewRef>();
const hostedRef = React.createRef<ViewRef>();

setPortalChild(
<View ref={hostWrapperRef} collapsable={false}>
Expand All @@ -137,8 +141,8 @@ export async function test(
});

it('measures a hosted view offset by its own padding modifier', async () => {
const hostWrapperRef = React.createRef<View>();
const hostedRef = React.createRef<View>();
const hostWrapperRef = React.createRef<ViewRef>();
const hostedRef = React.createRef<ViewRef>();

// The padding sits on the `RNHostView` itself, which is what the universal `RNHostView`
// makes of `style={{ padding }}`. Compose applies a modifier chain outside-in, so the
Expand All @@ -163,8 +167,8 @@ export async function test(
});

it('measures a hosted view offset by a padded Compose column', async () => {
const hostWrapperRef = React.createRef<View>();
const hostedRef = React.createRef<View>();
const hostWrapperRef = React.createRef<ViewRef>();
const hostedRef = React.createRef<ViewRef>();

setPortalChild(
<View ref={hostWrapperRef} collapsable={false}>
Expand All @@ -188,9 +192,9 @@ export async function test(
});

it('measures a hosted view stacked below another hosted view', async () => {
const hostWrapperRef = React.createRef<View>();
const firstRef = React.createRef<View>();
const secondRef = React.createRef<View>();
const hostWrapperRef = React.createRef<ViewRef>();
const firstRef = React.createRef<ViewRef>();
const secondRef = React.createRef<ViewRef>();

setPortalChild(
<View ref={hostWrapperRef} collapsable={false}>
Expand Down Expand Up @@ -222,8 +226,8 @@ export async function test(
});

it('measures a hosted view in a row, beside a Compose-only sibling', async () => {
const hostWrapperRef = React.createRef<View>();
const hostedRef = React.createRef<View>();
const hostWrapperRef = React.createRef<ViewRef>();
const hostedRef = React.createRef<ViewRef>();

setPortalChild(
<View ref={hostWrapperRef} collapsable={false}>
Expand All @@ -248,9 +252,9 @@ export async function test(
});

it('measures a hosted view in a row, beside another hosted view', async () => {
const hostWrapperRef = React.createRef<View>();
const firstRef = React.createRef<View>();
const secondRef = React.createRef<View>();
const hostWrapperRef = React.createRef<ViewRef>();
const firstRef = React.createRef<ViewRef>();
const secondRef = React.createRef<ViewRef>();

setPortalChild(
<View ref={hostWrapperRef} collapsable={false}>
Expand Down Expand Up @@ -280,12 +284,12 @@ export async function test(
});

it('measures a hosted view when the Host is inside a React Native ScrollView', async () => {
const scrollRef = React.createRef<ScrollView>();
const scrollRef = React.createRef<ScrollViewRef>();
// Anchored outside the `ScrollView` so it does not move with the content. A difference between
// two views that scroll together would cancel the scroll offset out and never notice it.
const viewportRef = React.createRef<View>();
const hostWrapperRef = React.createRef<View>();
const hostedRef = React.createRef<View>();
const viewportRef = React.createRef<ViewRef>();
const hostWrapperRef = React.createRef<ViewRef>();
const hostedRef = React.createRef<ViewRef>();

setPortalChild(
<View ref={viewportRef} collapsable={false} style={{ flex: 1 }}>
Expand Down Expand Up @@ -332,10 +336,10 @@ export async function test(
});

it('measures a PagerView page where Compose drew it, after paging to it', async () => {
const pagerWrapperRef = React.createRef<View>();
const pagerWrapperRef = React.createRef<ViewRef>();
const pagerRef = React.createRef<any>();
const firstRef = React.createRef<View>();
const secondRef = React.createRef<View>();
const firstRef = React.createRef<ViewRef>();
const secondRef = React.createRef<ViewRef>();

let onSelected: ((position: number) => void) | null = null;
const selected = new Promise<number>((resolve) => {
Expand Down Expand Up @@ -371,7 +375,7 @@ export async function test(
});

it('measures a hosted view in a modal bottom sheet relative to itself', async () => {
const hostedRef = React.createRef<View>();
const hostedRef = React.createRef<ViewRef>();

setPortalChild(
<Host matchContents>
Expand Down
40 changes: 22 additions & 18 deletions apps/test-suite/tests/ExpoUIMeasurement.ios.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,10 @@ import { padding } from '@expo/ui/swift-ui/modifiers';
import React from 'react';
import { ScrollView, View } from 'react-native';

// React Native types `View` as a function component, so the instance type is its ref type.
type ViewRef = React.ComponentRef<typeof View>;
type ScrollViewRef = React.ComponentRef<typeof ScrollView>;

// Tests that the actual placement of the UI matches what RN's measure API returns.
// UI is placed by SwiftUI and not Yoga, so these tests check that the placement reported to RN is correct and Pressability works.
export const name = 'ExpoUIMeasurement';
Expand All @@ -23,7 +27,7 @@ type Measurement = {
pageY: number;
};

function measureAsync(ref: React.RefObject<View | null>, label = 'view'): Promise<Measurement> {
function measureAsync(ref: React.RefObject<ViewRef | null>, label = 'view'): Promise<Measurement> {
return new Promise((resolve, reject) => {
const node = ref.current;
if (!node) {
Expand All @@ -45,7 +49,7 @@ function delay(ms: number): Promise<void> {
* mounts when it is on screen and animates in, so there is no single layout callback to wait on.
*/
async function measureWhenPresented(
ref: React.RefObject<View | null>,
ref: React.RefObject<ViewRef | null>,
label: string,
timeoutMs = 5000
): Promise<Measurement> {
Expand All @@ -72,8 +76,8 @@ export async function test(

describe(name, () => {
it('measures a hosted view where SwiftUI placed it, not where Yoga put its box', async () => {
const hostWrapperRef = React.createRef<View>();
const hostedRef = React.createRef<View>();
const hostWrapperRef = React.createRef<ViewRef>();
const hostedRef = React.createRef<ViewRef>();

let onLaidOut: () => void;
const laidOut = new Promise<void>((resolve) => {
Expand Down Expand Up @@ -105,9 +109,9 @@ export async function test(
});

it('measures a hosted view stacked below another hosted view', async () => {
const hostWrapperRef = React.createRef<View>();
const firstRef = React.createRef<View>();
const secondRef = React.createRef<View>();
const hostWrapperRef = React.createRef<ViewRef>();
const firstRef = React.createRef<ViewRef>();
const secondRef = React.createRef<ViewRef>();

let onLaidOut: () => void;
const laidOut = new Promise<void>((resolve) => {
Expand Down Expand Up @@ -142,8 +146,8 @@ export async function test(
});

it('measures a hosted view in a row, beside a SwiftUI-only sibling', async () => {
const hostWrapperRef = React.createRef<View>();
const hostedRef = React.createRef<View>();
const hostWrapperRef = React.createRef<ViewRef>();
const hostedRef = React.createRef<ViewRef>();

let onLaidOut: () => void;
const laidOut = new Promise<void>((resolve) => {
Expand Down Expand Up @@ -173,9 +177,9 @@ export async function test(
});

it('measures a hosted view in a row, beside another hosted view', async () => {
const hostWrapperRef = React.createRef<View>();
const firstRef = React.createRef<View>();
const secondRef = React.createRef<View>();
const hostWrapperRef = React.createRef<ViewRef>();
const firstRef = React.createRef<ViewRef>();
const secondRef = React.createRef<ViewRef>();

let onLaidOut: () => void;
const laidOut = new Promise<void>((resolve) => {
Expand Down Expand Up @@ -210,14 +214,14 @@ export async function test(
});

it('measures a hosted view when the Host is inside a React Native ScrollView', async () => {
const scrollRef = React.createRef<ScrollView>();
const scrollRef = React.createRef<ScrollViewRef>();
// Anchored outside the `ScrollView`, so it does not move when the content does. Measuring
// against it gives the box's real position on screen, which is what a touch is compared
// against — a difference between two views that scroll together would cancel the scroll
// offset out and never notice if it were wrong.
const viewportRef = React.createRef<View>();
const hostWrapperRef = React.createRef<View>();
const hostedRef = React.createRef<View>();
const viewportRef = React.createRef<ViewRef>();
const hostWrapperRef = React.createRef<ViewRef>();
const hostedRef = React.createRef<ViewRef>();

let onLaidOut: () => void;
const laidOut = new Promise<void>((resolve) => {
Expand Down Expand Up @@ -296,7 +300,7 @@ export async function test(

// A sheet content uses RootNodeKind trait so measurement happens relative to the RNHostView and not the RN's root surface.
it('measures a hosted view in a sheet relative to itself', async () => {
const hostedRef = React.createRef<View>();
const hostedRef = React.createRef<ViewRef>();

setPortalChild(
<Host matchContents>
Expand Down Expand Up @@ -324,7 +328,7 @@ export async function test(
});

it('measures a hosted view nested inside sheet content from the outer hosted view', async () => {
const nestedRef = React.createRef<View>();
const nestedRef = React.createRef<ViewRef>();

setPortalChild(
<Host matchContents>
Expand Down
Loading
Loading