first commit

This commit is contained in:
2026-03-10 16:18:05 +00:00
commit 11f9c069b5
31635 changed files with 3187747 additions and 0 deletions

184
node_modules/expo-router/ios/ExpoHeadModule.swift generated vendored Normal file
View File

@@ -0,0 +1,184 @@
// Copyright 2023-present 650 Industries. All rights reserved.
import ExpoModulesCore
import CoreSpotlight
import MobileCoreServices
struct MetadataOptions: Record {
@Field
// swiftlint:disable:next implicitly_unwrapped_optional
var activityType: String!
@Field
// swiftlint:disable:next implicitly_unwrapped_optional
var id: String!
@Field
var isEligibleForHandoff: Bool = true
@Field
var isEligibleForPrediction: Bool = true
@Field
var isEligibleForPublicIndexing: Bool = false
@Field
var isEligibleForSearch: Bool = true
@Field
var title: String?
@Field
var webpageURL: URL?
@Field
var imageUrl: URL?
@Field
var keywords: [String]?
@Field
var userInfo: [String: AnyHashable]?
@Field
var description: String?
}
// swiftlint:disable:next force_unwrapping
let indexRouteTag = Bundle.main.bundleIdentifier! + ".expo.index_route"
var launchedActivity: NSUserActivity?
internal class InvalidSchemeException: Exception {
override var reason: String {
"Scheme file:// is not allowed for location origin (webpageUrl in NSUserActivity)"
}
}
public class ExpoHeadModule: Module {
private var activities = Set<NSUserActivity>()
public required init(appContext: AppContext) {
super.init(appContext: appContext)
}
// Each module class must implement the definition function. The definition consists of components
// that describes the module's functionality and behavior.
// See https://docs.expo.dev/modules/module-api for more details about available components.
public func definition() -> ModuleDefinition {
// Sets the name of the module that JavaScript code will use to refer to the module.
// Takes a string as an argument. Can be inferred from module's class name, but it's
// recommended to set it explicitly for clarity.
// The module will be accessible from `requireNativeModule('ExpoHead')` in JavaScript.
Name("ExpoHead")
Constant("activities") {
[
"INDEXED_ROUTE": indexRouteTag
]
}
Function("getLaunchActivity") { () -> [String: Any]? in
if let activity = launchedActivity {
return [
"activityType": activity.activityType,
"description": activity.contentAttributeSet?.contentDescription,
"id": activity.persistentIdentifier,
"isEligibleForHandoff": activity.isEligibleForHandoff,
"isEligibleForPrediction": activity.isEligibleForPrediction,
"isEligibleForPublicIndexing": activity.isEligibleForPublicIndexing,
"isEligibleForSearch": activity.isEligibleForSearch,
"title": activity.title,
"webpageURL": activity.webpageURL,
"imageUrl": activity.contentAttributeSet?.thumbnailURL,
"keywords": activity.keywords,
"dateModified": activity.contentAttributeSet?.metadataModificationDate,
"userInfo": activity.userInfo
]
}
return nil
}
Function("createActivity") { (value: MetadataOptions) in
if let webpageUrl = value.webpageURL {
if webpageUrl.absoluteString.starts(with: "file://") == true {
throw Exception(name: "Invalid webpageUrl", description: "Scheme file:// is not allowed for location origin (webpageUrl in NSUserActivity). URL: \(webpageUrl.absoluteString)")
}
}
let activity = createOrUpdateActivity(value: value)
activity.becomeCurrent()
}
AsyncFunction("clearActivitiesAsync") { (ids: [String], promise: Promise) in
ids.forEach { id in
self.revokeActivity(id: id)
}
CSSearchableIndex.default().deleteSearchableItems(withIdentifiers: ids, completionHandler: { error in
if error != nil {
// swiftlint:disable:next force_cast
promise.reject(error as! Exception)
} else {
promise.resolve()
}
})
}
Function("suspendActivity") { (id: String) in
let activity = self.activities.first(where: { $0.persistentIdentifier == id })
activity?.resignCurrent()
}
Function("revokeActivity") { (id: String) in
self.revokeActivity(id: id)
}
}
func createOrUpdateActivity(value: MetadataOptions) -> NSUserActivity {
let att = CSSearchableItemAttributeSet(itemContentType: kUTTypeText as String)
let existing = self.activities.first(where: { $0.persistentIdentifier == value.id })
let activity = existing ?? NSUserActivity(activityType: value.activityType)
if existing == nil {
self.activities.insert(activity)
}
activity.targetContentIdentifier = value.id
activity.persistentIdentifier = value.id
activity.isEligibleForHandoff = value.isEligibleForHandoff
activity.isEligibleForPrediction = value.isEligibleForPrediction
activity.isEligibleForPublicIndexing = value.isEligibleForPublicIndexing
activity.isEligibleForSearch = value.isEligibleForSearch
activity.title = value.title
if let keywords = value.keywords {
activity.keywords = Set(keywords)
}
activity.userInfo = value.userInfo
if value.webpageURL != nil {
// If youre using all three APIs, it works well to use the URL of the relevant webpage as the value
// for uniqueIdentifier, relatedUniqueIdentifier, and webpageURL.
// https://developer.apple.com/library/archive/documentation/General/Conceptual/AppSearch/CombiningAPIs.html
activity.webpageURL = value.webpageURL
att.relatedUniqueIdentifier = value.webpageURL?.absoluteString
}
att.title = value.title
// Make all indexed routes deletable
att.domainIdentifier = indexRouteTag
if let localUrl = value.imageUrl?.path {
att.thumbnailURL = value.imageUrl
}
if let description = value.description {
att.contentDescription = description
}
activity.contentAttributeSet = att
return activity
}
@discardableResult
func revokeActivity(id: String) -> NSUserActivity? {
let activity = self.activities.first(where: { $0.persistentIdentifier == id })
activity?.invalidate()
if let activity = activity {
self.activities.remove(activity)
}
return activity
}
}