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
13 changes: 11 additions & 2 deletions .github/actions/expo-caches/action.yml
Original file line number Diff line number Diff line change
Expand Up @@ -168,8 +168,17 @@ runs:
uses: actions/cache@27d5ce7f107fe9357f9df03efb73ab90386fccae # v5.0.5
with:
path: ${{ runner.temp }}/.ccache
key: ${{ runner.os }}-ccache-${{ hashFiles('pnpm-lock.yaml', 'packages/**/*.c', 'packages/**/*.cpp', 'packages/**/*.h', 'packages/**/build.gradle', 'packages/**/build.gradle.kts', 'packages/**/settings.gradle', 'packages/**/settings.gradle.kts', 'apps/bare-expo/**/build.gradle', 'apps/bare-expo/**/settings.gradle') }}
restore-keys: ${{ runner.os }}-ccache-
# The key is divided into two parts:
#
# PART 1 - used in key and restore-keys
# pnpm-lock.yaml keeps track of the react native version, which tracks the NDK version, if it changes, we need to invalidate the cache.
#
# PART 2 - used only in the exact key
# ccache tracks these files without any sloppiness issues.
# - C/C++ source files
# - Gradle files: see https://github.com/expo/expo/pull/44884
key: ${{ runner.os }}-ccache-${{hashFiles('pnpm-lock.yaml')}}-${{ hashFiles('packages/**/*.c', 'packages/**/*.cpp', 'packages/**/*.h', 'packages/**/build.gradle', 'packages/**/build.gradle.kts', 'packages/**/settings.gradle', 'packages/**/settings.gradle.kts', 'apps/bare-expo/**/build.gradle', 'apps/bare-expo/**/settings.gradle', 'apps/bare-expo/android/app/src/main/jni/pch.h') }}
restore-keys: ${{ runner.os }}-ccache-${{hashFiles('pnpm-lock.yaml')}}

- name: 🔍️ Get cache key of Git LFS files
if: inputs.git-lfs == 'true'
Expand Down
11 changes: 9 additions & 2 deletions .github/actions/setup-ccache/action.yml
Original file line number Diff line number Diff line change
Expand Up @@ -37,7 +37,10 @@ runs:
# time_macros might help if in included modules there are macros like __TIME__ which would trigger a cache miss.
# system_headers: avoids hashing thousands of Apple SDK headers.
# modules, clang_index_store, ivfsoverlay: without these, hit rate on iOS would be 0%.
echo "CCACHE_SLOPPINESS=include_file_mtime,include_file_ctime,time_macros,modules,clang_index_store,system_headers,ivfsoverlay" >> $GITHUB_ENV
echo "CCACHE_SLOPPINESS=include_file_mtime,include_file_ctime,time_macros,modules,clang_index_store,system_headers,ivfsoverlay,pch_defines" >> $GITHUB_ENV

# Calculate hash based on a relative path - this prevents cache misses when an absolute path changes.
echo "CCACHE_BASEDIR=${{ github.workspace }}" >> $GITHUB_ENV

# Speeds up the process on cache misses by skipping the preprocessing step.
echo "CCACHE_DEPEND=true" >> $GITHUB_ENV
Expand Down Expand Up @@ -71,7 +74,11 @@ runs:
# Sloppiness options disable some of the ccache checks to increase hit rate.
# In our case we exclude ctime and mtime so cache is hit based on file content.
# time_macros might help if in included modules there are macros like __TIME__ which would trigger a cache miss.
echo "CCACHE_SLOPPINESS=include_file_ctime,include_file_mtime,time_macros" >> $GITHUB_ENV
# system_headers: avoids hashing NDK sysroot headers that don't change between builds.
echo "CCACHE_SLOPPINESS=include_file_ctime,include_file_mtime,time_macros,system_headers,pch_defines" >> $GITHUB_ENV

# Speeds up the process on cache misses by skipping the preprocessing step.
echo "CCACHE_DEPEND=true" >> $GITHUB_ENV

# Replaces compiler with ccache.
echo "CMAKE_C_COMPILER_LAUNCHER=$(which ccache)" >> $GITHUB_ENV
Expand Down
2 changes: 1 addition & 1 deletion apps/bare-expo/android/app/build.gradle
Original file line number Diff line number Diff line change
Expand Up @@ -123,7 +123,7 @@ android {
def enableShrinkResources = findProperty('android.enableShrinkResourcesInReleaseBuilds') ?: 'false'
shrinkResources enableShrinkResources.toBoolean()
minifyEnabled enableMinifyInReleaseBuilds
proguardFiles getDefaultProguardFile("proguard-android.txt"), "proguard-rules.pro"
proguardFiles getDefaultProguardFile("proguard-android-optimize.txt"), "proguard-rules.pro"
}
benchmark {
initWith buildTypes.release
Expand Down
25 changes: 14 additions & 11 deletions apps/bare-expo/android/app/src/main/jni/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -6,22 +6,20 @@ include(${REACT_ANDROID_DIR}/cmake-utils/ReactNative-application.cmake)

set(PCH_HEADER "${CMAKE_CURRENT_SOURCE_DIR}/pch.h")

set(_pch_owner_src "${CMAKE_CURRENT_BINARY_DIR}/appmodules_pch_owner.cpp")
file(WRITE "${_pch_owner_src}"
"// Generated by CMakeLists.txt. Translation unit exists solely so the\n"
"// owning target can produce a .pch binary that codegen targets reuse.\n")

add_library(appmodules_pch STATIC EXCLUDE_FROM_ALL "${_pch_owner_src}")
add_library(appmodules_pch STATIC EXCLUDE_FROM_ALL "${CMAKE_CURRENT_SOURCE_DIR}/appmodules_pch_owner.cpp")

# Apply the exact same compile options codegen targets get from RN's
target_compile_reactnative_options(appmodules_pch PRIVATE)

# Link dependencies needed by our PCH header
foreach (_dep IN ITEMS common_flags reactnative jsi folly_runtime fbjni)
if (TARGET ${_dep})
target_link_libraries(appmodules_pch PRIVATE ${_dep})
endif ()
endforeach ()
target_link_libraries(appmodules_pch PRIVATE common_flags reactnative jsi folly_runtime fbjni)

# Stop Clang from embedding a build timestamp in the .pch. Without this the PCH
# is non-reproducible across builds, so ccache can't reuse it and dependent
# translation units reject a restored PCH as "modified since built".
target_compile_options(appmodules_pch PRIVATE
"$<$<COMPILE_LANGUAGE:CXX>:-Xclang;-fno-pch-timestamp>"
)

target_precompile_headers(appmodules_pch PRIVATE
"$<$<COMPILE_LANGUAGE:CXX>:${PCH_HEADER}>"
Expand All @@ -42,6 +40,11 @@ function(add_pch_if_eligible target)
return()
endif ()

# Keep the flag consistent with the PCH owner - see the note above.
target_compile_options(${target} PRIVATE
"$<$<COMPILE_LANGUAGE:CXX>:-Xclang;-fno-pch-timestamp>"
)

target_precompile_headers(${target} REUSE_FROM appmodules_pch)
endfunction()

Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
// Translation unit exists solely so the owning target can produce a .pch
// binary that codegen targets reuse.
2 changes: 1 addition & 1 deletion apps/bare-expo/ios/Podfile.lock
Original file line number Diff line number Diff line change
Expand Up @@ -4098,7 +4098,7 @@ SPEC CHECKSUMS:
EXUpdates: c6488f0bebe92d6decb5f9b685d33ee91feeccf0
EXUpdatesInterface: 25408a97d682355eb9fb37e5aa6e22caece1881f
FBLazyVector: 5466888598cde67aedb4d3a819adf471d1a3d8c9
hermes-engine: e355eb94d3f8b7f4c08531a4d42af958d36c13de
hermes-engine: 4c998771d5218e20701b63d8358199a520a54447
libavif: 5f8e715bea24debec477006f21ef9e95432e254d
libdav1d: 23581a4d8ec811ff171ed5e2e05cd27bad64c39f
libwebp: 02b23773aedb6ff1fd38cec7a77b81414c6842a8
Expand Down
40 changes: 0 additions & 40 deletions apps/expo-go/ios/Client/AppDelegate.swift
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,6 @@ import ReactAppDependencyProvider

@main
class AppDelegate: ExpoAppDelegate {
var rootViewController: EXRootViewController?
var window: UIWindow?

var reactNativeDelegate: ExpoReactNativeFactoryDelegate?
Expand All @@ -23,47 +22,8 @@ class AppDelegate: ExpoAppDelegate {

FirebaseApp.configure()

if application.applicationState != UIApplication.State.background {
// App launched in foreground
setUpUserInterfaceForApplication(application, withLaunchOptions: launchOptions)
}

return super.application(application, didFinishLaunchingWithOptions: launchOptions)
}

override func applicationWillEnterForeground(_ application: UIApplication) {
setUpUserInterfaceForApplication(application, withLaunchOptions: nil)
super.applicationWillEnterForeground(application)
}

private func setUpUserInterfaceForApplication(_ application: UIApplication, withLaunchOptions launchOptions: [UIApplication.LaunchOptionsKey: Any]?) {
if self.window != nil {
return
}
ExpoKit.sharedInstance().registerRootViewControllerClass(EXRootViewController.self)
ExpoKit.sharedInstance().prepare()

let window = UIWindow(frame: UIScreen.main.bounds)
self.window = window
window.backgroundColor = UIColor.white
rootViewController = (ExpoKit.sharedInstance().rootViewController() as! EXRootViewController)
window.rootViewController = rootViewController
if let initialURL = EXKernelLinkingManager.initialUrl(fromLaunchOptions: launchOptions) {
// When the app is cold-launched via a URL scheme (e.g. exp://), iOS delivers the URL
// in two ways: (1) here in launchOptions, and (2) by calling application:openURL:options:
// after this method returns. If we handle it in both places, two RCTHost instances are
// created concurrently, which crashes on first install due to a Swift runtime metadata
// race condition. So we skip URL scheme deep links here and let openURL be the sole handler.
// Non-URL-scheme sources (process args via --initialUrl, universal links) don't have a
// separate callback, so we still handle those here.
let isURLSchemeDeepLink = (launchOptions?[.url] as? URL) == initialURL
if !isURLSchemeDeepLink {
rootViewController?.setInitialHomeURL(initialURL)
}
}

window.makeKeyAndVisible()
}
}

class ReactNativeDelegate: ExpoReactNativeFactoryDelegate {
Expand Down
82 changes: 82 additions & 0 deletions apps/expo-go/ios/Client/ExpoGoSceneDelegate.swift
Original file line number Diff line number Diff line change
@@ -0,0 +1,82 @@
// Copyright 2015-present 650 Industries. All rights reserved.

import UIKit
import ExpoModulesCore

@objc(ExpoGoSceneDelegate)
class ExpoGoSceneDelegate: UIResponder, UIWindowSceneDelegate {
var window: UIWindow?

func scene(
_ scene: UIScene,
willConnectTo session: UISceneSession,
options connectionOptions: UIScene.ConnectionOptions
) {
guard let windowScene = scene as? UIWindowScene else {
return
}

ExpoKit.sharedInstance().registerRootViewControllerClass(EXRootViewController.self)
ExpoKit.sharedInstance().prepare()

let window = UIWindow(windowScene: windowScene)
window.backgroundColor = .white
let rootViewController = ExpoKit.sharedInstance().rootViewController() as! EXRootViewController
window.rootViewController = rootViewController
self.window = window

(UIApplication.shared.delegate as? AppDelegate)?.window = window

if let initialURL = EXKernelLinkingManager.initialUrl(fromLaunchOptions: nil) {
rootViewController.setInitialHomeURL(initialURL)
}

window.makeKeyAndVisible()

handle(urlContexts: connectionOptions.urlContexts)
connectionOptions.userActivities.forEach { handle(userActivity: $0) }
}

func sceneDidDisconnect(_ scene: UIScene) {
window = nil
}

func sceneDidBecomeActive(_ scene: UIScene) {
ExpoAppDelegateSubscriberManager.applicationDidBecomeActive(UIApplication.shared)
}

func sceneWillResignActive(_ scene: UIScene) {
ExpoAppDelegateSubscriberManager.applicationWillResignActive(UIApplication.shared)
}

func sceneWillEnterForeground(_ scene: UIScene) {
ExpoAppDelegateSubscriberManager.applicationWillEnterForeground(UIApplication.shared)
}

func sceneDidEnterBackground(_ scene: UIScene) {
ExpoAppDelegateSubscriberManager.applicationDidEnterBackground(UIApplication.shared)
}

func scene(_ scene: UIScene, openURLContexts URLContexts: Set<UIOpenURLContext>) {
handle(urlContexts: URLContexts)
}

func scene(_ scene: UIScene, continue userActivity: NSUserActivity) {
handle(userActivity: userActivity)
}

private func handle(urlContexts: Set<UIOpenURLContext>) {
let linkingManager = EXKernel.sharedInstance().serviceRegistry.linkingManager
for context in urlContexts {
_ = linkingManager?.application(UIApplication.shared, open: context.url, options: [:])
}
}

private func handle(userActivity: NSUserActivity) {
_ = EXKernelLinkingManager.application(
UIApplication.shared,
continue: userActivity,
restorationHandler: { _ in }
)
}
}
17 changes: 17 additions & 0 deletions apps/expo-go/ios/Exponent/Supporting/Info.plist
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,23 @@
<array>
<string>com.expo.modules.backgroundtask.processing</string>
</array>
<key>UIApplicationSceneManifest</key>
<dict>
<key>UIApplicationSupportsMultipleScenes</key>
<false/>
<key>UISceneConfigurations</key>
<dict>
<key>UIWindowSceneSessionRoleApplication</key>
<array>
<dict>
<key>UISceneConfigurationName</key>
<string>Default Configuration</string>
<key>UISceneDelegateClassName</key>
<string>$(PRODUCT_MODULE_NAME).ExpoGoSceneDelegate</string>
</dict>
</array>
</dict>
</dict>
<key>CADisableMinimumFrameDurationOnPhone</key>
<true/>
<key>CFBundleDevelopmentRegion</key>
Expand Down
11 changes: 11 additions & 0 deletions apps/expo-go/ios/Podfile
Original file line number Diff line number Diff line change
Expand Up @@ -160,6 +160,17 @@ target 'Expo Go' do
config.build_settings['GCC_PREPROCESSOR_DEFINITIONS'] << 'RCT_DEV_SETTINGS_ENABLE_PACKAGER_CONNECTION=0'
end
end

if installer.pods_project
installer.pods_project.targets.each do |target|
target.build_configurations.each do |config|
current = config.build_settings['IPHONEOS_DEPLOYMENT_TARGET']
if current.to_s =~ /\A\d/ && Gem::Version.new(current) < Gem::Version.new('16.4')
config.build_settings['IPHONEOS_DEPLOYMENT_TARGET'] = '16.4'
end
end
end
end
end

target 'Tests' do
Expand Down
4 changes: 2 additions & 2 deletions apps/expo-go/ios/Podfile.lock
Original file line number Diff line number Diff line change
Expand Up @@ -4782,7 +4782,7 @@ SPEC CHECKSUMS:
GoogleAppMeasurement: 8a82b93a6400c8e6551c0bcd66a9177f2e067aed
GoogleDataTransport: aae35b7ea0c09004c3797d53c8c41f66f219d6a7
GoogleUtilities: 00c88b9a86066ef77f0da2fab05f65d7768ed8e1
hermes-engine: d5c6d584ad5c5461ad9e34e0afb5d40d56e428f5
hermes-engine: 42f0ed2cf70592b35e2ca49a6b725d31c8ad4136
libavif: 5f8e715bea24debec477006f21ef9e95432e254d
libdav1d: 23581a4d8ec811ff171ed5e2e05cd27bad64c39f
libwebp: 02b23773aedb6ff1fd38cec7a77b81414c6842a8
Expand Down Expand Up @@ -4905,6 +4905,6 @@ SPEC CHECKSUMS:
Yoga: f4b28f1978b0b41f73818f68941e8ef9d27ee857
ZXingObjC: 8898711ab495761b2dbbdec76d90164a6d7e14c5

PODFILE CHECKSUM: 330a7a37788c690eb6d1485a7c5003375ee538b2
PODFILE CHECKSUM: 58b0c3a5c62ae53bc42e1b1f1c0e85f6dc8a7f65

COCOAPODS: 1.16.2
2 changes: 1 addition & 1 deletion apps/minimal-tester/android/app/build.gradle
Original file line number Diff line number Diff line change
Expand Up @@ -116,7 +116,7 @@ android {
def enableShrinkResources = findProperty('android.enableShrinkResourcesInReleaseBuilds') ?: 'false'
shrinkResources enableShrinkResources.toBoolean()
minifyEnabled enableMinifyInReleaseBuilds
proguardFiles getDefaultProguardFile("proguard-android.txt"), "proguard-rules.pro"
proguardFiles getDefaultProguardFile("proguard-android-optimize.txt"), "proguard-rules.pro"
def enablePngCrunchInRelease = findProperty('android.enablePngCrunchInReleaseBuilds') ?: 'true'
crunchPngs enablePngCrunchInRelease.toBoolean()
}
Expand Down
12 changes: 11 additions & 1 deletion apps/test-suite/tests/MediaLibrary.js
Original file line number Diff line number Diff line change
Expand Up @@ -109,7 +109,7 @@ export async function test(t) {
? 30 * 1000
: t.jasmine.DEFAULT_TIMEOUT_INTERVAL;

describeWithPermissions('MediaLibrary', async () => {
describeWithPermissions('MediaLibrary', () => {
let files;
let permissions;

Expand Down Expand Up @@ -233,6 +233,16 @@ export async function test(t) {
t.expect(asset).toBeNull();
});

if (Platform.OS === 'android') {
t.it('getAssetContentUriAsync returns content uri', async () => {
const asset = testAssets[0];
const volume = Platform.Version === 29 ? 'external_primary' : 'external';
const contentUri = await MediaLibrary.getAssetContentUriAsync(asset);

t.expect(contentUri).toBe(`content://media/${volume}/images/media/${asset.id}`);
});
}

t.it(
'saveToLibraryAsync should throw when the provided path does not contain an extension',
async () => {
Expand Down
2 changes: 1 addition & 1 deletion docs/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -40,7 +40,7 @@
"@expo/styleguide-base": "^3.1.2",
"@expo/styleguide-cookie-consent": "^2.1.2",
"@expo/styleguide-icons": "^4.2.4",
"@expo/styleguide-search-ui": "^9.1.6",
"@expo/styleguide-search-ui": "^9.1.7",
"@formatjs/intl-localematcher": "^0.8.5",
"@kapaai/react-sdk": "^0.9.6",
"@mdx-js/loader": "^3.1.1",
Expand Down
Loading
Loading