diff --git a/.gitignore b/.gitignore index 23a1687..098aa2e 100644 --- a/.gitignore +++ b/.gitignore @@ -70,6 +70,9 @@ aries-oca-bundles/ credo-ts/ app/vendor/ +# Android native build cache +app/android/app/.cxx/ + # Android keystore release.keystore *.keystore.old diff --git a/.yarn/patches/@animo-id-expo-secure-environment-npm-0.1.5-3c2a8f1b94.patch b/.yarn/patches/@animo-id-expo-secure-environment-npm-0.1.5-3c2a8f1b94.patch new file mode 100644 index 0000000..2628a93 --- /dev/null +++ b/.yarn/patches/@animo-id-expo-secure-environment-npm-0.1.5-3c2a8f1b94.patch @@ -0,0 +1,18 @@ +diff --git a/android/build.gradle b/android/build.gradle +index cde6a970a43cc930546e59a80e8716a0980bc503..f7dc11cd461beedda314f3700dc42623d82a4029 100644 +--- a/android/build.gradle ++++ b/android/build.gradle +@@ -40,6 +40,13 @@ + lintOptions { + abortOnError false + } ++ compileOptions { ++ sourceCompatibility JavaVersion.VERSION_17 ++ targetCompatibility JavaVersion.VERSION_17 ++ } ++ kotlinOptions { ++ jvmTarget = "17" ++ } + } + + dependencies { diff --git a/.yarn/patches/@credo-ts-anoncreds-npm-0.5.17-9f101d8e96.patch b/.yarn/patches/@credo-ts-anoncreds-npm-0.5.17-9f101d8e96.patch deleted file mode 100644 index 656cc45..0000000 --- a/.yarn/patches/@credo-ts-anoncreds-npm-0.5.17-9f101d8e96.patch +++ /dev/null @@ -1,40 +0,0 @@ -diff --git a/build/utils/proofRequest.js b/build/utils/proofRequest.js -index f4ce51a890f0ac41ed1d9806f0350a2114890625..10d02bd809b4e6311618664b0ec4ad0ada8034dc 100644 ---- a/build/utils/proofRequest.js -+++ b/build/utils/proofRequest.js -@@ -7,12 +7,27 @@ function proofRequestUsesUnqualifiedIdentifiers(proofRequest) { - return [ - ...Object.values(proofRequest.requested_attributes), - ...Object.values(proofRequest.requested_predicates), -- ].some((attribute) => attribute.restrictions?.some((restriction) => (restriction.cred_def_id && (0, indyIdentifiers_1.isUnqualifiedCredentialDefinitionId)(restriction.cred_def_id)) || -- (restriction.schema_id && (0, indyIdentifiers_1.isUnqualifiedSchemaId)(restriction.schema_id)) || -- (restriction.issuer_did && (0, indyIdentifiers_1.isUnqualifiedIndyDid)(restriction.issuer_did)) || -- (restriction.issuer_id && (0, indyIdentifiers_1.isUnqualifiedIndyDid)(restriction.issuer_id)) || -- (restriction.schema_issuer_did && (0, indyIdentifiers_1.isUnqualifiedIndyDid)(restriction.schema_issuer_did)) || -- (restriction.schema_issuer_id && (0, indyIdentifiers_1.isUnqualifiedIndyDid)(restriction.schema_issuer_id)) || -- (restriction.rev_reg_id && (0, indyIdentifiers_1.isUnqualifiedRevocationRegistryId)(restriction.rev_reg_id)))); -+ ].some((attribute) => { -+ var _a; -+ return (_a = attribute.restrictions) === null || _a === void 0 ? void 0 : _a.some((restriction) => ( -+ // no qualified identifiers -+ !restriction.cred_def_id && -+ !restriction.schema_id && -+ !restriction.issuer_did && -+ !restriction.issuer_id && -+ !restriction.schema_issuer_did && -+ !restriction.schema_issuer_id && -+ !restriction.rev_reg_id -+ ) || -+ // any unqualified identifiers -+ (restriction.cred_def_id && (0, indyIdentifiers_1.isUnqualifiedCredentialDefinitionId)(restriction.cred_def_id)) || -+ (restriction.schema_id && (0, indyIdentifiers_1.isUnqualifiedSchemaId)(restriction.schema_id)) || -+ (restriction.issuer_did && (0, indyIdentifiers_1.isUnqualifiedIndyDid)(restriction.issuer_did)) || -+ (restriction.issuer_id && (0, indyIdentifiers_1.isUnqualifiedIndyDid)(restriction.issuer_id)) || -+ (restriction.schema_issuer_did && (0, indyIdentifiers_1.isUnqualifiedIndyDid)(restriction.schema_issuer_did)) || -+ (restriction.schema_issuer_id && (0, indyIdentifiers_1.isUnqualifiedIndyDid)(restriction.schema_issuer_id)) || -+ (restriction.rev_reg_id && (0, indyIdentifiers_1.isUnqualifiedRevocationRegistryId)(restriction.rev_reg_id)) -+ ) -+ }) - } - //# sourceMappingURL=proofRequest.js.map -\ No newline at end of file diff --git a/.yarn/patches/@credo-ts-core-npm-0.5.17-c528a69dd8.patch b/.yarn/patches/@credo-ts-core-npm-0.5.17-c528a69dd8.patch deleted file mode 100644 index 6c413d5..0000000 --- a/.yarn/patches/@credo-ts-core-npm-0.5.17-c528a69dd8.patch +++ /dev/null @@ -1,24 +0,0 @@ -diff --git a/build/modules/dif-presentation-exchange/DifPresentationExchangeService.js b/build/modules/dif-presentation-exchange/DifPresentationExchangeService.js -index f1723e774dc337b8ceae11cf5765d222fd07ea24..556fcef6877b0248134182551e6b46ebe9a758e4 100644 ---- a/build/modules/dif-presentation-exchange/DifPresentationExchangeService.js -+++ b/build/modules/dif-presentation-exchange/DifPresentationExchangeService.js -@@ -177,7 +177,18 @@ let DifPresentationExchangeService = class DifPresentationExchangeService { - presentationSubmission.descriptor_map.push(...descriptorMap); - }); - return { -- verifiablePresentations: verifiablePresentationResultsWithFormat.flatMap((resultWithFormat) => resultWithFormat.verifiablePresentationResult.verifiablePresentations.map((vp) => (0, utils_2.getVerifiablePresentationFromEncoded)(agentContext, vp))), -+ verifiablePresentations: verifiablePresentationResultsWithFormat.flatMap((resultWithFormat) => { -+ if (resultWithFormat.verifiablePresentationResult.verifiablePresentations) { -+ return resultWithFormat.verifiablePresentationResult.verifiablePresentations.map((vp) => -+ (0, utils_2.getVerifiablePresentationFromEncoded)(agentContext, vp) -+ ) -+ } else { -+ return (0, utils_2.getVerifiablePresentationFromEncoded)( -+ agentContext, -+ resultWithFormat.verifiablePresentationResult.verifiablePresentation -+ ) -+ } -+ }), - presentationSubmission, - presentationSubmissionLocation: verifiablePresentationResultsWithFormat[0].verifiablePresentationResult.presentationSubmissionLocation, - }; diff --git a/.yarn/patches/@credo-ts-core-npm-0.6.3-28b59086b0.patch b/.yarn/patches/@credo-ts-core-npm-0.6.3-28b59086b0.patch new file mode 100644 index 0000000..88a098e --- /dev/null +++ b/.yarn/patches/@credo-ts-core-npm-0.6.3-28b59086b0.patch @@ -0,0 +1,69 @@ +diff --git a/build/modules/vc/models/credential/W3cCredential.d.mts b/build/modules/vc/models/credential/W3cCredential.d.mts +index 6ecceb006c81a8f7dba8500b18e217c3d6b8c192..6df40bc454dec759ac878f20cb4eec9e74b742d0 100644 +--- a/build/modules/vc/models/credential/W3cCredential.d.mts ++++ b/build/modules/vc/models/credential/W3cCredential.d.mts +@@ -10,7 +10,7 @@ interface W3cCredentialOptions { + id?: string; + type: Array; + issuer: string | W3cIssuerOptions; +- issuanceDate: string; ++ issuanceDate?: string; + expirationDate?: string; + credentialSubject: SingleOrArray; + credentialStatus?: W3cCredentialStatus; +@@ -22,7 +22,7 @@ declare class W3cCredential { + id?: string; + type: Array; + issuer: string | W3cIssuer; +- issuanceDate: string; ++ issuanceDate?: string; + expirationDate?: string; + credentialSubject: SingleOrArray; + credentialSchema?: SingleOrArray; +diff --git a/build/modules/vc/models/credential/W3cCredential.mjs b/build/modules/vc/models/credential/W3cCredential.mjs +index f3ad42c21d31e28b0f297416f17d7e560454082d..783cae8b47016777ac82d96f599319e8cfd63b3d 100644 +--- a/build/modules/vc/models/credential/W3cCredential.mjs ++++ b/build/modules/vc/models/credential/W3cCredential.mjs +@@ -66,7 +66,13 @@ __decorate([ + IsW3cIssuer(), + __decorateMetadata("design:type", Object) + ], W3cCredential.prototype, "issuer", void 0); +-__decorate([IsRFC3339(), __decorateMetadata("design:type", String)], W3cCredential.prototype, "issuanceDate", void 0); ++// KEYRING PATCH (VCDM 2.0): issuanceDate is v1.1-only; VCDM 2.0 credentials ++// use validFrom instead, so the property must be optional to accept them. ++__decorate([ ++ IsRFC3339(), ++ IsOptional(), ++ __decorateMetadata("design:type", String) ++], W3cCredential.prototype, "issuanceDate", void 0); + __decorate([ + IsRFC3339(), + IsOptional(), +diff --git a/build/modules/vc/validators.mjs b/build/modules/vc/validators.mjs +index 1dc281ee34c7ee80285bf99008d2fa2bd85ef0e2..4fe87ad71253a0af11cae2f52be8f8eb8a041b8c 100644 +--- a/build/modules/vc/validators.mjs ++++ b/build/modules/vc/validators.mjs +@@ -5,15 +5,21 @@ import { CREDENTIALS_CONTEXT_V1_URL, VERIFIABLE_CREDENTIAL_TYPE, VERIFIABLE_PRES + import { ValidateBy, buildMessage, isString, isURL } from "class-validator"; + + //#region src/modules/vc/validators.ts ++// KEYRING PATCH (VCDM 2.0 over DIDComm JSON-LD): also accept the VCDM 2.0 ++// context URL as the first @context entry, so v2-context credentials can be ++// parsed/validated by the v1 W3cCredential model used by the DIDComm jsonld ++// credential format. See https://www.w3.org/TR/vc-data-model-2.0/ ++const CREDENTIALS_CONTEXT_V2_URL_PATCH = "https://www.w3.org/ns/credentials/v2"; + function IsCredentialJsonLdContext(validationOptions) { + const allowString = validationOptions?.allowString ?? false; + const credentialContext = validationOptions?.credentialContext ?? CREDENTIALS_CONTEXT_V1_URL; ++ const acceptedContexts = credentialContext === CREDENTIALS_CONTEXT_V1_URL ? [CREDENTIALS_CONTEXT_V1_URL, CREDENTIALS_CONTEXT_V2_URL_PATCH] : [credentialContext]; + return ValidateBy({ + name: "IsCredentialJsonLdContext", + validator: { + validate: (value) => { +- if (!Array.isArray(value)) return allowString && isString(value) && value === credentialContext; +- if (value[0] !== credentialContext) return false; ++ if (!Array.isArray(value)) return allowString && isString(value) && acceptedContexts.includes(value); ++ if (!acceptedContexts.includes(value[0])) return false; + return value.every((v) => isString(v) && isURL(v) || isJsonObject(v)); + }, + defaultMessage: buildMessage((eachPrefix) => `${eachPrefix}$property must be an array of strings or objects, where the first item is the verifiable credential context URL.`, validationOptions) diff --git a/.yarn/patches/@credo-ts-indy-vdr-npm-0.5.17-aa0b05041f.patch b/.yarn/patches/@credo-ts-indy-vdr-npm-0.5.17-aa0b05041f.patch deleted file mode 100644 index ee9f0dc..0000000 --- a/.yarn/patches/@credo-ts-indy-vdr-npm-0.5.17-aa0b05041f.patch +++ /dev/null @@ -1,13 +0,0 @@ -diff --git a/build/pool/IndyVdrPool.js b/build/pool/IndyVdrPool.js -index 7c157d6754dcba7526100f67dbed3c86b335b0cc..56437364edcb3d16e998fb4766d7b14cae63430f 100644 ---- a/build/pool/IndyVdrPool.js -+++ b/build/pool/IndyVdrPool.js -@@ -17,7 +17,7 @@ class IndyVdrPool { - } - connect() { - if (this._pool) { -- throw new error_1.IndyVdrError('Cannot connect to pool, already connected.'); -+ return; - } - this._pool = new indy_vdr_shared_1.PoolCreate({ - parameters: { diff --git a/.yarn/patches/@credo-ts-react-native-npm-0.6.3-secure-environment-biometrics.patch b/.yarn/patches/@credo-ts-react-native-npm-0.6.3-secure-environment-biometrics.patch new file mode 100644 index 0000000..534f5e5 --- /dev/null +++ b/.yarn/patches/@credo-ts-react-native-npm-0.6.3-secure-environment-biometrics.patch @@ -0,0 +1,68 @@ +diff --git a/build/kms/SecureEnvironmentKeyManagementService.d.mts b/build/kms/SecureEnvironmentKeyManagementService.d.mts +index a24147575a9e37473c63d112d7bb64c79dceaa54..7ff91e5712fed3d4ae4da49d6d7fe54c338e8ba9 100644 +--- a/build/kms/SecureEnvironmentKeyManagementService.d.mts ++++ b/build/kms/SecureEnvironmentKeyManagementService.d.mts +@@ -1,22 +1,27 @@ + import { AgentContext, Kms } from "@credo-ts/core"; + + //#region src/kms/SecureEnvironmentKeyManagementService.d.ts ++interface SecureEnvironmentKeyManagementServiceOptions { ++ biometricsBacked?: boolean; ++} + declare class SecureEnvironmentKeyManagementService implements Kms.KeyManagementService { + readonly backend = "secureEnvironment"; + private readonly secureEnvironment; ++ private readonly options; ++ constructor(options?: SecureEnvironmentKeyManagementServiceOptions); + isOperationSupported(_agentContext: AgentContext, operation: Kms.KmsOperation): boolean; + randomBytes(_agentContext: AgentContext, _options: Kms.KmsRandomBytesOptions): Kms.KmsRandomBytesReturn; + getPublicKey(_agentContext: AgentContext, keyId: string): Promise; + importKey(): Promise>; + deleteKey(_agentContext: AgentContext, options: Kms.KmsDeleteKeyOptions): Promise; + encrypt(): Promise; + decrypt(): Promise; + createKey(_agentContext: AgentContext, options: Kms.KmsCreateKeyOptions): Promise; + sign(_agentContext: AgentContext, options: Kms.KmsSignOptions): Promise; + verify(): Promise; + private publicJwkFromPublicKeyBytes; + private getKeyAsserted; + } + //#endregion +-export { SecureEnvironmentKeyManagementService }; ++export { SecureEnvironmentKeyManagementService, type SecureEnvironmentKeyManagementServiceOptions }; + //# sourceMappingURL=SecureEnvironmentKeyManagementService.d.mts.map +diff --git a/build/kms/SecureEnvironmentKeyManagementService.mjs b/build/kms/SecureEnvironmentKeyManagementService.mjs +index 45aa862698d9d3e164c36d5b61b5977282981983..23d58743281711002c2425d39f0ab1d976d5d911 100644 +--- a/build/kms/SecureEnvironmentKeyManagementService.mjs ++++ b/build/kms/SecureEnvironmentKeyManagementService.mjs +@@ -3,10 +3,11 @@ import { Kms, utils } from "@credo-ts/core"; + + //#region src/kms/SecureEnvironmentKeyManagementService.ts + var SecureEnvironmentKeyManagementService = class { +- constructor() { ++ constructor(options = {}) { + this.backend = "secureEnvironment"; + this.secureEnvironment = importSecureEnvironment(); ++ this.options = { biometricsBacked: true, ...options }; + } + isOperationSupported(_agentContext, operation) { + if (operation.operation === "createKey") return operation.type.kty === "EC" && operation.type.crv === "P-256"; + if (operation.operation === "sign") return operation.algorithm === "ES256"; +@@ -49,7 +50,7 @@ var SecureEnvironmentKeyManagementService = class { + const keyId = options.keyId ?? utils.uuid(); + const secureEnvironment = await this.secureEnvironment; + try { +- await secureEnvironment.generateKeypair(keyId); ++ await secureEnvironment.generateKeypair(keyId, this.options.biometricsBacked); + return { + keyId, + publicJwk: await this.getKeyAsserted(keyId) +@@ -64,7 +65,7 @@ var SecureEnvironmentKeyManagementService = class { + if (options.algorithm !== "ES256") throw new Kms.KeyManagementAlgorithmNotSupportedError(`algorithm '${options.algorithm}'. Only 'ES256' supported.`, this.backend); + const secureEnvironment = await this.secureEnvironment; + try { +- return { signature: await secureEnvironment.sign(options.keyId, options.data) }; ++ return { signature: await secureEnvironment.sign(options.keyId, new Uint8Array(options.data), this.options.biometricsBacked) }; + } catch (error) { + if (error instanceof secureEnvironment.KeyNotFoundError) throw new Kms.KeyManagementKeyNotFoundError(options.keyId, [this.backend]); + throw new Kms.KeyManagementError("Error signing with key", { cause: error }); diff --git a/.yarn/patches/@hyperledger-anoncreds-react-native-npm-0.2.4-644cafe308.patch b/.yarn/patches/@hyperledger-anoncreds-react-native-npm-0.2.4-644cafe308.patch deleted file mode 100644 index 63a99d9..0000000 --- a/.yarn/patches/@hyperledger-anoncreds-react-native-npm-0.2.4-644cafe308.patch +++ /dev/null @@ -1,21 +0,0 @@ -diff --git a/android/CMakeLists.txt b/android/CMakeLists.txt -index 5cc55c5ee3d05cbe9a7b92b0d1b031e0166c7456..3639134c3858f2cad688b6eebf778db8105006d4 100644 ---- a/android/CMakeLists.txt -+++ b/android/CMakeLists.txt -@@ -87,7 +87,15 @@ if(${REACT_NATIVE_VERSION} LESS 71) - ) - endif() - --if(${REACT_NATIVE_VERSION} GREATER_EQUAL 71) -+if(${REACT_NATIVE_VERSION} GREATER_EQUAL 76) -+ # RN 0.76 merged libreactnativejni into a single libreactnative.so prefab target -+ target_link_libraries( -+ ${PACKAGE_NAME} -+ ReactAndroid::jsi -+ ReactAndroid::reactnative -+ fbjni::fbjni -+ ) -+elseif(${REACT_NATIVE_VERSION} GREATER_EQUAL 71) - target_link_libraries( - ${PACKAGE_NAME} - ReactAndroid::jsi diff --git a/.yarn/patches/@hyperledger-aries-askar-react-native-npm-0.2.3-3207b51eab.patch b/.yarn/patches/@hyperledger-aries-askar-react-native-npm-0.2.3-3207b51eab.patch deleted file mode 100644 index 6775de7..0000000 --- a/.yarn/patches/@hyperledger-aries-askar-react-native-npm-0.2.3-3207b51eab.patch +++ /dev/null @@ -1,21 +0,0 @@ -diff --git a/android/CMakeLists.txt b/android/CMakeLists.txt -index 74b6aff9c7cf062724475a58b9030f655a939e18..54b65bc306c926a866c10e74c88a6fff8d1c3eca 100644 ---- a/android/CMakeLists.txt -+++ b/android/CMakeLists.txt -@@ -87,7 +87,15 @@ if(${REACT_NATIVE_VERSION} LESS 71) - ) - endif() - --if(${REACT_NATIVE_VERSION} GREATER_EQUAL 71) -+if(${REACT_NATIVE_VERSION} GREATER_EQUAL 76) -+ # RN 0.76 merged libreactnativejni into a single libreactnative.so prefab target -+ target_link_libraries( -+ ${PACKAGE_NAME} -+ ReactAndroid::jsi -+ ReactAndroid::reactnative -+ fbjni::fbjni -+ ) -+elseif(${REACT_NATIVE_VERSION} GREATER_EQUAL 71) - target_link_libraries( - ${PACKAGE_NAME} - ReactAndroid::jsi diff --git a/.yarn/patches/@hyperledger-indy-vdr-react-native-npm-0.2.2-627d424b96.patch b/.yarn/patches/@hyperledger-indy-vdr-react-native-npm-0.2.2-627d424b96.patch deleted file mode 100644 index cfefbf5..0000000 --- a/.yarn/patches/@hyperledger-indy-vdr-react-native-npm-0.2.2-627d424b96.patch +++ /dev/null @@ -1,194 +0,0 @@ -diff --git a/android/CMakeLists.txt b/android/CMakeLists.txt -index c84556e989cd95a18c5a8296931c8d97671a3c5c..47ef06ff796d4ce0ca0ffd1338dc5dc7965834a9 100644 ---- a/android/CMakeLists.txt -+++ b/android/CMakeLists.txt -@@ -87,7 +87,15 @@ if(${REACT_NATIVE_VERSION} LESS 71) - ) - endif() - --if(${REACT_NATIVE_VERSION} GREATER_EQUAL 71) -+if(${REACT_NATIVE_VERSION} GREATER_EQUAL 76) -+ # RN 0.76 merged libreactnativejni into a single libreactnative.so prefab target -+ target_link_libraries( -+ ${PACKAGE_NAME} -+ ReactAndroid::jsi -+ ReactAndroid::reactnative -+ fbjni::fbjni -+ ) -+elseif(${REACT_NATIVE_VERSION} GREATER_EQUAL 71) - target_link_libraries( - ${PACKAGE_NAME} - ReactAndroid::jsi -diff --git a/android/build.gradle b/android/build.gradle -index 9017d77eb32573415c7922cd83dae5cd792a885f..083320b13d82925625e57b929387a20a6d42c841 100644 ---- a/android/build.gradle -+++ b/android/build.gradle -@@ -59,6 +59,10 @@ def getExt(name) { - return rootProject.ext.get(name) - } - -+def getExtWithFallback(prop, fallback) { -+ return rootProject.ext.has(prop) ? rootProject.ext.get(prop) : fallback -+} -+ - def resolveBuildType() { - def buildType = "debug" - tasks.all({ task -> -@@ -81,7 +85,7 @@ android { - } - - defaultConfig { -- minSdkVersion 21 -+ minSdkVersion getExtWithFallback('minSdkVersion', '21') - targetSdkVersion getExt('targetSdkVersion') - - externalNativeBuild { -diff --git a/build/NativeBindings.d.ts b/build/NativeBindings.d.ts -index e3106250eb275f591ab53e42dc37cdf888d3406b..f3f2dcd9256d2addeeb4ce83afb3733c9d911f39 100644 ---- a/build/NativeBindings.d.ts -+++ b/build/NativeBindings.d.ts -@@ -11,6 +11,11 @@ export interface NativeBindings { - setCacheDirectory(options: { - path: string; - }): ReturnObject; -+ setLedgerTxnCache(options: { -+ capacity: number; -+ expiry_offset_ms: number; -+ path?: string; -+ }): ReturnObject; - setDefaultLogger(options: Record): ReturnObject; - setProtocolVersion(options: { - version: number; -diff --git a/build/ReactNativeIndyVdr.d.ts b/build/ReactNativeIndyVdr.d.ts -index 034c2d4527ef08eac1941ad784e497a948229ef1..b48eb78bc63c65641bbcf52dce713d4ad7a84a4f 100644 ---- a/build/ReactNativeIndyVdr.d.ts -+++ b/build/ReactNativeIndyVdr.d.ts -@@ -14,6 +14,11 @@ export declare class ReactNativeIndyVdr implements IndyVdr { - setCacheDirectory(options: { - path: string; - }): void; -+ setLedgerTxnCache(options: { -+ capacity: number; -+ expiry_offset_ms: number; -+ path?: string; -+ }): void; - setDefaultLogger(): void; - setProtocolVersion(options: { - version: number; -diff --git a/build/ReactNativeIndyVdr.js b/build/ReactNativeIndyVdr.js -index 16bdc5e8ee395295afa0ec255fee1e2c7a220c57..5fb112fa5df10aeffdd9d42a324702a6b25c3db1 100644 ---- a/build/ReactNativeIndyVdr.js -+++ b/build/ReactNativeIndyVdr.js -@@ -57,6 +57,10 @@ class ReactNativeIndyVdr { - const serializedOptions = (0, serialize_1.serializeArguments)(options); - this.indyVdr.setCacheDirectory(serializedOptions); - } -+ setLedgerTxnCache(options) { -+ const serializedOptions = (0, serialize_1.serializeArguments)(options); -+ this.indyVdr.setLedgerTxnCache(serializedOptions); -+ } - setDefaultLogger() { - this.handleError(this.indyVdr.setDefaultLogger({})); - } -diff --git a/build/ReactNativeIndyVdr.js.map b/build/ReactNativeIndyVdr.js.map -index 219c2d0156e6e3395061e41567831414c320e410..30fb92ec803052f901cf2858be8bda1569196a2c 100644 ---- a/build/ReactNativeIndyVdr.js.map -+++ b/build/ReactNativeIndyVdr.js.map -@@ -1 +1 @@ --{"version":3,"file":"ReactNativeIndyVdr.js","sourceRoot":"","sources":["../src/ReactNativeIndyVdr.ts"],"names":[],"mappings":"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"} -\ No newline at end of file -+{"version":3,"file":"ReactNativeIndyVdr.js","sourceRoot":"","sources":["../src/ReactNativeIndyVdr.ts"],"names":[],"mappings":"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"} -\ No newline at end of file -diff --git a/cpp/HostObject.cpp b/cpp/HostObject.cpp -index dca847963687111473125064c58c90b13f7c718b..c5c5e0a8227314809c31e6565bbecc7cce1c5478 100644 ---- a/cpp/HostObject.cpp -+++ b/cpp/HostObject.cpp -@@ -13,6 +13,7 @@ FunctionMap IndyVdrTurboModuleHostObject::functionMapping(jsi::Runtime &rt) { - fMap.insert(std::make_tuple("getCurrentError", &indyVdr::getCurrentError)); - fMap.insert(std::make_tuple("setConfig", &indyVdr::setConfig)); - fMap.insert(std::make_tuple("setCacheDirectory", &indyVdr::setCacheDirectory)); -+ fMap.insert(std::make_tuple("setLedgerTxnCache", &indyVdr::setLedgerTxnCache)); - fMap.insert(std::make_tuple("setDefaultLogger", &indyVdr::setDefaultLogger)); - fMap.insert( - std::make_tuple("setProtocolVersion", &indyVdr::setProtocolVersion)); -diff --git a/cpp/include/libindy_vdr.h b/cpp/include/libindy_vdr.h -index 7f61bb9faaa119ea74619c82937c8de838992c0a..6ce64ab2a429b940d117b664033f0e3369171eab 100644 ---- a/cpp/include/libindy_vdr.h -+++ b/cpp/include/libindy_vdr.h -@@ -481,6 +481,8 @@ ErrorCode indy_vdr_resolve(PoolHandle pool_handle, - - ErrorCode indy_vdr_set_cache_directory(FfiStr path); - -+ErrorCode indy_vdr_set_ledger_txn_cache(int32_t capacity, int64_t expiry_offset_ms, FfiStr path); -+ - ErrorCode indy_vdr_set_config(FfiStr config); - - ErrorCode indy_vdr_set_default_logger(void); -diff --git a/cpp/indyVdr.cpp b/cpp/indyVdr.cpp -index 0e3002cc6b504743ac70e777e52c387e26067bda..706134f8ccad62a790ee2f85a0f7b306cdfa5c85 100644 ---- a/cpp/indyVdr.cpp -+++ b/cpp/indyVdr.cpp -@@ -32,6 +32,16 @@ jsi::Value setCacheDirectory(jsi::Runtime &rt, jsi::Object options) { - return createReturnValue(rt, code, nullptr); - }; - -+jsi::Value setLedgerTxnCache(jsi::Runtime &rt, jsi::Object options) { -+ auto capacity = jsiToValue(rt, options, "capacity"); -+ auto expiry_offset_ms = jsiToValue(rt, options, "expiry_offset_ms"); -+ auto path = jsiToValue(rt, options, "path", true); -+ -+ ErrorCode code = indy_vdr_set_ledger_txn_cache(capacity, expiry_offset_ms, path.length() > 0 ? path.c_str() : nullptr); -+ -+ return createReturnValue(rt, code, nullptr); -+}; -+ - jsi::Value setDefaultLogger(jsi::Runtime &rt, jsi::Object options) { - ErrorCode code = indy_vdr_set_default_logger(); - -diff --git a/cpp/indyVdr.h b/cpp/indyVdr.h -index fa48a9253770faf2007913890f8458ffb26864f4..c708f3d483ff71dc90fe54af1a2b2eb087c58b26 100644 ---- a/cpp/indyVdr.h -+++ b/cpp/indyVdr.h -@@ -13,6 +13,7 @@ jsi::Value version(jsi::Runtime &rt, jsi::Object options); - jsi::Value getCurrentError(jsi::Runtime &rt, jsi::Object options); - jsi::Value setConfig(jsi::Runtime &rt, jsi::Object options); - jsi::Value setCacheDirectory(jsi::Runtime &rt, jsi::Object options); -+jsi::Value setLedgerTxnCache(jsi::Runtime &rt, jsi::Object options); - jsi::Value setDefaultLogger(jsi::Runtime &rt, jsi::Object options); - jsi::Value setProtocolVersion(jsi::Runtime &rt, jsi::Object options); - jsi::Value setSocksProxy(jsi::Runtime &rt, jsi::Object options); -diff --git a/cpp/turboModuleUtility.cpp b/cpp/turboModuleUtility.cpp -index 3ff7d9a455748748d84abf076dc29166bd94a717..5a029ea34225d5bb9f5610270677d5ffda80203a 100644 ---- a/cpp/turboModuleUtility.cpp -+++ b/cpp/turboModuleUtility.cpp -@@ -143,7 +143,7 @@ int64_t jsiToValue(jsi::Runtime &rt, jsi::Object &options, const char *name, - bool optional) { - jsi::Value value = options.getProperty(rt, name); - if ((value.isNull() || value.isUndefined()) && optional) -- return 0; -+ return -1; - - if (value.isNumber()) - return value.asNumber(); -@@ -169,7 +169,7 @@ int32_t jsiToValue(jsi::Runtime &rt, jsi::Object &options, const char *name, - bool optional) { - jsi::Value value = options.getProperty(rt, name); - if ((value.isNull() || value.isUndefined()) && optional) -- return 0; -+ return -1; - - if (value.isNumber()) - return value.asNumber(); -diff --git a/package.json b/package.json -index 084a7146e124e07cd3860819b9211be7d2369806..b911f8c6c360caea06946a3076e5148d5018c6ed 100644 ---- a/package.json -+++ b/package.json -@@ -58,7 +58,7 @@ - "binary": { - "module_name": "indy_vdr", - "module_path": "native", -- "remote_path": "v0.4.1", -+ "remote_path": "v0.4.3", - "host": "https://github.com/hyperledger/indy-vdr/releases/download/", - "package_name": "library-ios-android.tar.gz" - }, diff --git a/.yarn/patches/@hyperledger-indy-vdr-react-native-npm-0.2.4-d7ed0b15da.patch b/.yarn/patches/@hyperledger-indy-vdr-react-native-npm-0.2.4-d7ed0b15da.patch new file mode 100644 index 0000000..d7260d5 --- /dev/null +++ b/.yarn/patches/@hyperledger-indy-vdr-react-native-npm-0.2.4-d7ed0b15da.patch @@ -0,0 +1,22 @@ +diff --git a/cpp/turboModuleUtility.cpp b/cpp/turboModuleUtility.cpp +index 3ff7d9a455748748d84abf076dc29166bd94a717..5a029ea34225d5bb9f5610270677d5ffda80203a 100644 +--- a/cpp/turboModuleUtility.cpp ++++ b/cpp/turboModuleUtility.cpp +@@ -143,7 +143,7 @@ int64_t jsiToValue(jsi::Runtime &rt, jsi::Object &options, const char *name, + bool optional) { + jsi::Value value = options.getProperty(rt, name); + if ((value.isNull() || value.isUndefined()) && optional) +- return 0; ++ return -1; + + if (value.isNumber()) + return value.asNumber(); +@@ -169,7 +169,7 @@ int32_t jsiToValue(jsi::Runtime &rt, jsi::Object &options, const char *name, + bool optional) { + jsi::Value value = options.getProperty(rt, name); + if ((value.isNull() || value.isUndefined()) && optional) +- return 0; ++ return -1; + + if (value.isNumber()) + return value.asNumber(); diff --git a/.yarn/patches/@hyperledger-indy-vdr-shared-npm-0.2.2-b989282fc6.patch b/.yarn/patches/@hyperledger-indy-vdr-shared-npm-0.2.2-b989282fc6.patch deleted file mode 100644 index 99e2283..0000000 --- a/.yarn/patches/@hyperledger-indy-vdr-shared-npm-0.2.2-b989282fc6.patch +++ /dev/null @@ -1,16 +0,0 @@ -diff --git a/build/types/IndyVdr.d.ts b/build/types/IndyVdr.d.ts -index 99f5d50a851462c8c41e52ceb49795feebce0b4e..3aa7890e1f3c422daa6ec82fd6b42d0b924d18b5 100644 ---- a/build/types/IndyVdr.d.ts -+++ b/build/types/IndyVdr.d.ts -@@ -11,6 +11,11 @@ export interface IndyVdr { - setCacheDirectory(options: { - path: string; - }): void; -+ setLedgerTxnCache(options: { -+ capacity: number; -+ expiry_offset_ms: number; -+ path?: string; -+ }): void; - setDefaultLogger(): void; - setProtocolVersion(options: { - version: number; diff --git a/.yarn/patches/react-native-document-picker-npm-9.3.1-ce22d39a18.patch b/.yarn/patches/react-native-document-picker-npm-9.3.1-ce22d39a18.patch new file mode 100644 index 0000000..4fc4e70 --- /dev/null +++ b/.yarn/patches/react-native-document-picker-npm-9.3.1-ce22d39a18.patch @@ -0,0 +1,44 @@ +diff --git a/android/src/main/java/com/reactnativedocumentpicker/RNDocumentPickerModule.java b/android/src/main/java/com/reactnativedocumentpicker/RNDocumentPickerModule.java +index 5001525e27475858fe60cbdf77c5c62ff52a92ae..fe1412a869b85446b48f7a40d8c1fc7bee99d2a0 100644 +--- a/android/src/main/java/com/reactnativedocumentpicker/RNDocumentPickerModule.java ++++ b/android/src/main/java/com/reactnativedocumentpicker/RNDocumentPickerModule.java +@@ -18,7 +18,7 @@ import androidx.annotation.NonNull; + import com.facebook.react.bridge.ActivityEventListener; + import com.facebook.react.bridge.Arguments; + import com.facebook.react.bridge.BaseActivityEventListener; +-import com.facebook.react.bridge.GuardedResultAsyncTask; ++import com.facebook.react.bridge.GuardedAsyncTask; + import com.facebook.react.bridge.Promise; + import com.facebook.react.bridge.ReactApplicationContext; + import com.facebook.react.bridge.ReactContext; +@@ -229,7 +229,9 @@ public class RNDocumentPickerModule extends NativeDocumentPickerSpec { + } + } + +- private static class ProcessDataTask extends GuardedResultAsyncTask { ++ // GuardedResultAsyncTask was removed in React Native 0.81; use GuardedAsyncTask ++ // and resolve the promise from the background thread (Promise is thread-safe). ++ private static class ProcessDataTask extends GuardedAsyncTask { + private final WeakReference weakContext; + private final List uris; + private final String copyTo; +@@ -244,17 +246,12 @@ public class RNDocumentPickerModule extends NativeDocumentPickerSpec { + } + + @Override +- protected ReadableArray doInBackgroundGuarded() { ++ protected void doInBackgroundGuarded(Void... params) { + WritableArray results = Arguments.createArray(); + for (Uri uri : uris) { + results.pushMap(getMetadata(uri)); + } +- return results; +- } +- +- @Override +- protected void onPostExecuteGuarded(ReadableArray readableArray) { +- promise.resolve(readableArray); ++ promise.resolve(results); + } + + private WritableMap getMetadata(Uri uri) { diff --git a/.yarn/patches/react-native-npm-0.81.5-d8232ef145.patch b/.yarn/patches/react-native-npm-0.81.5-d8232ef145.patch new file mode 100644 index 0000000..5b6e7e6 --- /dev/null +++ b/.yarn/patches/react-native-npm-0.81.5-d8232ef145.patch @@ -0,0 +1,57 @@ +diff --git a/ReactCommon/react/renderer/components/textinput/BaseTextInputShadowNode.h b/ReactCommon/react/renderer/components/textinput/BaseTextInputShadowNode.h +index 8c8a225eaa98ac3efe5f3194d53560c68c21a052..c553c1ab47244b4f13c5603546549f1e13d46160 100644 +--- a/ReactCommon/react/renderer/components/textinput/BaseTextInputShadowNode.h ++++ b/ReactCommon/react/renderer/components/textinput/BaseTextInputShadowNode.h +@@ -25,6 +25,22 @@ + + namespace facebook::react { + ++// KEYRING PATCH (react-native#55719, merged upstream as 5229e507e1a1): ++// building the fragment with a full ShadowView retains the node's `state`, ++// chaining every TextInputState revision to the previous one. The chain is ++// destroyed recursively on the Hermes GC thread ("hades"), whose small stack ++// overflows after enough keystrokes -> SIGBUS/EXC_BAD_ACCESS crash observed ++// on real iPhones during the VRC E2E flow. ++inline ShadowView textInputShadowViewFromShadowNode( ++ const ShadowNode& shadowNode) { ++ auto shadowView = ShadowView{shadowNode}; ++ // Clearing `props` and `state` (which we don't use) allows avoiding retain ++ // cycles. ++ shadowView.props = nullptr; ++ shadowView.state = nullptr; ++ return shadowView; ++} ++ + /* + * Base `ShadowNode` for component. + */ +@@ -186,7 +202,7 @@ class BaseTextInputShadowNode : public ConcreteViewShadowNode< + attributedString.appendFragment(AttributedString::Fragment{ + .string = props.text, + .textAttributes = textAttributes, +- .parentShadowView = ShadowView(*this)}); ++ .parentShadowView = textInputShadowViewFromShadowNode(*this)}); + + auto attachments = BaseTextShadowNode::Attachments{}; + BaseTextShadowNode::buildAttributedString( +diff --git a/ReactCommon/react/renderer/components/textinput/platform/android/react/renderer/components/androidtextinput/AndroidTextInputShadowNode.cpp b/ReactCommon/react/renderer/components/textinput/platform/android/react/renderer/components/androidtextinput/AndroidTextInputShadowNode.cpp +index e9a546e0154f84a73278ae6c3c3bb2e26d640efa..0e9309fd84a6bc1c3d5d41aedc8482b1f2f45ecb 100644 +--- a/ReactCommon/react/renderer/components/textinput/platform/android/react/renderer/components/androidtextinput/AndroidTextInputShadowNode.cpp ++++ b/ReactCommon/react/renderer/components/textinput/platform/android/react/renderer/components/androidtextinput/AndroidTextInputShadowNode.cpp +@@ -187,7 +187,15 @@ AttributedString AndroidTextInputShadowNode::getAttributedString( + // text value's background will stack. This is a hack/workaround to prevent + // that effect. + fragment.textAttributes.backgroundColor = clearColor(); +- fragment.parentShadowView = ShadowView(*this); ++ // KEYRING PATCH (react-native#55719): same TextInputState retain-chain ++ // leak as BaseTextInputShadowNode — clear props/state on the ShadowView ++ // to avoid chaining every state revision to the previous one. ++ { ++ auto parentShadowView = ShadowView(*this); ++ parentShadowView.props = nullptr; ++ parentShadowView.state = nullptr; ++ fragment.parentShadowView = std::move(parentShadowView); ++ } + attributedString.prependFragment(std::move(fragment)); + } + diff --git a/README.md b/README.md index 2c58371..b2b7d51 100644 --- a/README.md +++ b/README.md @@ -177,6 +177,20 @@ yarn start Default ports: DIDComm on `9002`, web UI on `9003`. +### End-to-end tests + +Appium-driven two-device tests (fresh install → onboarding → VRC exchange) +live in [`e2e/`](e2e/README.md). From the repo root: + +```sh +yarn e2e:vrc # Android emulator + iOS simulator, unattended +yarn e2e:vrc:devices # physical phones — proves hardware attestation (attended) +yarn e2e:migration # Askar store-migration upgrade test +yarn e2e:smoke # single-device onboarding smoke test +``` + +Setup, app-build commands, and the real-device operator guide: [`e2e/README.md`](e2e/README.md). + ## Developing in keyring-bifold The `keyring-bifold/` directory is a Git submodule pointing to our Bifold fork. To work on core changes: diff --git a/UPGRADE_PROGRESS.md b/UPGRADE_PROGRESS.md index 887904e..373b751 100644 --- a/UPGRADE_PROGRESS.md +++ b/UPGRADE_PROGRESS.md @@ -4,7 +4,7 @@ > effort with zero conversation context. Update it at every phase gate and whenever a > significant decision or discovery is made. Keep it factual and current. -Last updated: 2026-07-04 (Phase 2 COMPLETE — RN 0.77.3, BCSC dropped, E2E green both platforms) +Last updated: 2026-07-13 (real-device attestation E2E green; HARDWARE_ATTESTATION_FLOW rewritten for native verify; DataIntegrityProof cryptosuite explicitly deferred — see docs/CRYPTO_SUITE_FOLLOWUP.md) --- @@ -45,7 +45,7 @@ openwallet-foundation/credo-ts#2704 still open as of 2026-06). | askar | `@hyperledger/aries-askar-react-native` 0.2.3 | renamed `@openwallet-foundation/askar-*` 0.6.0 | | anoncreds RN | 0.2.4 | check upstream bifold 3.0.16 resolutions | | indy-vdr RN | 0.2.2 (patched) | 0.2.4 (upstream carries its own patch) | -| VRC signature suite | Ed25519Signature2018 (VCDM 1.1) | Phase 5: DataIntegrityProof / eddsa-rdfc-2022 (VCDM 2.0) — verify credo JSON-LD VCDM 2.0 support first | +| VRC signature suite | **Ed25519Signature2018** on VCDM 2.0 payloads (intentional) | **Deferred:** DataIntegrityProof / `eddsa-rdfc-2022` — see `docs/CRYPTO_SUITE_FOLLOWUP.md` | Upstream bifold 3.0.16 root resolutions worth copying: react 19.1.0, react-native 0.81.5, react-native-vision-camera 4.7.3, expo ~54 (they added expo modules!), plus their patch set @@ -266,23 +266,270 @@ babel/metro/jest configs, `.env.sample`. PersonCredentialLoading (app keyring-theme). Snapshots updated. - PHASE 2 GATE PASSED: app jest 14/27 PASS, bifold core jest 134 suites / 1242 PASS, Android + iOS build PASS, two-device E2E VRC exchange PASS on Android and iOS. -- [ ] **Phase 3 — Big hop: bifold 3.0.16 + credo 0.6.3 + React 19 + RN 0.81** - - In `bifold/`: new branch `upgrade/bifold-3.x` = upstream v3.0.16 content; port §5.1 delta - onto it. Mechanical credo API rewrite everywhere: `agent.credentials` → - `agent.modules.credentials`, explicit DIDComm module registration, askar rename. - - Attestation package: start from upstream 3.0.16 version, re-apply Keyring crypto/signing. - - App: RN 0.81 + React 19 (reference: bc-wallet-mobile main), drop Storybook. - - New Architecture: try `newArchEnabled=true` (upstream default); custom native modules - (attestation) must be audited; fall back to false if needed, but record it. - - Adopt upstream patch set; wallet-open/migration smoke test (askar store compat). - - Gate: VRC conformance tests green, jest green, both bundle, E2E green. -- [ ] **Phase 4 — App-layer upstream sync** (port wanted bc-wallet-mobile improvements; - containers/DI, screens). Gate: full suite + E2E. -- [ ] **Phase 5 — VC 2.0 for VRC** (secondary goal) - - FIRST verify credo 0.6.3 supports issuing/verifying JSON-LD Data Integrity VCDM 2.0 - (its VCDM 2.0 support is documented for vc+jwt / dc+sd-jwt; LDP 2.0 unverified). - - contexts v2 in `vrc-contexts`, documentLoader in `vrc-shared`, witness-server verification, - conformance tests, RCE protocol version bump. No data migration (user decision). +- [x] **Phase 3 — Big hop: bifold 3.0.16 + credo 0.6.3 + React 19 + RN 0.81** + - [x] In `bifold/`: branch `upgrade/bifold-3.x` = upstream v3.0.16 content; §5.1 delta ported + (commit `68d9da80`). Credo 0.6.3 migration done (commit `cdb9289c`): DIDComm APIs under + `agent.modules.didcomm`, `DidCommModule` carries connections/credentials/proofs/oob/ + mediation config, renamed types/events (`DidCommConnectionRecord` etc.), + `kms.importKey` + `dids.create createKey` (JWK types) replace `wallet.createKey`, + askar renamed to `@openwallet-foundation/askar-*`, `W3cCredentialRecord.encoded` + replaces private `.credential`. witness-server + vrc-reference fully migrated + (sources AND unit tests — mock agents alias didcomm APIs under `modules.didcomm`; + jest needs babel-jest ESM transform for credo 0.6 `.mjs` builds, see the two + jest.config.js files). `receiveInvitationFromUrl` now REQUIRES a `label` in its + 2nd config arg (credo 0.6 moved agent label out of InitConfig). + - [x] bifold gate: `yarn build` 0 TS errors, lint + prettier clean, + `yarn coverage` 155 suites / 1398 tests PASS (core 1400 incl. 2 skipped, + vrc-reference 105, witness-server, vrc-shared). One flaky suite noted: + CredentialDetails.test.tsx can fail under full-run load (act() timing), passes + isolated and on rerun. + - [x] Pushed + PR opened: berkmancenter/keyring-bifold#26 (upgrade/bifold-3.x → main). + NOTE: branch-swap made history disjoint from fork main; fixed with a signed + tie-merge commit (`git commit-tree -S` with two parents, tree = Phase 3 tree). + DO NOT merge without Alberto's approval. + - [x] Attestation package: rebuilt from upstream 3.0.16 base, Keyring crypto re-applied. + - [x] App JS layer: RN 0.81.5 + React 19.1.0 wired, bifold 3.0.16 portals (incl. new + `@bifold/react-hooks` — `@credo-ts/react-hooks` is gone), credo 0.6.3 deps, + askar → `@openwallet-foundation/askar-react-native` 0.6.0, Storybook dropped + (dir + AppStorybook.tsx removed), branch `upgrade/phase3-bifold3`. Highlights: + - `bc-agent-modules.ts` rewritten for credo 0.6 (`DidCommModule` config, + `Kms.KeyManagementModule` with askar + expo secure-environment services, + explicit JSON-LD/AnonCreds DIDComm format services, VRC document loader). + - `useBCAgentSetup.ts`: wallet id/key now live in `AskarModule` store config — + no more `agent.wallet.open()`; transports register via + `agent.modules.didcomm.registerOutboundTransport`; indy-vdr pool warm-up + guards the BC-patch-only methods (`refreshPoolConnections`). + - DRPC-based BC attestation flow REMOVED (`@credo-ts/drpc` has no stable 0.6.x; + Keyring doesn't run BC's attestation service). `AttestationMonitor` keeps the + bifold interface; `requestAttestationCredential` now emits FailedRequestCredential. + `app/src/utils/drpc.ts` deleted. + - proofs/credentials API options renamed: `proofRecordId`→`proofExchangeRecordId`, + `credentialRecordId`→`credentialExchangeRecordId`. + - jest: transformIgnorePatterns synced with bifold core (credo .mjs, @noble, + @stablelib, expo...); `@bifold/*` mapped to bifold SOURCES (lib/commonjs build + has a circular-require bug under jest); reanimated mocked via official mock; + RN 0.81 Keyboard/BackHandler mocks ported from bifold jestSetup. + - babel: module-resolver `root: ['.']` REMOVED (it rewrote `from '.'` imports + inside node_modules to app root index.js under jest); added + `@babel/plugin-transform-export-namespace-from` + reanimated plugin. + - Fixed upstream bug in bifold `store.ts` (absolute `components/views/Banner` + import breaks consumers compiling core from source). + - [x] App gate (JS): typecheck 0 errors, eslint clean, jest 14 suites / 27 tests PASS + (6 snapshots updated for RN 0.81 Pressable/style flattening). + - [x] Android native build GREEN with **New Architecture enabled** (`newArchEnabled=true`), + `assembleDebug` passes. Changes: compileSdk/targetSdk 36, buildTools 36.0.0, + kotlin 2.1.20, gradle 8.14.3, AGP version now supplied by RN gradle plugin; + expo autolinking added to settings.gradle (`useExpoModules()`) and + MainApplication wrapped in `ReactNativeHostWrapper` + `loadReactNative(this)`; + `react.internal.disableJavaVersionAlignment=true` + subprojects Java-17 + compileOptions block (both from bifold samples/app — RN plugin vs expo + toolchain conflict); kotlin-stdlib force-resolutions and app java toolchain + block REMOVED (broke under AGP 8.12); gradle lockfiles regenerated + (`--write-locks`). Attestation module: Android now implements the 5 iOS-only + spec methods as UNSUPPORTED-reject stubs (New-Arch codegen makes them + abstract on both platforms) — bifold commit. + - [x] iOS native build GREEN (`xcodebuild` Debug, simulator). Podfile gained expo + autolinking (`use_expo_modules!` + `expo_patch_react_imports!`), pods + reinstalled (RN 0.81.5, hermes, 140 pods). AppDelegate.mm (RCTAppDelegate) + still compiles on 0.81 — migration to RCTReactNativeFactory deferred. + - [x] Release JS bundles green for BOTH platforms. metro.config fixes: + exclusionList import moved to `metro-config/private/...` (metro 0.83 exports), + `unstable_enablePackageExports` + conditions `['react-native','browser','require']` + (nanoid etc. need browser builds), bifold/node_modules added to + watchFolders/nodeModulesPaths, react-native-svg-transformer 0.14→1.5.1. + New app deps surfaced by bifold 3.x code paths: zustand ~4.5.4 (core has it + only as devDep), @expo/app-integrity ^55.0.9. + PATCH: react-native-document-picker 9.3.1 uses GuardedResultAsyncTask + (removed in RN 0.81) — yarn patch swaps it to GuardedAsyncTask. + - [x] Runtime smoke test GREEN on both platforms: Android emulator (Pixel 6 API 33) + boots to onboarding, iOS simulator (iPhone 17) boots to PIN unlock (existing + wallet opened — askar 0.6 store loads). Runtime fixes: + - metro resolveRequest singleton guard: imports of react/react-native/react-dom/ + @credo-ts/{core,didcomm,anoncreds} from OUTSIDE app/ re-resolve from the app + root, otherwise bifold/node_modules' second react copy loads in dev bundles + and hooks crash ("dispatcher.useContext of null" in bifold Button). + - '@bifold/react-hooks' added to BIFOLD_SOURCE_PACKAGES (verifier src imports it). + - react-native-date-picker REMOVED (unused; 5.0.13 breaks RN 0.81 iOS: + "RNDatePickerManager does not conform to RCTModuleProvider"). + - GOTCHA: killing the `yarn start` wrapper leaves the node metro child alive + holding :8081 — a stale metro served the old config for a while. pkill + 'cli.js start' or kill the listener pid from lsof. + - [x] Two-device E2E VRC exchange GREEN (2026-07-06): Android emulator ↔ iOS simulator, + full flow (onboarding → invitation → chat → bidirectional VRC issuance → contact + visible on both). Five fixes to get there: + - credo 0.6 event payload rename: `payload.credentialRecord` → + `payload.credentialExchangeRecord` in `app/src/services/attestation.ts` + (threw "Cannot read property 'id' of undefined" on every credential event; + proof events still use `payload.proofRecord`). + - Credo 0.6 event NAME rename (earlier fix, same class of bug): vrc-manager + + InAppMessageNotifier listen on `DidCommBasicMessageEventTypes.…` not the old + 0.5 string. + - Chat YES/NO + details links: RN's TouchableOpacity misses taps inside + GiftedChat's inverted list on Android with New Architecture — swapped to + `react-native-gesture-handler` touchables (gifted-chat already wraps in + GestureHandlerRootView). E2E also retries the YES tap. + - INFINITE RENDER LOOP ("Maximum update depth exceeded", both platforms, fired + after accepting an offer): `useCredentialByState`/`useProofByState` in + @bifold/react-hooks memoized `states` on ARRAY IDENTITY; app's + `useNotifications` passes fresh array literals each render → new array each + render → downstream effect loop (Connection screen via useNotifications). + React 19 surfaces this hard. Fixed by keying the memo on `state.join(',')`. + - Clock skew: holder rejected issued VC ("current date time is before + issuanceDate") because emulator/simulator clocks differ by a few seconds — + vrc-manager now backdates issuanceDate/validFrom by 5 min. + - LogBox: dev banners cover bottom-of-screen buttons (Done) and eat E2E taps — + `LogBox.ignoreAllLogs()` in dev (app/index.js). + - E2E harness gotchas: stale `IOS_APP`/`ANDROID_APK` env vars make Appium + install OLD builds (RN version-mismatch redbox); `enforceAppInstall: true` + added for iOS; unset the env vars before runs. + - [x] Askar 0.2→0.6 store migration check GREEN (2026-07-07): `e2e/run-store-migration.js` + installs the baseline apk (credo 0.5.17/askar 0.2.3, built from `upgrade-baseline-p0` + worktree as a RELEASE build with debug signing — a debug build would load the NEW + JS from metro and crash on the askar native mismatch), populates the old-format + store with a real VRC exchange against the new iOS build, then `adb install -r` + the new apk over it. Wallet opens with the same PIN, contact + VRC survive. + - MIGRATION BUG found+fixed: R-Card template records stored by credo-0.5 builds + have NO `proof`; credo 0.6 parses stored credentials as + W3cJsonLdVerifiableCredential (proof required), so `record.getTags()` threw and + OpenIDCredentialRecordProvider crashed with a render error on first launch after + upgrade. `migrateRCardTemplateProofs()` (vrc/services/rCardCredential.ts) adds the + same placeholder proof new templates get; runs in `useBCAgentSetup.ts` right after + `agent.initialize()`, before any provider reads W3C records. + - E2E harness: old release build's QR bottom-sheet ignores appium synthetic taps — + invitation delivered via deep link (`adb shell am start -a VIEW -d `), which + is also the real-user path. iOS `simctl privacy grant camera` kills the app; + terminate + sleep + activate avoids a black-screen race. Runtime permissions + granted via `adb shell pm grant` (manual installs skip autoGrantPermissions). + - [x] Gate: VRC conformance tests green (bifold side done), two-device E2E green. +- [x] **Phase 4 (lite) — App-layer upstream sync** (2026-07-07). Analysis first: most + upstream churn since the fork is BCSC product work (bcsc-theme/, variants build + system, dual-mode store) that Keyring does NOT adopt. Ported the generic pieces: + - [x] Error-handling framework (`app/src/errors/`): AppError + ErrorRegistry + (registry trimmed to Keyring-relevant codes, ranges kept aligned with upstream + so support references stay comparable) + errorHandler utils + ErrorInfoCard/ + AppErrorModal/ErrorBoundary components + `ErrorAlertProvider`/`useErrorAlert` + context. Upstream's Snowplow analytics coupling DROPPED — errors report to + Loki via the remote logger instead (`reportProblem()` in utils/logger.ts + returns a human-readable reference code, shown+copyable in the modal). + App.tsx now uses OUR ErrorBoundaryWrapper (was bifold's) and mounts + ErrorAlertProvider inside TourProvider. AppEventCode enum in + `app/src/events/appEventCode.ts` (trimmed from upstream's ~200 codes). + Ported jest suites: appError/errorRegistry/errorHandler (49 tests). + - [x] `PressableOpacity` (`app/src/components/`): Pressable-based TouchableOpacity + replacement (New-Arch touch reliability); used by ErrorInfoCard. + - [x] Small hooks: `usePreventGestureBack`, `useDeclineCredentialOffer`, + `useDeclineProofRequest` (adapted to `useAgent` from @bifold/react-hooks — + upstream uses their BCSC agent context), `useAutoRequestPermission`. + `useAlerts` NOT ported (hard-wired to BCSC stacks/screens/factory-reset). + - [x] Mediator pickup simplified to upstream's approach: unconditional + `PickUpV2LiveMode` (WebSocket push) in useBCAgentSetup; REMOVED the legacy + batch-pickup double-tap + 5s trust-ping polling loop (utils/mediator.ts + deleted, `MEDIATOR_USE_V2_BATCH_PICKUP` env flag retired). Verified against + our hosted mediator (credo-mediator.aaleon.com advertises wss) by the + two-device E2E — message delivery works on socket push alone. + - [x] Test-harness fix (bifold core jestSetup): RNGH's own jest mocks render + buttons without children, blanking gesture-handler touchable labels — + ChatMessage YES/NO tests failed. jestSetup now maps RNGH touchables to RN + equivalents (4 previously-failing tests green). + - [x] Gate GREEN (2026-07-07): app jest 16 suites/70 tests PASS; bifold core + 155 suites/1398 tests PASS; app+bifold typecheck PASS; two-device VRC + exchange E2E (Android emulator ↔ iOS simulator) PASS on live-mode-only + pickup — full flow inc. bidirectional VRC + contacts. +- [x] **Phase 5 — DTG spec alignment + VC 2.0 for VRC** — COMPLETE 2026-07-08. + Credo 0.6.3 verified (source-read): JSON-LD Data Integrity signing is **VCDM 1.1-only**. + The DIDComm jsonld format parses into `W3cCredential`, whose validators require + (a) first `@context` = the v1.1 URL and (b) a mandatory `issuanceDate`. The + `W3cV2CredentialService` (VCDM 2.0) only does vc+jwt / vc+sd-jwt (OpenID4VC stack, + not wired to DIDComm). DIDComm itself and Ed25519Signature2018 are version-agnostic. + - [x] **Task 1 — RCard/VRC separation**: VRC `issuer` is now a bare DID string for v2 + peers (PII out of the pseudonymous edge credential). RCard is an exchanged VDS + (`type: ["VerifiableCredential","RelationshipCard"]`, subject = counterparty DID, + `credentialSubject.card` = jCard) built from the local template + (`services/rCardCredential.ts buildRCardCredential`) and offered right after the + VRC (`issueRCardCredential` in vrc-manager, best-effort/non-blocking, deduped per + connection). Receiver AUTO-ACCEPTS RelationshipCard offers (tagged + `rcardExchange` metadata); RCard exchanges are filtered from chat bubbles, + notifications, wallet list, and VRC-flow overlay state. Contact display resolves + via `utils/rcardDisplayUtils.ts resolveContactDisplayInfo`: newest received RCard + first, fallback to legacy VRC issuer objects (sorted most-recent-first). New + RCard JSON-LD context in vrc-contexts (`https://www.firstperson.network/rcard/v1`) + with `@type: @json` for the jCard (JCS-canonicalized as a JSON literal, structure + survives RDF canonicalization). + - [x] **Task 2 — VWC digest via JCS (RFC 8785)**: pure-TS `jcsCanonicalize` in + `@bifold/vrc-contexts/src/jcs.ts` (recursive UTF-16 key sort, ECMAScript number + serialization, undefined handling); witness-server + vrc-reference Witness now + hash `jcsCanonicalize(vrcJson)` (was top-level-only key sort). Encoding stays + `sha256:`. Wallet doesn't verify digests today; the helper is exported for + when it does. + - [x] **Task 3 — VC 2.0 verification (credo patch)**: yarn patch + `.yarn/patches/@credo-ts-core-npm-0.6.3-28b59086b0.patch` applied in BOTH trees + via the `resolutions` entry itself (GOTCHA: a second broader `"@credo-ts/core": + "0.6.3"` resolution silently wins over a `@credo-ts/core@npm:0.6.3: patch:...` + entry — put the `patch:` ref directly on the main resolution). Patch: (a) + `IsCredentialJsonLdContext` also accepts `https://www.w3.org/ns/credentials/v2` + first; (b) `W3cCredential.issuanceDate` optional. VCDM 2.0 context document + bundled (`vrc-contexts/src/credentialsV2Context.ts`) + served by all three + document loaders. `cachedStandardContexts.ts` pins credo's DEFAULT_CONTEXTS + (security/ed25519 suites etc.) into the vrc-shared loader so Node-side + sign/verify never fetches from w3.org. Conformance: `vc20Validation.test.ts` + (model-level) + `vrc-reference vc20Conformance.test.ts` (full sign/verify + round-trip on a bare credo agent, v2 and v1.1). + - [x] **Task 4 — VC 2.0 issuance flip + RCE v2 negotiation**: handshake message now + carries `vrc:rceVersion:2` (old parsers ignore the suffix); peer's version stored + on `RelationshipDidRecord.counterpartyRceVersion` (absent = 1). For v2 peers: + VRC/RCard/VWC are VCDM 2.0 (v2 context first, `validFrom`/`validUntil`, no + issuanceDate). Witness-server mirrors the observed VRC's data model for the VWC + and its freshness check reads `validFrom || issuanceDate` (window widened to + 10 min = 5 min clock-skew backdate + 5 min margin); announcement now + `version: '2.0'`, capability `vc-2.0`. + **KEY LEARNING (cost a failed E2E)**: the v2 base context does NOT define the + Ed25519Signature2018 proof terms (v1.1 did), so jsonld-signatures APPENDS + `https://w3id.org/security/suites/ed25519-2018/v1` to `@context` during signing — + the signed credential then fails credo's holder-side deep-equality check against + the offer ("Received credential does not match credential request"). Fix: include + `ED25519_2018_SUITE_CONTEXT_URL` in `@context` at BUILD time in every v2 builder + (vrc-manager, rCardCredential, WitnessService, vrc-reference Participant/Witness). + - [x] **Backward compat with pre-Phase-5 peers (v1 path)** — found+fixed by the + backward-compat E2E: a v1 peer (no rceVersion announced) must get the FULL legacy + exchange, not just a 1.1-shaped VRC. Two fixes in vrc-manager: + (a) legacy VRCs embed the old issuer OBJECT `{id, name, email?, organization?}` + from the R-Card template (`buildLegacyIssuerObject`) — old apps read the contact + name from it; (b) RCard issuance is SKIPPED for v1 peers — they can't resolve the + RCard context (verification fails) and the unexpected offer surfaces as a second + actionable chat bubble that broke the old app's accept flow. + - [x] **Gates (all green 2026-07-08)**: + - bifold core jest 159 suites / 1434 passed (2 skipped); vrc-reference + + witness-server suites green; app jest/typecheck/lint green; core tsc + eslint clean + (witness-server has PRE-EXISTING `Timeout` tsc errors from baseline — not a regression). + - Two-device E2E VRC exchange (new↔new, Android emulator ↔ iOS simulator) PASS: + RCE v2 negotiated both ways, VC 2.0 VRCs verified, RCards auto-accepted, contact + names from RCards visible both sides. + - Backward-compat E2E PASS: Phase-4 baseline RELEASE apk (commit `dc944fd`, worktree + `/tmp/kw-p4-baseline` — build needs `yarn workspace @bifold/ build` for + app-consumed packages, skip witness-server which fails its build on baseline, plus + `./gradlew :bifold_react-native-attestation:generateCodegenArtifactsFromSchema` + before assembleRelease) ↔ NEW iOS build: old wallet receives a legacy 1.1 VRC with + issuer object, no RCard offered, contact visible on both; then `adb install -r` + the new apk over the old store → PIN unlock, agent init, contact + VRC survive. + - [x] **Task 6 — upstream credo contribution**: on hold. A write-up of the VCDM 2.0 + DIDComm JSON-LD gap and our yarn patch exists locally; any upstream issue/PR to + credo-ts happens only with explicit owner approval. If credo ever accepts the + change, our yarn patch dissolves at the next upgrade. + - [x] **Attestation hardening (2026-07-09)**: cherry-picked bifold PR #23 + (`fix: align Google attestation trust anchors with published roots`, now `88f80fe8` + on `upgrade/bifold-3.x`) so real-device Android hardware attestation validates + against Google's published roots instead of self-as-anchor. Verified on the new + stack: 7/7 attestation JUnit tests, 29/29 BiometricSignatureVerifier TS tests, + app `assembleDebug` green. PR #23 superseded/closed. + - **Deliberately deferred**: custom → official context URL switch (waiting on ToIP WG; + draft in `dtg-context-v1.draft.jsonld`, git-excluded); **DataIntegrityProof / + eddsa-rdfc-2022** (separate profound follow-up — parking lot: + `docs/CRYPTO_SUITE_FOLLOWUP.md`; keep issuing Ed25519Signature2018 until then); + BBS+/ZKP (separate future project); wallet-side VWC digest verification + (jcsCanonicalize exported and ready). + - [x] **Real-device hardware attestation E2E (2026-07-13)**: `yarn e2e:vrc:devices` + green — Secure Exchange both directions; native verify; Google multi-root + anchors. Docs: `docs/HARDWARE_ATTESTATION_FLOW.md` rewritten to match. ## 7. Baseline test results (Phase 0 gate — all green, recorded 2026-07-04) diff --git a/app/.env.sample b/app/.env.sample index 1b6dcaf..25f7ba0 100644 --- a/app/.env.sample +++ b/app/.env.sample @@ -1,8 +1,6 @@ # OCA_URL sourced from upstream bcgov/aries-oca-bundles repository OCA_URL=https://raw.githubusercontent.com/bcgov/aries-oca-bundles/main/ MEDIATOR_URL=https://f326-207-194-65-204.ngrok.io?c_i=eyJAdHlwZSI6ICJodHRwczovL2RpZGNvbW0ub3JnL2Nvbm5lY3Rpb25zLzEuMC9pbnZpdGF0aW9uIiwgIkBpZCI6ICI2MjQ0ZThiNS0wNWYzLTRhYWItYjM1Yy1lYWVlMWNmZTAyM2MiLCAicmVjaXBpZW50S2V5cyI6IFsiQ3lqM1BHRUJzQ3RyUGFtTTQyRngza3BlYmR2QWdNd1lGejlFS3RmNnlUN3giXSwgImxhYmVsIjogIk1lZGlhdG9yIiwgInNlcnZpY2VFbmRwb2ludCI6ICJodHRwczovL2YzMjYtMjA3LTE5NC02NS0yMDQubmdyb2suaW8ifQ== -# Enable Pickup V2 live mode + batch pickup (required for Credo-TS mediators) -MEDIATOR_USE_V2_BATCH_PICKUP=false MEDIATOR_USE_PUSH_NOTIFICATIONS=false LOAD_STORYBOOK=false PROOF_TEMPLATE_URL= diff --git a/app/App.tsx b/app/App.tsx index 7442ca7..e2023c8 100644 --- a/app/App.tsx +++ b/app/App.tsx @@ -3,7 +3,6 @@ import { AnimatedComponentsProvider, AuthProvider, ContainerProvider, - ErrorBoundaryWrapper, ErrorModal, initLanguages, initStoredLanguage, @@ -28,6 +27,8 @@ import { container } from 'tsyringe' import Root from '@/Root' import { KeyRingThemeNames, surveyMonkeyExitUrl, surveyMonkeyUrl } from '@/constants' +import { ErrorAlertProvider } from '@/contexts/ErrorAlertContext' +import { ErrorBoundaryWrapper } from '@/errors/components/ErrorBoundary' import { localization } from '@/localization' import { initialState, reducer } from '@/store' import { themes } from '@/theme' @@ -83,7 +84,9 @@ const App = () => { onClose={() => setSurveyVisible(false)} /> - + + + diff --git a/app/AppStorybook.tsx b/app/AppStorybook.tsx deleted file mode 100644 index 41ec751..0000000 --- a/app/AppStorybook.tsx +++ /dev/null @@ -1,18 +0,0 @@ -// import { initLanguages } from '@bifold/core' -import React from 'react' -import { LogBox } from 'react-native' - -// import keyring from './src' -import StorybookUIRoot from './storybook' - -// const { localization } = keyring - -// initLanguages(localization) - -LogBox.ignoreAllLogs() - -const Base = () => { - return -} - -export default Base diff --git a/app/__mocks__/@credo-ts/react-hooks.ts b/app/__mocks__/@bifold/react-hooks.ts similarity index 87% rename from app/__mocks__/@credo-ts/react-hooks.ts rename to app/__mocks__/@bifold/react-hooks.ts index 50bb0cf..3c75943 100644 --- a/app/__mocks__/@credo-ts/react-hooks.ts +++ b/app/__mocks__/@bifold/react-hooks.ts @@ -1,6 +1,10 @@ /* eslint-disable @typescript-eslint/no-explicit-any */ import { LegacyIndyCredentialFormat } from '@credo-ts/anoncreds' -import { CredentialExchangeRecord, CredentialProtocolOptions, ProofExchangeRecord } from '@credo-ts/core' +import { + CredentialProtocolOptions, + DidCommCredentialExchangeRecord as CredentialExchangeRecord, + DidCommProofExchangeRecord as ProofExchangeRecord, +} from '@credo-ts/didcomm' const useCredentials = jest.fn().mockReturnValue({ credentials: [] } as any) const useCredentialByState = jest.fn().mockReturnValue([] as CredentialExchangeRecord[]) diff --git a/app/__mocks__/@bifold/remote-logs.ts b/app/__mocks__/@bifold/remote-logs.ts index 7230752..0f6f5c0 100644 --- a/app/__mocks__/@bifold/remote-logs.ts +++ b/app/__mocks__/@bifold/remote-logs.ts @@ -2,6 +2,10 @@ export enum RemoteLoggerEventTypes { ENABLE_REMOTE_LOGGING = 'RemoteLogging.Enable', } +export type RemoteLoggerOptions = Record + +export const lokiTransport = jest.fn() + export class RemoteLogger { create() { return this diff --git a/app/__tests__/components/__snapshots__/EmptyList.test.tsx.snap b/app/__tests__/components/__snapshots__/EmptyList.test.tsx.snap index 88a6520..a61f7d3 100644 --- a/app/__tests__/components/__snapshots__/EmptyList.test.tsx.snap +++ b/app/__tests__/components/__snapshots__/EmptyList.test.tsx.snap @@ -120,9 +120,7 @@ exports[`EmptyList Component renders correctly 1`] = ` accessible={true} collapsable={false} focusable={true} - onBlur={[Function]} onClick={[Function]} - onFocus={[Function]} onResponderGrant={[Function]} onResponderMove={[Function]} onResponderRelease={[Function]} @@ -130,29 +128,22 @@ exports[`EmptyList Component renders correctly 1`] = ` onResponderTerminationRequest={[Function]} onStartShouldSetResponder={[Function]} style={ - [ - { - "overflow": "hidden", - }, - { - "backgroundColor": "#622C62", - "borderRadius": 10, - "elevation": 4, - "padding": 16, - "paddingHorizontal": 16, - "paddingVertical": 12, - "shadowColor": "#000000", - "shadowOffset": { - "height": 4, - "width": 0, - }, - "shadowOpacity": 0.15, - "shadowRadius": 4, + { + "backgroundColor": "#622C62", + "borderRadius": 10, + "elevation": 4, + "opacity": 1, + "padding": 16, + "paddingHorizontal": 16, + "paddingVertical": 12, + "shadowColor": "#000000", + "shadowOffset": { + "height": 4, + "width": 0, }, - false, - false, - false, - ] + "shadowOpacity": 0.15, + "shadowRadius": 4, + } } testID="com.ariesbifold:id/AddFirstCredential" > @@ -186,7 +177,6 @@ exports[`EmptyList Component renders correctly 1`] = ` }, false, false, - false, ], ] } diff --git a/app/__tests__/navigation/__snapshots__/QRCodeFlow.test.tsx.snap b/app/__tests__/navigation/__snapshots__/QRCodeFlow.test.tsx.snap index 2d34fa8..11d67ad 100644 --- a/app/__tests__/navigation/__snapshots__/QRCodeFlow.test.tsx.snap +++ b/app/__tests__/navigation/__snapshots__/QRCodeFlow.test.tsx.snap @@ -3,7 +3,6 @@ exports[`QR Code Flow Integration QRCodeExchangeSlider renders correctly in AdvancedIdentity context 1`] = ` @@ -255,20 +257,22 @@ exports[`QR Code Flow Integration QRCodeExchangeSlider renders correctly in Adva style={ [ { - "color": "#FFFFFF", + "color": "#4A4A4A", + "fontFamily": "SourceSans3-Regular", "fontSize": 18, "fontWeight": "normal", }, [ { "color": "#FFFFFF", + "fontFamily": "SourceSans3-Regular", "fontSize": 18, "fontWeight": "bold", + "lineHeight": 24, "textAlign": "center", }, false, false, - false, ], ] } @@ -308,9 +312,7 @@ exports[`QR Code Flow Integration QRCodeExchangeSlider renders correctly in Adva accessible={true} collapsable={false} focusable={true} - onBlur={[Function]} onClick={[Function]} - onFocus={[Function]} onResponderGrant={[Function]} onResponderMove={[Function]} onResponderRelease={[Function]} @@ -318,19 +320,20 @@ exports[`QR Code Flow Integration QRCodeExchangeSlider renders correctly in Adva onResponderTerminationRequest={[Function]} onStartShouldSetResponder={[Function]} style={ - [ - { - "overflow": "hidden", - }, - { - "backgroundColor": "#42803E", - "borderRadius": 4, - "padding": 16, + { + "backgroundColor": "#622C62", + "borderRadius": 10, + "elevation": 4, + "opacity": 1, + "padding": 16, + "shadowColor": "#000000", + "shadowOffset": { + "height": 4, + "width": 0, }, - false, - false, - false, - ] + "shadowOpacity": 0.15, + "shadowRadius": 4, + } } testID="com.ariesbifold:id/GenerateQRCode" > @@ -348,20 +351,22 @@ exports[`QR Code Flow Integration QRCodeExchangeSlider renders correctly in Adva style={ [ { - "color": "#FFFFFF", + "color": "#4A4A4A", + "fontFamily": "SourceSans3-Regular", "fontSize": 18, "fontWeight": "normal", }, [ { "color": "#FFFFFF", + "fontFamily": "SourceSans3-Regular", "fontSize": 18, "fontWeight": "bold", + "lineHeight": 24, "textAlign": "center", }, false, false, - false, ], ] } diff --git a/app/__tests__/navigation/__snapshots__/TabNavigation.test.tsx.snap b/app/__tests__/navigation/__snapshots__/TabNavigation.test.tsx.snap index 66236ca..cd990ef 100644 --- a/app/__tests__/navigation/__snapshots__/TabNavigation.test.tsx.snap +++ b/app/__tests__/navigation/__snapshots__/TabNavigation.test.tsx.snap @@ -3,7 +3,6 @@ exports[`Tab Navigation Integration QRCodeExchangeSlider renders correctly 1`] = ` @@ -255,20 +257,22 @@ exports[`Tab Navigation Integration QRCodeExchangeSlider renders correctly 1`] = style={ [ { - "color": "#FFFFFF", + "color": "#4A4A4A", + "fontFamily": "SourceSans3-Regular", "fontSize": 18, "fontWeight": "normal", }, [ { "color": "#FFFFFF", + "fontFamily": "SourceSans3-Regular", "fontSize": 18, "fontWeight": "bold", + "lineHeight": 24, "textAlign": "center", }, false, false, - false, ], ] } @@ -308,9 +312,7 @@ exports[`Tab Navigation Integration QRCodeExchangeSlider renders correctly 1`] = accessible={true} collapsable={false} focusable={true} - onBlur={[Function]} onClick={[Function]} - onFocus={[Function]} onResponderGrant={[Function]} onResponderMove={[Function]} onResponderRelease={[Function]} @@ -318,19 +320,20 @@ exports[`Tab Navigation Integration QRCodeExchangeSlider renders correctly 1`] = onResponderTerminationRequest={[Function]} onStartShouldSetResponder={[Function]} style={ - [ - { - "overflow": "hidden", - }, - { - "backgroundColor": "#42803E", - "borderRadius": 4, - "padding": 16, + { + "backgroundColor": "#622C62", + "borderRadius": 10, + "elevation": 4, + "opacity": 1, + "padding": 16, + "shadowColor": "#000000", + "shadowOffset": { + "height": 4, + "width": 0, }, - false, - false, - false, - ] + "shadowOpacity": 0.15, + "shadowRadius": 4, + } } testID="com.ariesbifold:id/GenerateQRCode" > @@ -348,20 +351,22 @@ exports[`Tab Navigation Integration QRCodeExchangeSlider renders correctly 1`] = style={ [ { - "color": "#FFFFFF", + "color": "#4A4A4A", + "fontFamily": "SourceSans3-Regular", "fontSize": 18, "fontWeight": "normal", }, [ { "color": "#FFFFFF", + "fontFamily": "SourceSans3-Regular", "fontSize": 18, "fontWeight": "bold", + "lineHeight": 24, "textAlign": "center", }, false, false, - false, ], ] } diff --git a/app/__tests__/screens/__snapshots__/Developer.test.tsx.snap b/app/__tests__/screens/__snapshots__/Developer.test.tsx.snap index 4df73c2..05d9fc2 100644 --- a/app/__tests__/screens/__snapshots__/Developer.test.tsx.snap +++ b/app/__tests__/screens/__snapshots__/Developer.test.tsx.snap @@ -103,8 +103,7 @@ exports[`Developer Screen screen renders correctly 1`] = ` style={ [ { - "height": 31, - "width": 51, + "alignSelf": "flex-start", }, { "backgroundColor": "#D3D3D3", @@ -358,8 +357,7 @@ exports[`Developer Screen screen renders correctly 1`] = ` style={ [ { - "height": 31, - "width": 51, + "alignSelf": "flex-start", }, { "backgroundColor": "#D3D3D3", @@ -469,8 +467,7 @@ exports[`Developer Screen screen renders correctly 1`] = ` style={ [ { - "height": 31, - "width": 51, + "alignSelf": "flex-start", }, { "backgroundColor": "#D3D3D3", @@ -580,8 +577,7 @@ exports[`Developer Screen screen renders correctly 1`] = ` style={ [ { - "height": 31, - "width": 51, + "alignSelf": "flex-start", }, { "backgroundColor": "#D3D3D3", @@ -691,8 +687,7 @@ exports[`Developer Screen screen renders correctly 1`] = ` style={ [ { - "height": 31, - "width": 51, + "alignSelf": "flex-start", }, { "backgroundColor": "#D3D3D3", @@ -802,8 +797,7 @@ exports[`Developer Screen screen renders correctly 1`] = ` style={ [ { - "height": 31, - "width": 51, + "alignSelf": "flex-start", }, { "backgroundColor": "#D3D3D3", @@ -913,8 +907,7 @@ exports[`Developer Screen screen renders correctly 1`] = ` style={ [ { - "height": 31, - "width": 51, + "alignSelf": "flex-start", }, { "backgroundColor": "#D3D3D3", @@ -1024,8 +1017,7 @@ exports[`Developer Screen screen renders correctly 1`] = ` style={ [ { - "height": 31, - "width": 51, + "alignSelf": "flex-start", }, { "backgroundColor": "#D3D3D3", @@ -1119,8 +1111,7 @@ exports[`Developer Screen screen renders correctly 1`] = ` style={ [ { - "height": 31, - "width": 51, + "alignSelf": "flex-start", }, { "backgroundColor": "#D3D3D3", @@ -1213,8 +1204,7 @@ exports[`Developer Screen screen renders correctly 1`] = ` style={ [ { - "height": 31, - "width": 51, + "alignSelf": "flex-start", }, { "backgroundColor": "#D3D3D3", @@ -1307,8 +1297,7 @@ exports[`Developer Screen screen renders correctly 1`] = ` style={ [ { - "height": 31, - "width": 51, + "alignSelf": "flex-start", }, { "backgroundColor": "#D3D3D3", diff --git a/app/__tests__/screens/__snapshots__/PersonCredential.test.tsx.snap b/app/__tests__/screens/__snapshots__/PersonCredential.test.tsx.snap index 4ce7526..a496c43 100644 --- a/app/__tests__/screens/__snapshots__/PersonCredential.test.tsx.snap +++ b/app/__tests__/screens/__snapshots__/PersonCredential.test.tsx.snap @@ -107,9 +107,7 @@ exports[`Person Credential Screen screen renders correctly 1`] = ` accessible={true} collapsable={false} focusable={true} - onBlur={[Function]} onClick={[Function]} - onFocus={[Function]} onResponderGrant={[Function]} onResponderMove={[Function]} onResponderRelease={[Function]} @@ -117,29 +115,22 @@ exports[`Person Credential Screen screen renders correctly 1`] = ` onResponderTerminationRequest={[Function]} onStartShouldSetResponder={[Function]} style={ - [ - { - "overflow": "hidden", - }, - { - "backgroundColor": "#622C62", - "borderRadius": 10, - "elevation": 4, - "padding": 16, - "paddingHorizontal": 16, - "paddingVertical": 12, - "shadowColor": "#000000", - "shadowOffset": { - "height": 4, - "width": 0, - }, - "shadowOpacity": 0.15, - "shadowRadius": 4, + { + "backgroundColor": "#622C62", + "borderRadius": 10, + "elevation": 4, + "opacity": 1, + "padding": 16, + "paddingHorizontal": 16, + "paddingVertical": 12, + "shadowColor": "#000000", + "shadowOffset": { + "height": 4, + "width": 0, }, - false, - false, - false, - ] + "shadowOpacity": 0.15, + "shadowRadius": 4, + } } testID="com.ariesbifold:id/InstallApp" > @@ -173,7 +164,6 @@ exports[`Person Credential Screen screen renders correctly 1`] = ` }, false, false, - false, ], ] } diff --git a/app/__tests__/screens/__snapshots__/RemoteLogWarning.test.tsx.snap b/app/__tests__/screens/__snapshots__/RemoteLogWarning.test.tsx.snap index 69f937f..b5e5475 100644 --- a/app/__tests__/screens/__snapshots__/RemoteLogWarning.test.tsx.snap +++ b/app/__tests__/screens/__snapshots__/RemoteLogWarning.test.tsx.snap @@ -412,7 +412,6 @@ exports[`RemoteLogWarning Screen screen renders correctly 1`] = ` style={ { "alignItems": "center", - "flex": 1, "flexDirection": "row-reverse", "margin": 10, } @@ -544,10 +543,8 @@ exports[`RemoteLogWarning Screen screen renders correctly 1`] = ` } accessible={true} collapsable={false} - focusable={true} - onBlur={[Function]} + focusable={false} onClick={[Function]} - onFocus={[Function]} onResponderGrant={[Function]} onResponderMove={[Function]} onResponderRelease={[Function]} @@ -555,35 +552,22 @@ exports[`RemoteLogWarning Screen screen renders correctly 1`] = ` onResponderTerminationRequest={[Function]} onStartShouldSetResponder={[Function]} style={ - [ - { - "overflow": "hidden", - }, - { - "backgroundColor": "#622C62", - "borderRadius": 10, - "elevation": 4, - "padding": 16, - "paddingHorizontal": 16, - "paddingVertical": 12, - "shadowColor": "#000000", - "shadowOffset": { - "height": 4, - "width": 0, - }, - "shadowOpacity": 0.15, - "shadowRadius": 4, - }, - { - "backgroundColor": "rgba(98, 44, 98, 0.7)", - "borderRadius": 10, - "padding": 16, - "paddingHorizontal": 16, - "paddingVertical": 12, + { + "backgroundColor": "rgba(98, 44, 98, 0.7)", + "borderRadius": 10, + "elevation": 4, + "opacity": 1, + "padding": 16, + "paddingHorizontal": 16, + "paddingVertical": 12, + "shadowColor": "#000000", + "shadowOffset": { + "height": 4, + "width": 0, }, - false, - false, - ] + "shadowOpacity": 0.15, + "shadowRadius": 4, + } } testID="com.ariesbifold:id/TurnOn" > @@ -624,7 +608,6 @@ exports[`RemoteLogWarning Screen screen renders correctly 1`] = ` "textAlign": "center", }, false, - false, ], ] } diff --git a/app/__tests__/utils/periodicPickup.test.ts b/app/__tests__/utils/periodicPickup.test.ts deleted file mode 100644 index 807fe12..0000000 --- a/app/__tests__/utils/periodicPickup.test.ts +++ /dev/null @@ -1,99 +0,0 @@ -import { Agent } from '@credo-ts/core' -import { startPeriodicTrustPing } from '@utils/mediator' - -jest.useFakeTimers({ legacyFakeTimers: true }) - -const createMockAgent = () => - ({ - mediationRecipient: { - findDefaultMediator: jest.fn().mockResolvedValue({ connectionId: 'mock-mediator-conn-id' }), - }, - connections: { - sendPing: jest.fn().mockResolvedValue(undefined), - }, - config: { - logger: { - debug: jest.fn(), - error: jest.fn(), - }, - }, - } as unknown as Agent) - -describe('startPeriodicTrustPing', () => { - let mockAgent: Agent - - beforeEach(() => { - jest.clearAllTimers() - jest.clearAllMocks() - mockAgent = createMockAgent() - }) - - it('does not send a ping immediately on start', () => { - startPeriodicTrustPing(mockAgent, 15000) - - expect(mockAgent.connections.sendPing).not.toHaveBeenCalled() - }) - - it('sends a trust ping after one interval', async () => { - startPeriodicTrustPing(mockAgent, 15000) - - jest.advanceTimersByTime(15000) - await Promise.resolve() - - expect(mockAgent.connections.sendPing).toHaveBeenCalledTimes(1) - expect(mockAgent.connections.sendPing).toHaveBeenCalledWith('mock-mediator-conn-id', { - responseRequested: false, - withReturnRouting: true, - }) - }) - - it('pings repeatedly on each interval', async () => { - startPeriodicTrustPing(mockAgent, 15000) - - for (let i = 0; i < 3; i++) { - jest.advanceTimersByTime(15000) - await Promise.resolve() - } - - expect(mockAgent.connections.sendPing).toHaveBeenCalledTimes(3) - }) - - it('stops pinging after cleanup', async () => { - const cleanup = startPeriodicTrustPing(mockAgent, 15000) - - jest.advanceTimersByTime(15000) - await Promise.resolve() - expect(mockAgent.connections.sendPing).toHaveBeenCalledTimes(1) - - cleanup() - - jest.advanceTimersByTime(30000) - await Promise.resolve() - expect(mockAgent.connections.sendPing).toHaveBeenCalledTimes(1) - }) - - it('survives errors and keeps pinging', async () => { - jest.mocked(mockAgent.connections.sendPing).mockRejectedValueOnce(new Error('WebSocket dead')) - - startPeriodicTrustPing(mockAgent, 15000) - - jest.advanceTimersByTime(15000) - await Promise.resolve() - expect(mockAgent.connections.sendPing).toHaveBeenCalledTimes(1) - - jest.advanceTimersByTime(15000) - await Promise.resolve() - expect(mockAgent.connections.sendPing).toHaveBeenCalledTimes(2) - }) - - it('skips ping if no default mediator is found', async () => { - jest.mocked(mockAgent.mediationRecipient.findDefaultMediator).mockResolvedValue(null) - - startPeriodicTrustPing(mockAgent, 15000) - - jest.advanceTimersByTime(15000) - await Promise.resolve() - - expect(mockAgent.connections.sendPing).not.toHaveBeenCalled() - }) -}) diff --git a/app/android/app/build.gradle b/app/android/app/build.gradle index 7126c80..74a4fcb 100644 --- a/app/android/app/build.gradle +++ b/app/android/app/build.gradle @@ -109,24 +109,8 @@ android { version "3.22.1" } } - compileOptions { - sourceCompatibility JavaVersion.VERSION_17 - targetCompatibility JavaVersion.VERSION_17 - } - - kotlinOptions { - jvmTarget = "17" - } - - kotlinOptions { - jvmTarget = "17" - } - - java { - toolchain { - languageVersion.set(JavaLanguageVersion.of(17)) - } - } + // Java/Kotlin toolchain + jvmTarget are managed by the RN 0.81 gradle + // plugin; setting them here now fails ("languageVersion is final") defaultConfig { applicationId "asml.bkc.harvard.wallet" diff --git a/app/android/app/gradle.lockfile b/app/android/app/gradle.lockfile index 482f59c..02c0c1b 100644 --- a/app/android/app/gradle.lockfile +++ b/app/android/app/gradle.lockfile @@ -1,354 +1,245 @@ # This is a Gradle generated file for dependency locking. # Manual edits can break the build and are not advised. # This file is expected to be part of source control. -androidx.activity:activity-ktx:1.9.3=debugRuntimeClasspath,debugUnitTestRuntimeClasspath,releaseRuntimeClasspath,releaseUnitTestRuntimeClasspath -androidx.activity:activity:1.6.0=debugAndroidTestCompileClasspath -androidx.activity:activity:1.9.3=debugCompileClasspath,debugRuntimeClasspath,debugUnitTestCompileClasspath,debugUnitTestRuntimeClasspath,releaseCompileClasspath,releaseRuntimeClasspath,releaseUnitTestCompileClasspath,releaseUnitTestRuntimeClasspath -androidx.annotation:annotation-experimental:1.3.0=debugAndroidTestCompileClasspath -androidx.annotation:annotation-experimental:1.4.1=debugCompileClasspath,debugRuntimeClasspath,debugUnitTestCompileClasspath,debugUnitTestRuntimeClasspath,releaseCompileClasspath,releaseRuntimeClasspath,releaseUnitTestCompileClasspath,releaseUnitTestRuntimeClasspath -androidx.annotation:annotation-jvm:1.10.0=debugCompileClasspath,debugRuntimeClasspath,debugUnitTestCompileClasspath,debugUnitTestRuntimeClasspath,releaseCompileClasspath,releaseRuntimeClasspath,releaseUnitTestCompileClasspath,releaseUnitTestRuntimeClasspath -androidx.annotation:annotation:1.10.0=debugCompileClasspath,debugRuntimeClasspath,debugUnitTestCompileClasspath,debugUnitTestRuntimeClasspath,releaseCompileClasspath,releaseRuntimeClasspath,releaseUnitTestCompileClasspath,releaseUnitTestRuntimeClasspath -androidx.annotation:annotation:1.3.0=debugAndroidTestCompileClasspath -androidx.appcompat:appcompat-resources:1.6.1=debugAndroidTestCompileClasspath,debugCompileClasspath,debugRuntimeClasspath,debugUnitTestCompileClasspath,debugUnitTestRuntimeClasspath,releaseCompileClasspath,releaseRuntimeClasspath,releaseUnitTestCompileClasspath,releaseUnitTestRuntimeClasspath -androidx.appcompat:appcompat:1.6.1=debugAndroidTestCompileClasspath,debugCompileClasspath,debugRuntimeClasspath,debugUnitTestCompileClasspath,debugUnitTestRuntimeClasspath,releaseCompileClasspath,releaseRuntimeClasspath,releaseUnitTestCompileClasspath,releaseUnitTestRuntimeClasspath -androidx.arch.core:core-common:2.1.0=debugAndroidTestCompileClasspath -androidx.arch.core:core-common:2.2.0=debugCompileClasspath,debugRuntimeClasspath,debugUnitTestCompileClasspath,debugUnitTestRuntimeClasspath,releaseCompileClasspath,releaseRuntimeClasspath,releaseUnitTestCompileClasspath,releaseUnitTestRuntimeClasspath -androidx.arch.core:core-runtime:2.0.0=debugAndroidTestCompileClasspath -androidx.arch.core:core-runtime:2.2.0=debugRuntimeClasspath,debugUnitTestCompileClasspath,debugUnitTestRuntimeClasspath,releaseCompileClasspath,releaseRuntimeClasspath,releaseUnitTestCompileClasspath,releaseUnitTestRuntimeClasspath -androidx.asynclayoutinflater:asynclayoutinflater:1.0.0=debugRuntimeClasspath,debugUnitTestRuntimeClasspath,releaseRuntimeClasspath,releaseUnitTestRuntimeClasspath -androidx.autofill:autofill:1.1.0=debugAndroidTestCompileClasspath,debugCompileClasspath,debugRuntimeClasspath,debugUnitTestCompileClasspath,debugUnitTestRuntimeClasspath,releaseCompileClasspath,releaseRuntimeClasspath,releaseUnitTestCompileClasspath,releaseUnitTestRuntimeClasspath -androidx.biometric:biometric:1.1.0=debugRuntimeClasspath,debugUnitTestRuntimeClasspath,releaseRuntimeClasspath,releaseUnitTestRuntimeClasspath -androidx.browser:browser:1.5.0=debugRuntimeClasspath,debugUnitTestRuntimeClasspath,releaseRuntimeClasspath,releaseUnitTestRuntimeClasspath -androidx.camera:camera-camera2:1.5.0-alpha03=debugRuntimeClasspath,debugUnitTestRuntimeClasspath,releaseRuntimeClasspath,releaseUnitTestRuntimeClasspath -androidx.camera:camera-core:1.5.0-alpha03=debugRuntimeClasspath,debugUnitTestRuntimeClasspath,releaseRuntimeClasspath,releaseUnitTestRuntimeClasspath -androidx.camera:camera-extensions:1.5.0-alpha03=debugRuntimeClasspath,debugUnitTestRuntimeClasspath,releaseRuntimeClasspath,releaseUnitTestRuntimeClasspath -androidx.camera:camera-lifecycle:1.5.0-alpha03=debugRuntimeClasspath,debugUnitTestRuntimeClasspath,releaseRuntimeClasspath,releaseUnitTestRuntimeClasspath -androidx.camera:camera-video:1.5.0-alpha03=debugRuntimeClasspath,debugUnitTestRuntimeClasspath,releaseRuntimeClasspath,releaseUnitTestRuntimeClasspath -androidx.camera:camera-view:1.5.0-alpha03=debugRuntimeClasspath,debugUnitTestRuntimeClasspath,releaseRuntimeClasspath,releaseUnitTestRuntimeClasspath -androidx.cardview:cardview:1.0.0=debugRuntimeClasspath,debugUnitTestRuntimeClasspath,releaseRuntimeClasspath,releaseUnitTestRuntimeClasspath -androidx.collection:collection-ktx:1.1.0=debugRuntimeClasspath,debugUnitTestRuntimeClasspath,releaseRuntimeClasspath,releaseUnitTestRuntimeClasspath -androidx.collection:collection:1.1.0=debugAndroidTestCompileClasspath -androidx.collection:collection:1.2.0=debugCompileClasspath,debugRuntimeClasspath,debugUnitTestCompileClasspath,debugUnitTestRuntimeClasspath,releaseCompileClasspath,releaseRuntimeClasspath,releaseUnitTestCompileClasspath,releaseUnitTestRuntimeClasspath -androidx.concurrent:concurrent-futures-ktx:1.1.0=debugRuntimeClasspath,debugUnitTestRuntimeClasspath,releaseRuntimeClasspath,releaseUnitTestRuntimeClasspath -androidx.concurrent:concurrent-futures:1.1.0=debugRuntimeClasspath,debugUnitTestRuntimeClasspath,releaseRuntimeClasspath,releaseUnitTestRuntimeClasspath -androidx.constraintlayout:constraintlayout-solver:2.0.1=debugRuntimeClasspath,debugUnitTestRuntimeClasspath,releaseRuntimeClasspath,releaseUnitTestRuntimeClasspath -androidx.constraintlayout:constraintlayout:2.0.1=debugRuntimeClasspath,debugUnitTestRuntimeClasspath,releaseRuntimeClasspath,releaseUnitTestRuntimeClasspath -androidx.coordinatorlayout:coordinatorlayout:1.2.0=debugRuntimeClasspath,debugUnitTestRuntimeClasspath,releaseRuntimeClasspath,releaseUnitTestRuntimeClasspath -androidx.core:core-ktx:1.13.1=debugCompileClasspath,debugRuntimeClasspath,debugUnitTestCompileClasspath,debugUnitTestRuntimeClasspath,releaseCompileClasspath,releaseRuntimeClasspath,releaseUnitTestCompileClasspath,releaseUnitTestRuntimeClasspath -androidx.core:core-ktx:1.2.0=debugAndroidTestCompileClasspath -androidx.core:core:1.13.1=debugCompileClasspath,debugRuntimeClasspath,debugUnitTestCompileClasspath,debugUnitTestRuntimeClasspath,releaseCompileClasspath,releaseRuntimeClasspath,releaseUnitTestCompileClasspath,releaseUnitTestRuntimeClasspath -androidx.core:core:1.9.0=debugAndroidTestCompileClasspath -androidx.cursoradapter:cursoradapter:1.0.0=debugAndroidTestCompileClasspath,debugCompileClasspath,debugRuntimeClasspath,debugUnitTestCompileClasspath,debugUnitTestRuntimeClasspath,releaseCompileClasspath,releaseRuntimeClasspath,releaseUnitTestCompileClasspath,releaseUnitTestRuntimeClasspath -androidx.customview:customview-poolingcontainer:1.0.0=debugRuntimeClasspath,debugUnitTestRuntimeClasspath,releaseRuntimeClasspath,releaseUnitTestRuntimeClasspath -androidx.customview:customview:1.0.0=debugAndroidTestCompileClasspath -androidx.customview:customview:1.1.0=debugCompileClasspath,debugRuntimeClasspath,debugUnitTestCompileClasspath,debugUnitTestRuntimeClasspath,releaseCompileClasspath,releaseRuntimeClasspath,releaseUnitTestCompileClasspath,releaseUnitTestRuntimeClasspath -androidx.documentfile:documentfile:1.0.0=debugRuntimeClasspath,debugUnitTestRuntimeClasspath,releaseRuntimeClasspath,releaseUnitTestRuntimeClasspath -androidx.drawerlayout:drawerlayout:1.0.0=debugAndroidTestCompileClasspath -androidx.drawerlayout:drawerlayout:1.1.1=debugCompileClasspath,debugRuntimeClasspath,debugUnitTestCompileClasspath,debugUnitTestRuntimeClasspath,releaseCompileClasspath,releaseRuntimeClasspath,releaseUnitTestCompileClasspath,releaseUnitTestRuntimeClasspath -androidx.dynamicanimation:dynamicanimation:1.0.0=debugRuntimeClasspath,debugUnitTestRuntimeClasspath,releaseRuntimeClasspath,releaseUnitTestRuntimeClasspath -androidx.emoji2:emoji2-views-helper:1.2.0=debugRuntimeClasspath,debugUnitTestRuntimeClasspath,releaseRuntimeClasspath,releaseUnitTestRuntimeClasspath -androidx.emoji2:emoji2:1.2.0=debugRuntimeClasspath,debugUnitTestRuntimeClasspath,releaseRuntimeClasspath,releaseUnitTestRuntimeClasspath -androidx.exifinterface:exifinterface:1.0.0=debugAndroidTestCompileClasspath -androidx.exifinterface:exifinterface:1.3.6=debugCompileClasspath,debugRuntimeClasspath,debugUnitTestCompileClasspath,debugUnitTestRuntimeClasspath,releaseCompileClasspath,releaseRuntimeClasspath,releaseUnitTestCompileClasspath,releaseUnitTestRuntimeClasspath -androidx.fragment:fragment-ktx:1.6.1=debugRuntimeClasspath,debugUnitTestRuntimeClasspath,releaseRuntimeClasspath,releaseUnitTestRuntimeClasspath -androidx.fragment:fragment:1.3.6=debugAndroidTestCompileClasspath -androidx.fragment:fragment:1.6.1=debugCompileClasspath,debugRuntimeClasspath,debugUnitTestCompileClasspath,debugUnitTestRuntimeClasspath,releaseCompileClasspath,releaseRuntimeClasspath,releaseUnitTestCompileClasspath,releaseUnitTestRuntimeClasspath -androidx.interpolator:interpolator:1.0.0=debugAndroidTestCompileClasspath,debugCompileClasspath,debugRuntimeClasspath,debugUnitTestCompileClasspath,debugUnitTestRuntimeClasspath,releaseCompileClasspath,releaseRuntimeClasspath,releaseUnitTestCompileClasspath,releaseUnitTestRuntimeClasspath -androidx.legacy:legacy-support-core-ui:1.0.0=debugRuntimeClasspath,debugUnitTestRuntimeClasspath,releaseRuntimeClasspath,releaseUnitTestRuntimeClasspath -androidx.legacy:legacy-support-core-utils:1.0.0=debugRuntimeClasspath,debugUnitTestRuntimeClasspath,releaseRuntimeClasspath,releaseUnitTestRuntimeClasspath -androidx.legacy:legacy-support-v4:1.0.0=debugRuntimeClasspath,debugUnitTestRuntimeClasspath,releaseRuntimeClasspath,releaseUnitTestRuntimeClasspath -androidx.lifecycle:lifecycle-common-jvm:2.8.7=debugCompileClasspath,debugRuntimeClasspath,debugUnitTestCompileClasspath,debugUnitTestRuntimeClasspath,releaseCompileClasspath,releaseRuntimeClasspath,releaseUnitTestCompileClasspath,releaseUnitTestRuntimeClasspath -androidx.lifecycle:lifecycle-common:2.5.1=debugAndroidTestCompileClasspath -androidx.lifecycle:lifecycle-common:2.8.7=debugCompileClasspath,debugRuntimeClasspath,debugUnitTestCompileClasspath,debugUnitTestRuntimeClasspath,releaseCompileClasspath,releaseRuntimeClasspath,releaseUnitTestCompileClasspath,releaseUnitTestRuntimeClasspath -androidx.lifecycle:lifecycle-livedata-core-ktx:2.8.7=debugRuntimeClasspath,debugUnitTestCompileClasspath,debugUnitTestRuntimeClasspath,releaseCompileClasspath,releaseRuntimeClasspath,releaseUnitTestCompileClasspath,releaseUnitTestRuntimeClasspath -androidx.lifecycle:lifecycle-livedata-core:2.5.1=debugAndroidTestCompileClasspath -androidx.lifecycle:lifecycle-livedata-core:2.8.7=debugCompileClasspath,debugRuntimeClasspath,debugUnitTestCompileClasspath,debugUnitTestRuntimeClasspath,releaseCompileClasspath,releaseRuntimeClasspath,releaseUnitTestCompileClasspath,releaseUnitTestRuntimeClasspath -androidx.lifecycle:lifecycle-livedata:2.0.0=debugAndroidTestCompileClasspath -androidx.lifecycle:lifecycle-livedata:2.8.7=debugRuntimeClasspath,debugUnitTestCompileClasspath,debugUnitTestRuntimeClasspath,releaseCompileClasspath,releaseRuntimeClasspath,releaseUnitTestCompileClasspath,releaseUnitTestRuntimeClasspath -androidx.lifecycle:lifecycle-process:2.8.7=debugRuntimeClasspath,debugUnitTestRuntimeClasspath,releaseRuntimeClasspath,releaseUnitTestRuntimeClasspath -androidx.lifecycle:lifecycle-runtime-android:2.8.7=debugCompileClasspath,debugRuntimeClasspath,debugUnitTestCompileClasspath,debugUnitTestRuntimeClasspath,releaseCompileClasspath,releaseRuntimeClasspath,releaseUnitTestCompileClasspath,releaseUnitTestRuntimeClasspath -androidx.lifecycle:lifecycle-runtime-ktx-android:2.8.7=debugRuntimeClasspath,debugUnitTestRuntimeClasspath,releaseRuntimeClasspath,releaseUnitTestRuntimeClasspath -androidx.lifecycle:lifecycle-runtime-ktx:2.8.7=debugRuntimeClasspath,debugUnitTestRuntimeClasspath,releaseRuntimeClasspath,releaseUnitTestRuntimeClasspath -androidx.lifecycle:lifecycle-runtime:2.5.1=debugAndroidTestCompileClasspath -androidx.lifecycle:lifecycle-runtime:2.8.7=debugCompileClasspath,debugRuntimeClasspath,debugUnitTestCompileClasspath,debugUnitTestRuntimeClasspath,releaseCompileClasspath,releaseRuntimeClasspath,releaseUnitTestCompileClasspath,releaseUnitTestRuntimeClasspath -androidx.lifecycle:lifecycle-viewmodel-android:2.8.7=debugCompileClasspath,debugRuntimeClasspath,debugUnitTestCompileClasspath,debugUnitTestRuntimeClasspath,releaseCompileClasspath,releaseRuntimeClasspath,releaseUnitTestCompileClasspath,releaseUnitTestRuntimeClasspath -androidx.lifecycle:lifecycle-viewmodel-ktx:2.8.7=debugRuntimeClasspath,debugUnitTestRuntimeClasspath,releaseRuntimeClasspath,releaseUnitTestRuntimeClasspath -androidx.lifecycle:lifecycle-viewmodel-savedstate:2.5.1=debugAndroidTestCompileClasspath -androidx.lifecycle:lifecycle-viewmodel-savedstate:2.8.7=debugCompileClasspath,debugRuntimeClasspath,debugUnitTestCompileClasspath,debugUnitTestRuntimeClasspath,releaseCompileClasspath,releaseRuntimeClasspath,releaseUnitTestCompileClasspath,releaseUnitTestRuntimeClasspath -androidx.lifecycle:lifecycle-viewmodel:2.5.1=debugAndroidTestCompileClasspath -androidx.lifecycle:lifecycle-viewmodel:2.8.7=debugCompileClasspath,debugRuntimeClasspath,debugUnitTestCompileClasspath,debugUnitTestRuntimeClasspath,releaseCompileClasspath,releaseRuntimeClasspath,releaseUnitTestCompileClasspath,releaseUnitTestRuntimeClasspath -androidx.loader:loader:1.0.0=debugAndroidTestCompileClasspath,debugUnitTestCompileClasspath,debugUnitTestRuntimeClasspath,releaseCompileClasspath,releaseRuntimeClasspath,releaseUnitTestCompileClasspath,releaseUnitTestRuntimeClasspath +androidx.activity:activity-ktx:1.9.3=debugRuntimeClasspath +androidx.activity:activity:1.9.3=debugCompileClasspath,debugRuntimeClasspath +androidx.annotation:annotation-experimental:1.4.1=debugCompileClasspath,debugRuntimeClasspath +androidx.annotation:annotation-jvm:1.10.0=debugCompileClasspath,debugRuntimeClasspath +androidx.annotation:annotation:1.10.0=debugCompileClasspath,debugRuntimeClasspath +androidx.appcompat:appcompat-resources:1.7.0=debugCompileClasspath,debugRuntimeClasspath +androidx.appcompat:appcompat:1.7.0=debugCompileClasspath,debugRuntimeClasspath +androidx.arch.core:core-common:2.2.0=debugCompileClasspath,debugRuntimeClasspath +androidx.arch.core:core-runtime:2.2.0=debugRuntimeClasspath +androidx.asynclayoutinflater:asynclayoutinflater:1.0.0=debugCompileClasspath,debugRuntimeClasspath +androidx.autofill:autofill:1.1.0=debugCompileClasspath,debugRuntimeClasspath +androidx.biometric:biometric:1.2.0-alpha05=debugCompileClasspath,debugRuntimeClasspath +androidx.browser:browser:1.5.0=debugRuntimeClasspath +androidx.camera:camera-camera2:1.5.0-alpha03=debugRuntimeClasspath +androidx.camera:camera-core:1.5.0-alpha03=debugRuntimeClasspath +androidx.camera:camera-extensions:1.5.0-alpha03=debugRuntimeClasspath +androidx.camera:camera-lifecycle:1.5.0-alpha03=debugRuntimeClasspath +androidx.camera:camera-video:1.5.0-alpha03=debugRuntimeClasspath +androidx.camera:camera-view:1.5.0-alpha03=debugRuntimeClasspath +androidx.cardview:cardview:1.0.0=debugRuntimeClasspath +androidx.collection:collection-jvm:1.4.2=debugCompileClasspath,debugRuntimeClasspath +androidx.collection:collection-ktx:1.4.2=debugRuntimeClasspath +androidx.collection:collection:1.4.2=debugCompileClasspath,debugRuntimeClasspath +androidx.concurrent:concurrent-futures-ktx:1.1.0=debugRuntimeClasspath +androidx.concurrent:concurrent-futures:1.1.0=debugRuntimeClasspath +androidx.constraintlayout:constraintlayout-solver:2.0.1=debugRuntimeClasspath +androidx.constraintlayout:constraintlayout:2.0.1=debugRuntimeClasspath +androidx.coordinatorlayout:coordinatorlayout:1.2.0=debugCompileClasspath,debugRuntimeClasspath +androidx.core:core-ktx:1.16.0=debugCompileClasspath,debugRuntimeClasspath +androidx.core:core-viewtree:1.0.0=debugCompileClasspath,debugRuntimeClasspath +androidx.core:core:1.16.0=debugCompileClasspath,debugRuntimeClasspath +androidx.cursoradapter:cursoradapter:1.0.0=debugCompileClasspath,debugRuntimeClasspath +androidx.customview:customview-poolingcontainer:1.0.0=debugRuntimeClasspath +androidx.customview:customview:1.1.0=debugCompileClasspath,debugRuntimeClasspath +androidx.datastore:datastore-android:1.1.1=debugRuntimeClasspath +androidx.datastore:datastore-core-android:1.1.1=debugRuntimeClasspath +androidx.datastore:datastore-core-okio-jvm:1.1.1=debugRuntimeClasspath +androidx.datastore:datastore-core-okio:1.1.1=debugRuntimeClasspath +androidx.datastore:datastore-core:1.1.1=debugRuntimeClasspath +androidx.datastore:datastore-preferences-android:1.1.1=debugRuntimeClasspath +androidx.datastore:datastore-preferences-core-jvm:1.1.1=debugRuntimeClasspath +androidx.datastore:datastore-preferences-core:1.1.1=debugRuntimeClasspath +androidx.datastore:datastore-preferences:1.1.1=debugRuntimeClasspath +androidx.datastore:datastore:1.1.1=debugRuntimeClasspath +androidx.documentfile:documentfile:1.1.0=debugCompileClasspath,debugRuntimeClasspath +androidx.drawerlayout:drawerlayout:1.1.1=debugCompileClasspath,debugRuntimeClasspath +androidx.dynamicanimation:dynamicanimation-ktx:1.0.0-alpha03=debugRuntimeClasspath +androidx.dynamicanimation:dynamicanimation:1.1.0-alpha03=debugRuntimeClasspath +androidx.emoji2:emoji2-views-helper:1.3.0=debugRuntimeClasspath +androidx.emoji2:emoji2:1.3.0=debugRuntimeClasspath +androidx.exifinterface:exifinterface:1.3.7=debugCompileClasspath,debugRuntimeClasspath +androidx.fragment:fragment-ktx:1.8.6=debugRuntimeClasspath +androidx.fragment:fragment:1.8.6=debugCompileClasspath,debugRuntimeClasspath +androidx.interpolator:interpolator:1.0.0=debugCompileClasspath,debugRuntimeClasspath +androidx.legacy:legacy-support-core-ui:1.0.0=debugCompileClasspath,debugRuntimeClasspath +androidx.legacy:legacy-support-core-utils:1.0.0=debugCompileClasspath,debugRuntimeClasspath +androidx.legacy:legacy-support-v4:1.0.0=debugCompileClasspath,debugRuntimeClasspath +androidx.lifecycle:lifecycle-common-java8:2.8.7=debugRuntimeClasspath +androidx.lifecycle:lifecycle-common-jvm:2.8.7=debugCompileClasspath,debugRuntimeClasspath +androidx.lifecycle:lifecycle-common:2.8.7=debugCompileClasspath,debugRuntimeClasspath +androidx.lifecycle:lifecycle-livedata-core-ktx:2.8.7=debugRuntimeClasspath +androidx.lifecycle:lifecycle-livedata-core:2.8.7=debugCompileClasspath,debugRuntimeClasspath +androidx.lifecycle:lifecycle-livedata:2.8.7=debugRuntimeClasspath +androidx.lifecycle:lifecycle-process:2.8.7=debugRuntimeClasspath +androidx.lifecycle:lifecycle-runtime-android:2.8.7=debugCompileClasspath,debugRuntimeClasspath +androidx.lifecycle:lifecycle-runtime-ktx-android:2.8.7=debugRuntimeClasspath +androidx.lifecycle:lifecycle-runtime-ktx:2.8.7=debugRuntimeClasspath +androidx.lifecycle:lifecycle-runtime:2.8.7=debugCompileClasspath,debugRuntimeClasspath +androidx.lifecycle:lifecycle-viewmodel-android:2.8.7=debugCompileClasspath,debugRuntimeClasspath +androidx.lifecycle:lifecycle-viewmodel-ktx:2.8.7=debugRuntimeClasspath +androidx.lifecycle:lifecycle-viewmodel-savedstate:2.8.7=debugCompileClasspath,debugRuntimeClasspath +androidx.lifecycle:lifecycle-viewmodel:2.8.7=debugCompileClasspath,debugRuntimeClasspath androidx.loader:loader:1.1.0=debugCompileClasspath,debugRuntimeClasspath -androidx.localbroadcastmanager:localbroadcastmanager:1.0.0=debugRuntimeClasspath,debugUnitTestRuntimeClasspath,releaseRuntimeClasspath,releaseUnitTestRuntimeClasspath -androidx.media3:media3-common:1.4.1=debugRuntimeClasspath,debugUnitTestRuntimeClasspath,releaseRuntimeClasspath,releaseUnitTestRuntimeClasspath -androidx.media3:media3-container:1.4.1=debugRuntimeClasspath,debugUnitTestRuntimeClasspath,releaseRuntimeClasspath,releaseUnitTestRuntimeClasspath -androidx.media3:media3-database:1.4.1=debugRuntimeClasspath,debugUnitTestRuntimeClasspath,releaseRuntimeClasspath,releaseUnitTestRuntimeClasspath -androidx.media3:media3-datasource-okhttp:1.4.1=debugRuntimeClasspath,debugUnitTestRuntimeClasspath,releaseRuntimeClasspath,releaseUnitTestRuntimeClasspath -androidx.media3:media3-datasource:1.4.1=debugRuntimeClasspath,debugUnitTestRuntimeClasspath,releaseRuntimeClasspath,releaseUnitTestRuntimeClasspath -androidx.media3:media3-decoder:1.4.1=debugRuntimeClasspath,debugUnitTestRuntimeClasspath,releaseRuntimeClasspath,releaseUnitTestRuntimeClasspath -androidx.media3:media3-exoplayer-dash:1.4.1=debugRuntimeClasspath,debugUnitTestRuntimeClasspath,releaseRuntimeClasspath,releaseUnitTestRuntimeClasspath -androidx.media3:media3-exoplayer-hls:1.4.1=debugRuntimeClasspath,debugUnitTestRuntimeClasspath,releaseRuntimeClasspath,releaseUnitTestRuntimeClasspath -androidx.media3:media3-exoplayer-smoothstreaming:1.4.1=debugRuntimeClasspath,debugUnitTestRuntimeClasspath,releaseRuntimeClasspath,releaseUnitTestRuntimeClasspath -androidx.media3:media3-exoplayer:1.4.1=debugRuntimeClasspath,debugUnitTestRuntimeClasspath,releaseRuntimeClasspath,releaseUnitTestRuntimeClasspath -androidx.media3:media3-extractor:1.4.1=debugRuntimeClasspath,debugUnitTestRuntimeClasspath,releaseRuntimeClasspath,releaseUnitTestRuntimeClasspath -androidx.media3:media3-session:1.4.1=debugRuntimeClasspath,debugUnitTestRuntimeClasspath,releaseRuntimeClasspath,releaseUnitTestRuntimeClasspath -androidx.media3:media3-ui:1.4.1=debugRuntimeClasspath,debugUnitTestRuntimeClasspath,releaseRuntimeClasspath,releaseUnitTestRuntimeClasspath -androidx.media:media:1.7.0=debugRuntimeClasspath,debugUnitTestRuntimeClasspath,releaseRuntimeClasspath,releaseUnitTestRuntimeClasspath -androidx.print:print:1.0.0=debugRuntimeClasspath,debugUnitTestRuntimeClasspath,releaseRuntimeClasspath,releaseUnitTestRuntimeClasspath -androidx.profileinstaller:profileinstaller:1.3.1=debugRuntimeClasspath,debugUnitTestRuntimeClasspath,releaseRuntimeClasspath,releaseUnitTestRuntimeClasspath -androidx.recyclerview:recyclerview:1.3.0=debugRuntimeClasspath,debugUnitTestRuntimeClasspath,releaseRuntimeClasspath,releaseUnitTestRuntimeClasspath -androidx.resourceinspection:resourceinspection-annotation:1.0.1=debugRuntimeClasspath,debugUnitTestRuntimeClasspath,releaseRuntimeClasspath,releaseUnitTestRuntimeClasspath -androidx.savedstate:savedstate-ktx:1.2.1=debugRuntimeClasspath,debugUnitTestRuntimeClasspath,releaseRuntimeClasspath,releaseUnitTestRuntimeClasspath -androidx.savedstate:savedstate:1.2.0=debugAndroidTestCompileClasspath -androidx.savedstate:savedstate:1.2.1=debugCompileClasspath,debugRuntimeClasspath,debugUnitTestCompileClasspath,debugUnitTestRuntimeClasspath,releaseCompileClasspath,releaseRuntimeClasspath,releaseUnitTestCompileClasspath,releaseUnitTestRuntimeClasspath -androidx.security:security-crypto:1.1.0-alpha03=debugRuntimeClasspath,debugUnitTestRuntimeClasspath,releaseRuntimeClasspath,releaseUnitTestRuntimeClasspath -androidx.slidingpanelayout:slidingpanelayout:1.0.0=debugRuntimeClasspath,debugUnitTestRuntimeClasspath,releaseRuntimeClasspath,releaseUnitTestRuntimeClasspath -androidx.startup:startup-runtime:1.1.1=debugRuntimeClasspath,debugUnitTestRuntimeClasspath,releaseRuntimeClasspath,releaseUnitTestRuntimeClasspath -androidx.swiperefreshlayout:swiperefreshlayout:1.1.0=debugAndroidTestCompileClasspath,debugCompileClasspath,debugRuntimeClasspath,debugUnitTestCompileClasspath,debugUnitTestRuntimeClasspath,releaseCompileClasspath,releaseRuntimeClasspath,releaseUnitTestCompileClasspath,releaseUnitTestRuntimeClasspath -androidx.tracing:tracing-ktx:1.2.0=debugRuntimeClasspath,debugUnitTestRuntimeClasspath,releaseRuntimeClasspath,releaseUnitTestRuntimeClasspath -androidx.tracing:tracing:1.1.0=debugAndroidTestCompileClasspath -androidx.tracing:tracing:1.2.0=debugCompileClasspath,debugRuntimeClasspath,debugUnitTestCompileClasspath,debugUnitTestRuntimeClasspath,releaseCompileClasspath,releaseRuntimeClasspath,releaseUnitTestCompileClasspath,releaseUnitTestRuntimeClasspath -androidx.transition:transition:1.2.0=debugRuntimeClasspath,debugUnitTestRuntimeClasspath,releaseRuntimeClasspath,releaseUnitTestRuntimeClasspath -androidx.vectordrawable:vectordrawable-animated:1.1.0=debugAndroidTestCompileClasspath,debugCompileClasspath,debugRuntimeClasspath,debugUnitTestCompileClasspath,debugUnitTestRuntimeClasspath,releaseCompileClasspath,releaseRuntimeClasspath,releaseUnitTestCompileClasspath,releaseUnitTestRuntimeClasspath -androidx.vectordrawable:vectordrawable:1.1.0=debugAndroidTestCompileClasspath,debugCompileClasspath,debugRuntimeClasspath,debugUnitTestCompileClasspath,debugUnitTestRuntimeClasspath,releaseCompileClasspath,releaseRuntimeClasspath,releaseUnitTestCompileClasspath,releaseUnitTestRuntimeClasspath -androidx.versionedparcelable:versionedparcelable:1.1.1=debugAndroidTestCompileClasspath,debugCompileClasspath,debugRuntimeClasspath,debugUnitTestCompileClasspath,debugUnitTestRuntimeClasspath,releaseCompileClasspath,releaseRuntimeClasspath,releaseUnitTestCompileClasspath,releaseUnitTestRuntimeClasspath -androidx.viewpager2:viewpager2:1.0.0=debugRuntimeClasspath,debugUnitTestRuntimeClasspath,releaseRuntimeClasspath,releaseUnitTestRuntimeClasspath -androidx.viewpager:viewpager:1.0.0=debugAndroidTestCompileClasspath,debugCompileClasspath,debugRuntimeClasspath,debugUnitTestCompileClasspath,debugUnitTestRuntimeClasspath,releaseCompileClasspath,releaseRuntimeClasspath,releaseUnitTestCompileClasspath,releaseUnitTestRuntimeClasspath -androidx.webkit:webkit:1.4.0=debugRuntimeClasspath,debugUnitTestRuntimeClasspath,releaseRuntimeClasspath,releaseUnitTestRuntimeClasspath -com.android.installreferrer:installreferrer:1.1.2=debugRuntimeClasspath,debugUnitTestRuntimeClasspath,releaseRuntimeClasspath,releaseUnitTestRuntimeClasspath -com.android.tools.ddms:ddmlib:31.7.3=_internal-unified-test-platform-android-device-provider-ddmlib -com.android.tools.emulator:proto:31.7.3=_internal-unified-test-platform-android-test-plugin-host-emulator-control,_internal-unified-test-platform-android-test-plugin-host-retention -com.android.tools.utp:android-device-provider-ddmlib-proto:31.7.3=_internal-unified-test-platform-android-device-provider-ddmlib -com.android.tools.utp:android-device-provider-ddmlib:31.7.3=_internal-unified-test-platform-android-device-provider-ddmlib -com.android.tools.utp:android-device-provider-gradle-proto:31.7.3=_internal-unified-test-platform-android-device-provider-gradle -com.android.tools.utp:android-device-provider-gradle:31.7.3=_internal-unified-test-platform-android-device-provider-gradle -com.android.tools.utp:android-device-provider-profile-proto:31.7.3=_internal-unified-test-platform-android-device-provider-ddmlib,_internal-unified-test-platform-android-device-provider-gradle -com.android.tools.utp:android-device-provider-profile:31.7.3=_internal-unified-test-platform-android-device-provider-ddmlib,_internal-unified-test-platform-android-device-provider-gradle -com.android.tools.utp:android-test-plugin-host-additional-test-output-proto:31.7.3=_internal-unified-test-platform-android-test-plugin-host-additional-test-output -com.android.tools.utp:android-test-plugin-host-additional-test-output:31.7.3=_internal-unified-test-platform-android-test-plugin-host-additional-test-output -com.android.tools.utp:android-test-plugin-host-apk-installer-proto:31.7.3=_internal-unified-test-platform-android-test-plugin-host-apk-installer -com.android.tools.utp:android-test-plugin-host-apk-installer:31.7.3=_internal-unified-test-platform-android-test-plugin-host-apk-installer -com.android.tools.utp:android-test-plugin-host-coverage-proto:31.7.3=_internal-unified-test-platform-android-test-plugin-host-coverage -com.android.tools.utp:android-test-plugin-host-coverage:31.7.3=_internal-unified-test-platform-android-test-plugin-host-coverage -com.android.tools.utp:android-test-plugin-host-device-info-proto:31.7.3=_internal-unified-test-platform-android-test-plugin-host-device-info -com.android.tools.utp:android-test-plugin-host-device-info:31.7.3=_internal-unified-test-platform-android-test-plugin-host-device-info -com.android.tools.utp:android-test-plugin-host-emulator-control-proto:31.7.3=_internal-unified-test-platform-android-test-plugin-host-emulator-control -com.android.tools.utp:android-test-plugin-host-emulator-control:31.7.3=_internal-unified-test-platform-android-test-plugin-host-emulator-control -com.android.tools.utp:android-test-plugin-host-logcat-proto:31.7.3=_internal-unified-test-platform-android-test-plugin-host-logcat -com.android.tools.utp:android-test-plugin-host-logcat:31.7.3=_internal-unified-test-platform-android-test-plugin-host-logcat -com.android.tools.utp:android-test-plugin-host-retention-proto:31.7.3=_internal-unified-test-platform-android-test-plugin-host-retention -com.android.tools.utp:android-test-plugin-host-retention:31.7.3=_internal-unified-test-platform-android-test-plugin-host-retention -com.android.tools.utp:android-test-plugin-result-listener-gradle-proto:31.7.3=_internal-unified-test-platform-android-test-plugin-result-listener-gradle -com.android.tools.utp:android-test-plugin-result-listener-gradle:31.7.3=_internal-unified-test-platform-android-test-plugin-result-listener-gradle -com.android.tools.utp:utp-common:31.7.3=_internal-unified-test-platform-android-test-plugin-host-additional-test-output,_internal-unified-test-platform-android-test-plugin-host-device-info,_internal-unified-test-platform-android-test-plugin-host-logcat,_internal-unified-test-platform-android-test-plugin-host-retention -com.android.tools:annotations:31.7.3=_internal-unified-test-platform-android-device-provider-ddmlib,_internal-unified-test-platform-android-device-provider-gradle,_internal-unified-test-platform-android-test-plugin-host-additional-test-output,_internal-unified-test-platform-android-test-plugin-host-apk-installer,_internal-unified-test-platform-android-test-plugin-host-coverage,_internal-unified-test-platform-android-test-plugin-host-device-info,_internal-unified-test-platform-android-test-plugin-host-emulator-control,_internal-unified-test-platform-android-test-plugin-host-logcat,_internal-unified-test-platform-android-test-plugin-host-retention,_internal-unified-test-platform-android-test-plugin-result-listener-gradle -com.android.tools:common:31.7.3=_internal-unified-test-platform-android-device-provider-ddmlib,_internal-unified-test-platform-android-device-provider-gradle,_internal-unified-test-platform-android-test-plugin-host-additional-test-output,_internal-unified-test-platform-android-test-plugin-host-apk-installer,_internal-unified-test-platform-android-test-plugin-host-coverage,_internal-unified-test-platform-android-test-plugin-host-device-info,_internal-unified-test-platform-android-test-plugin-host-emulator-control,_internal-unified-test-platform-android-test-plugin-host-logcat,_internal-unified-test-platform-android-test-plugin-host-retention,_internal-unified-test-platform-android-test-plugin-result-listener-gradle -com.facebook.conceal:conceal:1.1.3=debugRuntimeClasspath,debugUnitTestRuntimeClasspath,releaseRuntimeClasspath,releaseUnitTestRuntimeClasspath -com.facebook.fbjni:fbjni:0.7.0=debugAndroidTestCompileClasspath,debugCompileClasspath,debugRuntimeClasspath,debugUnitTestCompileClasspath,debugUnitTestRuntimeClasspath,releaseCompileClasspath,releaseRuntimeClasspath,releaseUnitTestCompileClasspath,releaseUnitTestRuntimeClasspath -com.facebook.fresco:drawee:3.4.0=debugAndroidTestCompileClasspath,debugCompileClasspath,debugRuntimeClasspath,debugUnitTestCompileClasspath,debugUnitTestRuntimeClasspath,releaseCompileClasspath,releaseRuntimeClasspath,releaseUnitTestCompileClasspath,releaseUnitTestRuntimeClasspath -com.facebook.fresco:fbcore:3.4.0=debugAndroidTestCompileClasspath,debugCompileClasspath,debugRuntimeClasspath,debugUnitTestCompileClasspath,debugUnitTestRuntimeClasspath,releaseCompileClasspath,releaseRuntimeClasspath,releaseUnitTestCompileClasspath,releaseUnitTestRuntimeClasspath -com.facebook.fresco:fresco:3.4.0=debugAndroidTestCompileClasspath,debugCompileClasspath,debugRuntimeClasspath,debugUnitTestCompileClasspath,debugUnitTestRuntimeClasspath,releaseCompileClasspath,releaseRuntimeClasspath,releaseUnitTestCompileClasspath,releaseUnitTestRuntimeClasspath -com.facebook.fresco:imagepipeline-base:3.4.0=debugAndroidTestCompileClasspath,debugCompileClasspath,debugRuntimeClasspath,debugUnitTestCompileClasspath,debugUnitTestRuntimeClasspath,releaseCompileClasspath,releaseRuntimeClasspath,releaseUnitTestCompileClasspath,releaseUnitTestRuntimeClasspath -com.facebook.fresco:imagepipeline-native:3.4.0=debugAndroidTestCompileClasspath,debugCompileClasspath,debugRuntimeClasspath,debugUnitTestCompileClasspath,debugUnitTestRuntimeClasspath,releaseCompileClasspath,releaseRuntimeClasspath,releaseUnitTestCompileClasspath,releaseUnitTestRuntimeClasspath -com.facebook.fresco:imagepipeline-okhttp3:3.4.0=debugAndroidTestCompileClasspath,debugCompileClasspath,debugRuntimeClasspath,debugUnitTestCompileClasspath,debugUnitTestRuntimeClasspath,releaseCompileClasspath,releaseRuntimeClasspath,releaseUnitTestCompileClasspath,releaseUnitTestRuntimeClasspath -com.facebook.fresco:imagepipeline:3.4.0=debugAndroidTestCompileClasspath,debugCompileClasspath,debugRuntimeClasspath,debugUnitTestCompileClasspath,debugUnitTestRuntimeClasspath,releaseCompileClasspath,releaseRuntimeClasspath,releaseUnitTestCompileClasspath,releaseUnitTestRuntimeClasspath -com.facebook.fresco:memory-type-ashmem:3.4.0=debugAndroidTestCompileClasspath,debugCompileClasspath,debugRuntimeClasspath,debugUnitTestCompileClasspath,debugUnitTestRuntimeClasspath,releaseCompileClasspath,releaseRuntimeClasspath,releaseUnitTestCompileClasspath,releaseUnitTestRuntimeClasspath -com.facebook.fresco:memory-type-java:3.4.0=debugAndroidTestCompileClasspath,debugCompileClasspath,debugRuntimeClasspath,debugUnitTestCompileClasspath,debugUnitTestRuntimeClasspath,releaseCompileClasspath,releaseRuntimeClasspath,releaseUnitTestCompileClasspath,releaseUnitTestRuntimeClasspath -com.facebook.fresco:memory-type-native:3.4.0=debugAndroidTestCompileClasspath,debugCompileClasspath,debugRuntimeClasspath,debugUnitTestCompileClasspath,debugUnitTestRuntimeClasspath,releaseCompileClasspath,releaseRuntimeClasspath,releaseUnitTestCompileClasspath,releaseUnitTestRuntimeClasspath -com.facebook.fresco:middleware:3.4.0=debugAndroidTestCompileClasspath,debugCompileClasspath,debugRuntimeClasspath,debugUnitTestCompileClasspath,debugUnitTestRuntimeClasspath,releaseCompileClasspath,releaseRuntimeClasspath,releaseUnitTestCompileClasspath,releaseUnitTestRuntimeClasspath -com.facebook.fresco:nativeimagefilters:3.4.0=debugAndroidTestCompileClasspath,debugCompileClasspath,debugRuntimeClasspath,debugUnitTestCompileClasspath,debugUnitTestRuntimeClasspath,releaseCompileClasspath,releaseRuntimeClasspath,releaseUnitTestCompileClasspath,releaseUnitTestRuntimeClasspath -com.facebook.fresco:nativeimagetranscoder:3.4.0=debugAndroidTestCompileClasspath,debugCompileClasspath,debugRuntimeClasspath,debugUnitTestCompileClasspath,debugUnitTestRuntimeClasspath,releaseCompileClasspath,releaseRuntimeClasspath,releaseUnitTestCompileClasspath,releaseUnitTestRuntimeClasspath -com.facebook.fresco:soloader:3.4.0=debugRuntimeClasspath,debugUnitTestRuntimeClasspath,releaseRuntimeClasspath,releaseUnitTestRuntimeClasspath -com.facebook.fresco:ui-common:3.4.0=debugAndroidTestCompileClasspath,debugCompileClasspath,debugRuntimeClasspath,debugUnitTestCompileClasspath,debugUnitTestRuntimeClasspath,releaseCompileClasspath,releaseRuntimeClasspath,releaseUnitTestCompileClasspath,releaseUnitTestRuntimeClasspath -com.facebook.fresco:ui-core:3.4.0=debugAndroidTestCompileClasspath,debugCompileClasspath,debugRuntimeClasspath,debugUnitTestCompileClasspath,debugUnitTestRuntimeClasspath,releaseCompileClasspath,releaseRuntimeClasspath,releaseUnitTestCompileClasspath,releaseUnitTestRuntimeClasspath -com.facebook.fresco:urimod:3.4.0=debugRuntimeClasspath,debugUnitTestRuntimeClasspath,releaseRuntimeClasspath,releaseUnitTestRuntimeClasspath -com.facebook.fresco:vito-source:3.4.0=debugRuntimeClasspath,debugUnitTestRuntimeClasspath,releaseRuntimeClasspath,releaseUnitTestRuntimeClasspath -com.facebook.infer.annotation:infer-annotation:0.18.0=debugAndroidTestCompileClasspath,debugCompileClasspath,debugRuntimeClasspath,debugUnitTestCompileClasspath,debugUnitTestRuntimeClasspath,releaseCompileClasspath,releaseRuntimeClasspath,releaseUnitTestCompileClasspath,releaseUnitTestRuntimeClasspath -com.facebook.react:hermes-android:0.77.3=debugAndroidTestCompileClasspath,debugCompileClasspath,debugRuntimeClasspath,debugUnitTestCompileClasspath,debugUnitTestRuntimeClasspath,releaseCompileClasspath,releaseRuntimeClasspath,releaseUnitTestCompileClasspath,releaseUnitTestRuntimeClasspath -com.facebook.react:react-android:0.77.3=debugAndroidTestCompileClasspath,debugCompileClasspath,debugRuntimeClasspath,debugUnitTestCompileClasspath,debugUnitTestRuntimeClasspath,releaseCompileClasspath,releaseRuntimeClasspath,releaseUnitTestCompileClasspath,releaseUnitTestRuntimeClasspath -com.facebook.soloader:annotation:0.12.1=debugAndroidTestCompileClasspath,debugCompileClasspath,debugRuntimeClasspath,debugUnitTestCompileClasspath,debugUnitTestRuntimeClasspath,releaseCompileClasspath,releaseRuntimeClasspath,releaseUnitTestCompileClasspath,releaseUnitTestRuntimeClasspath -com.facebook.soloader:nativeloader:0.12.1=debugAndroidTestCompileClasspath,debugCompileClasspath,debugRuntimeClasspath,debugUnitTestCompileClasspath,debugUnitTestRuntimeClasspath,releaseCompileClasspath,releaseRuntimeClasspath,releaseUnitTestCompileClasspath,releaseUnitTestRuntimeClasspath -com.facebook.soloader:soloader:0.12.1=debugAndroidTestCompileClasspath,debugCompileClasspath,debugRuntimeClasspath,debugUnitTestCompileClasspath,debugUnitTestRuntimeClasspath,releaseCompileClasspath,releaseRuntimeClasspath,releaseUnitTestCompileClasspath,releaseUnitTestRuntimeClasspath -com.facebook.yoga:proguard-annotations:1.19.0=debugAndroidTestCompileClasspath,debugCompileClasspath,debugRuntimeClasspath,debugUnitTestCompileClasspath,debugUnitTestRuntimeClasspath,releaseCompileClasspath,releaseRuntimeClasspath,releaseUnitTestCompileClasspath,releaseUnitTestRuntimeClasspath -com.github.bumptech.glide:annotations:4.12.0=debugRuntimeClasspath,debugUnitTestRuntimeClasspath,releaseRuntimeClasspath,releaseUnitTestRuntimeClasspath -com.github.bumptech.glide:disklrucache:4.12.0=debugRuntimeClasspath,debugUnitTestRuntimeClasspath,releaseRuntimeClasspath,releaseUnitTestRuntimeClasspath -com.github.bumptech.glide:gifdecoder:4.12.0=debugRuntimeClasspath,debugUnitTestRuntimeClasspath,releaseRuntimeClasspath,releaseUnitTestRuntimeClasspath -com.github.bumptech.glide:glide:4.12.0=debugRuntimeClasspath,debugUnitTestRuntimeClasspath,releaseRuntimeClasspath,releaseUnitTestRuntimeClasspath -com.github.stephenc.jcip:jcip-annotations:1.0-1=debugUnitTestRuntimeClasspath,releaseRuntimeClasspath,releaseUnitTestRuntimeClasspath -com.google.android.datatransport:transport-api:2.2.1=debugAndroidTestCompileClasspath -com.google.android.datatransport:transport-api:3.0.0=debugUnitTestCompileClasspath,debugUnitTestRuntimeClasspath,releaseCompileClasspath,releaseRuntimeClasspath,releaseUnitTestCompileClasspath,releaseUnitTestRuntimeClasspath +androidx.localbroadcastmanager:localbroadcastmanager:1.0.0=debugCompileClasspath,debugRuntimeClasspath +androidx.media3:media3-common:1.4.1=debugRuntimeClasspath +androidx.media3:media3-container:1.4.1=debugRuntimeClasspath +androidx.media3:media3-database:1.4.1=debugRuntimeClasspath +androidx.media3:media3-datasource-okhttp:1.4.1=debugRuntimeClasspath +androidx.media3:media3-datasource:1.4.1=debugRuntimeClasspath +androidx.media3:media3-decoder:1.4.1=debugRuntimeClasspath +androidx.media3:media3-exoplayer-dash:1.4.1=debugRuntimeClasspath +androidx.media3:media3-exoplayer-hls:1.4.1=debugRuntimeClasspath +androidx.media3:media3-exoplayer-smoothstreaming:1.4.1=debugRuntimeClasspath +androidx.media3:media3-exoplayer:1.4.1=debugRuntimeClasspath +androidx.media3:media3-extractor:1.4.1=debugRuntimeClasspath +androidx.media3:media3-session:1.4.1=debugRuntimeClasspath +androidx.media3:media3-ui:1.4.1=debugRuntimeClasspath +androidx.media:media:1.7.0=debugCompileClasspath,debugRuntimeClasspath +androidx.print:print:1.0.0=debugCompileClasspath,debugRuntimeClasspath +androidx.profileinstaller:profileinstaller:1.4.1=debugRuntimeClasspath +androidx.recyclerview:recyclerview:1.3.0=debugRuntimeClasspath +androidx.resourceinspection:resourceinspection-annotation:1.0.1=debugRuntimeClasspath +androidx.savedstate:savedstate-ktx:1.2.1=debugRuntimeClasspath +androidx.savedstate:savedstate:1.2.1=debugCompileClasspath,debugRuntimeClasspath +androidx.security:security-crypto:1.1.0-alpha03=debugRuntimeClasspath +androidx.slidingpanelayout:slidingpanelayout:1.0.0=debugCompileClasspath,debugRuntimeClasspath +androidx.startup:startup-runtime:1.1.1=debugRuntimeClasspath +androidx.swiperefreshlayout:swiperefreshlayout:1.1.0=debugCompileClasspath,debugRuntimeClasspath +androidx.tracing:tracing-ktx:1.2.0=debugRuntimeClasspath +androidx.tracing:tracing:1.2.0=debugCompileClasspath,debugRuntimeClasspath +androidx.transition:transition:1.5.0=debugRuntimeClasspath +androidx.vectordrawable:vectordrawable-animated:1.1.0=debugCompileClasspath,debugRuntimeClasspath +androidx.vectordrawable:vectordrawable:1.1.0=debugCompileClasspath,debugRuntimeClasspath +androidx.versionedparcelable:versionedparcelable:1.1.1=debugCompileClasspath,debugRuntimeClasspath +androidx.viewpager2:viewpager2:1.0.0=debugRuntimeClasspath +androidx.viewpager:viewpager:1.0.0=debugCompileClasspath,debugRuntimeClasspath +androidx.webkit:webkit:1.14.0=debugRuntimeClasspath +com.android.installreferrer:installreferrer:1.1.2=debugRuntimeClasspath +com.caverock:androidsvg-aar:1.4=debugRuntimeClasspath +com.facebook.fbjni:fbjni:0.7.0=debugCompileClasspath,debugRuntimeClasspath +com.facebook.fresco:drawee:3.6.0=debugCompileClasspath,debugRuntimeClasspath +com.facebook.fresco:fbcore:3.6.0=debugCompileClasspath,debugRuntimeClasspath +com.facebook.fresco:fresco:3.6.0=debugCompileClasspath,debugRuntimeClasspath +com.facebook.fresco:imagepipeline-base:3.6.0=debugCompileClasspath,debugRuntimeClasspath +com.facebook.fresco:imagepipeline-native:3.6.0=debugCompileClasspath,debugRuntimeClasspath +com.facebook.fresco:imagepipeline-okhttp3:3.6.0=debugCompileClasspath,debugRuntimeClasspath +com.facebook.fresco:imagepipeline:3.6.0=debugCompileClasspath,debugRuntimeClasspath +com.facebook.fresco:memory-type-ashmem:3.6.0=debugCompileClasspath,debugRuntimeClasspath +com.facebook.fresco:memory-type-java:3.6.0=debugCompileClasspath,debugRuntimeClasspath +com.facebook.fresco:memory-type-native:3.6.0=debugCompileClasspath,debugRuntimeClasspath +com.facebook.fresco:middleware:3.6.0=debugCompileClasspath,debugRuntimeClasspath +com.facebook.fresco:nativeimagefilters:3.6.0=debugCompileClasspath,debugRuntimeClasspath +com.facebook.fresco:nativeimagetranscoder:3.6.0=debugCompileClasspath,debugRuntimeClasspath +com.facebook.fresco:soloader:3.6.0=debugRuntimeClasspath +com.facebook.fresco:ui-common:3.6.0=debugCompileClasspath,debugRuntimeClasspath +com.facebook.fresco:ui-core:3.6.0=debugCompileClasspath,debugRuntimeClasspath +com.facebook.fresco:urimod:3.6.0=debugRuntimeClasspath +com.facebook.fresco:vito-source:3.6.0=debugRuntimeClasspath +com.facebook.infer.annotation:infer-annotation:0.18.0=debugCompileClasspath,debugRuntimeClasspath +com.facebook.react:hermes-android:0.81.5=debugCompileClasspath,debugRuntimeClasspath +com.facebook.react:react-android:0.81.5=debugCompileClasspath,debugRuntimeClasspath +com.facebook.soloader:annotation:0.12.1=debugCompileClasspath,debugRuntimeClasspath +com.facebook.soloader:nativeloader:0.12.1=debugCompileClasspath,debugRuntimeClasspath +com.facebook.soloader:soloader:0.12.1=debugCompileClasspath,debugRuntimeClasspath +com.facebook.yoga:proguard-annotations:1.19.0=debugCompileClasspath,debugRuntimeClasspath +com.github.bumptech.glide:annotations:4.12.0=debugRuntimeClasspath +com.github.bumptech.glide:disklrucache:4.12.0=debugRuntimeClasspath +com.github.bumptech.glide:gifdecoder:4.12.0=debugRuntimeClasspath +com.github.bumptech.glide:glide:4.12.0=debugRuntimeClasspath com.google.android.datatransport:transport-api:3.1.0=debugCompileClasspath,debugRuntimeClasspath -com.google.android.datatransport:transport-backend-cct:2.3.3=debugAndroidTestCompileClasspath -com.google.android.datatransport:transport-backend-cct:3.1.7=debugUnitTestCompileClasspath,debugUnitTestRuntimeClasspath,releaseCompileClasspath,releaseRuntimeClasspath,releaseUnitTestCompileClasspath,releaseUnitTestRuntimeClasspath com.google.android.datatransport:transport-backend-cct:3.1.9=debugCompileClasspath,debugRuntimeClasspath -com.google.android.datatransport:transport-runtime:2.2.6=debugAndroidTestCompileClasspath -com.google.android.datatransport:transport-runtime:3.1.7=debugUnitTestCompileClasspath,debugUnitTestRuntimeClasspath,releaseCompileClasspath,releaseRuntimeClasspath,releaseUnitTestCompileClasspath,releaseUnitTestRuntimeClasspath com.google.android.datatransport:transport-runtime:3.1.9=debugCompileClasspath,debugRuntimeClasspath -com.google.android.gms:play-services-auth-api-phone:18.0.1=debugUnitTestRuntimeClasspath,releaseRuntimeClasspath,releaseUnitTestRuntimeClasspath com.google.android.gms:play-services-auth-api-phone:18.0.2=debugRuntimeClasspath com.google.android.gms:play-services-auth-base:18.0.10=debugRuntimeClasspath -com.google.android.gms:play-services-auth-base:18.0.4=debugUnitTestRuntimeClasspath,releaseRuntimeClasspath,releaseUnitTestRuntimeClasspath -com.google.android.gms:play-services-auth:20.3.0=debugUnitTestRuntimeClasspath,releaseRuntimeClasspath,releaseUnitTestRuntimeClasspath com.google.android.gms:play-services-auth:21.3.0=debugRuntimeClasspath -com.google.android.gms:play-services-base:18.1.0=debugAndroidTestCompileClasspath -com.google.android.gms:play-services-base:18.5.0=debugCompileClasspath,debugRuntimeClasspath,debugUnitTestCompileClasspath,debugUnitTestRuntimeClasspath,releaseCompileClasspath,releaseRuntimeClasspath,releaseUnitTestCompileClasspath,releaseUnitTestRuntimeClasspath -com.google.android.gms:play-services-basement:18.1.0=debugAndroidTestCompileClasspath -com.google.android.gms:play-services-basement:18.4.0=debugCompileClasspath,debugRuntimeClasspath,debugUnitTestCompileClasspath,debugUnitTestRuntimeClasspath,releaseCompileClasspath,releaseRuntimeClasspath,releaseUnitTestCompileClasspath,releaseUnitTestRuntimeClasspath -com.google.android.gms:play-services-cloud-messaging:17.0.1=debugUnitTestRuntimeClasspath,releaseRuntimeClasspath,releaseUnitTestRuntimeClasspath +com.google.android.gms:play-services-base:18.5.0=debugCompileClasspath,debugRuntimeClasspath +com.google.android.gms:play-services-basement:18.4.0=debugCompileClasspath,debugRuntimeClasspath com.google.android.gms:play-services-cloud-messaging:17.2.0=debugRuntimeClasspath com.google.android.gms:play-services-fido:20.0.1=debugRuntimeClasspath -com.google.android.gms:play-services-iid:17.0.0=debugRuntimeClasspath,debugUnitTestRuntimeClasspath,releaseRuntimeClasspath,releaseUnitTestRuntimeClasspath -com.google.android.gms:play-services-mlkit-barcode-scanning:18.3.0=debugAndroidTestCompileClasspath -com.google.android.gms:play-services-mlkit-barcode-scanning:18.3.1=debugCompileClasspath,debugRuntimeClasspath,debugUnitTestCompileClasspath,debugUnitTestRuntimeClasspath,releaseCompileClasspath,releaseRuntimeClasspath,releaseUnitTestCompileClasspath,releaseUnitTestRuntimeClasspath -com.google.android.gms:play-services-stats:17.0.2=debugRuntimeClasspath,debugUnitTestRuntimeClasspath,releaseRuntimeClasspath,releaseUnitTestRuntimeClasspath -com.google.android.gms:play-services-tasks:18.0.2=debugAndroidTestCompileClasspath -com.google.android.gms:play-services-tasks:18.2.0=debugCompileClasspath,debugRuntimeClasspath,debugUnitTestCompileClasspath,debugUnitTestRuntimeClasspath,releaseCompileClasspath,releaseRuntimeClasspath,releaseUnitTestCompileClasspath,releaseUnitTestRuntimeClasspath -com.google.android.material:material:1.6.1=debugRuntimeClasspath,debugUnitTestRuntimeClasspath,releaseRuntimeClasspath,releaseUnitTestRuntimeClasspath -com.google.android.odml:image:1.0.0-beta1=debugAndroidTestCompileClasspath,debugCompileClasspath,debugRuntimeClasspath,debugUnitTestCompileClasspath,debugUnitTestRuntimeClasspath,releaseCompileClasspath,releaseRuntimeClasspath,releaseUnitTestCompileClasspath,releaseUnitTestRuntimeClasspath -com.google.android.play:integrity:1.2.0=debugRuntimeClasspath,debugUnitTestRuntimeClasspath,releaseRuntimeClasspath,releaseUnitTestRuntimeClasspath -com.google.android:annotations:4.1.1.4=_internal-unified-test-platform-android-test-plugin-host-emulator-control,_internal-unified-test-platform-android-test-plugin-host-retention,_internal-unified-test-platform-android-test-plugin-result-listener-gradle -com.google.api.grpc:proto-google-common-protos:2.17.0=_internal-unified-test-platform-android-test-plugin-host-emulator-control,_internal-unified-test-platform-android-test-plugin-host-retention,_internal-unified-test-platform-android-test-plugin-result-listener-gradle -com.google.auto.value:auto-value-annotations:1.6.3=debugRuntimeClasspath,debugUnitTestRuntimeClasspath,releaseRuntimeClasspath,releaseUnitTestRuntimeClasspath -com.google.code.findbugs:jsr305:3.0.2=_internal-unified-test-platform-android-device-provider-ddmlib,_internal-unified-test-platform-android-device-provider-gradle,_internal-unified-test-platform-android-test-plugin-host-additional-test-output,_internal-unified-test-platform-android-test-plugin-host-apk-installer,_internal-unified-test-platform-android-test-plugin-host-coverage,_internal-unified-test-platform-android-test-plugin-host-device-info,_internal-unified-test-platform-android-test-plugin-host-emulator-control,_internal-unified-test-platform-android-test-plugin-host-logcat,_internal-unified-test-platform-android-test-plugin-host-retention,_internal-unified-test-platform-android-test-plugin-result-listener-gradle,debugAndroidTestCompileClasspath,debugCompileClasspath,debugRuntimeClasspath,debugUnitTestCompileClasspath,debugUnitTestRuntimeClasspath,releaseCompileClasspath,releaseRuntimeClasspath,releaseUnitTestCompileClasspath,releaseUnitTestRuntimeClasspath -com.google.code.gson:gson:2.10.1=_internal-unified-test-platform-android-test-plugin-host-emulator-control,_internal-unified-test-platform-android-test-plugin-host-retention,_internal-unified-test-platform-android-test-plugin-result-listener-gradle,debugUnitTestRuntimeClasspath,releaseRuntimeClasspath,releaseUnitTestRuntimeClasspath -com.google.crypto.tink:tink-android:1.5.0=debugRuntimeClasspath,debugUnitTestRuntimeClasspath,releaseRuntimeClasspath,releaseUnitTestRuntimeClasspath -com.google.crypto.tink:tink:1.7.0=_internal-unified-test-platform-android-test-plugin-host-emulator-control -com.google.errorprone:error_prone_annotations:2.18.0=_internal-unified-test-platform-android-device-provider-ddmlib,_internal-unified-test-platform-android-device-provider-gradle,_internal-unified-test-platform-android-test-plugin-host-additional-test-output,_internal-unified-test-platform-android-test-plugin-host-apk-installer,_internal-unified-test-platform-android-test-plugin-host-coverage,_internal-unified-test-platform-android-test-plugin-host-device-info,_internal-unified-test-platform-android-test-plugin-host-emulator-control,_internal-unified-test-platform-android-test-plugin-host-logcat,_internal-unified-test-platform-android-test-plugin-host-retention,_internal-unified-test-platform-android-test-plugin-result-listener-gradle +com.google.android.gms:play-services-iid:17.0.0=debugRuntimeClasspath +com.google.android.gms:play-services-mlkit-barcode-scanning:18.3.1=debugCompileClasspath,debugRuntimeClasspath +com.google.android.gms:play-services-stats:17.0.2=debugRuntimeClasspath +com.google.android.gms:play-services-tasks:18.2.0=debugCompileClasspath,debugRuntimeClasspath +com.google.android.material:material:1.12.0=debugRuntimeClasspath +com.google.android.odml:image:1.0.0-beta1=debugCompileClasspath,debugRuntimeClasspath +com.google.android.play:core-common:2.0.4=debugRuntimeClasspath +com.google.android.play:integrity:1.4.0=debugRuntimeClasspath +com.google.auto.value:auto-value-annotations:1.6.3=debugRuntimeClasspath +com.google.code.findbugs:jsr305:3.0.2=debugCompileClasspath,debugRuntimeClasspath +com.google.crypto.tink:tink-android:1.5.0=debugRuntimeClasspath com.google.errorprone:error_prone_annotations:2.26.0=debugRuntimeClasspath -com.google.errorprone:error_prone_annotations:2.9.0=debugUnitTestCompileClasspath,debugUnitTestRuntimeClasspath,releaseCompileClasspath,releaseRuntimeClasspath,releaseUnitTestCompileClasspath,releaseUnitTestRuntimeClasspath -com.google.firebase:firebase-annotations:16.0.0=debugAndroidTestCompileClasspath -com.google.firebase:firebase-annotations:16.1.0=debugUnitTestCompileClasspath,debugUnitTestRuntimeClasspath,releaseCompileClasspath,releaseRuntimeClasspath,releaseUnitTestCompileClasspath,releaseUnitTestRuntimeClasspath com.google.firebase:firebase-annotations:16.2.0=debugCompileClasspath,debugRuntimeClasspath -com.google.firebase:firebase-bom:26.8.0=debugAndroidTestCompileClasspath -com.google.firebase:firebase-bom:30.5.0=debugUnitTestCompileClasspath,debugUnitTestRuntimeClasspath,releaseCompileClasspath,releaseRuntimeClasspath,releaseUnitTestCompileClasspath,releaseUnitTestRuntimeClasspath com.google.firebase:firebase-bom:33.12.0=debugCompileClasspath,debugRuntimeClasspath com.google.firebase:firebase-common-ktx:21.0.0=debugRuntimeClasspath -com.google.firebase:firebase-common:20.1.2=debugUnitTestRuntimeClasspath,releaseRuntimeClasspath,releaseUnitTestRuntimeClasspath com.google.firebase:firebase-common:21.0.0=debugRuntimeClasspath -com.google.firebase:firebase-components:16.1.0=debugAndroidTestCompileClasspath -com.google.firebase:firebase-components:17.0.1=debugUnitTestCompileClasspath,debugUnitTestRuntimeClasspath,releaseCompileClasspath,releaseRuntimeClasspath,releaseUnitTestCompileClasspath,releaseUnitTestRuntimeClasspath com.google.firebase:firebase-components:18.0.0=debugCompileClasspath,debugRuntimeClasspath -com.google.firebase:firebase-datatransport:18.1.6=debugUnitTestRuntimeClasspath,releaseRuntimeClasspath,releaseUnitTestRuntimeClasspath com.google.firebase:firebase-datatransport:18.2.0=debugRuntimeClasspath -com.google.firebase:firebase-encoders-json:17.1.0=debugAndroidTestCompileClasspath -com.google.firebase:firebase-encoders-json:18.0.0=debugCompileClasspath,debugRuntimeClasspath,debugUnitTestCompileClasspath,debugUnitTestRuntimeClasspath,releaseCompileClasspath,releaseRuntimeClasspath,releaseUnitTestCompileClasspath,releaseUnitTestRuntimeClasspath -com.google.firebase:firebase-encoders-proto:16.0.0=debugCompileClasspath,debugRuntimeClasspath,debugUnitTestCompileClasspath,debugUnitTestRuntimeClasspath,releaseCompileClasspath,releaseRuntimeClasspath,releaseUnitTestCompileClasspath,releaseUnitTestRuntimeClasspath -com.google.firebase:firebase-encoders:16.1.0=debugAndroidTestCompileClasspath -com.google.firebase:firebase-encoders:17.0.0=debugCompileClasspath,debugRuntimeClasspath,debugUnitTestCompileClasspath,debugUnitTestRuntimeClasspath,releaseCompileClasspath,releaseRuntimeClasspath,releaseUnitTestCompileClasspath,releaseUnitTestRuntimeClasspath -com.google.firebase:firebase-iid-interop:17.1.0=debugRuntimeClasspath,debugUnitTestRuntimeClasspath,releaseRuntimeClasspath,releaseUnitTestRuntimeClasspath -com.google.firebase:firebase-installations-interop:17.0.2=debugUnitTestRuntimeClasspath,releaseRuntimeClasspath,releaseUnitTestRuntimeClasspath +com.google.firebase:firebase-encoders-json:18.0.0=debugCompileClasspath,debugRuntimeClasspath +com.google.firebase:firebase-encoders-proto:16.0.0=debugCompileClasspath,debugRuntimeClasspath +com.google.firebase:firebase-encoders:17.0.0=debugCompileClasspath,debugRuntimeClasspath +com.google.firebase:firebase-iid-interop:17.1.0=debugRuntimeClasspath com.google.firebase:firebase-installations-interop:17.1.1=debugRuntimeClasspath -com.google.firebase:firebase-installations:17.0.3=debugUnitTestRuntimeClasspath,releaseRuntimeClasspath,releaseUnitTestRuntimeClasspath com.google.firebase:firebase-installations:18.0.0=debugRuntimeClasspath -com.google.firebase:firebase-measurement-connector:19.0.0=debugRuntimeClasspath,debugUnitTestRuntimeClasspath,releaseRuntimeClasspath,releaseUnitTestRuntimeClasspath -com.google.firebase:firebase-messaging:23.0.8=debugUnitTestRuntimeClasspath,releaseRuntimeClasspath,releaseUnitTestRuntimeClasspath +com.google.firebase:firebase-measurement-connector:19.0.0=debugRuntimeClasspath com.google.firebase:firebase-messaging:24.1.1=debugRuntimeClasspath -com.google.guava:failureaccess:1.0.1=_internal-unified-test-platform-android-device-provider-ddmlib,_internal-unified-test-platform-android-device-provider-gradle,_internal-unified-test-platform-android-test-plugin-host-additional-test-output,_internal-unified-test-platform-android-test-plugin-host-apk-installer,_internal-unified-test-platform-android-test-plugin-host-coverage,_internal-unified-test-platform-android-test-plugin-host-device-info,_internal-unified-test-platform-android-test-plugin-host-emulator-control,_internal-unified-test-platform-android-test-plugin-host-logcat,_internal-unified-test-platform-android-test-plugin-host-retention,_internal-unified-test-platform-android-test-plugin-result-listener-gradle -com.google.guava:failureaccess:1.0.2=debugRuntimeClasspath,debugUnitTestRuntimeClasspath,releaseRuntimeClasspath,releaseUnitTestRuntimeClasspath -com.google.guava:guava:32.0.1-jre=_internal-unified-test-platform-android-device-provider-ddmlib,_internal-unified-test-platform-android-device-provider-gradle,_internal-unified-test-platform-android-test-plugin-host-additional-test-output,_internal-unified-test-platform-android-test-plugin-host-apk-installer,_internal-unified-test-platform-android-test-plugin-host-coverage,_internal-unified-test-platform-android-test-plugin-host-device-info,_internal-unified-test-platform-android-test-plugin-host-emulator-control,_internal-unified-test-platform-android-test-plugin-host-logcat,_internal-unified-test-platform-android-test-plugin-host-retention,_internal-unified-test-platform-android-test-plugin-result-listener-gradle -com.google.guava:guava:33.0.0-android=debugRuntimeClasspath,debugUnitTestRuntimeClasspath,releaseRuntimeClasspath,releaseUnitTestRuntimeClasspath -com.google.guava:listenablefuture:9999.0-empty-to-avoid-conflict-with-guava=_internal-unified-test-platform-android-device-provider-ddmlib,_internal-unified-test-platform-android-device-provider-gradle,_internal-unified-test-platform-android-test-plugin-host-additional-test-output,_internal-unified-test-platform-android-test-plugin-host-apk-installer,_internal-unified-test-platform-android-test-plugin-host-coverage,_internal-unified-test-platform-android-test-plugin-host-device-info,_internal-unified-test-platform-android-test-plugin-host-emulator-control,_internal-unified-test-platform-android-test-plugin-host-logcat,_internal-unified-test-platform-android-test-plugin-host-retention,_internal-unified-test-platform-android-test-plugin-result-listener-gradle,debugRuntimeClasspath,debugUnitTestRuntimeClasspath,releaseRuntimeClasspath,releaseUnitTestRuntimeClasspath -com.google.j2objc:j2objc-annotations:2.8=_internal-unified-test-platform-android-device-provider-ddmlib,_internal-unified-test-platform-android-device-provider-gradle,_internal-unified-test-platform-android-test-plugin-host-additional-test-output,_internal-unified-test-platform-android-test-plugin-host-apk-installer,_internal-unified-test-platform-android-test-plugin-host-coverage,_internal-unified-test-platform-android-test-plugin-host-device-info,_internal-unified-test-platform-android-test-plugin-host-emulator-control,_internal-unified-test-platform-android-test-plugin-host-logcat,_internal-unified-test-platform-android-test-plugin-host-retention,_internal-unified-test-platform-android-test-plugin-result-listener-gradle -com.google.mlkit:barcode-scanning-common:17.0.0=debugAndroidTestCompileClasspath,debugCompileClasspath,debugRuntimeClasspath,debugUnitTestCompileClasspath,debugUnitTestRuntimeClasspath,releaseCompileClasspath,releaseRuntimeClasspath,releaseUnitTestCompileClasspath,releaseUnitTestRuntimeClasspath -com.google.mlkit:barcode-scanning:17.2.0=debugAndroidTestCompileClasspath,debugCompileClasspath,debugRuntimeClasspath,debugUnitTestCompileClasspath,debugUnitTestRuntimeClasspath,releaseCompileClasspath,releaseRuntimeClasspath,releaseUnitTestCompileClasspath,releaseUnitTestRuntimeClasspath -com.google.mlkit:common:18.11.0=debugCompileClasspath,debugRuntimeClasspath,debugUnitTestCompileClasspath,debugUnitTestRuntimeClasspath,releaseCompileClasspath,releaseRuntimeClasspath,releaseUnitTestCompileClasspath,releaseUnitTestRuntimeClasspath -com.google.mlkit:common:18.9.0=debugAndroidTestCompileClasspath -com.google.mlkit:vision-common:17.3.0=debugAndroidTestCompileClasspath,debugCompileClasspath,debugRuntimeClasspath,debugUnitTestCompileClasspath,debugUnitTestRuntimeClasspath,releaseCompileClasspath,releaseRuntimeClasspath,releaseUnitTestCompileClasspath,releaseUnitTestRuntimeClasspath -com.google.mlkit:vision-interfaces:16.2.0=debugAndroidTestCompileClasspath -com.google.mlkit:vision-interfaces:16.3.0=debugCompileClasspath,debugRuntimeClasspath,debugUnitTestCompileClasspath,debugUnitTestRuntimeClasspath,releaseCompileClasspath,releaseRuntimeClasspath,releaseUnitTestCompileClasspath,releaseUnitTestRuntimeClasspath -com.google.protobuf:protobuf-java:3.22.3=_internal-unified-test-platform-android-device-provider-ddmlib,_internal-unified-test-platform-android-device-provider-gradle,_internal-unified-test-platform-android-test-plugin-host-additional-test-output,_internal-unified-test-platform-android-test-plugin-host-apk-installer,_internal-unified-test-platform-android-test-plugin-host-coverage,_internal-unified-test-platform-android-test-plugin-host-device-info,_internal-unified-test-platform-android-test-plugin-host-emulator-control,_internal-unified-test-platform-android-test-plugin-host-logcat,_internal-unified-test-platform-android-test-plugin-host-retention,_internal-unified-test-platform-android-test-plugin-result-listener-gradle -com.google.testing.platform:android-device-provider-local:0.0.9-alpha02=_internal-unified-test-platform-android-device-provider-ddmlib,_internal-unified-test-platform-android-device-provider-gradle,_internal-unified-test-platform-android-test-plugin-host-additional-test-output,_internal-unified-test-platform-android-test-plugin-host-apk-installer,_internal-unified-test-platform-android-test-plugin-host-coverage,_internal-unified-test-platform-android-test-plugin-host-device-info,_internal-unified-test-platform-android-test-plugin-host-emulator-control,_internal-unified-test-platform-android-test-plugin-host-logcat,_internal-unified-test-platform-android-test-plugin-host-retention,_internal-unified-test-platform-android-test-plugin-result-listener-gradle -com.google.testing.platform:android-driver-instrumentation:0.0.9-alpha02=_internal-unified-test-platform-android-driver-instrumentation,_internal-unified-test-platform-android-test-plugin-host-emulator-control -com.google.testing.platform:android-test-plugin:0.0.9-alpha02=_internal-unified-test-platform-android-test-plugin -com.google.testing.platform:core-proto:0.0.9-alpha02=_internal-unified-test-platform-android-device-provider-ddmlib,_internal-unified-test-platform-android-device-provider-gradle,_internal-unified-test-platform-android-test-plugin-host-apk-installer,_internal-unified-test-platform-android-test-plugin-result-listener-gradle -com.google.testing.platform:core:0.0.9-alpha02=_internal-unified-test-platform-core -com.google.testing.platform:launcher:0.0.9-alpha02=_internal-unified-test-platform-android-test-plugin-host-additional-test-output,_internal-unified-test-platform-android-test-plugin-host-device-info,_internal-unified-test-platform-android-test-plugin-host-logcat,_internal-unified-test-platform-android-test-plugin-host-retention,_internal-unified-test-platform-launcher -com.lambdapioneer.argon2kt:argon2kt:1.3.0=debugRuntimeClasspath,debugUnitTestRuntimeClasspath,releaseRuntimeClasspath,releaseUnitTestRuntimeClasspath -com.nimbusds:nimbus-jose-jwt:9.37.3=debugUnitTestRuntimeClasspath,releaseRuntimeClasspath,releaseUnitTestRuntimeClasspath -com.parse.bolts:bolts-tasks:1.4.0=debugRuntimeClasspath,debugUnitTestRuntimeClasspath,releaseRuntimeClasspath,releaseUnitTestRuntimeClasspath -com.squareup.okhttp3:okhttp-urlconnection:4.9.2=debugAndroidTestCompileClasspath,debugCompileClasspath,debugRuntimeClasspath,debugUnitTestCompileClasspath,debugUnitTestRuntimeClasspath,releaseCompileClasspath,releaseRuntimeClasspath,releaseUnitTestCompileClasspath,releaseUnitTestRuntimeClasspath -com.squareup.okhttp3:okhttp:4.12.0=debugCompileClasspath,debugRuntimeClasspath,debugUnitTestCompileClasspath,debugUnitTestRuntimeClasspath,releaseCompileClasspath,releaseRuntimeClasspath,releaseUnitTestCompileClasspath,releaseUnitTestRuntimeClasspath -com.squareup.okhttp3:okhttp:4.9.2=debugAndroidTestCompileClasspath -com.squareup.okio:okio-jvm:3.6.0=debugCompileClasspath,debugRuntimeClasspath,debugUnitTestCompileClasspath,debugUnitTestRuntimeClasspath,releaseCompileClasspath,releaseRuntimeClasspath,releaseUnitTestCompileClasspath,releaseUnitTestRuntimeClasspath -com.squareup.okio:okio:2.9.0=debugAndroidTestCompileClasspath -com.squareup.okio:okio:3.6.0=debugCompileClasspath,debugRuntimeClasspath,debugUnitTestCompileClasspath,debugUnitTestRuntimeClasspath,releaseCompileClasspath,releaseRuntimeClasspath,releaseUnitTestCompileClasspath,releaseUnitTestRuntimeClasspath -commons-io:commons-io:2.13.0=_internal-unified-test-platform-android-test-plugin-host-emulator-control,_internal-unified-test-platform-android-test-plugin-host-retention -io.grpc:grpc-api:1.57.0=_internal-unified-test-platform-android-test-plugin-host-emulator-control,_internal-unified-test-platform-android-test-plugin-host-retention,_internal-unified-test-platform-android-test-plugin-result-listener-gradle -io.grpc:grpc-context:1.57.0=_internal-unified-test-platform-android-test-plugin-host-emulator-control,_internal-unified-test-platform-android-test-plugin-host-retention,_internal-unified-test-platform-android-test-plugin-result-listener-gradle -io.grpc:grpc-core:1.57.0=_internal-unified-test-platform-android-test-plugin-host-emulator-control,_internal-unified-test-platform-android-test-plugin-host-retention,_internal-unified-test-platform-android-test-plugin-result-listener-gradle -io.grpc:grpc-netty:1.57.0=_internal-unified-test-platform-android-test-plugin-host-emulator-control,_internal-unified-test-platform-android-test-plugin-host-retention,_internal-unified-test-platform-android-test-plugin-result-listener-gradle -io.grpc:grpc-protobuf-lite:1.57.0=_internal-unified-test-platform-android-test-plugin-host-emulator-control,_internal-unified-test-platform-android-test-plugin-host-retention,_internal-unified-test-platform-android-test-plugin-result-listener-gradle -io.grpc:grpc-protobuf:1.57.0=_internal-unified-test-platform-android-test-plugin-host-emulator-control,_internal-unified-test-platform-android-test-plugin-host-retention,_internal-unified-test-platform-android-test-plugin-result-listener-gradle -io.grpc:grpc-stub:1.57.0=_internal-unified-test-platform-android-test-plugin-host-emulator-control,_internal-unified-test-platform-android-test-plugin-host-retention,_internal-unified-test-platform-android-test-plugin-result-listener-gradle -io.netty:netty-buffer:4.1.93.Final=_internal-unified-test-platform-android-test-plugin-host-emulator-control,_internal-unified-test-platform-android-test-plugin-host-retention,_internal-unified-test-platform-android-test-plugin-result-listener-gradle -io.netty:netty-codec-http2:4.1.93.Final=_internal-unified-test-platform-android-test-plugin-host-emulator-control,_internal-unified-test-platform-android-test-plugin-host-retention,_internal-unified-test-platform-android-test-plugin-result-listener-gradle -io.netty:netty-codec-http:4.1.93.Final=_internal-unified-test-platform-android-test-plugin-host-emulator-control,_internal-unified-test-platform-android-test-plugin-host-retention,_internal-unified-test-platform-android-test-plugin-result-listener-gradle -io.netty:netty-codec-socks:4.1.93.Final=_internal-unified-test-platform-android-test-plugin-host-emulator-control,_internal-unified-test-platform-android-test-plugin-host-retention,_internal-unified-test-platform-android-test-plugin-result-listener-gradle -io.netty:netty-codec:4.1.93.Final=_internal-unified-test-platform-android-test-plugin-host-emulator-control,_internal-unified-test-platform-android-test-plugin-host-retention,_internal-unified-test-platform-android-test-plugin-result-listener-gradle -io.netty:netty-common:4.1.93.Final=_internal-unified-test-platform-android-test-plugin-host-emulator-control,_internal-unified-test-platform-android-test-plugin-host-retention,_internal-unified-test-platform-android-test-plugin-result-listener-gradle -io.netty:netty-handler-proxy:4.1.93.Final=_internal-unified-test-platform-android-test-plugin-host-emulator-control,_internal-unified-test-platform-android-test-plugin-host-retention,_internal-unified-test-platform-android-test-plugin-result-listener-gradle -io.netty:netty-handler:4.1.93.Final=_internal-unified-test-platform-android-test-plugin-host-emulator-control,_internal-unified-test-platform-android-test-plugin-host-retention,_internal-unified-test-platform-android-test-plugin-result-listener-gradle -io.netty:netty-resolver:4.1.93.Final=_internal-unified-test-platform-android-test-plugin-host-emulator-control,_internal-unified-test-platform-android-test-plugin-host-retention,_internal-unified-test-platform-android-test-plugin-result-listener-gradle -io.netty:netty-transport-native-unix-common:4.1.93.Final=_internal-unified-test-platform-android-test-plugin-host-emulator-control,_internal-unified-test-platform-android-test-plugin-host-retention,_internal-unified-test-platform-android-test-plugin-result-listener-gradle -io.netty:netty-transport:4.1.93.Final=_internal-unified-test-platform-android-test-plugin-host-emulator-control,_internal-unified-test-platform-android-test-plugin-host-retention,_internal-unified-test-platform-android-test-plugin-result-listener-gradle -io.perfmark:perfmark-api:0.26.0=_internal-unified-test-platform-android-test-plugin-host-emulator-control,_internal-unified-test-platform-android-test-plugin-host-retention,_internal-unified-test-platform-android-test-plugin-result-listener-gradle -io.reactivex.rxjava2:rxandroid:2.1.1=debugAndroidTestCompileClasspath,debugCompileClasspath,debugRuntimeClasspath,debugUnitTestCompileClasspath,debugUnitTestRuntimeClasspath,releaseCompileClasspath,releaseRuntimeClasspath,releaseUnitTestCompileClasspath,releaseUnitTestRuntimeClasspath -io.reactivex.rxjava2:rxjava:2.2.21=debugAndroidTestCompileClasspath,debugCompileClasspath,debugRuntimeClasspath,debugUnitTestCompileClasspath,debugUnitTestRuntimeClasspath,releaseCompileClasspath,releaseRuntimeClasspath,releaseUnitTestCompileClasspath,releaseUnitTestRuntimeClasspath -javax.annotation:javax.annotation-api:1.3.2=_internal-unified-test-platform-android-test-plugin-host-emulator-control,_internal-unified-test-platform-android-test-plugin-host-retention,_internal-unified-test-platform-android-test-plugin-result-listener-gradle -javax.inject:javax.inject:1=debugAndroidTestCompileClasspath,debugCompileClasspath,debugRuntimeClasspath,debugUnitTestCompileClasspath,debugUnitTestRuntimeClasspath,releaseCompileClasspath,releaseRuntimeClasspath,releaseUnitTestCompileClasspath,releaseUnitTestRuntimeClasspath -jp.wasabeef:blurry:4.0.1=debugRuntimeClasspath,debugUnitTestRuntimeClasspath,releaseRuntimeClasspath,releaseUnitTestRuntimeClasspath -net.java.dev.jna:jna-platform:5.6.0=_internal-unified-test-platform-android-device-provider-ddmlib,_internal-unified-test-platform-android-device-provider-gradle,_internal-unified-test-platform-android-test-plugin-host-additional-test-output,_internal-unified-test-platform-android-test-plugin-host-apk-installer,_internal-unified-test-platform-android-test-plugin-host-coverage,_internal-unified-test-platform-android-test-plugin-host-device-info,_internal-unified-test-platform-android-test-plugin-host-emulator-control,_internal-unified-test-platform-android-test-plugin-host-logcat,_internal-unified-test-platform-android-test-plugin-host-retention,_internal-unified-test-platform-android-test-plugin-result-listener-gradle -net.java.dev.jna:jna:5.14.0=debugAndroidTestCompileClasspath,debugCompileClasspath,debugRuntimeClasspath,debugUnitTestCompileClasspath,debugUnitTestRuntimeClasspath,releaseCompileClasspath,releaseRuntimeClasspath,releaseUnitTestCompileClasspath,releaseUnitTestRuntimeClasspath -net.java.dev.jna:jna:5.6.0=_internal-unified-test-platform-android-device-provider-ddmlib,_internal-unified-test-platform-android-device-provider-gradle,_internal-unified-test-platform-android-test-plugin-host-additional-test-output,_internal-unified-test-platform-android-test-plugin-host-apk-installer,_internal-unified-test-platform-android-test-plugin-host-coverage,_internal-unified-test-platform-android-test-plugin-host-device-info,_internal-unified-test-platform-android-test-plugin-host-emulator-control,_internal-unified-test-platform-android-test-plugin-host-logcat,_internal-unified-test-platform-android-test-plugin-host-retention,_internal-unified-test-platform-android-test-plugin-result-listener-gradle -net.sf.kxml:kxml2:2.3.0=_internal-unified-test-platform-android-device-provider-ddmlib -net.time4j:time4j-android:4.8-2021a=debugRuntimeClasspath,debugUnitTestRuntimeClasspath,releaseRuntimeClasspath,releaseUnitTestRuntimeClasspath -org.apache.commons:commons-lang3:3.11=debugAndroidTestCompileClasspath,debugCompileClasspath,debugRuntimeClasspath,debugUnitTestCompileClasspath,debugUnitTestRuntimeClasspath,releaseCompileClasspath,releaseRuntimeClasspath,releaseUnitTestCompileClasspath,releaseUnitTestRuntimeClasspath -org.checkerframework:checker-qual:3.33.0=_internal-unified-test-platform-android-device-provider-ddmlib,_internal-unified-test-platform-android-device-provider-gradle,_internal-unified-test-platform-android-test-plugin-host-additional-test-output,_internal-unified-test-platform-android-test-plugin-host-apk-installer,_internal-unified-test-platform-android-test-plugin-host-coverage,_internal-unified-test-platform-android-test-plugin-host-device-info,_internal-unified-test-platform-android-test-plugin-host-emulator-control,_internal-unified-test-platform-android-test-plugin-host-logcat,_internal-unified-test-platform-android-test-plugin-host-retention,_internal-unified-test-platform-android-test-plugin-result-listener-gradle -org.codehaus.mojo:animal-sniffer-annotations:1.23=_internal-unified-test-platform-android-test-plugin-host-emulator-control,_internal-unified-test-platform-android-test-plugin-host-retention,_internal-unified-test-platform-android-test-plugin-result-listener-gradle -org.greenrobot:eventbus:3.1.0=debugRuntimeClasspath,debugUnitTestRuntimeClasspath,releaseRuntimeClasspath,releaseUnitTestRuntimeClasspath -org.jacoco:org.jacoco.agent:0.8.8=androidJacocoAnt -org.jacoco:org.jacoco.ant:0.8.8=androidJacocoAnt -org.jacoco:org.jacoco.core:0.8.8=androidJacocoAnt -org.jacoco:org.jacoco.report:0.8.8=androidJacocoAnt -org.jetbrains.intellij.deps:trove4j:1.0.20200330=kotlinBuildToolsApiClasspath,kotlinCompilerClasspath,kotlinKlibCommonizerClasspath -org.jetbrains.kotlin:kotlin-annotations-jvm:1.3.72=debugAndroidTestCompileClasspath,debugCompileClasspath,debugRuntimeClasspath,debugUnitTestCompileClasspath,debugUnitTestRuntimeClasspath,releaseCompileClasspath,releaseRuntimeClasspath,releaseUnitTestCompileClasspath,releaseUnitTestRuntimeClasspath -org.jetbrains.kotlin:kotlin-build-common:2.0.21=kotlinBuildToolsApiClasspath -org.jetbrains.kotlin:kotlin-build-tools-api:2.0.21=kotlinBuildToolsApiClasspath -org.jetbrains.kotlin:kotlin-build-tools-impl:2.0.21=kotlinBuildToolsApiClasspath -org.jetbrains.kotlin:kotlin-compiler-embeddable:2.0.21=kotlinBuildToolsApiClasspath,kotlinCompilerClasspath,kotlinKlibCommonizerClasspath -org.jetbrains.kotlin:kotlin-compiler-runner:2.0.21=kotlinBuildToolsApiClasspath -org.jetbrains.kotlin:kotlin-daemon-client:2.0.21=kotlinBuildToolsApiClasspath -org.jetbrains.kotlin:kotlin-daemon-embeddable:2.0.21=kotlinBuildToolsApiClasspath,kotlinCompilerClasspath,kotlinKlibCommonizerClasspath -org.jetbrains.kotlin:kotlin-klib-commonizer-embeddable:2.0.21=kotlinKlibCommonizerClasspath -org.jetbrains.kotlin:kotlin-native-prebuilt:2.0.21=kotlinNativeBundleConfiguration -org.jetbrains.kotlin:kotlin-reflect:1.6.10=kotlinBuildToolsApiClasspath,kotlinCompilerClasspath,kotlinKlibCommonizerClasspath -org.jetbrains.kotlin:kotlin-script-runtime:2.0.21=kotlinBuildToolsApiClasspath,kotlinCompilerClasspath,kotlinKlibCommonizerClasspath -org.jetbrains.kotlin:kotlin-scripting-common:2.0.21=kotlinBuildToolsApiClasspath -org.jetbrains.kotlin:kotlin-scripting-compiler-embeddable:2.0.21=kotlinBuildToolsApiClasspath -org.jetbrains.kotlin:kotlin-scripting-compiler-impl-embeddable:2.0.21=kotlinBuildToolsApiClasspath -org.jetbrains.kotlin:kotlin-scripting-jvm:2.0.21=kotlinBuildToolsApiClasspath -org.jetbrains.kotlin:kotlin-stdlib-common:2.0.21=_internal-unified-test-platform-android-device-provider-ddmlib,_internal-unified-test-platform-android-test-plugin-host-emulator-control,_internal-unified-test-platform-android-test-plugin-host-retention,_internal-unified-test-platform-android-test-plugin-result-listener-gradle,debugAndroidTestCompileClasspath,debugCompileClasspath,debugRuntimeClasspath,debugUnitTestCompileClasspath,debugUnitTestRuntimeClasspath,releaseCompileClasspath,releaseRuntimeClasspath,releaseUnitTestCompileClasspath,releaseUnitTestRuntimeClasspath -org.jetbrains.kotlin:kotlin-stdlib-jdk7:2.0.21=_internal-unified-test-platform-android-device-provider-ddmlib,_internal-unified-test-platform-android-device-provider-gradle,_internal-unified-test-platform-android-test-plugin-host-additional-test-output,_internal-unified-test-platform-android-test-plugin-host-apk-installer,_internal-unified-test-platform-android-test-plugin-host-coverage,_internal-unified-test-platform-android-test-plugin-host-device-info,_internal-unified-test-platform-android-test-plugin-host-emulator-control,_internal-unified-test-platform-android-test-plugin-host-logcat,_internal-unified-test-platform-android-test-plugin-host-retention,_internal-unified-test-platform-android-test-plugin-result-listener-gradle,debugAndroidTestCompileClasspath,debugCompileClasspath,debugRuntimeClasspath,debugUnitTestCompileClasspath,debugUnitTestRuntimeClasspath,releaseCompileClasspath,releaseRuntimeClasspath,releaseUnitTestCompileClasspath,releaseUnitTestRuntimeClasspath -org.jetbrains.kotlin:kotlin-stdlib-jdk8:2.0.21=_internal-unified-test-platform-android-device-provider-ddmlib,_internal-unified-test-platform-android-device-provider-gradle,_internal-unified-test-platform-android-test-plugin-host-additional-test-output,_internal-unified-test-platform-android-test-plugin-host-apk-installer,_internal-unified-test-platform-android-test-plugin-host-coverage,_internal-unified-test-platform-android-test-plugin-host-device-info,_internal-unified-test-platform-android-test-plugin-host-emulator-control,_internal-unified-test-platform-android-test-plugin-host-logcat,_internal-unified-test-platform-android-test-plugin-host-retention,_internal-unified-test-platform-android-test-plugin-result-listener-gradle,debugAndroidTestCompileClasspath,debugCompileClasspath,debugRuntimeClasspath,debugUnitTestCompileClasspath,debugUnitTestRuntimeClasspath,releaseCompileClasspath,releaseRuntimeClasspath,releaseUnitTestCompileClasspath,releaseUnitTestRuntimeClasspath -org.jetbrains.kotlin:kotlin-stdlib:2.0.21=_internal-unified-test-platform-android-device-provider-ddmlib,_internal-unified-test-platform-android-device-provider-gradle,_internal-unified-test-platform-android-test-plugin-host-additional-test-output,_internal-unified-test-platform-android-test-plugin-host-apk-installer,_internal-unified-test-platform-android-test-plugin-host-coverage,_internal-unified-test-platform-android-test-plugin-host-device-info,_internal-unified-test-platform-android-test-plugin-host-emulator-control,_internal-unified-test-platform-android-test-plugin-host-logcat,_internal-unified-test-platform-android-test-plugin-host-retention,_internal-unified-test-platform-android-test-plugin-result-listener-gradle,debugAndroidTestCompileClasspath,debugCompileClasspath,debugRuntimeClasspath,debugUnitTestCompileClasspath,debugUnitTestRuntimeClasspath,kotlinBuildToolsApiClasspath,kotlinCompilerClasspath,kotlinKlibCommonizerClasspath,releaseCompileClasspath,releaseRuntimeClasspath,releaseUnitTestCompileClasspath,releaseUnitTestRuntimeClasspath -org.jetbrains.kotlinx:kotlinx-coroutines-android:1.6.1=debugAndroidTestCompileClasspath -org.jetbrains.kotlinx:kotlinx-coroutines-android:1.9.0=debugCompileClasspath,debugRuntimeClasspath,debugUnitTestCompileClasspath,debugUnitTestRuntimeClasspath,releaseCompileClasspath,releaseRuntimeClasspath,releaseUnitTestCompileClasspath,releaseUnitTestRuntimeClasspath -org.jetbrains.kotlinx:kotlinx-coroutines-bom:1.6.1=debugAndroidTestCompileClasspath -org.jetbrains.kotlinx:kotlinx-coroutines-bom:1.6.4=_internal-unified-test-platform-android-device-provider-ddmlib,_internal-unified-test-platform-android-test-plugin-host-emulator-control,_internal-unified-test-platform-android-test-plugin-host-retention,_internal-unified-test-platform-android-test-plugin-result-listener-gradle -org.jetbrains.kotlinx:kotlinx-coroutines-bom:1.9.0=debugCompileClasspath,debugRuntimeClasspath,debugUnitTestCompileClasspath,debugUnitTestRuntimeClasspath,releaseCompileClasspath,releaseRuntimeClasspath,releaseUnitTestCompileClasspath,releaseUnitTestRuntimeClasspath -org.jetbrains.kotlinx:kotlinx-coroutines-core-jvm:1.6.1=debugAndroidTestCompileClasspath -org.jetbrains.kotlinx:kotlinx-coroutines-core-jvm:1.6.4=_internal-unified-test-platform-android-device-provider-ddmlib,_internal-unified-test-platform-android-test-plugin-host-emulator-control,_internal-unified-test-platform-android-test-plugin-host-retention,_internal-unified-test-platform-android-test-plugin-result-listener-gradle,kotlinBuildToolsApiClasspath,kotlinCompilerClasspath,kotlinKlibCommonizerClasspath -org.jetbrains.kotlinx:kotlinx-coroutines-core-jvm:1.9.0=debugCompileClasspath,debugRuntimeClasspath,debugUnitTestCompileClasspath,debugUnitTestRuntimeClasspath,releaseCompileClasspath,releaseRuntimeClasspath,releaseUnitTestCompileClasspath,releaseUnitTestRuntimeClasspath -org.jetbrains.kotlinx:kotlinx-coroutines-core:1.6.1=debugAndroidTestCompileClasspath -org.jetbrains.kotlinx:kotlinx-coroutines-core:1.6.4=_internal-unified-test-platform-android-device-provider-ddmlib,_internal-unified-test-platform-android-test-plugin-host-emulator-control,_internal-unified-test-platform-android-test-plugin-host-retention,_internal-unified-test-platform-android-test-plugin-result-listener-gradle -org.jetbrains.kotlinx:kotlinx-coroutines-core:1.9.0=debugCompileClasspath,debugRuntimeClasspath,debugUnitTestCompileClasspath,debugUnitTestRuntimeClasspath,releaseCompileClasspath,releaseRuntimeClasspath,releaseUnitTestCompileClasspath,releaseUnitTestRuntimeClasspath +com.google.guava:failureaccess:1.0.2=debugRuntimeClasspath +com.google.guava:guava:33.0.0-android=debugRuntimeClasspath +com.google.guava:listenablefuture:9999.0-empty-to-avoid-conflict-with-guava=debugRuntimeClasspath +com.google.mlkit:barcode-scanning-common:17.0.0=debugCompileClasspath,debugRuntimeClasspath +com.google.mlkit:barcode-scanning:17.2.0=debugCompileClasspath,debugRuntimeClasspath +com.google.mlkit:common:18.11.0=debugCompileClasspath,debugRuntimeClasspath +com.google.mlkit:vision-common:17.3.0=debugCompileClasspath,debugRuntimeClasspath +com.google.mlkit:vision-interfaces:16.3.0=debugCompileClasspath,debugRuntimeClasspath +com.google.prefab:cli:2.1.0=_internal_prefab_binary +com.lambdapioneer.argon2kt:argon2kt:1.3.0=debugRuntimeClasspath +com.parse.bolts:bolts-tasks:1.4.0=debugRuntimeClasspath +com.squareup.okhttp3:okhttp-urlconnection:4.9.2=debugCompileClasspath,debugRuntimeClasspath +com.squareup.okhttp3:okhttp:4.12.0=debugCompileClasspath,debugRuntimeClasspath +com.squareup.okio:okio-jvm:3.9.1=debugCompileClasspath,debugRuntimeClasspath +com.squareup.okio:okio:3.9.1=debugCompileClasspath,debugRuntimeClasspath +commons-codec:commons-codec:1.10=debugCompileClasspath,debugRuntimeClasspath +commons-io:commons-io:2.6=debugCompileClasspath,debugRuntimeClasspath +io.coil-kt.coil3:coil-android:3.0.4=debugRuntimeClasspath +io.coil-kt.coil3:coil-core-android:3.0.4=debugRuntimeClasspath +io.coil-kt.coil3:coil-core:3.0.4=debugRuntimeClasspath +io.coil-kt.coil3:coil-network-core-android:3.0.4=debugRuntimeClasspath +io.coil-kt.coil3:coil-network-core:3.0.4=debugRuntimeClasspath +io.coil-kt.coil3:coil-network-okhttp-jvm:3.0.4=debugRuntimeClasspath +io.coil-kt.coil3:coil-network-okhttp:3.0.4=debugRuntimeClasspath +io.coil-kt.coil3:coil-svg-android:3.0.4=debugRuntimeClasspath +io.coil-kt.coil3:coil-svg:3.0.4=debugRuntimeClasspath +io.coil-kt.coil3:coil:3.0.4=debugRuntimeClasspath +io.reactivex.rxjava2:rxandroid:2.1.1=debugCompileClasspath,debugRuntimeClasspath +io.reactivex.rxjava2:rxjava:2.2.21=debugCompileClasspath,debugRuntimeClasspath +javax.inject:javax.inject:1=debugCompileClasspath,debugRuntimeClasspath +jp.wasabeef:blurry:4.0.1=debugRuntimeClasspath +net.java.dev.jna:jna:5.14.0=debugCompileClasspath,debugRuntimeClasspath +org.apache.commons:commons-lang3:3.11=debugCompileClasspath,debugRuntimeClasspath +org.greenrobot:eventbus:3.1.0=debugRuntimeClasspath +org.jetbrains.intellij.deps:trove4j:1.0.20200330=kotlinBuildToolsApiClasspath,kotlinCompilerClasspath +org.jetbrains.kotlin:kotlin-android-extensions-runtime:1.9.22=debugRuntimeClasspath +org.jetbrains.kotlin:kotlin-annotations-jvm:1.3.72=debugCompileClasspath,debugRuntimeClasspath +org.jetbrains.kotlin:kotlin-bom:1.8.22=debugRuntimeClasspath +org.jetbrains.kotlin:kotlin-build-tools-api:2.1.20=kotlinBuildToolsApiClasspath +org.jetbrains.kotlin:kotlin-build-tools-impl:2.1.20=kotlinBuildToolsApiClasspath +org.jetbrains.kotlin:kotlin-compiler-embeddable:2.1.20=kotlinBuildToolsApiClasspath,kotlinCompilerClasspath +org.jetbrains.kotlin:kotlin-compiler-runner:2.1.20=kotlinBuildToolsApiClasspath +org.jetbrains.kotlin:kotlin-daemon-client:2.1.20=kotlinBuildToolsApiClasspath +org.jetbrains.kotlin:kotlin-daemon-embeddable:2.1.20=kotlinBuildToolsApiClasspath,kotlinCompilerClasspath +org.jetbrains.kotlin:kotlin-parcelize-runtime:1.9.22=debugRuntimeClasspath +org.jetbrains.kotlin:kotlin-reflect:1.6.10=kotlinBuildToolsApiClasspath,kotlinCompilerClasspath +org.jetbrains.kotlin:kotlin-reflect:2.1.20=debugRuntimeClasspath +org.jetbrains.kotlin:kotlin-script-runtime:2.1.20=kotlinBuildToolsApiClasspath,kotlinCompilerClasspath +org.jetbrains.kotlin:kotlin-scripting-common:2.1.20=kotlinBuildToolsApiClasspath +org.jetbrains.kotlin:kotlin-scripting-compiler-embeddable:2.1.20=kotlinBuildToolsApiClasspath +org.jetbrains.kotlin:kotlin-scripting-compiler-impl-embeddable:2.1.20=kotlinBuildToolsApiClasspath +org.jetbrains.kotlin:kotlin-scripting-jvm:2.1.20=kotlinBuildToolsApiClasspath +org.jetbrains.kotlin:kotlin-stdlib-jdk7:2.1.20=debugCompileClasspath,debugRuntimeClasspath +org.jetbrains.kotlin:kotlin-stdlib-jdk8:1.8.22=debugCompileClasspath,debugRuntimeClasspath +org.jetbrains.kotlin:kotlin-stdlib:2.1.20=debugCompileClasspath,debugRuntimeClasspath,kotlinBuildToolsApiClasspath,kotlinCompilerClasspath +org.jetbrains.kotlinx:kotlinx-coroutines-android:1.9.0=debugCompileClasspath,debugRuntimeClasspath +org.jetbrains.kotlinx:kotlinx-coroutines-bom:1.9.0=debugCompileClasspath,debugRuntimeClasspath +org.jetbrains.kotlinx:kotlinx-coroutines-core-jvm:1.8.0=kotlinBuildToolsApiClasspath,kotlinCompilerClasspath +org.jetbrains.kotlinx:kotlinx-coroutines-core-jvm:1.9.0=debugCompileClasspath,debugRuntimeClasspath +org.jetbrains.kotlinx:kotlinx-coroutines-core:1.9.0=debugCompileClasspath,debugRuntimeClasspath org.jetbrains.kotlinx:kotlinx-coroutines-play-services:1.9.0=debugRuntimeClasspath -org.jetbrains:annotations:13.0=_internal-unified-test-platform-android-device-provider-gradle,_internal-unified-test-platform-android-test-plugin-host-additional-test-output,_internal-unified-test-platform-android-test-plugin-host-apk-installer,_internal-unified-test-platform-android-test-plugin-host-coverage,_internal-unified-test-platform-android-test-plugin-host-device-info,_internal-unified-test-platform-android-test-plugin-host-emulator-control,_internal-unified-test-platform-android-test-plugin-host-logcat,_internal-unified-test-platform-android-test-plugin-host-retention,_internal-unified-test-platform-android-test-plugin-result-listener-gradle,debugAndroidTestCompileClasspath,kotlinBuildToolsApiClasspath,kotlinCompilerClasspath,kotlinKlibCommonizerClasspath -org.jetbrains:annotations:23.0.0=_internal-unified-test-platform-android-device-provider-ddmlib,debugCompileClasspath,debugRuntimeClasspath,debugUnitTestCompileClasspath,debugUnitTestRuntimeClasspath,releaseCompileClasspath,releaseRuntimeClasspath,releaseUnitTestCompileClasspath,releaseUnitTestRuntimeClasspath -org.jitsi:webrtc:124.0.0=debugAndroidTestCompileClasspath,debugCompileClasspath,debugRuntimeClasspath,debugUnitTestCompileClasspath,debugUnitTestRuntimeClasspath,releaseCompileClasspath,releaseRuntimeClasspath,releaseUnitTestCompileClasspath,releaseUnitTestRuntimeClasspath -org.ow2.asm:asm-analysis:9.2=androidJacocoAnt -org.ow2.asm:asm-commons:9.2=androidJacocoAnt -org.ow2.asm:asm-tree:9.2=androidJacocoAnt -org.ow2.asm:asm:9.2=androidJacocoAnt -org.reactivestreams:reactive-streams:1.0.3=debugAndroidTestCompileClasspath,debugCompileClasspath,debugRuntimeClasspath,debugUnitTestCompileClasspath,debugUnitTestRuntimeClasspath,releaseCompileClasspath,releaseRuntimeClasspath,releaseUnitTestCompileClasspath,releaseUnitTestRuntimeClasspath -empty=androidApis,androidJdkImage,androidTestApiDependenciesMetadata,androidTestCompileOnlyDependenciesMetadata,androidTestDebugApiDependenciesMetadata,androidTestDebugCompileOnlyDependenciesMetadata,androidTestDebugImplementationDependenciesMetadata,androidTestDebugIntransitiveDependenciesMetadata,androidTestDebugRuntimeOnlyDependenciesMetadata,androidTestImplementationDependenciesMetadata,androidTestIntransitiveDependenciesMetadata,androidTestReleaseApiDependenciesMetadata,androidTestReleaseCompileOnlyDependenciesMetadata,androidTestReleaseImplementationDependenciesMetadata,androidTestReleaseIntransitiveDependenciesMetadata,androidTestReleaseRuntimeOnlyDependenciesMetadata,androidTestRuntimeOnlyDependenciesMetadata,androidTestUtil,apiDependenciesMetadata,compileOnlyDependenciesMetadata,coreLibraryDesugaring,debugAndroidTestAnnotationProcessorClasspath,debugAndroidTestApiDependenciesMetadata,debugAndroidTestCompileOnlyDependenciesMetadata,debugAndroidTestImplementationDependenciesMetadata,debugAndroidTestIntransitiveDependenciesMetadata,debugAndroidTestRuntimeClasspath,debugAndroidTestRuntimeOnlyDependenciesMetadata,debugAnnotationProcessorClasspath,debugApiDependenciesMetadata,debugCompileOnlyDependenciesMetadata,debugImplementationDependenciesMetadata,debugIntransitiveDependenciesMetadata,debugReverseMetadataValues,debugRuntimeOnlyDependenciesMetadata,debugUnitTestAnnotationProcessorClasspath,debugUnitTestApiDependenciesMetadata,debugUnitTestCompileOnlyDependenciesMetadata,debugUnitTestImplementationDependenciesMetadata,debugUnitTestIntransitiveDependenciesMetadata,debugUnitTestRuntimeOnlyDependenciesMetadata,debugWearBundling,intransitiveDependenciesMetadata,kotlinCompilerPluginClasspath,kotlinCompilerPluginClasspathDebug,kotlinCompilerPluginClasspathDebugAndroidTest,kotlinCompilerPluginClasspathDebugUnitTest,kotlinCompilerPluginClasspathRelease,kotlinCompilerPluginClasspathReleaseUnitTest,kotlinNativeCompilerPluginClasspath,lintChecks,lintPublish,releaseAnnotationProcessorClasspath,releaseApiDependenciesMetadata,releaseCompileOnlyDependenciesMetadata,releaseImplementationDependenciesMetadata,releaseIntransitiveDependenciesMetadata,releaseReverseMetadataValues,releaseRuntimeOnlyDependenciesMetadata,releaseUnitTestAnnotationProcessorClasspath,releaseUnitTestApiDependenciesMetadata,releaseUnitTestCompileOnlyDependenciesMetadata,releaseUnitTestImplementationDependenciesMetadata,releaseUnitTestIntransitiveDependenciesMetadata,releaseUnitTestRuntimeOnlyDependenciesMetadata,releaseWearBundling,runtimeOnlyDependenciesMetadata,testApiDependenciesMetadata,testCompileOnlyDependenciesMetadata,testDebugApiDependenciesMetadata,testDebugCompileOnlyDependenciesMetadata,testDebugImplementationDependenciesMetadata,testDebugIntransitiveDependenciesMetadata,testDebugRuntimeOnlyDependenciesMetadata,testFixturesApiDependenciesMetadata,testFixturesCompileOnlyDependenciesMetadata,testFixturesDebugApiDependenciesMetadata,testFixturesDebugCompileOnlyDependenciesMetadata,testFixturesDebugImplementationDependenciesMetadata,testFixturesDebugIntransitiveDependenciesMetadata,testFixturesDebugRuntimeOnlyDependenciesMetadata,testFixturesImplementationDependenciesMetadata,testFixturesIntransitiveDependenciesMetadata,testFixturesReleaseApiDependenciesMetadata,testFixturesReleaseCompileOnlyDependenciesMetadata,testFixturesReleaseImplementationDependenciesMetadata,testFixturesReleaseIntransitiveDependenciesMetadata,testFixturesReleaseRuntimeOnlyDependenciesMetadata,testFixturesRuntimeOnlyDependenciesMetadata,testImplementationDependenciesMetadata,testIntransitiveDependenciesMetadata,testReleaseApiDependenciesMetadata,testReleaseCompileOnlyDependenciesMetadata,testReleaseImplementationDependenciesMetadata,testReleaseIntransitiveDependenciesMetadata,testReleaseRuntimeOnlyDependenciesMetadata,testRuntimeOnlyDependenciesMetadata +org.jetbrains:annotations:13.0=kotlinBuildToolsApiClasspath,kotlinCompilerClasspath +org.jetbrains:annotations:23.0.0=debugCompileClasspath,debugRuntimeClasspath +org.jitsi:webrtc:124.0.0=debugCompileClasspath,debugRuntimeClasspath +org.jspecify:jspecify:1.0.0=debugCompileClasspath,debugRuntimeClasspath +org.reactivestreams:reactive-streams:1.0.3=debugCompileClasspath,debugRuntimeClasspath +empty=androidApis,androidJdkImage,debugAnnotationProcessorClasspath,debugReverseMetadataValues,kotlinCompilerPluginClasspathDebug diff --git a/app/android/app/src/main/java/ca/bc/gov/BCWallet/MainApplication.kt b/app/android/app/src/main/java/ca/bc/gov/BCWallet/MainApplication.kt index c5bf285..3299b58 100644 --- a/app/android/app/src/main/java/ca/bc/gov/BCWallet/MainApplication.kt +++ b/app/android/app/src/main/java/ca/bc/gov/BCWallet/MainApplication.kt @@ -1,23 +1,24 @@ package asml.bkc.harvard.wallet import android.app.Application +import android.content.res.Configuration import com.facebook.react.PackageList import com.facebook.react.ReactApplication import com.facebook.react.ReactHost +import com.facebook.react.ReactNativeApplicationEntryPoint.loadReactNative import com.facebook.react.ReactNativeHost import com.facebook.react.ReactPackage -import com.facebook.react.defaults.DefaultNewArchitectureEntryPoint.load import com.facebook.react.defaults.DefaultReactHost.getDefaultReactHost import com.facebook.react.defaults.DefaultReactNativeHost -import com.facebook.react.soloader.OpenSourceMergedSoMapping -import com.facebook.soloader.SoLoader +import expo.modules.ApplicationLifecycleDispatcher +import expo.modules.ReactNativeHostWrapper import org.wonday.orientation.OrientationActivityLifecycle class MainApplication : Application(), ReactApplication { override val reactNativeHost: ReactNativeHost = - object : DefaultReactNativeHost(this) { + ReactNativeHostWrapper(this, object : DefaultReactNativeHost(this) { override fun getPackages(): List = PackageList(this).packages.apply { // Packages that cannot be autolinked yet can be added manually here, for example: @@ -28,7 +29,7 @@ class MainApplication : Application(), ReactApplication { override fun getUseDeveloperSupport(): Boolean = BuildConfig.DEBUG override val isNewArchEnabled: Boolean = BuildConfig.IS_NEW_ARCHITECTURE_ENABLED override val isHermesEnabled: Boolean = BuildConfig.IS_HERMES_ENABLED - } + }) override val reactHost: ReactHost get() = getDefaultReactHost(this.applicationContext, reactNativeHost) @@ -36,10 +37,12 @@ class MainApplication : Application(), ReactApplication { override fun onCreate() { registerActivityLifecycleCallbacks(OrientationActivityLifecycle.getInstance()) super.onCreate() - SoLoader.init(this, OpenSourceMergedSoMapping) - if (BuildConfig.IS_NEW_ARCHITECTURE_ENABLED) { - // If you opted-in for the New Architecture, we load the native entry point for this app - load() - } + loadReactNative(this) + ApplicationLifecycleDispatcher.onApplicationCreate(this) + } + + override fun onConfigurationChanged(newConfig: Configuration) { + super.onConfigurationChanged(newConfig) + ApplicationLifecycleDispatcher.onConfigurationChanged(this, newConfig) } } \ No newline at end of file diff --git a/app/android/build.gradle b/app/android/build.gradle index 5008072..c0a0b06 100644 --- a/app/android/build.gradle +++ b/app/android/build.gradle @@ -2,12 +2,12 @@ buildscript { ext { - buildToolsVersion = "35.0.0" + buildToolsVersion = "36.0.0" minSdkVersion = 24 - compileSdkVersion = 35 - targetSdkVersion = 35 + compileSdkVersion = 36 + targetSdkVersion = 36 ndkVersion = "27.1.12297006" - kotlinVersion = "2.0.21" + kotlinVersion = "2.1.20" androidXBrowser = "1.5.0" javaVersion = JavaVersion.VERSION_17 } @@ -16,7 +16,8 @@ buildscript { mavenCentral() } dependencies { - classpath("com.android.tools.build:gradle:8.7.3") + // AGP version comes from @react-native/gradle-plugin (RN 0.81 -> AGP 8.12) + classpath("com.android.tools.build:gradle") classpath('com.google.gms:google-services:4.4.2') classpath("com.facebook.react:react-native-gradle-plugin") classpath("org.jetbrains.kotlin:kotlin-gradle-plugin:$kotlinVersion") @@ -41,20 +42,28 @@ allprojects { google() maven { url 'https://www.jitpack.io' } } - - configurations.all { - resolutionStrategy { - force "org.jetbrains.kotlin:kotlin-stdlib:$kotlinVersion" - force "org.jetbrains.kotlin:kotlin-stdlib-jdk7:$kotlinVersion" - force "org.jetbrains.kotlin:kotlin-stdlib-jdk8:$kotlinVersion" - } - } } subprojects { configurations.all { it.resolutionStrategy.activateDependencyLocking() } + + // Align every Android subproject on Java 17 (expo-modules-core otherwise + // compiles Java at 1.8 while Kotlin targets 17 and the build fails). + // Same approach as bifold samples/app. + afterEvaluate { project -> + ["com.android.application", "com.android.library"].each { pluginId -> + project.plugins.withId(pluginId) { + project.android { + compileOptions { + sourceCompatibility JavaVersion.VERSION_17 + targetCompatibility JavaVersion.VERSION_17 + } + } + } + } + } } dependencyLocking { diff --git a/app/android/gradle.properties b/app/android/gradle.properties index 99b4594..de54e12 100644 --- a/app/android/gradle.properties +++ b/app/android/gradle.properties @@ -42,7 +42,10 @@ reactNativeArchitectures=armeabi-v7a,arm64-v8a,x86,x86_64 # your application. You should enable this flag either if you want # to write custom TurboModules/Fabric components OR use libraries that # are providing them. -newArchEnabled=false +newArchEnabled=true +# Expo modules manage the Java toolchain; stop the RN plugin from re-finalizing it +# (same workaround as bifold samples/app) +react.internal.disableJavaVersionAlignment=true # Use this property to enable or disable the Hermes JS engine. # If set to false, you will be using JSC instead. hermesEnabled=true \ No newline at end of file diff --git a/app/android/gradle/wrapper/gradle-wrapper.properties b/app/android/gradle/wrapper/gradle-wrapper.properties index 86baf49..d4081da 100644 --- a/app/android/gradle/wrapper/gradle-wrapper.properties +++ b/app/android/gradle/wrapper/gradle-wrapper.properties @@ -1,7 +1,7 @@ distributionBase=GRADLE_USER_HOME distributionPath=wrapper/dists -distributionUrl=https\://services.gradle.org/distributions/gradle-8.10.2-all.zip +distributionUrl=https\://services.gradle.org/distributions/gradle-8.14.3-bin.zip networkTimeout=10000 -alidateDistributionUrl=true +validateDistributionUrl=true zipStoreBase=GRADLE_USER_HOME zipStorePath=wrapper/dists diff --git a/app/android/settings.gradle b/app/android/settings.gradle index 2efff52..73887fe 100644 --- a/app/android/settings.gradle +++ b/app/android/settings.gradle @@ -4,3 +4,7 @@ extensions.configure(com.facebook.react.ReactSettingsExtension){ ex -> ex.autoli rootProject.name = 'KeyRing' include ':app' includeBuild('../node_modules/@react-native/gradle-plugin') + +// Expo modules autolinking (expo-crypto, expo-secure-store, @animo-id/expo-secure-environment) +apply from: new File(["node", "--print", "require.resolve('expo/package.json')"].execute(null, rootDir).text.trim(), "../scripts/autolinking.gradle") +useExpoModules() diff --git a/app/babel.config.js b/app/babel.config.js index 5b6cac5..89fb8b7 100644 --- a/app/babel.config.js +++ b/app/babel.config.js @@ -1,10 +1,13 @@ const presets = ['module:@react-native/babel-preset'] const plugins = [ + '@babel/plugin-transform-export-namespace-from', [ 'module-resolver', { - root: ['.'], - extensions: ['.tsx', 'ts'], + // NOTE: no `root` here on purpose - with root: ['.'] module-resolver + // rewrites `from '.'` imports inside node_modules (e.g. gesture-handler's + // ReanimatedSwipeable) to the app root index.js, breaking jest + extensions: ['.ts', '.tsx', '.js', '.jsx', '.json'], alias: { '@': './src', '@assets': './src/assets', @@ -25,6 +28,9 @@ if (process.env['ENV'] === 'prod') { plugins.push('transform-remove-console') } +// react-native-reanimated plugin must be listed last +plugins.push('react-native-reanimated/plugin') + module.exports = { presets, plugins, diff --git a/app/index.js b/app/index.js index 8af22e8..dce4ba8 100644 --- a/app/index.js +++ b/app/index.js @@ -129,12 +129,12 @@ if (!global.atob) { global.atob = decode } -// Dev-only: silence the LogBox toast for known-noisy warnings (indy ledger DID -// cache warm-up times out on test networks; the toast overlays the UI and breaks -// E2E taps). Errors still land in the metro console. +// Dev-only: disable LogBox notification banners entirely. The banners overlay +// the bottom of the screen (where primary buttons live) and repeatedly break +// E2E taps. All warnings/errors still land in Metro/logcat/syslog. const { AppRegistry, LogBox } = require('react-native') if (global.__DEV__) { - LogBox.ignoreLogs([/IndyVdrError/, /Possible unhandled promise rejection/]) + LogBox.ignoreAllLogs() } const App = require('./App').default const { name: appName } = require('./app.json') diff --git a/app/ios/AriesBifold.xcodeproj/project.pbxproj b/app/ios/AriesBifold.xcodeproj/project.pbxproj index f448916..3210ece 100644 --- a/app/ios/AriesBifold.xcodeproj/project.pbxproj +++ b/app/ios/AriesBifold.xcodeproj/project.pbxproj @@ -12,7 +12,9 @@ 1A157F462BACCDEA00E30CDB /* PrivacyInfo.xcprivacy in Resources */ = {isa = PBXBuildFile; fileRef = 1A157F452BACCDEA00E30CDB /* PrivacyInfo.xcprivacy */; }; 1A762CD62D87E24100455F4C /* AppDelegate.mm in Sources */ = {isa = PBXBuildFile; fileRef = 1A762CD52D87E24100455F4C /* AppDelegate.mm */; }; 2F9994AE2A8D83CB004E773E /* GoogleService-Info.plist in Resources */ = {isa = PBXBuildFile; fileRef = 2F9994AD2A8D83CB004E773E /* GoogleService-Info.plist */; }; + 460C62056C817F32DD50B03E /* ExpoModulesProvider.swift in Sources */ = {isa = PBXBuildFile; fileRef = 8695E760B846E4F378AB5655 /* ExpoModulesProvider.swift */; }; 4AA41CC1208649828A6C7F7F /* GT-America-Mono-Regular.OTF in Resources */ = {isa = PBXBuildFile; fileRef = 791DE193A8F54ABDB4C0A6E7 /* GT-America-Mono-Regular.OTF */; }; + 50FEB047FBD813EA82B0B9E8 /* ExpoModulesProvider.swift in Sources */ = {isa = PBXBuildFile; fileRef = FB705808CC6C27175E93BD23 /* ExpoModulesProvider.swift */; }; 51DF9B21480F42A9BD3A92CC /* SourceSans3-Light.ttf in Resources */ = {isa = PBXBuildFile; fileRef = 1518883F928D41DF9687C602 /* SourceSans3-Light.ttf */; }; 566FB1F2273B158E003E9BEE /* Media.xcassets in Resources */ = {isa = PBXBuildFile; fileRef = 566FB1F1273B158E003E9BEE /* Media.xcassets */; }; 5F13137F43F5857730628E88 /* libPods-AriesBifold-AriesBifoldTests.a in Frameworks */ = {isa = PBXBuildFile; fileRef = D2FEEE17975EE5C7D138D250 /* libPods-AriesBifold-AriesBifoldTests.a */; }; @@ -70,6 +72,7 @@ 7AF003B82E01D25300389FF2 /* GT-America-Regular.OTF */ = {isa = PBXFileReference; lastKnownFileType = file; path = "GT-America-Regular.OTF"; sourceTree = ""; }; 7D2E34625C1340E6979A7172 /* SourceSans3-It.ttf */ = {isa = PBXFileReference; explicitFileType = undefined; fileEncoding = 9; includeInIndex = 0; lastKnownFileType = unknown; name = "SourceSans3-It.ttf"; path = "../src/assets/fonts/SourceSans3-It.ttf"; sourceTree = ""; }; 81AB9BB72411601600AC10FF /* LaunchScreen.storyboard */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = file.storyboard; name = LaunchScreen.storyboard; path = AriesBifold/LaunchScreen.storyboard; sourceTree = ""; }; + 8695E760B846E4F378AB5655 /* ExpoModulesProvider.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; name = ExpoModulesProvider.swift; path = "Pods/Target Support Files/Pods-AriesBifold-AriesBifoldTests/ExpoModulesProvider.swift"; sourceTree = ""; }; 99A1BC81F291BF040E41B70D /* libPods-AriesBifold.a */ = {isa = PBXFileReference; explicitFileType = archive.ar; includeInIndex = 0; path = "libPods-AriesBifold.a"; sourceTree = BUILT_PRODUCTS_DIR; }; A68707143FAC4C9A8B391935 /* GT-America-Mono-Bold.OTF */ = {isa = PBXFileReference; explicitFileType = undefined; fileEncoding = 9; includeInIndex = 0; lastKnownFileType = unknown; name = "GT-America-Mono-Bold.OTF"; path = "../src/assets/fonts/GT-America-Mono-Bold.OTF"; sourceTree = ""; }; CA217BD1171D444992207F53 /* GT-America-Bold.OTF */ = {isa = PBXFileReference; explicitFileType = undefined; fileEncoding = 9; includeInIndex = 0; lastKnownFileType = unknown; name = "GT-America-Bold.OTF"; path = "../src/assets/fonts/GT-America-Bold.OTF"; sourceTree = ""; }; @@ -79,6 +82,7 @@ E5D436714AEB456F859D1A6A /* MaterialIcons.ttf */ = {isa = PBXFileReference; explicitFileType = undefined; fileEncoding = 9; includeInIndex = 0; lastKnownFileType = unknown; name = MaterialIcons.ttf; path = ../src/assets/fonts/MaterialIcons.ttf; sourceTree = ""; }; ED297162215061F000B7C4FE /* JavaScriptCore.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = JavaScriptCore.framework; path = System/Library/Frameworks/JavaScriptCore.framework; sourceTree = SDKROOT; }; FAE9144464984615A799B578 /* GT-America-Regular.OTF */ = {isa = PBXFileReference; explicitFileType = undefined; fileEncoding = 9; includeInIndex = 0; lastKnownFileType = unknown; name = "GT-America-Regular.OTF"; path = "../src/assets/fonts/GT-America-Regular.OTF"; sourceTree = ""; }; + FB705808CC6C27175E93BD23 /* ExpoModulesProvider.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; name = ExpoModulesProvider.swift; path = "Pods/Target Support Files/Pods-AriesBifold/ExpoModulesProvider.swift"; sourceTree = ""; }; /* End PBXFileReference section */ /* Begin PBXFrameworksBuildPhase section */ @@ -141,6 +145,14 @@ name = Frameworks; sourceTree = ""; }; + 53C76CBB26DD45D2AF027D8F /* AriesBifold */ = { + isa = PBXGroup; + children = ( + FB705808CC6C27175E93BD23 /* ExpoModulesProvider.swift */, + ); + name = AriesBifold; + sourceTree = ""; + }; 56A83D5927D95BBF002FE8FE /* Resources */ = { isa = PBXGroup; children = ( @@ -166,6 +178,15 @@ name = Resources; sourceTree = ""; }; + 7B61326B67920F8F6A63C808 /* ExpoModulesProviders */ = { + isa = PBXGroup; + children = ( + 53C76CBB26DD45D2AF027D8F /* AriesBifold */, + F5DF803F29736DDAA342CFF2 /* AriesBifoldTests */, + ); + name = ExpoModulesProviders; + sourceTree = ""; + }; 832341AE1AAA6A7D00B99B32 /* Libraries */ = { isa = PBXGroup; children = ( @@ -187,6 +208,7 @@ 2D16E6871FA4F8E400B85C8A /* Frameworks */, 56A83D5927D95BBF002FE8FE /* Resources */, 8ACF6F3B2962FE31C0EE5408 /* Pods */, + 7B61326B67920F8F6A63C808 /* ExpoModulesProviders */, ); indentWidth = 2; sourceTree = ""; @@ -213,6 +235,14 @@ path = Pods; sourceTree = ""; }; + F5DF803F29736DDAA342CFF2 /* AriesBifoldTests */ = { + isa = PBXGroup; + children = ( + 8695E760B846E4F378AB5655 /* ExpoModulesProvider.swift */, + ); + name = AriesBifoldTests; + sourceTree = ""; + }; /* End PBXGroup section */ /* Begin PBXNativeTarget section */ @@ -221,6 +251,7 @@ buildConfigurationList = 00E357021AD99517003FC87E /* Build configuration list for PBXNativeTarget "AriesBifoldTests" */; buildPhases = ( 8E2BB1F0C19AA17EB70A2E46 /* [CP] Check Pods Manifest.lock */, + 79AC122EB8FB7BB97DCFBE03 /* [Expo] Configure project */, 00E356EA1AD99517003FC87E /* Sources */, 00E356EB1AD99517003FC87E /* Frameworks */, 00E356EC1AD99517003FC87E /* Resources */, @@ -243,6 +274,7 @@ buildPhases = ( D19D45CA82EB16EA5021312D /* [CP] Check Pods Manifest.lock */, FD10A7F022414F080027D42C /* Start Packager */, + 1BC411DB87B5A949793F4FC1 /* [Expo] Configure project */, 13B07F871A680F5B00A75B9A /* Sources */, 13B07F8C1A680F5B00A75B9A /* Frameworks */, 13B07F8E1A680F5B00A75B9A /* Resources */, @@ -343,6 +375,30 @@ shellPath = /bin/zsh; shellScript = "set -e\n\n../node_modules/react-native/scripts/react-native-xcode.sh\n"; }; + 1BC411DB87B5A949793F4FC1 /* [Expo] Configure project */ = { + isa = PBXShellScriptBuildPhase; + alwaysOutOfDate = 1; + buildActionMask = 2147483647; + files = ( + ); + inputFileListPaths = ( + ); + inputPaths = ( + "$(SRCROOT)/.xcode.env", + "$(SRCROOT)/.xcode.env.local", + "$(SRCROOT)/AriesBifold/AriesBifold.entitlements", + "$(SRCROOT)/Pods/Target Support Files/Pods-AriesBifold/expo-configure-project.sh", + ); + name = "[Expo] Configure project"; + outputFileListPaths = ( + ); + outputPaths = ( + "$(SRCROOT)/Pods/Target Support Files/Pods-AriesBifold/ExpoModulesProvider.swift", + ); + runOnlyForDeploymentPostprocessing = 0; + shellPath = /bin/sh; + shellScript = "# This script configures Expo modules and generates the modules provider file.\nbash -l -c \"./Pods/Target\\ Support\\ Files/Pods-AriesBifold/expo-configure-project.sh\"\n"; + }; 2971F0F156B890557487DDEB /* [CP] Embed Pods Frameworks */ = { isa = PBXShellScriptBuildPhase; buildActionMask = 2147483647; @@ -377,6 +433,29 @@ shellScript = "\"${PODS_ROOT}/Target Support Files/Pods-AriesBifold-AriesBifoldTests/Pods-AriesBifold-AriesBifoldTests-resources.sh\"\n"; showEnvVarsInLog = 0; }; + 79AC122EB8FB7BB97DCFBE03 /* [Expo] Configure project */ = { + isa = PBXShellScriptBuildPhase; + alwaysOutOfDate = 1; + buildActionMask = 2147483647; + files = ( + ); + inputFileListPaths = ( + ); + inputPaths = ( + "$(SRCROOT)/.xcode.env", + "$(SRCROOT)/.xcode.env.local", + "$(SRCROOT)/Pods/Target Support Files/Pods-AriesBifold-AriesBifoldTests/expo-configure-project.sh", + ); + name = "[Expo] Configure project"; + outputFileListPaths = ( + ); + outputPaths = ( + "$(SRCROOT)/Pods/Target Support Files/Pods-AriesBifold-AriesBifoldTests/ExpoModulesProvider.swift", + ); + runOnlyForDeploymentPostprocessing = 0; + shellPath = /bin/sh; + shellScript = "# This script configures Expo modules and generates the modules provider file.\nbash -l -c \"./Pods/Target\\ Support\\ Files/Pods-AriesBifold-AriesBifoldTests/expo-configure-project.sh\"\n"; + }; 889B52BA36E6E01B35CF05F4 /* [CP] Embed Pods Frameworks */ = { isa = PBXShellScriptBuildPhase; buildActionMask = 2147483647; @@ -495,6 +574,7 @@ buildActionMask = 2147483647; files = ( 00E356F31AD99517003FC87E /* AriesBifoldTests.m in Sources */, + 460C62056C817F32DD50B03E /* ExpoModulesProvider.swift in Sources */, ); runOnlyForDeploymentPostprocessing = 0; }; @@ -504,6 +584,7 @@ files = ( 1A762CD62D87E24100455F4C /* AppDelegate.mm in Sources */, 13B07FC11A68108700A75B9A /* main.m in Sources */, + 50FEB047FBD813EA82B0B9E8 /* ExpoModulesProvider.swift in Sources */, ); runOnlyForDeploymentPostprocessing = 0; }; @@ -540,6 +621,7 @@ "-lc++", "$(inherited)", ); + OTHER_SWIFT_FLAGS = "$(inherited) -D EXPO_CONFIGURATION_DEBUG"; PRODUCT_BUNDLE_IDENTIFIER = "org.reactjs.native.example.$(PRODUCT_NAME:rfc1034identifier)"; PRODUCT_NAME = "$(TARGET_NAME)"; TEST_HOST = "$(BUILT_PRODUCTS_DIR)/AriesBifold.app/AriesBifold"; @@ -565,6 +647,7 @@ "-lc++", "$(inherited)", ); + OTHER_SWIFT_FLAGS = "$(inherited) -D EXPO_CONFIGURATION_RELEASE"; PRODUCT_BUNDLE_IDENTIFIER = "org.reactjs.native.example.$(PRODUCT_NAME:rfc1034identifier)"; PRODUCT_NAME = "$(TARGET_NAME)"; TEST_HOST = "$(BUILT_PRODUCTS_DIR)/AriesBifold.app/AriesBifold"; @@ -600,6 +683,7 @@ "-ObjC", "-lc++", ); + OTHER_SWIFT_FLAGS = "$(inherited) -D EXPO_CONFIGURATION_DEBUG"; PRODUCT_BUNDLE_IDENTIFIER = asml.bkc.harvard.wallet; PRODUCT_NAME = KeyRing; PROVISIONING_PROFILE_SPECIFIER = ""; @@ -642,6 +726,7 @@ "-ObjC", "-lc++", ); + OTHER_SWIFT_FLAGS = "$(inherited) -D EXPO_CONFIGURATION_RELEASE"; PRODUCT_BUNDLE_IDENTIFIER = asml.bkc.harvard.wallet; PRODUCT_NAME = KeyRing; PROVISIONING_PROFILE_SPECIFIER = ""; diff --git a/app/ios/AriesBifold/Info.plist b/app/ios/AriesBifold/Info.plist index f1e7c02..96e7c22 100644 --- a/app/ios/AriesBifold/Info.plist +++ b/app/ios/AriesBifold/Info.plist @@ -51,6 +51,8 @@ LSRequiresIPhoneOS + LSSupportsOpeningDocumentsInPlace + NSAppTransportSecurity NSAllowsArbitraryLoads @@ -68,14 +70,6 @@ $(PRODUCT_NAME) needs access to Bluetooth to manage audio routing during calls NSBluetoothPeripheralUsageDescription $(PRODUCT_NAME) needs access to Bluetooth to connect to audio devices during calls - NSCameraUsageDescription - Camera used for QR Code scanning and video calls - NSFaceIDUsageDescription - $(PRODUCT_NAME) wants to use your FaceID/TouchID to authenticate your identity - NSLocationWhenInUseUsageDescription - We include this permission because a library our app uses references it, even though we don't use it directly - NSLocalNetworkUsageDescription - $(PRODUCT_NAME) needs access to the local network to discover witness servers for credential verification NSBonjourServices _witness._tcp @@ -83,8 +77,18 @@ _witness._tcp.local _witness._tcp.local. + NSCameraUsageDescription + Camera used for QR Code scanning and video calls + NSFaceIDUsageDescription + $(PRODUCT_NAME) wants to use your FaceID/TouchID to authenticate your identity + NSLocalNetworkUsageDescription + $(PRODUCT_NAME) needs access to the local network to discover witness servers for credential verification + NSLocationWhenInUseUsageDescription + We include this permission because a library our app uses references it, even though we don't use it directly NSMicrophoneUsageDescription $(PRODUCT_NAME) needs access to your microphone to enable video calls + RCTNewArchEnabled + UIAppFonts MaterialIcons.ttf @@ -107,6 +111,8 @@ audio voip + UIFileSharingEnabled + UILaunchStoryboardName LaunchScreen UIRequiredDeviceCapabilities @@ -128,9 +134,5 @@ UIViewControllerBasedStatusBarAppearance - UIFileSharingEnabled - - LSSupportsOpeningDocumentsInPlace - diff --git a/app/ios/Podfile b/app/ios/Podfile index 17a09ec..cb8b276 100644 --- a/app/ios/Podfile +++ b/app/ios/Podfile @@ -1,3 +1,4 @@ +require File.join(File.dirname(`node --print "require.resolve('expo/package.json')"`), "scripts/autolinking") source 'https://cdn.cocoapods.org' require_relative '../node_modules/react-native/scripts/react_native_pods' @@ -51,6 +52,14 @@ if linkage != nil end target 'AriesBifold' do + use_expo_modules! + post_integrate do |installer| + begin + expo_patch_react_imports!(installer) + rescue => e + Pod::UI.warn e + end + end config = use_native_modules! pod 'Firebase', :modular_headers => true diff --git a/app/ios/Podfile.lock b/app/ios/Podfile.lock index 7b969e6..0c1e154 100644 --- a/app/ios/Podfile.lock +++ b/app/ios/Podfile.lock @@ -1,9 +1,9 @@ PODS: - - anoncreds (0.2.4): + - anoncreds (0.3.4): - React - React-callinvoker - React-Core - - aries-askar (0.2.3): + - askar (0.6.0): - React - React-callinvoker - React-Core @@ -13,8 +13,86 @@ PODS: - CatCrypto (0.3.2) - CocoaAsyncSocket (7.6.5) - DoubleConversion (1.1.6) - - fast_float (6.1.4) - - FBLazyVector (0.77.3) + - EXConstants (18.0.13): + - ExpoModulesCore + - Expo (54.0.35): + - boost + - DoubleConversion + - ExpoModulesCore + - fast_float + - fmt + - glog + - hermes-engine + - RCT-Folly + - RCT-Folly/Fabric + - RCTRequired + - RCTTypeSafety + - React-Core + - React-debug + - React-Fabric + - React-featureflags + - React-graphics + - React-ImageManager + - React-jsi + - React-NativeModulesApple + - React-RCTAppDelegate + - React-RCTFabric + - React-renderercss + - React-rendererdebug + - React-utils + - ReactAppDependencyProvider + - ReactCodegen + - ReactCommon/turbomodule/bridging + - ReactCommon/turbomodule/core + - SocketRocket + - Yoga + - ExpoAppIntegrity (55.0.14): + - ExpoModulesCore + - ExpoAsset (12.0.13): + - ExpoModulesCore + - ExpoCrypto (15.0.9): + - ExpoModulesCore + - ExpoFileSystem (19.0.23): + - ExpoModulesCore + - ExpoFont (14.0.12): + - ExpoModulesCore + - ExpoKeepAwake (15.0.8): + - ExpoModulesCore + - ExpoModulesCore (3.0.30): + - boost + - DoubleConversion + - fast_float + - fmt + - glog + - hermes-engine + - RCT-Folly + - RCT-Folly/Fabric + - RCTRequired + - RCTTypeSafety + - React-Core + - React-debug + - React-Fabric + - React-featureflags + - React-graphics + - React-ImageManager + - React-jsi + - React-jsinspector + - React-NativeModulesApple + - React-RCTFabric + - React-renderercss + - React-rendererdebug + - React-utils + - ReactCodegen + - ReactCommon/turbomodule/bridging + - ReactCommon/turbomodule/core + - SocketRocket + - Yoga + - ExpoSecureEnvironment (0.1.5): + - ExpoModulesCore + - ExpoSecureStore (15.0.8): + - ExpoModulesCore + - fast_float (8.0.0) + - FBLazyVector (0.81.5) - Firebase (11.11.0): - Firebase/Core (= 11.11.0) - Firebase/Core (11.11.0): @@ -130,10 +208,10 @@ PODS: - GoogleUtilities/UserDefaults (8.1.2): - GoogleUtilities/Logger - GoogleUtilities/Privacy - - hermes-engine (0.77.3): - - hermes-engine/Pre-built (= 0.77.3) - - hermes-engine/Pre-built (0.77.3) - - indy-vdr (0.2.2): + - hermes-engine (0.81.5): + - hermes-engine/Pre-built (= 0.81.5) + - hermes-engine/Pre-built (0.81.5) + - indy-vdr (0.2.4): - React - React-callinvoker - React-Core @@ -148,63 +226,76 @@ PODS: - RCT-Folly (2024.11.18.00): - boost - DoubleConversion - - fast_float (= 6.1.4) + - fast_float (= 8.0.0) - fmt (= 11.0.2) - glog - RCT-Folly/Default (= 2024.11.18.00) - RCT-Folly/Default (2024.11.18.00): - boost - DoubleConversion - - fast_float (= 6.1.4) + - fast_float (= 8.0.0) - fmt (= 11.0.2) - glog - RCT-Folly/Fabric (2024.11.18.00): - boost - DoubleConversion - - fast_float (= 6.1.4) + - fast_float (= 8.0.0) - fmt (= 11.0.2) - glog - - RCTDeprecation (0.77.3) - - RCTRequired (0.77.3) - - RCTTypeSafety (0.77.3): - - FBLazyVector (= 0.77.3) - - RCTRequired (= 0.77.3) - - React-Core (= 0.77.3) - - React (0.77.3): - - React-Core (= 0.77.3) - - React-Core/DevSupport (= 0.77.3) - - React-Core/RCTWebSocket (= 0.77.3) - - React-RCTActionSheet (= 0.77.3) - - React-RCTAnimation (= 0.77.3) - - React-RCTBlob (= 0.77.3) - - React-RCTImage (= 0.77.3) - - React-RCTLinking (= 0.77.3) - - React-RCTNetwork (= 0.77.3) - - React-RCTSettings (= 0.77.3) - - React-RCTText (= 0.77.3) - - React-RCTVibration (= 0.77.3) - - React-callinvoker (0.77.3) - - React-Core (0.77.3): - - glog - - hermes-engine - - RCT-Folly (= 2024.11.18.00) + - RCTDeprecation (0.81.5) + - RCTRequired (0.81.5) + - RCTTypeSafety (0.81.5): + - FBLazyVector (= 0.81.5) + - RCTRequired (= 0.81.5) + - React-Core (= 0.81.5) + - React (0.81.5): + - React-Core (= 0.81.5) + - React-Core/DevSupport (= 0.81.5) + - React-Core/RCTWebSocket (= 0.81.5) + - React-RCTActionSheet (= 0.81.5) + - React-RCTAnimation (= 0.81.5) + - React-RCTBlob (= 0.81.5) + - React-RCTImage (= 0.81.5) + - React-RCTLinking (= 0.81.5) + - React-RCTNetwork (= 0.81.5) + - React-RCTSettings (= 0.81.5) + - React-RCTText (= 0.81.5) + - React-RCTVibration (= 0.81.5) + - React-callinvoker (0.81.5) + - React-Core (0.81.5): + - boost + - DoubleConversion + - fast_float + - fmt + - glog + - hermes-engine + - RCT-Folly + - RCT-Folly/Fabric - RCTDeprecation - - React-Core/Default (= 0.77.3) + - React-Core/Default (= 0.81.5) - React-cxxreact - React-featureflags - React-hermes - React-jsi - React-jsiexecutor - React-jsinspector + - React-jsinspectorcdp + - React-jsitooling - React-perflogger + - React-runtimeexecutor - React-runtimescheduler - React-utils - - SocketRocket (= 0.7.1) + - SocketRocket - Yoga - - React-Core/CoreModulesHeaders (0.77.3): + - React-Core/CoreModulesHeaders (0.81.5): + - boost + - DoubleConversion + - fast_float + - fmt - glog - hermes-engine - - RCT-Folly (= 2024.11.18.00) + - RCT-Folly + - RCT-Folly/Fabric - RCTDeprecation - React-Core/Default - React-cxxreact @@ -213,15 +304,23 @@ PODS: - React-jsi - React-jsiexecutor - React-jsinspector + - React-jsinspectorcdp + - React-jsitooling - React-perflogger + - React-runtimeexecutor - React-runtimescheduler - React-utils - - SocketRocket (= 0.7.1) + - SocketRocket - Yoga - - React-Core/Default (0.77.3): + - React-Core/Default (0.81.5): + - boost + - DoubleConversion + - fast_float + - fmt - glog - hermes-engine - - RCT-Folly (= 2024.11.18.00) + - RCT-Folly + - RCT-Folly/Fabric - RCTDeprecation - React-cxxreact - React-featureflags @@ -229,33 +328,49 @@ PODS: - React-jsi - React-jsiexecutor - React-jsinspector + - React-jsinspectorcdp + - React-jsitooling - React-perflogger + - React-runtimeexecutor - React-runtimescheduler - React-utils - - SocketRocket (= 0.7.1) + - SocketRocket - Yoga - - React-Core/DevSupport (0.77.3): + - React-Core/DevSupport (0.81.5): + - boost + - DoubleConversion + - fast_float + - fmt - glog - hermes-engine - - RCT-Folly (= 2024.11.18.00) + - RCT-Folly + - RCT-Folly/Fabric - RCTDeprecation - - React-Core/Default (= 0.77.3) - - React-Core/RCTWebSocket (= 0.77.3) + - React-Core/Default (= 0.81.5) + - React-Core/RCTWebSocket (= 0.81.5) - React-cxxreact - React-featureflags - React-hermes - React-jsi - React-jsiexecutor - React-jsinspector + - React-jsinspectorcdp + - React-jsitooling - React-perflogger + - React-runtimeexecutor - React-runtimescheduler - React-utils - - SocketRocket (= 0.7.1) + - SocketRocket - Yoga - - React-Core/RCTActionSheetHeaders (0.77.3): + - React-Core/RCTActionSheetHeaders (0.81.5): + - boost + - DoubleConversion + - fast_float + - fmt - glog - hermes-engine - - RCT-Folly (= 2024.11.18.00) + - RCT-Folly + - RCT-Folly/Fabric - RCTDeprecation - React-Core/Default - React-cxxreact @@ -264,15 +379,23 @@ PODS: - React-jsi - React-jsiexecutor - React-jsinspector + - React-jsinspectorcdp + - React-jsitooling - React-perflogger + - React-runtimeexecutor - React-runtimescheduler - React-utils - - SocketRocket (= 0.7.1) + - SocketRocket - Yoga - - React-Core/RCTAnimationHeaders (0.77.3): + - React-Core/RCTAnimationHeaders (0.81.5): + - boost + - DoubleConversion + - fast_float + - fmt - glog - hermes-engine - - RCT-Folly (= 2024.11.18.00) + - RCT-Folly + - RCT-Folly/Fabric - RCTDeprecation - React-Core/Default - React-cxxreact @@ -281,15 +404,23 @@ PODS: - React-jsi - React-jsiexecutor - React-jsinspector + - React-jsinspectorcdp + - React-jsitooling - React-perflogger + - React-runtimeexecutor - React-runtimescheduler - React-utils - - SocketRocket (= 0.7.1) + - SocketRocket - Yoga - - React-Core/RCTBlobHeaders (0.77.3): + - React-Core/RCTBlobHeaders (0.81.5): + - boost + - DoubleConversion + - fast_float + - fmt - glog - hermes-engine - - RCT-Folly (= 2024.11.18.00) + - RCT-Folly + - RCT-Folly/Fabric - RCTDeprecation - React-Core/Default - React-cxxreact @@ -298,15 +429,23 @@ PODS: - React-jsi - React-jsiexecutor - React-jsinspector + - React-jsinspectorcdp + - React-jsitooling - React-perflogger + - React-runtimeexecutor - React-runtimescheduler - React-utils - - SocketRocket (= 0.7.1) + - SocketRocket - Yoga - - React-Core/RCTImageHeaders (0.77.3): + - React-Core/RCTImageHeaders (0.81.5): + - boost + - DoubleConversion + - fast_float + - fmt - glog - hermes-engine - - RCT-Folly (= 2024.11.18.00) + - RCT-Folly + - RCT-Folly/Fabric - RCTDeprecation - React-Core/Default - React-cxxreact @@ -315,15 +454,23 @@ PODS: - React-jsi - React-jsiexecutor - React-jsinspector + - React-jsinspectorcdp + - React-jsitooling - React-perflogger + - React-runtimeexecutor - React-runtimescheduler - React-utils - - SocketRocket (= 0.7.1) + - SocketRocket - Yoga - - React-Core/RCTLinkingHeaders (0.77.3): + - React-Core/RCTLinkingHeaders (0.81.5): + - boost + - DoubleConversion + - fast_float + - fmt - glog - hermes-engine - - RCT-Folly (= 2024.11.18.00) + - RCT-Folly + - RCT-Folly/Fabric - RCTDeprecation - React-Core/Default - React-cxxreact @@ -332,15 +479,23 @@ PODS: - React-jsi - React-jsiexecutor - React-jsinspector + - React-jsinspectorcdp + - React-jsitooling - React-perflogger + - React-runtimeexecutor - React-runtimescheduler - React-utils - - SocketRocket (= 0.7.1) + - SocketRocket - Yoga - - React-Core/RCTNetworkHeaders (0.77.3): + - React-Core/RCTNetworkHeaders (0.81.5): + - boost + - DoubleConversion + - fast_float + - fmt - glog - hermes-engine - - RCT-Folly (= 2024.11.18.00) + - RCT-Folly + - RCT-Folly/Fabric - RCTDeprecation - React-Core/Default - React-cxxreact @@ -349,15 +504,23 @@ PODS: - React-jsi - React-jsiexecutor - React-jsinspector + - React-jsinspectorcdp + - React-jsitooling - React-perflogger + - React-runtimeexecutor - React-runtimescheduler - React-utils - - SocketRocket (= 0.7.1) + - SocketRocket - Yoga - - React-Core/RCTSettingsHeaders (0.77.3): + - React-Core/RCTSettingsHeaders (0.81.5): + - boost + - DoubleConversion + - fast_float + - fmt - glog - hermes-engine - - RCT-Folly (= 2024.11.18.00) + - RCT-Folly + - RCT-Folly/Fabric - RCTDeprecation - React-Core/Default - React-cxxreact @@ -366,15 +529,23 @@ PODS: - React-jsi - React-jsiexecutor - React-jsinspector + - React-jsinspectorcdp + - React-jsitooling - React-perflogger + - React-runtimeexecutor - React-runtimescheduler - React-utils - - SocketRocket (= 0.7.1) + - SocketRocket - Yoga - - React-Core/RCTTextHeaders (0.77.3): + - React-Core/RCTTextHeaders (0.81.5): + - boost + - DoubleConversion + - fast_float + - fmt - glog - hermes-engine - - RCT-Folly (= 2024.11.18.00) + - RCT-Folly + - RCT-Folly/Fabric - RCTDeprecation - React-Core/Default - React-cxxreact @@ -383,15 +554,23 @@ PODS: - React-jsi - React-jsiexecutor - React-jsinspector + - React-jsinspectorcdp + - React-jsitooling - React-perflogger + - React-runtimeexecutor - React-runtimescheduler - React-utils - - SocketRocket (= 0.7.1) + - SocketRocket - Yoga - - React-Core/RCTVibrationHeaders (0.77.3): + - React-Core/RCTVibrationHeaders (0.81.5): + - boost + - DoubleConversion + - fast_float + - fmt - glog - hermes-engine - - RCT-Folly (= 2024.11.18.00) + - RCT-Folly + - RCT-Folly/Fabric - RCTDeprecation - React-Core/Default - React-cxxreact @@ -400,63 +579,90 @@ PODS: - React-jsi - React-jsiexecutor - React-jsinspector + - React-jsinspectorcdp + - React-jsitooling - React-perflogger + - React-runtimeexecutor - React-runtimescheduler - React-utils - - SocketRocket (= 0.7.1) + - SocketRocket - Yoga - - React-Core/RCTWebSocket (0.77.3): + - React-Core/RCTWebSocket (0.81.5): + - boost + - DoubleConversion + - fast_float + - fmt - glog - hermes-engine - - RCT-Folly (= 2024.11.18.00) + - RCT-Folly + - RCT-Folly/Fabric - RCTDeprecation - - React-Core/Default (= 0.77.3) + - React-Core/Default (= 0.81.5) - React-cxxreact - React-featureflags - React-hermes - React-jsi - React-jsiexecutor - React-jsinspector + - React-jsinspectorcdp + - React-jsitooling - React-perflogger + - React-runtimeexecutor - React-runtimescheduler - React-utils - - SocketRocket (= 0.7.1) + - SocketRocket - Yoga - - React-CoreModules (0.77.3): + - React-CoreModules (0.81.5): + - boost - DoubleConversion - - fast_float (= 6.1.4) - - fmt (= 11.0.2) - - RCT-Folly (= 2024.11.18.00) - - RCTTypeSafety (= 0.77.3) - - React-Core/CoreModulesHeaders (= 0.77.3) - - React-jsi (= 0.77.3) + - fast_float + - fmt + - glog + - RCT-Folly + - RCT-Folly/Fabric + - RCTTypeSafety (= 0.81.5) + - React-Core/CoreModulesHeaders (= 0.81.5) + - React-jsi (= 0.81.5) - React-jsinspector + - React-jsinspectorcdp + - React-jsinspectortracing - React-NativeModulesApple - React-RCTBlob - React-RCTFBReactNativeSpec - - React-RCTImage (= 0.77.3) + - React-RCTImage (= 0.81.5) + - React-runtimeexecutor - ReactCommon - - SocketRocket (= 0.7.1) - - React-cxxreact (0.77.3): + - SocketRocket + - React-cxxreact (0.81.5): - boost - DoubleConversion - - fast_float (= 6.1.4) - - fmt (= 11.0.2) + - fast_float + - fmt - glog - hermes-engine - - RCT-Folly (= 2024.11.18.00) - - React-callinvoker (= 0.77.3) - - React-debug (= 0.77.3) - - React-jsi (= 0.77.3) + - RCT-Folly + - RCT-Folly/Fabric + - React-callinvoker (= 0.81.5) + - React-debug (= 0.81.5) + - React-jsi (= 0.81.5) - React-jsinspector - - React-logger (= 0.77.3) - - React-perflogger (= 0.77.3) - - React-runtimeexecutor (= 0.77.3) - - React-timing (= 0.77.3) - - React-debug (0.77.3) - - React-defaultsnativemodule (0.77.3): + - React-jsinspectorcdp + - React-jsinspectortracing + - React-logger (= 0.81.5) + - React-perflogger (= 0.81.5) + - React-runtimeexecutor + - React-timing (= 0.81.5) + - SocketRocket + - React-debug (0.81.5) + - React-defaultsnativemodule (0.81.5): + - boost + - DoubleConversion + - fast_float + - fmt + - glog - hermes-engine - RCT-Folly + - RCT-Folly/Fabric - React-domnativemodule - React-featureflagsnativemodule - React-idlecallbacksnativemodule @@ -464,60 +670,78 @@ PODS: - React-jsiexecutor - React-microtasksnativemodule - React-RCTFBReactNativeSpec - - React-domnativemodule (0.77.3): + - SocketRocket + - React-domnativemodule (0.81.5): + - boost + - DoubleConversion + - fast_float + - fmt + - glog - hermes-engine - RCT-Folly + - RCT-Folly/Fabric - React-Fabric + - React-Fabric/bridging - React-FabricComponents - React-graphics - React-jsi - React-jsiexecutor - React-RCTFBReactNativeSpec + - React-runtimeexecutor - ReactCommon/turbomodule/core + - SocketRocket - Yoga - - React-Fabric (0.77.3): + - React-Fabric (0.81.5): + - boost - DoubleConversion - - fast_float (= 6.1.4) - - fmt (= 11.0.2) + - fast_float + - fmt - glog - hermes-engine - - RCT-Folly/Fabric (= 2024.11.18.00) + - RCT-Folly + - RCT-Folly/Fabric - RCTRequired - RCTTypeSafety - React-Core - React-cxxreact - React-debug - - React-Fabric/animations (= 0.77.3) - - React-Fabric/attributedstring (= 0.77.3) - - React-Fabric/componentregistry (= 0.77.3) - - React-Fabric/componentregistrynative (= 0.77.3) - - React-Fabric/components (= 0.77.3) - - React-Fabric/core (= 0.77.3) - - React-Fabric/dom (= 0.77.3) - - React-Fabric/imagemanager (= 0.77.3) - - React-Fabric/leakchecker (= 0.77.3) - - React-Fabric/mounting (= 0.77.3) - - React-Fabric/observers (= 0.77.3) - - React-Fabric/scheduler (= 0.77.3) - - React-Fabric/telemetry (= 0.77.3) - - React-Fabric/templateprocessor (= 0.77.3) - - React-Fabric/uimanager (= 0.77.3) + - React-Fabric/animations (= 0.81.5) + - React-Fabric/attributedstring (= 0.81.5) + - React-Fabric/bridging (= 0.81.5) + - React-Fabric/componentregistry (= 0.81.5) + - React-Fabric/componentregistrynative (= 0.81.5) + - React-Fabric/components (= 0.81.5) + - React-Fabric/consistency (= 0.81.5) + - React-Fabric/core (= 0.81.5) + - React-Fabric/dom (= 0.81.5) + - React-Fabric/imagemanager (= 0.81.5) + - React-Fabric/leakchecker (= 0.81.5) + - React-Fabric/mounting (= 0.81.5) + - React-Fabric/observers (= 0.81.5) + - React-Fabric/scheduler (= 0.81.5) + - React-Fabric/telemetry (= 0.81.5) + - React-Fabric/templateprocessor (= 0.81.5) + - React-Fabric/uimanager (= 0.81.5) - React-featureflags - React-graphics - React-jsi - React-jsiexecutor - React-logger - React-rendererdebug + - React-runtimeexecutor - React-runtimescheduler - React-utils - ReactCommon/turbomodule/core - - React-Fabric/animations (0.77.3): + - SocketRocket + - React-Fabric/animations (0.81.5): + - boost - DoubleConversion - - fast_float (= 6.1.4) - - fmt (= 11.0.2) + - fast_float + - fmt - glog - hermes-engine - - RCT-Folly/Fabric (= 2024.11.18.00) + - RCT-Folly + - RCT-Folly/Fabric - RCTRequired - RCTTypeSafety - React-Core @@ -529,16 +753,20 @@ PODS: - React-jsiexecutor - React-logger - React-rendererdebug + - React-runtimeexecutor - React-runtimescheduler - React-utils - ReactCommon/turbomodule/core - - React-Fabric/attributedstring (0.77.3): + - SocketRocket + - React-Fabric/attributedstring (0.81.5): + - boost - DoubleConversion - - fast_float (= 6.1.4) - - fmt (= 11.0.2) + - fast_float + - fmt - glog - hermes-engine - - RCT-Folly/Fabric (= 2024.11.18.00) + - RCT-Folly + - RCT-Folly/Fabric - RCTRequired - RCTTypeSafety - React-Core @@ -550,16 +778,20 @@ PODS: - React-jsiexecutor - React-logger - React-rendererdebug + - React-runtimeexecutor - React-runtimescheduler - React-utils - ReactCommon/turbomodule/core - - React-Fabric/componentregistry (0.77.3): + - SocketRocket + - React-Fabric/bridging (0.81.5): + - boost - DoubleConversion - - fast_float (= 6.1.4) - - fmt (= 11.0.2) + - fast_float + - fmt - glog - hermes-engine - - RCT-Folly/Fabric (= 2024.11.18.00) + - RCT-Folly + - RCT-Folly/Fabric - RCTRequired - RCTTypeSafety - React-Core @@ -571,16 +803,20 @@ PODS: - React-jsiexecutor - React-logger - React-rendererdebug + - React-runtimeexecutor - React-runtimescheduler - React-utils - ReactCommon/turbomodule/core - - React-Fabric/componentregistrynative (0.77.3): + - SocketRocket + - React-Fabric/componentregistry (0.81.5): + - boost - DoubleConversion - - fast_float (= 6.1.4) - - fmt (= 11.0.2) + - fast_float + - fmt - glog - hermes-engine - - RCT-Folly/Fabric (= 2024.11.18.00) + - RCT-Folly + - RCT-Folly/Fabric - RCTRequired - RCTTypeSafety - React-Core @@ -592,61 +828,74 @@ PODS: - React-jsiexecutor - React-logger - React-rendererdebug + - React-runtimeexecutor - React-runtimescheduler - React-utils - ReactCommon/turbomodule/core - - React-Fabric/components (0.77.3): + - SocketRocket + - React-Fabric/componentregistrynative (0.81.5): + - boost - DoubleConversion - - fast_float (= 6.1.4) - - fmt (= 11.0.2) + - fast_float + - fmt - glog - hermes-engine - - RCT-Folly/Fabric (= 2024.11.18.00) + - RCT-Folly + - RCT-Folly/Fabric - RCTRequired - RCTTypeSafety - React-Core - React-cxxreact - React-debug - - React-Fabric/components/legacyviewmanagerinterop (= 0.77.3) - - React-Fabric/components/root (= 0.77.3) - - React-Fabric/components/view (= 0.77.3) - React-featureflags - React-graphics - React-jsi - React-jsiexecutor - React-logger - React-rendererdebug + - React-runtimeexecutor - React-runtimescheduler - React-utils - ReactCommon/turbomodule/core - - React-Fabric/components/legacyviewmanagerinterop (0.77.3): + - SocketRocket + - React-Fabric/components (0.81.5): + - boost - DoubleConversion - - fast_float (= 6.1.4) - - fmt (= 11.0.2) + - fast_float + - fmt - glog - hermes-engine - - RCT-Folly/Fabric (= 2024.11.18.00) + - RCT-Folly + - RCT-Folly/Fabric - RCTRequired - RCTTypeSafety - React-Core - React-cxxreact - React-debug + - React-Fabric/components/legacyviewmanagerinterop (= 0.81.5) + - React-Fabric/components/root (= 0.81.5) + - React-Fabric/components/scrollview (= 0.81.5) + - React-Fabric/components/view (= 0.81.5) - React-featureflags - React-graphics - React-jsi - React-jsiexecutor - React-logger - React-rendererdebug + - React-runtimeexecutor - React-runtimescheduler - React-utils - ReactCommon/turbomodule/core - - React-Fabric/components/root (0.77.3): + - SocketRocket + - React-Fabric/components/legacyviewmanagerinterop (0.81.5): + - boost - DoubleConversion - - fast_float (= 6.1.4) - - fmt (= 11.0.2) + - fast_float + - fmt - glog - hermes-engine - - RCT-Folly/Fabric (= 2024.11.18.00) + - RCT-Folly + - RCT-Folly/Fabric - RCTRequired - RCTTypeSafety - React-Core @@ -658,16 +907,20 @@ PODS: - React-jsiexecutor - React-logger - React-rendererdebug + - React-runtimeexecutor - React-runtimescheduler - React-utils - ReactCommon/turbomodule/core - - React-Fabric/components/view (0.77.3): + - SocketRocket + - React-Fabric/components/root (0.81.5): + - boost - DoubleConversion - - fast_float (= 6.1.4) - - fmt (= 11.0.2) + - fast_float + - fmt - glog - hermes-engine - - RCT-Folly/Fabric (= 2024.11.18.00) + - RCT-Folly + - RCT-Folly/Fabric - RCTRequired - RCTTypeSafety - React-Core @@ -679,17 +932,20 @@ PODS: - React-jsiexecutor - React-logger - React-rendererdebug + - React-runtimeexecutor - React-runtimescheduler - React-utils - ReactCommon/turbomodule/core - - Yoga - - React-Fabric/core (0.77.3): + - SocketRocket + - React-Fabric/components/scrollview (0.81.5): + - boost - DoubleConversion - - fast_float (= 6.1.4) - - fmt (= 11.0.2) + - fast_float + - fmt - glog - hermes-engine - - RCT-Folly/Fabric (= 2024.11.18.00) + - RCT-Folly + - RCT-Folly/Fabric - RCTRequired - RCTTypeSafety - React-Core @@ -701,16 +957,20 @@ PODS: - React-jsiexecutor - React-logger - React-rendererdebug + - React-runtimeexecutor - React-runtimescheduler - React-utils - ReactCommon/turbomodule/core - - React-Fabric/dom (0.77.3): + - SocketRocket + - React-Fabric/components/view (0.81.5): + - boost - DoubleConversion - - fast_float (= 6.1.4) - - fmt (= 11.0.2) + - fast_float + - fmt - glog - hermes-engine - - RCT-Folly/Fabric (= 2024.11.18.00) + - RCT-Folly + - RCT-Folly/Fabric - RCTRequired - RCTTypeSafety - React-Core @@ -721,17 +981,23 @@ PODS: - React-jsi - React-jsiexecutor - React-logger + - React-renderercss - React-rendererdebug + - React-runtimeexecutor - React-runtimescheduler - React-utils - ReactCommon/turbomodule/core - - React-Fabric/imagemanager (0.77.3): + - SocketRocket + - Yoga + - React-Fabric/consistency (0.81.5): + - boost - DoubleConversion - - fast_float (= 6.1.4) - - fmt (= 11.0.2) + - fast_float + - fmt - glog - hermes-engine - - RCT-Folly/Fabric (= 2024.11.18.00) + - RCT-Folly + - RCT-Folly/Fabric - RCTRequired - RCTTypeSafety - React-Core @@ -743,16 +1009,20 @@ PODS: - React-jsiexecutor - React-logger - React-rendererdebug + - React-runtimeexecutor - React-runtimescheduler - React-utils - ReactCommon/turbomodule/core - - React-Fabric/leakchecker (0.77.3): + - SocketRocket + - React-Fabric/core (0.81.5): + - boost - DoubleConversion - - fast_float (= 6.1.4) - - fmt (= 11.0.2) + - fast_float + - fmt - glog - hermes-engine - - RCT-Folly/Fabric (= 2024.11.18.00) + - RCT-Folly + - RCT-Folly/Fabric - RCTRequired - RCTTypeSafety - React-Core @@ -764,16 +1034,20 @@ PODS: - React-jsiexecutor - React-logger - React-rendererdebug + - React-runtimeexecutor - React-runtimescheduler - React-utils - ReactCommon/turbomodule/core - - React-Fabric/mounting (0.77.3): + - SocketRocket + - React-Fabric/dom (0.81.5): + - boost - DoubleConversion - - fast_float (= 6.1.4) - - fmt (= 11.0.2) + - fast_float + - fmt - glog - hermes-engine - - RCT-Folly/Fabric (= 2024.11.18.00) + - RCT-Folly + - RCT-Folly/Fabric - RCTRequired - RCTTypeSafety - React-Core @@ -785,38 +1059,45 @@ PODS: - React-jsiexecutor - React-logger - React-rendererdebug + - React-runtimeexecutor - React-runtimescheduler - React-utils - ReactCommon/turbomodule/core - - React-Fabric/observers (0.77.3): + - SocketRocket + - React-Fabric/imagemanager (0.81.5): + - boost - DoubleConversion - - fast_float (= 6.1.4) - - fmt (= 11.0.2) + - fast_float + - fmt - glog - hermes-engine - - RCT-Folly/Fabric (= 2024.11.18.00) + - RCT-Folly + - RCT-Folly/Fabric - RCTRequired - RCTTypeSafety - React-Core - React-cxxreact - React-debug - - React-Fabric/observers/events (= 0.77.3) - React-featureflags - React-graphics - React-jsi - React-jsiexecutor - React-logger - React-rendererdebug + - React-runtimeexecutor - React-runtimescheduler - React-utils - ReactCommon/turbomodule/core - - React-Fabric/observers/events (0.77.3): + - SocketRocket + - React-Fabric/leakchecker (0.81.5): + - boost - DoubleConversion - - fast_float (= 6.1.4) - - fmt (= 11.0.2) + - fast_float + - fmt - glog - hermes-engine - - RCT-Folly/Fabric (= 2024.11.18.00) + - RCT-Folly + - RCT-Folly/Fabric - RCTRequired - RCTTypeSafety - React-Core @@ -828,60 +1109,71 @@ PODS: - React-jsiexecutor - React-logger - React-rendererdebug + - React-runtimeexecutor - React-runtimescheduler - React-utils - ReactCommon/turbomodule/core - - React-Fabric/scheduler (0.77.3): + - SocketRocket + - React-Fabric/mounting (0.81.5): + - boost - DoubleConversion - - fast_float (= 6.1.4) - - fmt (= 11.0.2) + - fast_float + - fmt - glog - hermes-engine - - RCT-Folly/Fabric (= 2024.11.18.00) + - RCT-Folly + - RCT-Folly/Fabric - RCTRequired - RCTTypeSafety - React-Core - React-cxxreact - React-debug - - React-Fabric/observers/events - React-featureflags - React-graphics - React-jsi - React-jsiexecutor - React-logger - - React-performancetimeline - React-rendererdebug + - React-runtimeexecutor - React-runtimescheduler - React-utils - ReactCommon/turbomodule/core - - React-Fabric/telemetry (0.77.3): + - SocketRocket + - React-Fabric/observers (0.81.5): + - boost - DoubleConversion - - fast_float (= 6.1.4) - - fmt (= 11.0.2) + - fast_float + - fmt - glog - hermes-engine - - RCT-Folly/Fabric (= 2024.11.18.00) + - RCT-Folly + - RCT-Folly/Fabric - RCTRequired - RCTTypeSafety - React-Core - React-cxxreact - React-debug + - React-Fabric/observers/events (= 0.81.5) - React-featureflags - React-graphics - React-jsi - React-jsiexecutor - React-logger - React-rendererdebug + - React-runtimeexecutor - React-runtimescheduler - React-utils - ReactCommon/turbomodule/core - - React-Fabric/templateprocessor (0.77.3): + - SocketRocket + - React-Fabric/observers/events (0.81.5): + - boost - DoubleConversion - - fast_float (= 6.1.4) - - fmt (= 11.0.2) + - fast_float + - fmt - glog - hermes-engine - - RCT-Folly/Fabric (= 2024.11.18.00) + - RCT-Folly + - RCT-Folly/Fabric - RCTRequired - RCTTypeSafety - React-Core @@ -893,39 +1185,47 @@ PODS: - React-jsiexecutor - React-logger - React-rendererdebug + - React-runtimeexecutor - React-runtimescheduler - React-utils - ReactCommon/turbomodule/core - - React-Fabric/uimanager (0.77.3): + - SocketRocket + - React-Fabric/scheduler (0.81.5): + - boost - DoubleConversion - - fast_float (= 6.1.4) - - fmt (= 11.0.2) + - fast_float + - fmt - glog - hermes-engine - - RCT-Folly/Fabric (= 2024.11.18.00) + - RCT-Folly + - RCT-Folly/Fabric - RCTRequired - RCTTypeSafety - React-Core - React-cxxreact - React-debug - - React-Fabric/uimanager/consistency (= 0.77.3) + - React-Fabric/observers/events - React-featureflags - React-graphics - React-jsi - React-jsiexecutor - React-logger - - React-rendererconsistency + - React-performancetimeline - React-rendererdebug + - React-runtimeexecutor - React-runtimescheduler - React-utils - ReactCommon/turbomodule/core - - React-Fabric/uimanager/consistency (0.77.3): + - SocketRocket + - React-Fabric/telemetry (0.81.5): + - boost - DoubleConversion - - fast_float (= 6.1.4) - - fmt (= 11.0.2) + - fast_float + - fmt - glog - hermes-engine - - RCT-Folly/Fabric (= 2024.11.18.00) + - RCT-Folly + - RCT-Folly/Fabric - RCTRequired - RCTTypeSafety - React-Core @@ -936,144 +1236,166 @@ PODS: - React-jsi - React-jsiexecutor - React-logger - - React-rendererconsistency - React-rendererdebug + - React-runtimeexecutor - React-runtimescheduler - React-utils - ReactCommon/turbomodule/core - - React-FabricComponents (0.77.3): + - SocketRocket + - React-Fabric/templateprocessor (0.81.5): + - boost - DoubleConversion - - fast_float (= 6.1.4) - - fmt (= 11.0.2) + - fast_float + - fmt - glog - hermes-engine - - RCT-Folly/Fabric (= 2024.11.18.00) + - RCT-Folly + - RCT-Folly/Fabric - RCTRequired - RCTTypeSafety - React-Core - React-cxxreact - React-debug - - React-Fabric - - React-FabricComponents/components (= 0.77.3) - - React-FabricComponents/textlayoutmanager (= 0.77.3) - React-featureflags - React-graphics - React-jsi - React-jsiexecutor - React-logger - React-rendererdebug + - React-runtimeexecutor - React-runtimescheduler - React-utils - ReactCommon/turbomodule/core - - Yoga - - React-FabricComponents/components (0.77.3): + - SocketRocket + - React-Fabric/uimanager (0.81.5): + - boost - DoubleConversion - - fast_float (= 6.1.4) - - fmt (= 11.0.2) + - fast_float + - fmt - glog - hermes-engine - - RCT-Folly/Fabric (= 2024.11.18.00) + - RCT-Folly + - RCT-Folly/Fabric - RCTRequired - RCTTypeSafety - React-Core - React-cxxreact - React-debug - - React-Fabric - - React-FabricComponents/components/inputaccessory (= 0.77.3) - - React-FabricComponents/components/iostextinput (= 0.77.3) - - React-FabricComponents/components/modal (= 0.77.3) - - React-FabricComponents/components/rncore (= 0.77.3) - - React-FabricComponents/components/safeareaview (= 0.77.3) - - React-FabricComponents/components/scrollview (= 0.77.3) - - React-FabricComponents/components/text (= 0.77.3) - - React-FabricComponents/components/textinput (= 0.77.3) - - React-FabricComponents/components/unimplementedview (= 0.77.3) + - React-Fabric/uimanager/consistency (= 0.81.5) - React-featureflags - React-graphics - React-jsi - React-jsiexecutor - React-logger + - React-rendererconsistency - React-rendererdebug + - React-runtimeexecutor - React-runtimescheduler - React-utils - ReactCommon/turbomodule/core - - Yoga - - React-FabricComponents/components/inputaccessory (0.77.3): + - SocketRocket + - React-Fabric/uimanager/consistency (0.81.5): + - boost - DoubleConversion - - fast_float (= 6.1.4) - - fmt (= 11.0.2) + - fast_float + - fmt - glog - hermes-engine - - RCT-Folly/Fabric (= 2024.11.18.00) + - RCT-Folly + - RCT-Folly/Fabric - RCTRequired - RCTTypeSafety - React-Core - React-cxxreact - React-debug - - React-Fabric - React-featureflags - React-graphics - React-jsi - React-jsiexecutor - React-logger + - React-rendererconsistency - React-rendererdebug + - React-runtimeexecutor - React-runtimescheduler - React-utils - ReactCommon/turbomodule/core - - Yoga - - React-FabricComponents/components/iostextinput (0.77.3): + - SocketRocket + - React-FabricComponents (0.81.5): + - boost - DoubleConversion - - fast_float (= 6.1.4) - - fmt (= 11.0.2) + - fast_float + - fmt - glog - hermes-engine - - RCT-Folly/Fabric (= 2024.11.18.00) + - RCT-Folly + - RCT-Folly/Fabric - RCTRequired - RCTTypeSafety - React-Core - React-cxxreact - React-debug - React-Fabric + - React-FabricComponents/components (= 0.81.5) + - React-FabricComponents/textlayoutmanager (= 0.81.5) - React-featureflags - React-graphics - React-jsi - React-jsiexecutor - React-logger + - React-RCTFBReactNativeSpec - React-rendererdebug - React-runtimescheduler - React-utils - ReactCommon/turbomodule/core + - SocketRocket - Yoga - - React-FabricComponents/components/modal (0.77.3): + - React-FabricComponents/components (0.81.5): + - boost - DoubleConversion - - fast_float (= 6.1.4) - - fmt (= 11.0.2) + - fast_float + - fmt - glog - hermes-engine - - RCT-Folly/Fabric (= 2024.11.18.00) + - RCT-Folly + - RCT-Folly/Fabric - RCTRequired - RCTTypeSafety - React-Core - React-cxxreact - React-debug - React-Fabric + - React-FabricComponents/components/inputaccessory (= 0.81.5) + - React-FabricComponents/components/iostextinput (= 0.81.5) + - React-FabricComponents/components/modal (= 0.81.5) + - React-FabricComponents/components/rncore (= 0.81.5) + - React-FabricComponents/components/safeareaview (= 0.81.5) + - React-FabricComponents/components/scrollview (= 0.81.5) + - React-FabricComponents/components/switch (= 0.81.5) + - React-FabricComponents/components/text (= 0.81.5) + - React-FabricComponents/components/textinput (= 0.81.5) + - React-FabricComponents/components/unimplementedview (= 0.81.5) + - React-FabricComponents/components/virtualview (= 0.81.5) - React-featureflags - React-graphics - React-jsi - React-jsiexecutor - React-logger + - React-RCTFBReactNativeSpec - React-rendererdebug - React-runtimescheduler - React-utils - ReactCommon/turbomodule/core + - SocketRocket - Yoga - - React-FabricComponents/components/rncore (0.77.3): + - React-FabricComponents/components/inputaccessory (0.81.5): + - boost - DoubleConversion - - fast_float (= 6.1.4) - - fmt (= 11.0.2) + - fast_float + - fmt - glog - hermes-engine - - RCT-Folly/Fabric (= 2024.11.18.00) + - RCT-Folly + - RCT-Folly/Fabric - RCTRequired - RCTTypeSafety - React-Core @@ -1085,18 +1407,22 @@ PODS: - React-jsi - React-jsiexecutor - React-logger + - React-RCTFBReactNativeSpec - React-rendererdebug - React-runtimescheduler - React-utils - ReactCommon/turbomodule/core + - SocketRocket - Yoga - - React-FabricComponents/components/safeareaview (0.77.3): + - React-FabricComponents/components/iostextinput (0.81.5): + - boost - DoubleConversion - - fast_float (= 6.1.4) - - fmt (= 11.0.2) + - fast_float + - fmt - glog - hermes-engine - - RCT-Folly/Fabric (= 2024.11.18.00) + - RCT-Folly + - RCT-Folly/Fabric - RCTRequired - RCTTypeSafety - React-Core @@ -1108,18 +1434,22 @@ PODS: - React-jsi - React-jsiexecutor - React-logger + - React-RCTFBReactNativeSpec - React-rendererdebug - React-runtimescheduler - React-utils - ReactCommon/turbomodule/core + - SocketRocket - Yoga - - React-FabricComponents/components/scrollview (0.77.3): + - React-FabricComponents/components/modal (0.81.5): + - boost - DoubleConversion - - fast_float (= 6.1.4) - - fmt (= 11.0.2) + - fast_float + - fmt - glog - hermes-engine - - RCT-Folly/Fabric (= 2024.11.18.00) + - RCT-Folly + - RCT-Folly/Fabric - RCTRequired - RCTTypeSafety - React-Core @@ -1131,18 +1461,22 @@ PODS: - React-jsi - React-jsiexecutor - React-logger + - React-RCTFBReactNativeSpec - React-rendererdebug - React-runtimescheduler - React-utils - ReactCommon/turbomodule/core + - SocketRocket - Yoga - - React-FabricComponents/components/text (0.77.3): + - React-FabricComponents/components/rncore (0.81.5): + - boost - DoubleConversion - - fast_float (= 6.1.4) - - fmt (= 11.0.2) + - fast_float + - fmt - glog - hermes-engine - - RCT-Folly/Fabric (= 2024.11.18.00) + - RCT-Folly + - RCT-Folly/Fabric - RCTRequired - RCTTypeSafety - React-Core @@ -1154,18 +1488,22 @@ PODS: - React-jsi - React-jsiexecutor - React-logger + - React-RCTFBReactNativeSpec - React-rendererdebug - React-runtimescheduler - React-utils - ReactCommon/turbomodule/core + - SocketRocket - Yoga - - React-FabricComponents/components/textinput (0.77.3): + - React-FabricComponents/components/safeareaview (0.81.5): + - boost - DoubleConversion - - fast_float (= 6.1.4) - - fmt (= 11.0.2) + - fast_float + - fmt - glog - hermes-engine - - RCT-Folly/Fabric (= 2024.11.18.00) + - RCT-Folly + - RCT-Folly/Fabric - RCTRequired - RCTTypeSafety - React-Core @@ -1177,18 +1515,22 @@ PODS: - React-jsi - React-jsiexecutor - React-logger + - React-RCTFBReactNativeSpec - React-rendererdebug - React-runtimescheduler - React-utils - ReactCommon/turbomodule/core + - SocketRocket - Yoga - - React-FabricComponents/components/unimplementedview (0.77.3): + - React-FabricComponents/components/scrollview (0.81.5): + - boost - DoubleConversion - - fast_float (= 6.1.4) - - fmt (= 11.0.2) + - fast_float + - fmt - glog - hermes-engine - - RCT-Folly/Fabric (= 2024.11.18.00) + - RCT-Folly + - RCT-Folly/Fabric - RCTRequired - RCTTypeSafety - React-Core @@ -1200,18 +1542,22 @@ PODS: - React-jsi - React-jsiexecutor - React-logger + - React-RCTFBReactNativeSpec - React-rendererdebug - React-runtimescheduler - React-utils - ReactCommon/turbomodule/core + - SocketRocket - Yoga - - React-FabricComponents/textlayoutmanager (0.77.3): + - React-FabricComponents/components/switch (0.81.5): + - boost - DoubleConversion - - fast_float (= 6.1.4) - - fmt (= 11.0.2) + - fast_float + - fmt - glog - hermes-engine - - RCT-Folly/Fabric (= 2024.11.18.00) + - RCT-Folly + - RCT-Folly/Fabric - RCTRequired - RCTTypeSafety - React-Core @@ -1223,210 +1569,534 @@ PODS: - React-jsi - React-jsiexecutor - React-logger + - React-RCTFBReactNativeSpec - React-rendererdebug - React-runtimescheduler - React-utils - ReactCommon/turbomodule/core + - SocketRocket - Yoga - - React-FabricImage (0.77.3): + - React-FabricComponents/components/text (0.81.5): + - boost - DoubleConversion - - fast_float (= 6.1.4) - - fmt (= 11.0.2) + - fast_float + - fmt - glog - hermes-engine - - RCT-Folly/Fabric (= 2024.11.18.00) - - RCTRequired (= 0.77.3) - - RCTTypeSafety (= 0.77.3) + - RCT-Folly + - RCT-Folly/Fabric + - RCTRequired + - RCTTypeSafety + - React-Core + - React-cxxreact + - React-debug - React-Fabric - React-featureflags - React-graphics - - React-ImageManager - React-jsi - - React-jsiexecutor (= 0.77.3) + - React-jsiexecutor - React-logger + - React-RCTFBReactNativeSpec - React-rendererdebug + - React-runtimescheduler - React-utils - - ReactCommon - - Yoga - - React-featureflags (0.77.3) - - React-featureflagsnativemodule (0.77.3): - - hermes-engine - - RCT-Folly - - React-featureflags - - React-jsi - - React-jsiexecutor - - React-RCTFBReactNativeSpec - ReactCommon/turbomodule/core - - React-graphics (0.77.3): - - DoubleConversion - - fast_float (= 6.1.4) - - fmt (= 11.0.2) - - glog - - RCT-Folly/Fabric (= 2024.11.18.00) - - React-jsi - - React-jsiexecutor - - React-utils - - React-hermes (0.77.3): + - SocketRocket + - Yoga + - React-FabricComponents/components/textinput (0.81.5): + - boost - DoubleConversion - - fast_float (= 6.1.4) - - fmt (= 11.0.2) + - fast_float + - fmt - glog - - hermes-engine - - RCT-Folly (= 2024.11.18.00) - - React-cxxreact (= 0.77.3) - - React-jsi - - React-jsiexecutor (= 0.77.3) - - React-jsinspector - - React-perflogger (= 0.77.3) - - React-runtimeexecutor - - React-idlecallbacksnativemodule (0.77.3): - hermes-engine - RCT-Folly - - React-jsi - - React-jsiexecutor - - React-RCTFBReactNativeSpec - - React-runtimescheduler - - ReactCommon/turbomodule/core - - React-ImageManager (0.77.3): - - glog - RCT-Folly/Fabric - - React-Core/Default + - RCTRequired + - RCTTypeSafety + - React-Core + - React-cxxreact - React-debug - React-Fabric + - React-featureflags - React-graphics + - React-jsi + - React-jsiexecutor + - React-logger + - React-RCTFBReactNativeSpec - React-rendererdebug + - React-runtimescheduler - React-utils - - React-jserrorhandler (0.77.3): - - glog - - hermes-engine - - RCT-Folly/Fabric (= 2024.11.18.00) - - React-cxxreact - - React-debug - - React-featureflags - - React-jsi - - ReactCommon/turbomodule/bridging - - React-jsi (0.77.3): + - ReactCommon/turbomodule/core + - SocketRocket + - Yoga + - React-FabricComponents/components/unimplementedview (0.81.5): - boost - DoubleConversion - - fast_float (= 6.1.4) - - fmt (= 11.0.2) - - glog - - hermes-engine - - RCT-Folly (= 2024.11.18.00) - - React-jsiexecutor (0.77.3): - - DoubleConversion - - fast_float (= 6.1.4) - - fmt (= 11.0.2) - - glog - - hermes-engine - - RCT-Folly (= 2024.11.18.00) - - React-cxxreact (= 0.77.3) - - React-jsi (= 0.77.3) - - React-jsinspector - - React-perflogger (= 0.77.3) - - React-jsinspector (0.77.3): - - DoubleConversion - - glog - - hermes-engine - - RCT-Folly (= 2024.11.18.00) - - React-featureflags - - React-jsi - - React-perflogger (= 0.77.3) - - React-runtimeexecutor (= 0.77.3) - - React-jsitracing (0.77.3): - - React-jsi - - React-logger (0.77.3): - - glog - - React-Mapbuffer (0.77.3): + - fast_float + - fmt - glog - - React-debug - - React-microtasksnativemodule (0.77.3): - hermes-engine - RCT-Folly + - RCT-Folly/Fabric + - RCTRequired + - RCTTypeSafety + - React-Core + - React-cxxreact + - React-debug + - React-Fabric + - React-featureflags + - React-graphics - React-jsi - React-jsiexecutor + - React-logger - React-RCTFBReactNativeSpec + - React-rendererdebug + - React-runtimescheduler + - React-utils - ReactCommon/turbomodule/core - - react-native-attestation (0.1.0-alpha.1): + - SocketRocket + - Yoga + - React-FabricComponents/components/virtualview (0.81.5): + - boost - DoubleConversion + - fast_float + - fmt - glog - hermes-engine - - RCT-Folly (= 2024.11.18.00) + - RCT-Folly + - RCT-Folly/Fabric - RCTRequired - RCTTypeSafety - React-Core + - React-cxxreact - React-debug - React-Fabric - React-featureflags - React-graphics - - React-ImageManager - - React-NativeModulesApple - - React-RCTFabric + - React-jsi + - React-jsiexecutor + - React-logger + - React-RCTFBReactNativeSpec - React-rendererdebug + - React-runtimescheduler - React-utils - - ReactCodegen - - ReactCommon/turbomodule/bridging - ReactCommon/turbomodule/core + - SocketRocket - Yoga - - react-native-config (1.5.5): - - react-native-config/App (= 1.5.5) - - react-native-config/App (1.5.5): - - React-Core - - react-native-date-picker (5.0.13): + - React-FabricComponents/textlayoutmanager (0.81.5): + - boost - DoubleConversion + - fast_float + - fmt - glog - hermes-engine - - RCT-Folly (= 2024.11.18.00) + - RCT-Folly + - RCT-Folly/Fabric - RCTRequired - RCTTypeSafety - React-Core + - React-cxxreact - React-debug - React-Fabric - React-featureflags - React-graphics - - React-ImageManager - - React-NativeModulesApple - - React-RCTFabric + - React-jsi + - React-jsiexecutor + - React-logger + - React-RCTFBReactNativeSpec - React-rendererdebug + - React-runtimescheduler - React-utils - - ReactCodegen - - ReactCommon/turbomodule/bridging - ReactCommon/turbomodule/core + - SocketRocket - Yoga - - react-native-document-picker (9.3.1): + - React-FabricImage (0.81.5): + - boost - DoubleConversion + - fast_float + - fmt - glog - hermes-engine - - RCT-Folly (= 2024.11.18.00) - - RCTRequired - - RCTTypeSafety - - React-Core - - React-debug + - RCT-Folly + - RCT-Folly/Fabric + - RCTRequired (= 0.81.5) + - RCTTypeSafety (= 0.81.5) - React-Fabric - React-featureflags - React-graphics - React-ImageManager - - React-NativeModulesApple - - React-RCTFabric + - React-jsi + - React-jsiexecutor (= 0.81.5) + - React-logger + - React-rendererdebug + - React-utils + - ReactCommon + - SocketRocket + - Yoga + - React-featureflags (0.81.5): + - boost + - DoubleConversion + - fast_float + - fmt + - glog + - RCT-Folly + - RCT-Folly/Fabric + - SocketRocket + - React-featureflagsnativemodule (0.81.5): + - boost + - DoubleConversion + - fast_float + - fmt + - glog + - hermes-engine + - RCT-Folly + - RCT-Folly/Fabric + - React-featureflags + - React-jsi + - React-jsiexecutor + - React-RCTFBReactNativeSpec + - ReactCommon/turbomodule/core + - SocketRocket + - React-graphics (0.81.5): + - boost + - DoubleConversion + - fast_float + - fmt + - glog + - hermes-engine + - RCT-Folly + - RCT-Folly/Fabric + - React-jsi + - React-jsiexecutor + - React-utils + - SocketRocket + - React-hermes (0.81.5): + - boost + - DoubleConversion + - fast_float + - fmt + - glog + - hermes-engine + - RCT-Folly + - RCT-Folly/Fabric + - React-cxxreact (= 0.81.5) + - React-jsi + - React-jsiexecutor (= 0.81.5) + - React-jsinspector + - React-jsinspectorcdp + - React-jsinspectortracing + - React-perflogger (= 0.81.5) + - React-runtimeexecutor + - SocketRocket + - React-idlecallbacksnativemodule (0.81.5): + - boost + - DoubleConversion + - fast_float + - fmt + - glog + - hermes-engine + - RCT-Folly + - RCT-Folly/Fabric + - React-jsi + - React-jsiexecutor + - React-RCTFBReactNativeSpec + - React-runtimeexecutor + - React-runtimescheduler + - ReactCommon/turbomodule/core + - SocketRocket + - React-ImageManager (0.81.5): + - boost + - DoubleConversion + - fast_float + - fmt + - glog + - RCT-Folly + - RCT-Folly/Fabric + - React-Core/Default + - React-debug + - React-Fabric + - React-graphics + - React-rendererdebug + - React-utils + - SocketRocket + - React-jserrorhandler (0.81.5): + - boost + - DoubleConversion + - fast_float + - fmt + - glog + - hermes-engine + - RCT-Folly + - RCT-Folly/Fabric + - React-cxxreact + - React-debug + - React-featureflags + - React-jsi + - ReactCommon/turbomodule/bridging + - SocketRocket + - React-jsi (0.81.5): + - boost + - DoubleConversion + - fast_float + - fmt + - glog + - hermes-engine + - RCT-Folly + - RCT-Folly/Fabric + - SocketRocket + - React-jsiexecutor (0.81.5): + - boost + - DoubleConversion + - fast_float + - fmt + - glog + - hermes-engine + - RCT-Folly + - RCT-Folly/Fabric + - React-cxxreact (= 0.81.5) + - React-jsi (= 0.81.5) + - React-jsinspector + - React-jsinspectorcdp + - React-jsinspectortracing + - React-perflogger (= 0.81.5) + - React-runtimeexecutor + - SocketRocket + - React-jsinspector (0.81.5): + - boost + - DoubleConversion + - fast_float + - fmt + - glog + - hermes-engine + - RCT-Folly + - RCT-Folly/Fabric + - React-featureflags + - React-jsi + - React-jsinspectorcdp + - React-jsinspectornetwork + - React-jsinspectortracing + - React-oscompat + - React-perflogger (= 0.81.5) + - React-runtimeexecutor + - SocketRocket + - React-jsinspectorcdp (0.81.5): + - boost + - DoubleConversion + - fast_float + - fmt + - glog + - RCT-Folly + - RCT-Folly/Fabric + - SocketRocket + - React-jsinspectornetwork (0.81.5): + - boost + - DoubleConversion + - fast_float + - fmt + - glog + - RCT-Folly + - RCT-Folly/Fabric + - React-featureflags + - React-jsinspectorcdp + - React-performancetimeline + - React-timing + - SocketRocket + - React-jsinspectortracing (0.81.5): + - boost + - DoubleConversion + - fast_float + - fmt + - glog + - RCT-Folly + - RCT-Folly/Fabric + - React-oscompat + - React-timing + - SocketRocket + - React-jsitooling (0.81.5): + - boost + - DoubleConversion + - fast_float + - fmt + - glog + - RCT-Folly + - RCT-Folly/Fabric + - React-cxxreact (= 0.81.5) + - React-jsi (= 0.81.5) + - React-jsinspector + - React-jsinspectorcdp + - React-jsinspectortracing + - React-runtimeexecutor + - SocketRocket + - React-jsitracing (0.81.5): + - React-jsi + - React-logger (0.81.5): + - boost + - DoubleConversion + - fast_float + - fmt + - glog + - RCT-Folly + - RCT-Folly/Fabric + - SocketRocket + - React-Mapbuffer (0.81.5): + - boost + - DoubleConversion + - fast_float + - fmt + - glog + - RCT-Folly + - RCT-Folly/Fabric + - React-debug + - SocketRocket + - React-microtasksnativemodule (0.81.5): + - boost + - DoubleConversion + - fast_float + - fmt + - glog + - hermes-engine + - RCT-Folly + - RCT-Folly/Fabric + - React-jsi + - React-jsiexecutor + - React-RCTFBReactNativeSpec + - ReactCommon/turbomodule/core + - SocketRocket + - react-native-attestation (3.0.16): + - boost + - DoubleConversion + - fast_float + - fmt + - glog + - hermes-engine + - RCT-Folly + - RCT-Folly/Fabric + - RCTRequired + - RCTTypeSafety + - React-Core + - React-debug + - React-Fabric + - React-featureflags + - React-graphics + - React-ImageManager + - React-jsi + - React-NativeModulesApple + - React-RCTFabric + - React-renderercss + - React-rendererdebug + - React-utils + - ReactCodegen + - ReactCommon/turbomodule/bridging + - ReactCommon/turbomodule/core + - SocketRocket + - Yoga + - react-native-config (1.5.5): + - react-native-config/App (= 1.5.5) + - react-native-config/App (1.5.5): + - React-Core + - react-native-document-picker (9.3.1): + - boost + - DoubleConversion + - fast_float + - fmt + - glog + - hermes-engine + - RCT-Folly + - RCT-Folly/Fabric + - RCTRequired + - RCTTypeSafety + - React-Core + - React-debug + - React-Fabric + - React-featureflags + - React-graphics + - React-ImageManager + - React-jsi + - React-NativeModulesApple + - React-RCTFabric + - React-renderercss - React-rendererdebug - React-utils - ReactCodegen - ReactCommon/turbomodule/bridging - ReactCommon/turbomodule/core + - SocketRocket - Yoga - react-native-encrypted-storage (4.0.3): - React-Core - react-native-get-random-values (1.11.0): - React-Core - - react-native-netinfo (11.3.3): + - react-native-keyboard-controller (1.18.6): + - boost + - DoubleConversion + - fast_float + - fmt + - glog + - hermes-engine + - RCT-Folly + - RCT-Folly/Fabric + - RCTRequired + - RCTTypeSafety + - React-Core + - React-debug + - React-Fabric + - React-featureflags + - React-graphics + - React-ImageManager + - React-jsi + - react-native-keyboard-controller/common (= 1.18.6) + - React-NativeModulesApple + - React-RCTFabric + - React-renderercss + - React-rendererdebug + - React-utils + - ReactCodegen + - ReactCommon/turbomodule/bridging + - ReactCommon/turbomodule/core + - SocketRocket + - Yoga + - react-native-keyboard-controller/common (1.18.6): + - boost + - DoubleConversion + - fast_float + - fmt + - glog + - hermes-engine + - RCT-Folly + - RCT-Folly/Fabric + - RCTRequired + - RCTTypeSafety + - React-Core + - React-debug + - React-Fabric + - React-featureflags + - React-graphics + - React-ImageManager + - React-jsi + - React-NativeModulesApple + - React-RCTFabric + - React-renderercss + - React-rendererdebug + - React-utils + - ReactCodegen + - ReactCommon/turbomodule/bridging + - ReactCommon/turbomodule/core + - SocketRocket + - Yoga + - react-native-netinfo (11.4.1): - React-Core - react-native-orientation-locker (1.6.0): - React-Core - - react-native-safe-area-context (5.1.0): + - react-native-safe-area-context (5.6.2): + - boost - DoubleConversion + - fast_float + - fmt - glog - hermes-engine - - RCT-Folly (= 2024.11.18.00) + - RCT-Folly + - RCT-Folly/Fabric - RCTRequired - RCTTypeSafety - React-Core @@ -1435,21 +2105,28 @@ PODS: - React-featureflags - React-graphics - React-ImageManager - - react-native-safe-area-context/common (= 5.1.0) - - react-native-safe-area-context/fabric (= 5.1.0) + - React-jsi + - react-native-safe-area-context/common (= 5.6.2) + - react-native-safe-area-context/fabric (= 5.6.2) - React-NativeModulesApple - React-RCTFabric + - React-renderercss - React-rendererdebug - React-utils - ReactCodegen - ReactCommon/turbomodule/bridging - ReactCommon/turbomodule/core + - SocketRocket - Yoga - - react-native-safe-area-context/common (5.1.0): + - react-native-safe-area-context/common (5.6.2): + - boost - DoubleConversion + - fast_float + - fmt - glog - hermes-engine - - RCT-Folly (= 2024.11.18.00) + - RCT-Folly + - RCT-Folly/Fabric - RCTRequired - RCTTypeSafety - React-Core @@ -1458,19 +2135,26 @@ PODS: - React-featureflags - React-graphics - React-ImageManager + - React-jsi - React-NativeModulesApple - React-RCTFabric + - React-renderercss - React-rendererdebug - React-utils - ReactCodegen - ReactCommon/turbomodule/bridging - ReactCommon/turbomodule/core + - SocketRocket - Yoga - - react-native-safe-area-context/fabric (5.1.0): + - react-native-safe-area-context/fabric (5.6.2): + - boost - DoubleConversion + - fast_float + - fmt - glog - hermes-engine - - RCT-Folly (= 2024.11.18.00) + - RCT-Folly + - RCT-Folly/Fabric - RCTRequired - RCTTypeSafety - React-Core @@ -1479,20 +2163,27 @@ PODS: - React-featureflags - React-graphics - React-ImageManager + - React-jsi - react-native-safe-area-context/common - React-NativeModulesApple - React-RCTFabric + - React-renderercss - React-rendererdebug - React-utils - ReactCodegen - ReactCommon/turbomodule/bridging - ReactCommon/turbomodule/core + - SocketRocket - Yoga - react-native-screenguard (1.1.0): + - boost - DoubleConversion + - fast_float + - fmt - glog - hermes-engine - - RCT-Folly (= 2024.11.18.00) + - RCT-Folly + - RCT-Folly/Fabric - RCTRequired - RCTTypeSafety - React-Core @@ -1501,14 +2192,17 @@ PODS: - React-featureflags - React-graphics - React-ImageManager + - React-jsi - React-NativeModulesApple - React-RCTFabric + - React-renderercss - React-rendererdebug - React-utils - ReactCodegen - ReactCommon/turbomodule/bridging - ReactCommon/turbomodule/core - SDWebImage (~> 5.21.0) + - SocketRocket - Yoga - react-native-splash-screen (3.3.0): - React-Core @@ -1516,10 +2210,14 @@ PODS: - CocoaAsyncSocket - React-Core - react-native-video (6.16.1): + - boost - DoubleConversion + - fast_float + - fmt - glog - hermes-engine - - RCT-Folly (= 2024.11.18.00) + - RCT-Folly + - RCT-Folly/Fabric - RCTRequired - RCTTypeSafety - React-Core @@ -1528,20 +2226,27 @@ PODS: - React-featureflags - React-graphics - React-ImageManager + - React-jsi - react-native-video/Video (= 6.16.1) - React-NativeModulesApple - React-RCTFabric + - React-renderercss - React-rendererdebug - React-utils - ReactCodegen - ReactCommon/turbomodule/bridging - ReactCommon/turbomodule/core + - SocketRocket - Yoga - react-native-video/Fabric (6.16.1): + - boost - DoubleConversion + - fast_float + - fmt - glog - hermes-engine - - RCT-Folly (= 2024.11.18.00) + - RCT-Folly + - RCT-Folly/Fabric - RCTRequired - RCTTypeSafety - React-Core @@ -1550,19 +2255,26 @@ PODS: - React-featureflags - React-graphics - React-ImageManager + - React-jsi - React-NativeModulesApple - React-RCTFabric + - React-renderercss - React-rendererdebug - React-utils - ReactCodegen - ReactCommon/turbomodule/bridging - ReactCommon/turbomodule/core + - SocketRocket - Yoga - react-native-video/Video (6.16.1): + - boost - DoubleConversion + - fast_float + - fmt - glog - hermes-engine - - RCT-Folly (= 2024.11.18.00) + - RCT-Folly + - RCT-Folly/Fabric - RCTRequired - RCTTypeSafety - React-Core @@ -1571,14 +2283,17 @@ PODS: - React-featureflags - React-graphics - React-ImageManager + - React-jsi - react-native-video/Fabric - React-NativeModulesApple - React-RCTFabric + - React-renderercss - React-rendererdebug - React-utils - ReactCodegen - ReactCommon/turbomodule/bridging - ReactCommon/turbomodule/core + - SocketRocket - Yoga - react-native-volume-manager (1.10.0): - Mute @@ -1586,11 +2301,15 @@ PODS: - react-native-webrtc (124.0.6): - JitsiWebRTC (~> 124.0.0) - React-Core - - react-native-webview (13.13.5): + - react-native-webview (13.15.0): + - boost - DoubleConversion + - fast_float + - fmt - glog - hermes-engine - - RCT-Folly (= 2024.11.18.00) + - RCT-Folly + - RCT-Folly/Fabric - RCTRequired - RCTTypeSafety - React-Core @@ -1599,48 +2318,89 @@ PODS: - React-featureflags - React-graphics - React-ImageManager + - React-jsi - React-NativeModulesApple - React-RCTFabric + - React-renderercss - React-rendererdebug - React-utils - ReactCodegen - ReactCommon/turbomodule/bridging - ReactCommon/turbomodule/core + - SocketRocket - Yoga - react-native-zeroconf (0.14.0): - React-Core - - React-nativeconfig (0.77.3) - - React-NativeModulesApple (0.77.3): + - React-NativeModulesApple (0.81.5): + - boost + - DoubleConversion + - fast_float + - fmt - glog - hermes-engine + - RCT-Folly + - RCT-Folly/Fabric - React-callinvoker - React-Core - React-cxxreact + - React-featureflags - React-jsi - React-jsinspector + - React-jsinspectorcdp - React-runtimeexecutor - ReactCommon/turbomodule/bridging - ReactCommon/turbomodule/core - - React-perflogger (0.77.3): + - SocketRocket + - React-oscompat (0.81.5) + - React-perflogger (0.81.5): + - boost - DoubleConversion - - RCT-Folly (= 2024.11.18.00) - - React-performancetimeline (0.77.3): - - RCT-Folly (= 2024.11.18.00) - - React-cxxreact + - fast_float + - fmt + - glog + - RCT-Folly + - RCT-Folly/Fabric + - SocketRocket + - React-performancetimeline (0.81.5): + - boost + - DoubleConversion + - fast_float + - fmt + - glog + - RCT-Folly + - RCT-Folly/Fabric - React-featureflags + - React-jsinspectortracing + - React-perflogger - React-timing - - React-RCTActionSheet (0.77.3): - - React-Core/RCTActionSheetHeaders (= 0.77.3) - - React-RCTAnimation (0.77.3): - - RCT-Folly (= 2024.11.18.00) + - SocketRocket + - React-RCTActionSheet (0.81.5): + - React-Core/RCTActionSheetHeaders (= 0.81.5) + - React-RCTAnimation (0.81.5): + - boost + - DoubleConversion + - fast_float + - fmt + - glog + - RCT-Folly + - RCT-Folly/Fabric - RCTTypeSafety - React-Core/RCTAnimationHeaders + - React-featureflags - React-jsi - React-NativeModulesApple - React-RCTFBReactNativeSpec - ReactCommon - - React-RCTAppDelegate (0.77.3): - - RCT-Folly (= 2024.11.18.00) + - SocketRocket + - React-RCTAppDelegate (0.81.5): + - boost + - DoubleConversion + - fast_float + - fmt + - glog + - hermes-engine + - RCT-Folly + - RCT-Folly/Fabric - RCTRequired - RCTTypeSafety - React-Core @@ -1651,37 +2411,49 @@ PODS: - React-featureflags - React-graphics - React-hermes - - React-nativeconfig + - React-jsitooling - React-NativeModulesApple - React-RCTFabric - React-RCTFBReactNativeSpec - React-RCTImage - React-RCTNetwork + - React-RCTRuntime - React-rendererdebug - React-RuntimeApple - React-RuntimeCore - - React-RuntimeHermes + - React-runtimeexecutor - React-runtimescheduler - React-utils - ReactCommon - - React-RCTBlob (0.77.3): + - SocketRocket + - React-RCTBlob (0.81.5): + - boost - DoubleConversion - - fast_float (= 6.1.4) - - fmt (= 11.0.2) + - fast_float + - fmt + - glog - hermes-engine - - RCT-Folly (= 2024.11.18.00) + - RCT-Folly + - RCT-Folly/Fabric - React-Core/RCTBlobHeaders - React-Core/RCTWebSocket - React-jsi - React-jsinspector + - React-jsinspectorcdp - React-NativeModulesApple - React-RCTFBReactNativeSpec - React-RCTNetwork - ReactCommon - - React-RCTFabric (0.77.3): + - SocketRocket + - React-RCTFabric (0.81.5): + - boost + - DoubleConversion + - fast_float + - fmt - glog - hermes-engine - - RCT-Folly/Fabric (= 2024.11.18.00) + - RCT-Folly + - RCT-Folly/Fabric - React-Core - React-debug - React-Fabric @@ -1692,27 +2464,70 @@ PODS: - React-ImageManager - React-jsi - React-jsinspector - - React-nativeconfig + - React-jsinspectorcdp + - React-jsinspectornetwork + - React-jsinspectortracing - React-performancetimeline + - React-RCTAnimation + - React-RCTFBReactNativeSpec - React-RCTImage - React-RCTText - React-rendererconsistency + - React-renderercss - React-rendererdebug + - React-runtimeexecutor - React-runtimescheduler - React-utils + - SocketRocket - Yoga - - React-RCTFBReactNativeSpec (0.77.3): + - React-RCTFBReactNativeSpec (0.81.5): + - boost + - DoubleConversion + - fast_float + - fmt + - glog - hermes-engine - RCT-Folly + - RCT-Folly/Fabric - RCTRequired - RCTTypeSafety - React-Core - React-jsi - - React-jsiexecutor - React-NativeModulesApple + - React-RCTFBReactNativeSpec/components (= 0.81.5) + - ReactCommon + - SocketRocket + - React-RCTFBReactNativeSpec/components (0.81.5): + - boost + - DoubleConversion + - fast_float + - fmt + - glog + - hermes-engine + - RCT-Folly + - RCT-Folly/Fabric + - RCTRequired + - RCTTypeSafety + - React-Core + - React-debug + - React-Fabric + - React-featureflags + - React-graphics + - React-jsi + - React-NativeModulesApple + - React-rendererdebug + - React-utils - ReactCommon - - React-RCTImage (0.77.3): - - RCT-Folly (= 2024.11.18.00) + - SocketRocket + - Yoga + - React-RCTImage (0.81.5): + - boost + - DoubleConversion + - fast_float + - fmt + - glog + - RCT-Folly + - RCT-Folly/Fabric - RCTTypeSafety - React-Core/RCTImageHeaders - React-jsi @@ -1720,50 +2535,107 @@ PODS: - React-RCTFBReactNativeSpec - React-RCTNetwork - ReactCommon - - React-RCTLinking (0.77.3): - - React-Core/RCTLinkingHeaders (= 0.77.3) - - React-jsi (= 0.77.3) + - SocketRocket + - React-RCTLinking (0.81.5): + - React-Core/RCTLinkingHeaders (= 0.81.5) + - React-jsi (= 0.81.5) - React-NativeModulesApple - React-RCTFBReactNativeSpec - ReactCommon - - ReactCommon/turbomodule/core (= 0.77.3) - - React-RCTNetwork (0.77.3): - - RCT-Folly (= 2024.11.18.00) + - ReactCommon/turbomodule/core (= 0.81.5) + - React-RCTNetwork (0.81.5): + - boost + - DoubleConversion + - fast_float + - fmt + - glog + - RCT-Folly + - RCT-Folly/Fabric - RCTTypeSafety - React-Core/RCTNetworkHeaders + - React-featureflags - React-jsi + - React-jsinspectorcdp + - React-jsinspectornetwork - React-NativeModulesApple - React-RCTFBReactNativeSpec - ReactCommon - - React-RCTSettings (0.77.3): - - RCT-Folly (= 2024.11.18.00) + - SocketRocket + - React-RCTRuntime (0.81.5): + - boost + - DoubleConversion + - fast_float + - fmt + - glog + - hermes-engine + - RCT-Folly + - RCT-Folly/Fabric + - React-Core + - React-jsi + - React-jsinspector + - React-jsinspectorcdp + - React-jsinspectortracing + - React-jsitooling + - React-RuntimeApple + - React-RuntimeCore + - React-runtimeexecutor + - React-RuntimeHermes + - SocketRocket + - React-RCTSettings (0.81.5): + - boost + - DoubleConversion + - fast_float + - fmt + - glog + - RCT-Folly + - RCT-Folly/Fabric - RCTTypeSafety - React-Core/RCTSettingsHeaders - React-jsi - React-NativeModulesApple - React-RCTFBReactNativeSpec - ReactCommon - - React-RCTText (0.77.3): - - React-Core/RCTTextHeaders (= 0.77.3) + - SocketRocket + - React-RCTText (0.81.5): + - React-Core/RCTTextHeaders (= 0.81.5) - Yoga - - React-RCTVibration (0.77.3): - - RCT-Folly (= 2024.11.18.00) + - React-RCTVibration (0.81.5): + - boost + - DoubleConversion + - fast_float + - fmt + - glog + - RCT-Folly + - RCT-Folly/Fabric - React-Core/RCTVibrationHeaders - React-jsi - React-NativeModulesApple - React-RCTFBReactNativeSpec - ReactCommon - - React-rendererconsistency (0.77.3) - - React-rendererdebug (0.77.3): + - SocketRocket + - React-rendererconsistency (0.81.5) + - React-renderercss (0.81.5): + - React-debug + - React-utils + - React-rendererdebug (0.81.5): + - boost - DoubleConversion - - fast_float (= 6.1.4) - - fmt (= 11.0.2) - - RCT-Folly (= 2024.11.18.00) + - fast_float + - fmt + - glog + - RCT-Folly + - RCT-Folly/Fabric - React-debug - - React-rncore (0.77.3) - - React-RuntimeApple (0.77.3): + - SocketRocket + - React-RuntimeApple (0.81.5): + - boost + - DoubleConversion + - fast_float + - fmt + - glog - hermes-engine - - RCT-Folly/Fabric (= 2024.11.18.00) + - RCT-Folly + - RCT-Folly/Fabric - React-callinvoker - React-Core/Default - React-CoreModules @@ -1773,6 +2645,7 @@ PODS: - React-jsi - React-jsiexecutor - React-jsinspector + - React-jsitooling - React-Mapbuffer - React-NativeModulesApple - React-RCTFabric @@ -1782,10 +2655,16 @@ PODS: - React-RuntimeHermes - React-runtimescheduler - React-utils - - React-RuntimeCore (0.77.3): + - SocketRocket + - React-RuntimeCore (0.81.5): + - boost + - DoubleConversion + - fast_float + - fmt - glog - hermes-engine - - RCT-Folly/Fabric (= 2024.11.18.00) + - RCT-Folly + - RCT-Folly/Fabric - React-cxxreact - React-Fabric - React-featureflags @@ -1793,52 +2672,93 @@ PODS: - React-jsi - React-jsiexecutor - React-jsinspector + - React-jsitooling - React-performancetimeline - React-runtimeexecutor - React-runtimescheduler - React-utils - - React-runtimeexecutor (0.77.3): - - React-jsi (= 0.77.3) - - React-RuntimeHermes (0.77.3): + - SocketRocket + - React-runtimeexecutor (0.81.5): + - boost + - DoubleConversion + - fast_float + - fmt + - glog + - RCT-Folly + - RCT-Folly/Fabric + - React-debug + - React-featureflags + - React-jsi (= 0.81.5) + - React-utils + - SocketRocket + - React-RuntimeHermes (0.81.5): + - boost + - DoubleConversion + - fast_float + - fmt + - glog - hermes-engine - - RCT-Folly/Fabric (= 2024.11.18.00) + - RCT-Folly + - RCT-Folly/Fabric - React-featureflags - React-hermes - React-jsi - React-jsinspector + - React-jsinspectorcdp + - React-jsinspectortracing + - React-jsitooling - React-jsitracing - - React-nativeconfig - React-RuntimeCore + - React-runtimeexecutor - React-utils - - React-runtimescheduler (0.77.3): + - SocketRocket + - React-runtimescheduler (0.81.5): + - boost + - DoubleConversion + - fast_float + - fmt - glog - hermes-engine - - RCT-Folly (= 2024.11.18.00) + - RCT-Folly + - RCT-Folly/Fabric - React-callinvoker - React-cxxreact - React-debug - React-featureflags - React-jsi + - React-jsinspectortracing - React-performancetimeline - React-rendererconsistency - React-rendererdebug - React-runtimeexecutor - React-timing - React-utils - - React-timing (0.77.3) - - React-utils (0.77.3): + - SocketRocket + - React-timing (0.81.5): + - React-debug + - React-utils (0.81.5): + - boost + - DoubleConversion + - fast_float + - fmt - glog - hermes-engine - - RCT-Folly (= 2024.11.18.00) + - RCT-Folly + - RCT-Folly/Fabric - React-debug - - React-jsi (= 0.77.3) - - ReactAppDependencyProvider (0.77.3): + - React-jsi (= 0.81.5) + - SocketRocket + - ReactAppDependencyProvider (0.81.5): - ReactCodegen - - ReactCodegen (0.77.3): + - ReactCodegen (0.81.5): + - boost - DoubleConversion + - fast_float + - fmt - glog - hermes-engine - RCT-Folly + - RCT-Folly/Fabric - RCTRequired - RCTTypeSafety - React-Core @@ -1855,59 +2775,81 @@ PODS: - React-utils - ReactCommon/turbomodule/bridging - ReactCommon/turbomodule/core - - ReactCommon (0.77.3): - - ReactCommon/turbomodule (= 0.77.3) - - ReactCommon/turbomodule (0.77.3): + - SocketRocket + - ReactCommon (0.81.5): + - boost - DoubleConversion - - fast_float (= 6.1.4) - - fmt (= 11.0.2) + - fast_float + - fmt + - glog + - RCT-Folly + - RCT-Folly/Fabric + - ReactCommon/turbomodule (= 0.81.5) + - SocketRocket + - ReactCommon/turbomodule (0.81.5): + - boost + - DoubleConversion + - fast_float + - fmt - glog - hermes-engine - - RCT-Folly (= 2024.11.18.00) - - React-callinvoker (= 0.77.3) - - React-cxxreact (= 0.77.3) - - React-jsi (= 0.77.3) - - React-logger (= 0.77.3) - - React-perflogger (= 0.77.3) - - ReactCommon/turbomodule/bridging (= 0.77.3) - - ReactCommon/turbomodule/core (= 0.77.3) - - ReactCommon/turbomodule/bridging (0.77.3): + - RCT-Folly + - RCT-Folly/Fabric + - React-callinvoker (= 0.81.5) + - React-cxxreact (= 0.81.5) + - React-jsi (= 0.81.5) + - React-logger (= 0.81.5) + - React-perflogger (= 0.81.5) + - ReactCommon/turbomodule/bridging (= 0.81.5) + - ReactCommon/turbomodule/core (= 0.81.5) + - SocketRocket + - ReactCommon/turbomodule/bridging (0.81.5): + - boost - DoubleConversion - - fast_float (= 6.1.4) - - fmt (= 11.0.2) + - fast_float + - fmt - glog - hermes-engine - - RCT-Folly (= 2024.11.18.00) - - React-callinvoker (= 0.77.3) - - React-cxxreact (= 0.77.3) - - React-jsi (= 0.77.3) - - React-logger (= 0.77.3) - - React-perflogger (= 0.77.3) - - ReactCommon/turbomodule/core (0.77.3): + - RCT-Folly + - RCT-Folly/Fabric + - React-callinvoker (= 0.81.5) + - React-cxxreact (= 0.81.5) + - React-jsi (= 0.81.5) + - React-logger (= 0.81.5) + - React-perflogger (= 0.81.5) + - SocketRocket + - ReactCommon/turbomodule/core (0.81.5): + - boost - DoubleConversion - - fast_float (= 6.1.4) - - fmt (= 11.0.2) + - fast_float + - fmt - glog - hermes-engine - - RCT-Folly (= 2024.11.18.00) - - React-callinvoker (= 0.77.3) - - React-cxxreact (= 0.77.3) - - React-debug (= 0.77.3) - - React-featureflags (= 0.77.3) - - React-jsi (= 0.77.3) - - React-logger (= 0.77.3) - - React-perflogger (= 0.77.3) - - React-utils (= 0.77.3) + - RCT-Folly + - RCT-Folly/Fabric + - React-callinvoker (= 0.81.5) + - React-cxxreact (= 0.81.5) + - React-debug (= 0.81.5) + - React-featureflags (= 0.81.5) + - React-jsi (= 0.81.5) + - React-logger (= 0.81.5) + - React-perflogger (= 0.81.5) + - React-utils (= 0.81.5) + - SocketRocket - ReactNativeIncallManager (4.2.1): - React-Core - RNArgon2 (2.0.1): - CatCrypto - React-Core - - RNCAsyncStorage (1.22.3): + - RNCAsyncStorage (2.2.0): + - boost - DoubleConversion + - fast_float + - fmt - glog - hermes-engine - - RCT-Folly (= 2024.11.18.00) + - RCT-Folly + - RCT-Folly/Fabric - RCTRequired - RCTTypeSafety - React-Core @@ -1916,19 +2858,26 @@ PODS: - React-featureflags - React-graphics - React-ImageManager + - React-jsi - React-NativeModulesApple - React-RCTFabric + - React-renderercss - React-rendererdebug - React-utils - ReactCodegen - ReactCommon/turbomodule/bridging - ReactCommon/turbomodule/core + - SocketRocket - Yoga - RNCClipboard (1.16.3): + - boost - DoubleConversion + - fast_float + - fmt - glog - hermes-engine - - RCT-Folly (= 2024.11.18.00) + - RCT-Folly + - RCT-Folly/Fabric - RCTRequired - RCTTypeSafety - React-Core @@ -1937,13 +2886,16 @@ PODS: - React-featureflags - React-graphics - React-ImageManager + - React-jsi - React-NativeModulesApple - React-RCTFabric + - React-renderercss - React-rendererdebug - React-utils - ReactCodegen - ReactCommon/turbomodule/bridging - ReactCommon/turbomodule/core + - SocketRocket - Yoga - RNDeviceInfo (8.7.1): - React-Core @@ -1957,11 +2909,15 @@ PODS: - RNFBApp - RNFS (2.20.0): - React-Core - - RNGestureHandler (2.22.1): + - RNGestureHandler (2.28.0): + - boost - DoubleConversion + - fast_float + - fmt - glog - hermes-engine - - RCT-Folly (= 2024.11.18.00) + - RCT-Folly + - RCT-Folly/Fabric - RCTRequired - RCTTypeSafety - React-Core @@ -1970,25 +2926,206 @@ PODS: - React-featureflags - React-graphics - React-ImageManager + - React-jsi - React-NativeModulesApple - React-RCTFabric + - React-renderercss - React-rendererdebug - React-utils - ReactCodegen - ReactCommon/turbomodule/bridging - ReactCommon/turbomodule/core + - SocketRocket - Yoga - RNInAppBrowser (3.7.0): - React-Core - - RNKeychain (8.1.3): + - RNKeychain (10.0.0): + - boost + - DoubleConversion + - fast_float + - fmt + - glog + - hermes-engine + - RCT-Folly + - RCT-Folly/Fabric + - RCTRequired + - RCTTypeSafety - React-Core + - React-debug + - React-Fabric + - React-featureflags + - React-graphics + - React-ImageManager + - React-jsi + - React-NativeModulesApple + - React-RCTFabric + - React-renderercss + - React-rendererdebug + - React-utils + - ReactCodegen + - ReactCommon/turbomodule/bridging + - ReactCommon/turbomodule/core + - SocketRocket + - Yoga - RNLocalize (2.2.6): - React-Core - RNPermissions (5.4.2): + - boost + - DoubleConversion + - fast_float + - fmt + - glog + - hermes-engine + - RCT-Folly + - RCT-Folly/Fabric + - RCTRequired + - RCTTypeSafety + - React-Core + - React-debug + - React-Fabric + - React-featureflags + - React-graphics + - React-ImageManager + - React-jsi + - React-NativeModulesApple + - React-RCTFabric + - React-renderercss + - React-rendererdebug + - React-utils + - ReactCodegen + - ReactCommon/turbomodule/bridging + - ReactCommon/turbomodule/core + - SocketRocket + - Yoga + - RNReanimated (3.19.5): + - boost + - DoubleConversion + - fast_float + - fmt + - glog + - hermes-engine + - RCT-Folly + - RCT-Folly/Fabric + - RCTRequired + - RCTTypeSafety + - React-Core + - React-debug + - React-Fabric + - React-featureflags + - React-graphics + - React-hermes + - React-ImageManager + - React-jsi + - React-NativeModulesApple + - React-RCTFabric + - React-renderercss + - React-rendererdebug + - React-utils + - ReactCodegen + - ReactCommon/turbomodule/bridging + - ReactCommon/turbomodule/core + - RNReanimated/reanimated (= 3.19.5) + - RNReanimated/worklets (= 3.19.5) + - SocketRocket + - Yoga + - RNReanimated/reanimated (3.19.5): + - boost + - DoubleConversion + - fast_float + - fmt + - glog + - hermes-engine + - RCT-Folly + - RCT-Folly/Fabric + - RCTRequired + - RCTTypeSafety + - React-Core + - React-debug + - React-Fabric + - React-featureflags + - React-graphics + - React-hermes + - React-ImageManager + - React-jsi + - React-NativeModulesApple + - React-RCTFabric + - React-renderercss + - React-rendererdebug + - React-utils + - ReactCodegen + - ReactCommon/turbomodule/bridging + - ReactCommon/turbomodule/core + - RNReanimated/reanimated/apple (= 3.19.5) + - SocketRocket + - Yoga + - RNReanimated/reanimated/apple (3.19.5): + - boost + - DoubleConversion + - fast_float + - fmt + - glog + - hermes-engine + - RCT-Folly + - RCT-Folly/Fabric + - RCTRequired + - RCTTypeSafety + - React-Core + - React-debug + - React-Fabric + - React-featureflags + - React-graphics + - React-hermes + - React-ImageManager + - React-jsi + - React-NativeModulesApple + - React-RCTFabric + - React-renderercss + - React-rendererdebug + - React-utils + - ReactCodegen + - ReactCommon/turbomodule/bridging + - ReactCommon/turbomodule/core + - SocketRocket + - Yoga + - RNReanimated/worklets (3.19.5): + - boost + - DoubleConversion + - fast_float + - fmt + - glog + - hermes-engine + - RCT-Folly + - RCT-Folly/Fabric + - RCTRequired + - RCTTypeSafety + - React-Core + - React-debug + - React-Fabric + - React-featureflags + - React-graphics + - React-hermes + - React-ImageManager + - React-jsi + - React-NativeModulesApple + - React-RCTFabric + - React-renderercss + - React-rendererdebug + - React-utils + - ReactCodegen + - ReactCommon/turbomodule/bridging + - ReactCommon/turbomodule/core + - RNReanimated/worklets/apple (= 3.19.5) + - SocketRocket + - Yoga + - RNReanimated/worklets/apple (3.19.5): + - boost - DoubleConversion + - fast_float + - fmt - glog - hermes-engine - - RCT-Folly (= 2024.11.18.00) + - RCT-Folly + - RCT-Folly/Fabric - RCTRequired - RCTTypeSafety - React-Core @@ -1996,20 +3133,28 @@ PODS: - React-Fabric - React-featureflags - React-graphics + - React-hermes - React-ImageManager + - React-jsi - React-NativeModulesApple - React-RCTFabric + - React-renderercss - React-rendererdebug - React-utils - ReactCodegen - ReactCommon/turbomodule/bridging - ReactCommon/turbomodule/core + - SocketRocket - Yoga - - RNScreens (4.6.0): + - RNScreens (4.16.0): + - boost - DoubleConversion + - fast_float + - fmt - glog - hermes-engine - - RCT-Folly (= 2024.11.18.00) + - RCT-Folly + - RCT-Folly/Fabric - RCTRequired - RCTTypeSafety - React-Core @@ -2018,21 +3163,28 @@ PODS: - React-featureflags - React-graphics - React-ImageManager + - React-jsi - React-NativeModulesApple - React-RCTFabric - React-RCTImage + - React-renderercss - React-rendererdebug - React-utils - ReactCodegen - ReactCommon/turbomodule/bridging - ReactCommon/turbomodule/core - - RNScreens/common (= 4.6.0) + - RNScreens/common (= 4.16.0) + - SocketRocket - Yoga - - RNScreens/common (4.6.0): + - RNScreens/common (4.16.0): + - boost - DoubleConversion + - fast_float + - fmt - glog - hermes-engine - - RCT-Folly (= 2024.11.18.00) + - RCT-Folly + - RCT-Folly/Fabric - RCTRequired - RCTTypeSafety - React-Core @@ -2041,20 +3193,27 @@ PODS: - React-featureflags - React-graphics - React-ImageManager + - React-jsi - React-NativeModulesApple - React-RCTFabric - React-RCTImage + - React-renderercss - React-rendererdebug - React-utils - ReactCodegen - ReactCommon/turbomodule/bridging - ReactCommon/turbomodule/core + - SocketRocket - Yoga - - RNSVG (15.11.2): + - RNSVG (15.12.1): + - boost - DoubleConversion + - fast_float + - fmt - glog - hermes-engine - - RCT-Folly (= 2024.11.18.00) + - RCT-Folly + - RCT-Folly/Fabric - RCTRequired - RCTTypeSafety - React-Core @@ -2063,20 +3222,27 @@ PODS: - React-featureflags - React-graphics - React-ImageManager + - React-jsi - React-NativeModulesApple - React-RCTFabric + - React-renderercss - React-rendererdebug - React-utils - ReactCodegen - ReactCommon/turbomodule/bridging - ReactCommon/turbomodule/core - - RNSVG/common (= 15.11.2) + - RNSVG/common (= 15.12.1) + - SocketRocket - Yoga - - RNSVG/common (15.11.2): + - RNSVG/common (15.12.1): + - boost - DoubleConversion + - fast_float + - fmt - glog - hermes-engine - - RCT-Folly (= 2024.11.18.00) + - RCT-Folly + - RCT-Folly/Fabric - RCTRequired - RCTTypeSafety - React-Core @@ -2085,19 +3251,26 @@ PODS: - React-featureflags - React-graphics - React-ImageManager + - React-jsi - React-NativeModulesApple - React-RCTFabric + - React-renderercss - React-rendererdebug - React-utils - ReactCodegen - ReactCommon/turbomodule/bridging - ReactCommon/turbomodule/core + - SocketRocket - Yoga - - RNVectorIcons (10.0.3): + - RNVectorIcons (10.3.0): + - boost - DoubleConversion + - fast_float + - fmt - glog - hermes-engine - - RCT-Folly (= 2024.11.18.00) + - RCT-Folly + - RCT-Folly/Fabric - RCTRequired - RCTTypeSafety - React-Core @@ -2106,13 +3279,16 @@ PODS: - React-featureflags - React-graphics - React-ImageManager + - React-jsi - React-NativeModulesApple - React-RCTFabric + - React-renderercss - React-rendererdebug - React-utils - ReactCodegen - ReactCommon/turbomodule/bridging - ReactCommon/turbomodule/core + - SocketRocket - Yoga - SDWebImage (5.21.7): - SDWebImage/Core (= 5.21.7) @@ -2128,10 +3304,21 @@ PODS: DEPENDENCIES: - "anoncreds (from `../node_modules/@hyperledger/anoncreds-react-native`)" - - "aries-askar (from `../node_modules/@hyperledger/aries-askar-react-native`)" + - "askar (from `../node_modules/@openwallet-foundation/askar-react-native`)" - boost (from `../node_modules/react-native/third-party-podspecs/boost.podspec`) - BVLinearGradient (from `../node_modules/react-native-linear-gradient`) - DoubleConversion (from `../node_modules/react-native/third-party-podspecs/DoubleConversion.podspec`) + - EXConstants (from `../node_modules/expo-constants/ios`) + - Expo (from `../node_modules/expo`) + - "ExpoAppIntegrity (from `../node_modules/@expo/app-integrity/ios`)" + - ExpoAsset (from `../node_modules/expo-asset/ios`) + - ExpoCrypto (from `../node_modules/expo-crypto/ios`) + - ExpoFileSystem (from `../node_modules/expo-file-system/ios`) + - ExpoFont (from `../node_modules/expo-font/ios`) + - ExpoKeepAwake (from `../node_modules/expo-keep-awake/ios`) + - ExpoModulesCore (from `../node_modules/expo-modules-core`) + - "ExpoSecureEnvironment (from `../node_modules/@animo-id/expo-secure-environment/ios`)" + - ExpoSecureStore (from `../node_modules/expo-secure-store/ios`) - fast_float (from `../node_modules/react-native/third-party-podspecs/fast_float.podspec`) - FBLazyVector (from `../node_modules/react-native/Libraries/FBLazyVector`) - Firebase @@ -2143,7 +3330,6 @@ DEPENDENCIES: - hermes-engine (from `../node_modules/react-native/sdks/hermes-engine/hermes-engine.podspec`) - "indy-vdr (from `../node_modules/@hyperledger/indy-vdr-react-native`)" - RCT-Folly (from `../node_modules/react-native/third-party-podspecs/RCT-Folly.podspec`) - - RCT-Folly/Fabric (from `../node_modules/react-native/third-party-podspecs/RCT-Folly.podspec`) - RCTDeprecation (from `../node_modules/react-native/ReactApple/Libraries/RCTFoundation/RCTDeprecation`) - RCTRequired (from `../node_modules/react-native/Libraries/Required`) - RCTTypeSafety (from `../node_modules/react-native/Libraries/TypeSafety`) @@ -2169,16 +3355,20 @@ DEPENDENCIES: - React-jsi (from `../node_modules/react-native/ReactCommon/jsi`) - React-jsiexecutor (from `../node_modules/react-native/ReactCommon/jsiexecutor`) - React-jsinspector (from `../node_modules/react-native/ReactCommon/jsinspector-modern`) + - React-jsinspectorcdp (from `../node_modules/react-native/ReactCommon/jsinspector-modern/cdp`) + - React-jsinspectornetwork (from `../node_modules/react-native/ReactCommon/jsinspector-modern/network`) + - React-jsinspectortracing (from `../node_modules/react-native/ReactCommon/jsinspector-modern/tracing`) + - React-jsitooling (from `../node_modules/react-native/ReactCommon/jsitooling`) - React-jsitracing (from `../node_modules/react-native/ReactCommon/hermes/executor/`) - React-logger (from `../node_modules/react-native/ReactCommon/logger`) - React-Mapbuffer (from `../node_modules/react-native/ReactCommon`) - React-microtasksnativemodule (from `../node_modules/react-native/ReactCommon/react/nativemodule/microtasks`) - "react-native-attestation (from `../node_modules/@bifold/react-native-attestation`)" - react-native-config (from `../node_modules/react-native-config`) - - react-native-date-picker (from `../node_modules/react-native-date-picker`) - react-native-document-picker (from `../node_modules/react-native-document-picker`) - react-native-encrypted-storage (from `../node_modules/react-native-encrypted-storage`) - react-native-get-random-values (from `../node_modules/react-native-get-random-values`) + - react-native-keyboard-controller (from `../node_modules/react-native-keyboard-controller`) - "react-native-netinfo (from `../node_modules/@react-native-community/netinfo`)" - react-native-orientation-locker (from `../node_modules/react-native-orientation-locker`) - react-native-safe-area-context (from `../node_modules/react-native-safe-area-context`) @@ -2190,8 +3380,8 @@ DEPENDENCIES: - react-native-webrtc (from `../node_modules/react-native-webrtc`) - react-native-webview (from `../node_modules/react-native-webview`) - react-native-zeroconf (from `../node_modules/react-native-zeroconf`) - - React-nativeconfig (from `../node_modules/react-native/ReactCommon`) - React-NativeModulesApple (from `../node_modules/react-native/ReactCommon/react/nativemodule/core/platform/ios`) + - React-oscompat (from `../node_modules/react-native/ReactCommon/oscompat`) - React-perflogger (from `../node_modules/react-native/ReactCommon/reactperflogger`) - React-performancetimeline (from `../node_modules/react-native/ReactCommon/react/performance/timeline`) - React-RCTActionSheet (from `../node_modules/react-native/Libraries/ActionSheetIOS`) @@ -2203,12 +3393,13 @@ DEPENDENCIES: - React-RCTImage (from `../node_modules/react-native/Libraries/Image`) - React-RCTLinking (from `../node_modules/react-native/Libraries/LinkingIOS`) - React-RCTNetwork (from `../node_modules/react-native/Libraries/Network`) + - React-RCTRuntime (from `../node_modules/react-native/React/Runtime`) - React-RCTSettings (from `../node_modules/react-native/Libraries/Settings`) - React-RCTText (from `../node_modules/react-native/Libraries/Text`) - React-RCTVibration (from `../node_modules/react-native/Libraries/Vibration`) - React-rendererconsistency (from `../node_modules/react-native/ReactCommon/react/renderer/consistency`) + - React-renderercss (from `../node_modules/react-native/ReactCommon/react/renderer/css`) - React-rendererdebug (from `../node_modules/react-native/ReactCommon/react/renderer/debug`) - - React-rncore (from `../node_modules/react-native/ReactCommon`) - React-RuntimeApple (from `../node_modules/react-native/ReactCommon/react/runtime/platform/ios`) - React-RuntimeCore (from `../node_modules/react-native/ReactCommon/react/runtime`) - React-runtimeexecutor (from `../node_modules/react-native/ReactCommon/runtimeexecutor`) @@ -2232,9 +3423,11 @@ DEPENDENCIES: - RNKeychain (from `../node_modules/react-native-keychain`) - RNLocalize (from `../node_modules/react-native-localize`) - RNPermissions (from `../node_modules/react-native-permissions`) + - RNReanimated (from `../node_modules/react-native-reanimated`) - RNScreens (from `../node_modules/react-native-screens`) - RNSVG (from `../node_modules/react-native-svg`) - RNVectorIcons (from `../node_modules/react-native-vector-icons`) + - SocketRocket (~> 0.7.1) - VisionCamera (from `../node_modules/react-native-vision-camera`) - Yoga (from `../node_modules/react-native/ReactCommon/yoga`) @@ -2262,14 +3455,36 @@ SPEC REPOS: EXTERNAL SOURCES: anoncreds: :path: "../node_modules/@hyperledger/anoncreds-react-native" - aries-askar: - :path: "../node_modules/@hyperledger/aries-askar-react-native" + askar: + :path: "../node_modules/@openwallet-foundation/askar-react-native" boost: :podspec: "../node_modules/react-native/third-party-podspecs/boost.podspec" BVLinearGradient: :path: "../node_modules/react-native-linear-gradient" DoubleConversion: :podspec: "../node_modules/react-native/third-party-podspecs/DoubleConversion.podspec" + EXConstants: + :path: "../node_modules/expo-constants/ios" + Expo: + :path: "../node_modules/expo" + ExpoAppIntegrity: + :path: "../node_modules/@expo/app-integrity/ios" + ExpoAsset: + :path: "../node_modules/expo-asset/ios" + ExpoCrypto: + :path: "../node_modules/expo-crypto/ios" + ExpoFileSystem: + :path: "../node_modules/expo-file-system/ios" + ExpoFont: + :path: "../node_modules/expo-font/ios" + ExpoKeepAwake: + :path: "../node_modules/expo-keep-awake/ios" + ExpoModulesCore: + :path: "../node_modules/expo-modules-core" + ExpoSecureEnvironment: + :path: "../node_modules/@animo-id/expo-secure-environment/ios" + ExpoSecureStore: + :path: "../node_modules/expo-secure-store/ios" fast_float: :podspec: "../node_modules/react-native/third-party-podspecs/fast_float.podspec" FBLazyVector: @@ -2280,7 +3495,7 @@ EXTERNAL SOURCES: :podspec: "../node_modules/react-native/third-party-podspecs/glog.podspec" hermes-engine: :podspec: "../node_modules/react-native/sdks/hermes-engine/hermes-engine.podspec" - :tag: hermes-2024-11-25-RNv0.77.0-d4f25d534ab744866448b36ca3bf3d97c08e638c + :tag: hermes-2025-07-07-RNv0.81.0-e0fc67142ec0763c6b6153ca2bf96df815539782 indy-vdr: :path: "../node_modules/@hyperledger/indy-vdr-react-native" RCT-Folly: @@ -2333,6 +3548,14 @@ EXTERNAL SOURCES: :path: "../node_modules/react-native/ReactCommon/jsiexecutor" React-jsinspector: :path: "../node_modules/react-native/ReactCommon/jsinspector-modern" + React-jsinspectorcdp: + :path: "../node_modules/react-native/ReactCommon/jsinspector-modern/cdp" + React-jsinspectornetwork: + :path: "../node_modules/react-native/ReactCommon/jsinspector-modern/network" + React-jsinspectortracing: + :path: "../node_modules/react-native/ReactCommon/jsinspector-modern/tracing" + React-jsitooling: + :path: "../node_modules/react-native/ReactCommon/jsitooling" React-jsitracing: :path: "../node_modules/react-native/ReactCommon/hermes/executor/" React-logger: @@ -2345,14 +3568,14 @@ EXTERNAL SOURCES: :path: "../node_modules/@bifold/react-native-attestation" react-native-config: :path: "../node_modules/react-native-config" - react-native-date-picker: - :path: "../node_modules/react-native-date-picker" react-native-document-picker: :path: "../node_modules/react-native-document-picker" react-native-encrypted-storage: :path: "../node_modules/react-native-encrypted-storage" react-native-get-random-values: :path: "../node_modules/react-native-get-random-values" + react-native-keyboard-controller: + :path: "../node_modules/react-native-keyboard-controller" react-native-netinfo: :path: "../node_modules/@react-native-community/netinfo" react-native-orientation-locker: @@ -2375,10 +3598,10 @@ EXTERNAL SOURCES: :path: "../node_modules/react-native-webview" react-native-zeroconf: :path: "../node_modules/react-native-zeroconf" - React-nativeconfig: - :path: "../node_modules/react-native/ReactCommon" React-NativeModulesApple: :path: "../node_modules/react-native/ReactCommon/react/nativemodule/core/platform/ios" + React-oscompat: + :path: "../node_modules/react-native/ReactCommon/oscompat" React-perflogger: :path: "../node_modules/react-native/ReactCommon/reactperflogger" React-performancetimeline: @@ -2401,6 +3624,8 @@ EXTERNAL SOURCES: :path: "../node_modules/react-native/Libraries/LinkingIOS" React-RCTNetwork: :path: "../node_modules/react-native/Libraries/Network" + React-RCTRuntime: + :path: "../node_modules/react-native/React/Runtime" React-RCTSettings: :path: "../node_modules/react-native/Libraries/Settings" React-RCTText: @@ -2409,10 +3634,10 @@ EXTERNAL SOURCES: :path: "../node_modules/react-native/Libraries/Vibration" React-rendererconsistency: :path: "../node_modules/react-native/ReactCommon/react/renderer/consistency" + React-renderercss: + :path: "../node_modules/react-native/ReactCommon/react/renderer/css" React-rendererdebug: :path: "../node_modules/react-native/ReactCommon/react/renderer/debug" - React-rncore: - :path: "../node_modules/react-native/ReactCommon" React-RuntimeApple: :path: "../node_modules/react-native/ReactCommon/react/runtime/platform/ios" React-RuntimeCore: @@ -2459,6 +3684,8 @@ EXTERNAL SOURCES: :path: "../node_modules/react-native-localize" RNPermissions: :path: "../node_modules/react-native-permissions" + RNReanimated: + :path: "../node_modules/react-native-reanimated" RNScreens: :path: "../node_modules/react-native-screens" RNSVG: @@ -2471,15 +3698,26 @@ EXTERNAL SOURCES: :path: "../node_modules/react-native/ReactCommon/yoga" SPEC CHECKSUMS: - anoncreds: 4b29b0ef841fc1a96910aab8f047c090ee6acb89 - aries-askar: 6fce8d0405b8c84e654a694be1954649cf7955a3 + anoncreds: d48fc0f3bde44f97aef5bb907f6821bf9191d758 + askar: d15c0dd9a376a8e3245030f0baf7ddca0058f76d boost: 7e761d76ca2ce687f7cc98e698152abd03a18f90 BVLinearGradient: cb006ba232a1f3e4f341bb62c42d1098c284da70 CatCrypto: a477899b6be4954e75be4897e732da098cc0a5a8 CocoaAsyncSocket: 065fd1e645c7abab64f7a6a2007a48038fdc6a99 DoubleConversion: cb417026b2400c8f53ae97020b2be961b59470cb - fast_float: 06eeec4fe712a76acc9376682e4808b05ce978b6 - FBLazyVector: 23d8c5470c648a635893dc0956c6dbaead54b656 + EXConstants: fce59a631a06c4151602843667f7cfe35f81e271 + Expo: 4479cae646b5d3ce16f45ce0e920fadbc0e7396e + ExpoAppIntegrity: 4e47b5f12af29dcf917bca2c12bd1d8b9e968460 + ExpoAsset: 9e5a7c9c0a9fb83ad5b2bb365141f2bd7f289b66 + ExpoCrypto: e2a2c4c748aac8485e5675f027b7901f511d43ff + ExpoFileSystem: a8e7fb1e958471764fb48d281cf9fa81a9e4d77c + ExpoFont: dfb7c572372b610da45b41e3b436321fd6a97215 + ExpoKeepAwake: 55f75eca6499bb9e4231ebad6f3e9cb8f99c0296 + ExpoModulesCore: 20899b4dd703e10a543ff4c50ee1543e47d90082 + ExpoSecureEnvironment: bdba36c15073279baf3b8787f2e1eb42146a0761 + ExpoSecureStore: d32f751874a2ceb5aaeebeb3578e165c1ba2b24a + fast_float: b32c788ed9c6a8c584d114d0047beda9664e7cc6 + FBLazyVector: 5beb8028d5a2e75dd9634917f23e23d3a061d2aa Firebase: 6a8f201c61eda24e98f1ce2b44b1b9c2caf525cc FirebaseAnalytics: acfa848bf81e1a4dbf60ef1f0eddd7328fe6673e FirebaseCore: 2321536f9c423b1f857e047a82b8a42abc6d9e2c @@ -2488,112 +3726,118 @@ SPEC CHECKSUMS: FirebaseInstallations: 781e0e37aa0e1c92b44d00e739aba79ad31b2dba FirebaseMessaging: c7be9357fd8ba33bc45b9a6c3cdff0b466e1e2a4 fmt: a40bb5bd0294ea969aaaba240a927bd33d878cdd - glog: eb93e2f488219332457c3c4eafd2738ddc7e80b8 + glog: 5683914934d5b6e4240e497e0f4a3b42d1854183 GoogleAppMeasurement: 8a82b93a6400c8e6551c0bcd66a9177f2e067aed GoogleDataTransport: aae35b7ea0c09004c3797d53c8c41f66f219d6a7 GoogleUtilities: 766ace00c6b10d8148408f329d10c4f051931850 - hermes-engine: b2187dbe13edb0db8fcb2a93a69c1987a30d98a4 - indy-vdr: aada31078a9ed270dd618fadb4cf69bcdc333d68 + hermes-engine: 9f4dfe93326146a1c99eb535b1cb0b857a3cd172 + indy-vdr: 3606e7be9ed3b5fc67a80b198982015adfdadc7f JitsiWebRTC: b47805ab5668be38e7ee60e2258f49badfe8e1d0 Mute: 20135a96076f140cc82bfc8b810e2d6150d8ec7e nanopb: fad817b59e0457d11a5dfbde799381cd727c1275 PromisesObjC: 752c3227f599e3467650e47ea36f433eeb10c273 - RCT-Folly: e78785aa9ba2ed998ea4151e314036f6c49e6d82 - RCTDeprecation: 6ee92578d332db1d4e03267d3ae98bcf8b780863 - RCTRequired: 5b3da0e0f91fddda935574b81748c3e3d3649ee7 - RCTTypeSafety: 870cb072be3d3f310ecec897c3d297a931f8f7e1 - React: 535fa5014fb1743f6654a980acb16dae339e1944 - React-callinvoker: dd1ecd51f8d3c76a551afdf6dab6d51c1ead5501 - React-Core: a3e36c059a195bd213d005db36c9e68957b78632 - React-CoreModules: 46467a2b34b053eb7262104e07bf5d835a9afe77 - React-cxxreact: 500e7b011a14eeefdcf6c0eb982fe4db055c2670 - React-debug: 41315631a01cf5cc3c9498482b97be21c49f8e8d - React-defaultsnativemodule: a06364257949e77dc39bcfd08e2d801c189bb58c - React-domnativemodule: dcda8a2b62bb34ed5db94470a3a72f32a76e1e31 - React-Fabric: dc1d3aa4b6a92e4a703c02ca6c4add312754eb84 - React-FabricComponents: 451f7b72aa80001520a20747b7b1e21350d6fba8 - React-FabricImage: 15c3bfe577a60c492134519219627316fb48af05 - React-featureflags: 08f06c820a37b29ed3ef9dddc6763c086339bc28 - React-featureflagsnativemodule: 3f6b19ac469a5d26e3a52e5198735c1799f1e324 - React-graphics: df8448a604e8fd03325e0f3d760b13e57416871c - React-hermes: 67f3ee00fdbe085e722fd89811073678ba28c10a - React-idlecallbacksnativemodule: 26de008466429c4a6feb772cde37d3eda5c1e045 - React-ImageManager: 52a8c48c4c7c5a8124e8c363693bd2908b01c5f6 - React-jserrorhandler: faa483d54dd358b11e81adcd5e6373da6030ed70 - React-jsi: d5332d79759159a0127348d9b20cc90527dd40e8 - React-jsiexecutor: 72c8df1af2c18736f6685cce4205c480f3783039 - React-jsinspector: e444c5725dbb31aa7ce556d972511f8997b38bc5 - React-jsitracing: 955646960c72c03e6e87df8706cab6bcdf960042 - React-logger: a23563f96a622637d7cce687bdf304929104effd - React-Mapbuffer: 1864935968d15b9b73d8e413d29c780f0ab50038 - React-microtasksnativemodule: 3b784cf40f7c3c9500b9a5f9e4eec5c9bbfbef8f - react-native-attestation: 0bbb1201478f83c05063dc77beb7f99aa7cc525a + RCT-Folly: 846fda9475e61ec7bcbf8a3fe81edfcaeb090669 + RCTDeprecation: 5eb1d2eeff5fb91151e8a8eef45b6c7658b6c897 + RCTRequired: cebcf9442fc296c9b89ac791dfd463021d9f6f23 + RCTTypeSafety: b99aa872829ee18f6e777e0ef55852521c5a6788 + React: 914f8695f9bf38e6418228c2ffb70021e559f92f + React-callinvoker: 23cd4e33928608bd0cc35357597568b8b9a5f068 + React-Core: 6a0a97598e9455348113bfe4c573fe8edac34469 + React-CoreModules: a88a6ca48b668401b9780e272e2a607e70f9f955 + React-cxxreact: 06265fd7e8d5c3b6b49e00d328ef76e5f1ae9c8b + React-debug: 039d3dbd3078613e02e3960439bbf52f6d321bc4 + React-defaultsnativemodule: 09efbfa17b15445907689c577e371558d8b08135 + React-domnativemodule: 6284a09207d8e0e974affb0d84b43a0c1aee2554 + React-Fabric: 5ffa7f2a10fb3bf835f97990d341419ae338963d + React-FabricComponents: 25173bc205a6b7c18d87121891f3acef1c329b04 + React-FabricImage: aa90e4b2b34a79f9b4ee56328ad9222cb672f1f3 + React-featureflags: 7bdaca8af1def3ec9203743c91b11ac7c2cb2574 + React-featureflagsnativemodule: 6840bc359820d5e44f1de1f9ba69706e0a88a60b + React-graphics: b0a76138e325f9c5dfcc8fbc62491ab252ca736c + React-hermes: a852be3ab9e1f515e46ba3ea9f48c31d4a9df437 + React-idlecallbacksnativemodule: 38895fd946b2dcb0af387f2176f5f2e578b14277 + React-ImageManager: 44409a10adff7091c9e678b97ee59c7b0576b8ae + React-jserrorhandler: 3852205bbfc68277cd4e7392ad1fa74a170150fd + React-jsi: 7b53959aea60909ac6bbe4dd0bdec6c10d7dc597 + React-jsiexecutor: 19938072af05ade148474bac41e0324a2d733f44 + React-jsinspector: 0aecd79939adf576c6dd7bbbddf90b630e7827e4 + React-jsinspectorcdp: 8245973529c78d150aebddd2c497ee290349faf0 + React-jsinspectornetwork: 496a12dbc80835fac10acf29b9c4386ddcc472f1 + React-jsinspectortracing: 1939b3e0cec087983384c5561bf925f35287d760 + React-jsitooling: 86c70336d5c371b4289499e9303b6da118ad3eeb + React-jsitracing: 8eb0d50d7874886fb3ec7f85e0567f1964a20075 + React-logger: a913317214a26565cd4c045347edf1bcacb80a3f + React-Mapbuffer: 94f4264de2cb156960cd82b338a403f4653f2fd9 + React-microtasksnativemodule: 6c4ee39a36958c39c97b074d28f360246a335e84 + react-native-attestation: 59a8566766131a61587d9ceb7602040e31fdab7f react-native-config: 644074ab88db883fcfaa584f03520ec29589d7df - react-native-date-picker: 729d0384b49f516c6712625aa571d55af5cdb1e0 - react-native-document-picker: bfe9c7d72908d2faba56a4765373c6367090ae2e + react-native-document-picker: dcf5e57f3bcae61bf8384a1c6f90896f81e17941 react-native-encrypted-storage: 569d114e329b1c2c2d9f8c84bcdbe4478dda2258 react-native-get-random-values: d16467cf726c618e9c7a8c3c39c31faa2244bbba - react-native-netinfo: 28c2462c85067fe653615f6f595673bdca93a287 + react-native-keyboard-controller: 7e305e26078360602b5d523ff84250b5a054a6ff + react-native-netinfo: cec9c4e86083cb5b6aba0e0711f563e2fbbff187 react-native-orientation-locker: ee8bb2177365ca74f51dc1e11218fe544634d523 - react-native-safe-area-context: efd435f89b73d91f37438e5ac2d725f0e7adff95 - react-native-screenguard: 8172a4f514c46fd76fe84c5a599e818fc3b81b87 + react-native-safe-area-context: c00143b4823773bba23f2f19f85663ae89ceb460 + react-native-screenguard: 4cdef4ef526bba6728917e4d188b1e8083081953 react-native-splash-screen: 95994222cc95c236bd3cdc59fe45ed5f27969594 react-native-tcp-socket: ae8abcfebc071216302a09d9ed1e375d4e877484 - react-native-video: bb03ea28ed6554fd615a71bb6e8c9bddab201555 + react-native-video: a509f299d71020addc12bff98bc094c142d3f09c react-native-volume-manager: d9d2863a2374420af89c89662333ea6adf506988 react-native-webrtc: 96fdff9e3a942ed88cafe01898da1c93fd628957 - react-native-webview: 5095dd03fc98a529e44a6bb81aed21062b5f879e + react-native-webview: 4cbb7f05f2c50671a7dcff4012d3e85faad271e4 react-native-zeroconf: eb2e5584308f20f5fc3eb0cea2ceafbbd345b48b - React-nativeconfig: f77b4627803bf7886a1f2e96b33b8af34e583cc4 - React-NativeModulesApple: dfa86c79c621f2a9cdb39636570c2e1623b71367 - React-perflogger: 1f83401f01544142b32151ef6c66870455c64994 - React-performancetimeline: 514430bf73208debfb0b9981fdab0e3e67987447 - React-RCTActionSheet: f8f5545f473a87a8ab124046fe58905b82c55322 - React-RCTAnimation: bb5332589ee135a4b3e06f9475659ae73a36f669 - React-RCTAppDelegate: 56493d143af24c5d728880adcf7849b3deb864e4 - React-RCTBlob: 9305f10874660b7d7bd02f6567e1b97c29b5cc43 - React-RCTFabric: c116c07d3d57e7bd03d64e445f43b33cd57a1b51 - React-RCTFBReactNativeSpec: 87fc0066242c08a7b7d03297d5ea803ac0df6575 - React-RCTImage: f099c09decb34b6849518e85aa8cd6318381ed98 - React-RCTLinking: ab70f4b60e21b0abb8c2adc58ae0460cffecdd8f - React-RCTNetwork: ba84704fa893dcc090d5028b932ed049332b9e6f - React-RCTSettings: bad043f6652f2641fccf9654c3f789e970ca63c8 - React-RCTText: bed66ec05d4dedfc48d6db8d3cf60e714b2d010d - React-RCTVibration: 22179961d1aadd7996355785c490c134037de1d9 - React-rendererconsistency: 9f5292176e629370402cbfe4e88c19b3c68e79a3 - React-rendererdebug: 1d63129046b7a8624f0a5d2cb4cc4a1dda41eeaf - React-rncore: 8a77fbb638aab2ef0a3e4e122ddc5310a8299699 - React-RuntimeApple: cf68b82dc184c7f8855aa6bae298b4b24880d549 - React-RuntimeCore: 98ab2e46540d3560712334257b01d6305c0cb422 - React-runtimeexecutor: 2dc71d251ce5630b11d384bc80d7fbb9d9d93623 - React-RuntimeHermes: 7cc49896e48214abee8f2a9bf91e7a91606ff018 - React-runtimescheduler: a51c3e414e288f3ab876b8b6e50e89c805ffd704 - React-timing: 7d80ad4297c57ec4cb49da4a5db1b82f93fedb2a - React-utils: 6b632afea2c4ec4b782497fb61af859a5b1b355f - ReactAppDependencyProvider: 31015410a4a53b9fd0a908ad4d6e3e2b9a25086a - ReactCodegen: eac5d74d85dff515b48a5c36f154bc4128f217e6 - ReactCommon: bf4612cba0fa356b529385029f470d5529dddde4 + React-NativeModulesApple: ebf2ce72b35870036900d6498b33724386540a71 + React-oscompat: eb0626e8ba1a2c61673c991bf9dc21834898475d + React-perflogger: 509e1f9a3ee28df71b0a66de806ac515ce951246 + React-performancetimeline: 43a1ea36ac47853b479ae85e04c1c339721e99f1 + React-RCTActionSheet: 30fe8f9f8d86db4a25ff34595a658ecd837485fc + React-RCTAnimation: 3126eb1cb8e7a6ca33a52fd833d8018aa9311af1 + React-RCTAppDelegate: b03981c790aa40cf26e0f78cc0f1f2df8287ead4 + React-RCTBlob: 53c35e85c85d6bdaa55dc81a0b290d4e78431095 + React-RCTFabric: 4e2a4176f99b6b8f2d2eda9fc82453a3e6c3ef8e + React-RCTFBReactNativeSpec: 947126c649e04b95457a40bc97c4b2a76206534b + React-RCTImage: 074b2faa71a152a456c974e118b60c9eeda94a64 + React-RCTLinking: e5ca17a4f7ae2ad7b0c0483be77e1b383ecd0a8a + React-RCTNetwork: c508d7548c9eceac30a8100a846ea00033a03366 + React-RCTRuntime: 6813778046c775c124179d9e4d7b33d4129bbd84 + React-RCTSettings: dd84c857a4fce42c1e08c1dabcda894e25af4a6e + React-RCTText: 6e4b177d047f98bccb90d6fb1ebdd3391cf8b299 + React-RCTVibration: 9572d4a06a0c92650bcc62913e50eb2a89f19fb6 + React-rendererconsistency: 6f0622076d7b26eda57a582db5ffd8b05fe94652 + React-renderercss: c00b6db35f01e2f17e496d1d0793fc0be89d4f7b + React-rendererdebug: 17f707ba5ba1ed7a10dd997a2e27b2431b24a180 + React-RuntimeApple: b9b9a53afd594eb49c3e6891f84327d1834a2c5e + React-RuntimeCore: 5a0c78665206a44c4a030e2b4af0c8d6ad05ae77 + React-runtimeexecutor: 7f56789cd23bd4ea1f95595eb5c27e08cee3a19e + React-RuntimeHermes: b2d6bc03f4cc9d2eb7ee0a1bfe16c226cb2114ce + React-runtimescheduler: 5cc5c0568bf216e1ee8f3c2c0a1cff2ef3091b32 + React-timing: b1e27e61bd184fab3792947685bebdb2dc55af9a + React-utils: ddf52534853a3b5f19d4615b1a1f172b504673f2 + ReactAppDependencyProvider: 1bcd3527ac0390a1c898c114f81ff954be35ed79 + ReactCodegen: 6c26f8c25d0b5ae66f86a1cce1777076ac8bcbd8 + ReactCommon: 5f0e5c09a64a2717215dd84380e1a747810406f2 ReactNativeIncallManager: dccd3e7499caa3bb73d3acfedf4fb0360f1a87d5 RNArgon2: 708e188b7a4d4ec8baf62463927c47abef453a94 - RNCAsyncStorage: 886aecfc41ffbd3ad8bbf20399008dcdb9825c8d - RNCClipboard: ba9fda8e2c9f003a29f7f66793069c4d0dada955 + RNCAsyncStorage: 29f0230e1a25f36c20b05f65e2eb8958d6526e82 + RNCClipboard: 4b58c780f63676367640f23c8e114e9bd0cf86ac RNDeviceInfo: d3e91ffb33ee97a7982108476edb68cb3672efa6 RNFBApp: 4105e54d9ca4a1c10893a032268470f670181110 RNFBMessaging: 6857871d9dff8f26b0c325fc7d97ba69cb77d213 RNFS: 89de7d7f4c0f6bafa05343c578f61118c8282ed8 - RNGestureHandler: 657b9ff1f40ee3ace3de2bcf467f86d9a6874197 + RNGestureHandler: 3a73f098d74712952870e948b3d9cf7b6cae9961 RNInAppBrowser: 6d3eb68d471b9834335c664704719b8be1bfdb20 - RNKeychain: c497f7844b24577523bb84a6e8af9d217957972f + RNKeychain: a2c134ab796272c3d605e035ab727591000b30f3 RNLocalize: 8bf466de4c92d4721b254aabe1ff0a1456e7b9f4 - RNPermissions: 0631a73d8f4ad4456d7b8800c8d229bc25fd69bf - RNScreens: 5a1573ceb1a13b2d0663cbfb42cb4aa8803554eb - RNSVG: 877cd57c2db63dc9f1fd1bbb5e95506ccd481df6 - RNVectorIcons: e3de86373e72222279df103848d78f41c5236806 + RNPermissions: b07b9c6c05a5842a1d5d1e7025d95d9903b2ab51 + RNReanimated: 9af1b9f7d221d1cc2f99d935bab08419cae7c1ce + RNScreens: 0bbf16c074ae6bb1058a7bf2d1ae017f4306797c + RNSVG: 6f39605a4c4d200b11435c35bd077553c6b5963a + RNVectorIcons: 791f13226ec4a3fd13062eda9e892159f0981fae SDWebImage: e9fc87c1aab89a8ab1bbd74eba378c6f53be8abf SocketRocket: d4aabe649be1e368d1318fdf28a022d714d65748 VisionCamera: b51af005669c6642dd1b4fca434eda4c1778de87 - Yoga: 7d51419602153919f32aec72812e324d495ee49d + Yoga: d7064c22f7ba5890471d32dd95e72c77ec911f26 -PODFILE CHECKSUM: 060c20073a028f4f9dfcc51e2c64b8a5a0f9f416 +PODFILE CHECKSUM: 5dcb1c4cfd3f07b2f4465bf766c61d4f6f6088b1 -COCOAPODS: 1.15.2 +COCOAPODS: 1.14.3 diff --git a/app/ios/PrivacyInfo.xcprivacy b/app/ios/PrivacyInfo.xcprivacy index 4250b15..a403e5f 100644 --- a/app/ios/PrivacyInfo.xcprivacy +++ b/app/ios/PrivacyInfo.xcprivacy @@ -19,23 +19,26 @@ NSPrivacyAccessedAPICategoryFileTimestamp NSPrivacyAccessedAPITypeReasons + 0A2A.1 + 3B52.1 C617.1 NSPrivacyAccessedAPIType - NSPrivacyAccessedAPICategorySystemBootTime + NSPrivacyAccessedAPICategoryDiskSpace NSPrivacyAccessedAPITypeReasons - 35F9.1 + E174.1 + 85F4.1 NSPrivacyAccessedAPIType - NSPrivacyAccessedAPICategoryDiskSpace + NSPrivacyAccessedAPICategorySystemBootTime NSPrivacyAccessedAPITypeReasons - E174.1 + 35F9.1 diff --git a/app/jest.config.js b/app/jest.config.js index e0e33aa..447992e 100644 --- a/app/jest.config.js +++ b/app/jest.config.js @@ -16,9 +16,16 @@ module.exports = { '^uuid$': require.resolve('uuid'), '@credo-ts/core': require.resolve('@credo-ts/core'), '@credo-ts/anoncreds': require.resolve('@credo-ts/anoncreds'), - '@bifold/core': require.resolve('@bifold/core'), + '@credo-ts/didcomm': require.resolve('@credo-ts/didcomm'), + // Use bifold sources directly (like bifold's own jest configs) to avoid + // circular-require issues in the lib/commonjs build under jest + '^@bifold/core$': '/../bifold/packages/core/src/index.ts', + '^@bifold/verifier$': '/../bifold/packages/verifier/src/index.ts', + '^@bifold/oca/build/legacy$': '/../bifold/packages/oca/src/legacy/index.ts', + '^@bifold/oca$': '/../bifold/packages/oca/src/index.ts', + '^@bifold/react-hooks$': '/../bifold/packages/react-hooks/src/index.ts', '@bifold/remote-logs': '/__mocks__/@bifold/remote-logs.ts', - '@hyperledger/aries-askar-react-native': require.resolve('@hyperledger/aries-askar-react-native'), + '@openwallet-foundation/askar-react-native': require.resolve('@openwallet-foundation/askar-react-native'), // CRITICAL: Force Jest to use app's React instead of bifold's // Multiple copies of React cause "Invalid hook call" errors '^react$': require.resolve('react'), @@ -27,6 +34,11 @@ module.exports = { // When portal: follows symlink to bifold, it can resolve packages from bifold's node_modules // This ensures tests use app's versions with proper mocks from jestSetup.js '^react-native$': require.resolve('react-native'), + // Also map react-native subpath imports (e.g. react-native/Libraries/...) + // so bifold sources can't drag in bifold/node_modules' second RN copy + '^react-native/(.*)$': `${require('path').dirname(require.resolve('react-native/package.json'))}/$1`, + '^react-native-reanimated$': require.resolve('react-native-reanimated'), + '^react-native-keyboard-controller$': require.resolve('react-native-keyboard-controller'), '^react-native-splash-screen$': require.resolve('react-native-splash-screen'), '^react-native-toast-message$': require.resolve('react-native-toast-message'), '^react-native-device-info$': require.resolve('react-native-device-info'), @@ -53,12 +65,15 @@ module.exports = { '^react-native-screenguard$': require.resolve('react-native-screenguard'), '^react-native-tcp-socket$': require.resolve('react-native-tcp-socket'), '^react-native-vector-icons$': require.resolve('react-native-vector-icons'), + // Expo modules used by bifold core - reuse bifold's jest mocks + 'expo-crypto': '/../bifold/packages/core/__mocks__/@expo/expo-crypto.js', + '@expo/app-integrity': '/../bifold/packages/core/__mocks__/@expo/app-integrity.js', }, transform: { - '^.+\\.(js|jsx|ts|tsx)$': 'babel-jest', + '^.+\\.(js|jsx|ts|tsx|mjs)$': 'babel-jest', }, transformIgnorePatterns: [ - 'node_modules\\/(?!(.*react-native.*)|(uuid)|(@aries-framework\\/core)|(@aries-framework\\/anoncreds)|(@hyperledger\\/aries-bifold-core))', + 'node_modules/(?!(.*react-native.*|@credo-ts|@openwallet-foundation|@openid4vc|@noble|@stablelib|@digitalcredentials|dcql|valibot|query-string|decode-uri-component|filter-obj|split-on-first|uuid|@bifold|expo(nent)?|@expo(nent)?/.*)/)', ], testRegex: '(/__tests__/.*|(\\.|/)(test|spec))\\.[jt]sx?$', testPathIgnorePatterns: ['\\.snap$', '/node_modules/', '/lib', '/__tests__/contexts/'], diff --git a/app/jestSetup.js b/app/jestSetup.js index 6f2e40e..36ce43f 100644 --- a/app/jestSetup.js +++ b/app/jestSetup.js @@ -25,5 +25,56 @@ jest.mock('react-native-permissions', () => require('react-native-permissions/mo jest.mock('react-native-splash-screen', () => ({})) jest.mock('@bifold/react-native-attestation', () => ({})) jest.mock('@hyperledger/anoncreds-react-native', () => ({})) -jest.mock('@hyperledger/aries-askar-react-native', () => ({})) +jest.mock('@openwallet-foundation/askar-react-native', () => ({})) jest.mock('@hyperledger/indy-vdr-react-native', () => ({})) + +// React 18+/19: enable proper act() behavior in tests +globalThis.IS_REACT_ACT_ENVIRONMENT = true + +jest.mock('react-native-reanimated', () => require('react-native-reanimated/mock')) + +// Mirror bifold's jestSetup: keep RefreshOrchestrator from spinning timers/logs +jest.mock('../bifold/packages/core/src/modules/openid/refresh/RefreshOrchestrator', () => ({ + RefreshOrchestrator: jest.fn().mockImplementation(() => ({ + configure: jest.fn(), + start: jest.fn(), + stop: jest.fn(), + runOnce: jest.fn(), + })), +})) + +jest.mock('react-native-keyboard-controller', () => { + const { ScrollView, View } = jest.requireActual('react-native') + return { + KeyboardProvider: ({ children }) => children, + KeyboardAwareScrollView: ScrollView, + KeyboardAvoidingView: View, + } +}) + +// Mock Keyboard to fix KeyboardAvoidingView cleanup issues in tests +// React Native 0.81+ exports Keyboard as .default +const mockKeyboard = { + addListener: jest.fn(() => ({ remove: jest.fn() })), + removeListener: jest.fn(), + dismiss: jest.fn(), + scheduleLayoutAnimation: jest.fn(), + isVisible: jest.fn(() => false), + metrics: jest.fn(() => null), +} +jest.mock('react-native/Libraries/Components/Keyboard/Keyboard', () => ({ + default: mockKeyboard, + ...mockKeyboard, +})) + +// Mock BackHandler to return subscription with remove() method +// This covers the new subscription-based API used in React Native 0.81+ +const mockBackHandler = { + addEventListener: jest.fn(() => ({ remove: jest.fn() })), + removeEventListener: jest.fn(), + exitApp: jest.fn(), +} +jest.mock('react-native/Libraries/Utilities/BackHandler', () => ({ + default: mockBackHandler, + ...mockBackHandler, +})) diff --git a/app/metro.config.js b/app/metro.config.js index 0d45d47..c59370a 100644 --- a/app/metro.config.js +++ b/app/metro.config.js @@ -2,7 +2,9 @@ const { getDefaultConfig, mergeConfig } = require('@react-native/metro-config') const fs = require('fs') const path = require('path') const escape = require('escape-string-regexp') -const exclusionList = require('metro-config/src/defaults/exclusionList') +// metro 0.83+ moved internal files under exports "./private/*" +const exclusionListModule = require('metro-config/private/defaults/exclusionList') +const exclusionList = exclusionListModule.default ?? exclusionListModule require('dotenv').config() const packageDirs = [ @@ -12,6 +14,7 @@ const packageDirs = [ fs.realpathSync(path.join(__dirname, 'node_modules', '@bifold/verifier')), fs.realpathSync(path.join(__dirname, 'node_modules', '@bifold/react-native-attestation')), fs.realpathSync(path.join(__dirname, 'node_modules', '@bifold/vrc-contexts')), + fs.realpathSync(path.join(__dirname, 'node_modules', '@bifold/react-hooks')), ] // In development, resolve these to source for hot reload; CI/production uses built output. @@ -20,6 +23,7 @@ const BIFOLD_SOURCE_PACKAGES = [ '@bifold/verifier', '@bifold/vrc-contexts', '@bifold/react-native-attestation', + '@bifold/react-hooks', ] const bifoldSourceDirByPackage = {} for (const dir of packageDirs) { @@ -33,7 +37,11 @@ for (const dir of packageDirs) { } } -const watchFolders = [...packageDirs] +// bifold workspace deps hoist to bifold/node_modules; metro must watch it to +// resolve them from bifold's built lib output (production bundles) +const bifoldNodeModules = fs.realpathSync(path.join(__dirname, '..', 'bifold', 'node_modules')) + +const watchFolders = [...packageDirs, bifoldNodeModules] const extraExclusionlist = [] const extraNodeModules = {} @@ -47,6 +55,9 @@ const polyfillModules = { buffer: path.join(__dirname, 'node_modules', 'buffer'), // Force rdf-canonize to use our patched version from app's node_modules 'rdf-canonize': path.join(__dirname, 'node_modules', 'rdf-canonize'), + // bifold workspace cross-deps hoist to bifold/node_modules, which metro + // doesn't watch; resolve them through the app's portals instead + '@bifold/react-hooks': path.join(__dirname, 'node_modules', '@bifold/react-hooks'), } for (const packageDir of packageDirs) { @@ -102,8 +113,27 @@ module.exports = (async () => { }, assetExts: assetExts.filter((ext) => ext !== 'svg'), sourceExts: [...sourceExts, 'svg', 'cjs'], + // Prefer browser builds (e.g. nanoid) over node builds that require('crypto'). + // Same setup as bifold samples/app. + unstable_enablePackageExports: true, + unstable_conditionNames: ['react-native', 'browser', 'require'], + nodeModulesPaths: [path.join(__dirname, 'node_modules'), bifoldNodeModules], // Force specific module imports to use our polyfilled/patched versions resolveRequest: (context, moduleName, platform) => { + // Singleton packages: always resolve from the app's node_modules so + // bifold sources never load a second copy (bifold/node_modules is on + // nodeModulesPaths, which would otherwise win for react etc.) + const singletonPrefixes = ['react', 'react-native', 'react-dom', '@credo-ts/core', '@credo-ts/didcomm', '@credo-ts/anoncreds'] + const isSingleton = singletonPrefixes.some((pkg) => moduleName === pkg || moduleName.startsWith(`${pkg}/`)) + if (isSingleton && !context.originModulePath.startsWith(__dirname)) { + // Re-resolve as if requested from the app root (keeps package + // "exports" handling intact, unlike remapping to an absolute path) + return context.resolveRequest( + { ...context, originModulePath: path.join(__dirname, 'index.js') }, + moduleName, + platform + ) + } // Ensure js-sha256 is resolved from app's node_modules // This is needed by patched @digitalcredentials/jsonld-signatures and rdf-canonize if (moduleName === 'js-sha256') { diff --git a/app/package.json b/app/package.json index 5dbcba6..f690c23 100644 --- a/app/package.json +++ b/app/package.json @@ -35,58 +35,58 @@ "prettier:fix": "prettier --loglevel=warn --write '**/*.+(js|jsx|json|ts|tsx|md|yml|yaml)'", "pre-commit-lint": "yarn lint-staged", "typecheck": "tsc --noEmit", - "storybook": "start-storybook -p 7007", - "build-storybook": "build-storybook", "ios:setup": "bundle install && cd ios && bundle exec pod install", "android:setup": "cd android && ./gradlew app:dependencies --write-locks", "setup": "yarn ios:setup && yarn android:setup" }, "dependencies": { - "@bifold/core": "2.7.4", - "@bifold/oca": "2.7.4", - "@bifold/react-native-attestation": "2.7.4", - "@bifold/remote-logs": "2.7.4", - "@bifold/verifier": "2.7.4", - "@bifold/vrc-contexts": "0.0.1", + "@animo-id/expo-secure-environment": "0.1.5", + "@bifold/core": "3.0.16", + "@bifold/oca": "3.0.16", + "@bifold/react-hooks": "3.0.16", + "@bifold/react-native-attestation": "3.0.16", + "@bifold/remote-logs": "3.0.16", + "@bifold/verifier": "3.0.16", + "@bifold/vrc-contexts": "0.1.0-alpha.1", "@craftzdog/react-native-buffer": "^6.1.1", - "@credo-ts/anoncreds": "0.5.17", - "@credo-ts/askar": "0.5.17", - "@credo-ts/core": "0.5.17", - "@credo-ts/drpc": "0.5.17", - "@credo-ts/indy-sdk-to-askar-migration": "0.5.17", - "@credo-ts/indy-vdr": "0.5.17", - "@credo-ts/openid4vc": "0.5.17", - "@credo-ts/push-notifications": "0.7.0", - "@credo-ts/question-answer": "0.5.17", - "@credo-ts/react-hooks": "0.6.1", - "@credo-ts/react-native": "0.5.17", - "@credo-ts/webvh": "0.5.17", - "@formatjs/intl-datetimeformat": "~4.2.6", - "@formatjs/intl-displaynames": "~5.2.6", - "@formatjs/intl-getcanonicallocales": "~1.7.3", - "@formatjs/intl-listformat": "~6.3.6", - "@formatjs/intl-locale": "~2.4.47", - "@formatjs/intl-numberformat": "~7.2.6", - "@formatjs/intl-pluralrules": "~4.1.6", - "@formatjs/intl-relativetimeformat": "~9.3.3", - "@hyperledger/anoncreds-react-native": "patch:@hyperledger/anoncreds-react-native@npm%3A0.2.4#~/.yarn/patches/@hyperledger-anoncreds-react-native-npm-0.2.4-644cafe308.patch", - "@hyperledger/aries-askar-react-native": "patch:@hyperledger/aries-askar-react-native@npm%3A0.2.3#~/.yarn/patches/@hyperledger-aries-askar-react-native-npm-0.2.3-3207b51eab.patch", - "@hyperledger/indy-vdr-react-native": "patch:@hyperledger/indy-vdr-react-native@npm%3A0.2.2#~/.yarn/patches/@hyperledger-indy-vdr-react-native-npm-0.2.2-627d424b96.patch", - "@hyperledger/indy-vdr-shared": "0.2.2", + "@credo-ts/anoncreds": "0.6.3", + "@credo-ts/askar": "0.6.3", + "@credo-ts/core": "0.6.3", + "@credo-ts/didcomm": "0.6.3", + "@credo-ts/indy-vdr": "0.6.3", + "@credo-ts/openid4vc": "0.6.3", + "@credo-ts/question-answer": "0.6.3", + "@credo-ts/react-native": "0.6.3", + "@credo-ts/webvh": "0.6.3", + "@expo/app-integrity": "^55.0.9", + "@formatjs/intl-datetimeformat": "~6.18.2", + "@formatjs/intl-displaynames": "~6.8.13", + "@formatjs/intl-getcanonicallocales": "~2.5.6", + "@formatjs/intl-listformat": "~7.7.13", + "@formatjs/intl-locale": "~4.2.13", + "@formatjs/intl-numberformat": "~8.15.6", + "@formatjs/intl-pluralrules": "~5.4.6", + "@formatjs/intl-relativetimeformat": "~11.4.13", + "@hyperledger/anoncreds-react-native": "0.3.4", + "@hyperledger/indy-vdr-react-native": "0.2.4", + "@hyperledger/indy-vdr-shared": "0.2.4", + "@openwallet-foundation/askar-react-native": "0.6.0", "@pexip/infinity-api": "~19.1.2", - "@react-native-async-storage/async-storage": "~1.22.3", + "@react-native-async-storage/async-storage": "~2.2.0", "@react-native-clipboard/clipboard": "~1.16.3", - "@react-native-community/netinfo": "~11.3.3", + "@react-native-community/netinfo": "~11.4.1", "@react-native-firebase/app": "~21.14.0", "@react-native-firebase/messaging": "~21.14.0", "@react-navigation/bottom-tabs": "~6.0.9", "@react-navigation/devtools": "~6.0.27", "@react-navigation/native": "~6.0.16", "@react-navigation/stack": "~6.3.29", - "axios": "~1.4.0", + "axios": "~1.13.2", "base-64": "~1.0.0", "buffer": "^6.0.3", - "credo-ts-indy-vdr-proxy-client": "0.2.4", + "expo": "~54.0.31", + "expo-crypto": "~15.0.8", + "expo-secure-store": "~15.0.8", "fast-text-encoding": "~1.0.6", "i18next": "~21.6.16", "js-sha256": "^0.11.1", @@ -96,9 +96,9 @@ "lodash.startcase": "~4.4.0", "moment": "~2.29.4", "query-string": "~7.1.3", - "react": "~18.3.1", + "react": "19.1.0", "react-i18next": "~11.17.1", - "react-native": "0.77.3", + "react-native": "patch:react-native@npm%3A0.81.5#~/.yarn/patches/react-native-npm-0.81.5-d8232ef145.patch", "react-native-animated-pagination-dots": "~0.1.73", "react-native-argon2": "~2.0.1", "react-native-bouncy-checkbox": "~3.0.7", @@ -106,67 +106,64 @@ "react-native-collapsible": "~1.6.2", "react-native-config": "~1.5.5", "react-native-confirmation-code-field": "~7.3.2", - "react-native-date-picker": "~5.0.13", "react-native-device-info": "~8.7.1", - "react-native-document-picker": "^9.3.1", + "react-native-document-picker": "patch:react-native-document-picker@npm%3A9.3.1#~/.yarn/patches/react-native-document-picker-npm-9.3.1-ce22d39a18.patch", "react-native-encrypted-storage": "~4.0.3", "react-native-fs": "~2.20.0", - "react-native-gesture-handler": "~2.22.0", + "react-native-gesture-handler": "~2.28.0", "react-native-get-random-values": "~1.11.0", - "react-native-gifted-chat": "*", + "react-native-gifted-chat": "~3.3.2", "react-native-inappbrowser-reborn": "~3.7.0", "react-native-incall-manager": "~4.2.1", - "react-native-keychain": "~8.1.3", + "react-native-keyboard-controller": "~1.18.5", + "react-native-keychain": "~10.0.0", "react-native-linear-gradient": "^2.8.3", "react-native-localize": "~2.2.6", "react-native-logs": "~5.1.0", "react-native-orientation-locker": "~1.6.0", "react-native-permissions": "~5.4.1", "react-native-qrcode-svg": "~6.2.0", - "react-native-safe-area-context": "~5.1.0", + "react-native-reanimated": "~3.19.5", + "react-native-safe-area-context": "~5.6.2", "react-native-scalable-image": "~1.1.0", "react-native-screenguard": "~1.1.0", - "react-native-screens": "~4.6.0", + "react-native-screens": "~4.16.0", "react-native-splash-screen": "~3.3.0", - "react-native-svg": "~15.11.1", + "react-native-svg": "~15.12.1", "react-native-tcp-socket": "~6.0.6", "react-native-toast-message": "~2.1.10", + "react-native-url-polyfill": "3.0.0", "react-native-uuid": "~2.0.3", - "react-native-vector-icons": "~10.0.3", + "react-native-vector-icons": "~10.3.0", "react-native-video": "~6.16.1", "react-native-vision-camera": "4.7.3", "react-native-volume-manager": "~1.10.0", "react-native-webrtc": "~124.0.6", - "react-native-webview": "~13.13.1", + "react-native-webview": "~13.15.0", "react-native-zeroconf": "~0.14.0", "readable-stream": "^4.7.0", "reflect-metadata": "~0.1.14", "rxjs": "~7.8.2", "stream-browserify": "^3.0.0", "tsyringe": "~4.8.0", - "uuid": "~9.0.1" + "uuid": "~9.0.1", + "zustand": "~4.5.4" }, "devDependencies": { - "@babel/core": "~7.25.2", - "@babel/preset-env": "~7.25.3", - "@babel/runtime": "~7.25.0", + "@babel/core": "~7.28.6", + "@babel/plugin-transform-export-namespace-from": "^7.27.1", + "@babel/preset-env": "~7.28.6", + "@babel/runtime": "~7.28.6", "@commitlint/cli": "~11.0.0", "@eslint/js": "~8.57.1", - "@react-native-community/cli": "15.0.1", - "@react-native-community/cli-platform-android": "15.0.1", - "@react-native-community/cli-platform-ios": "15.0.1", - "@react-native/babel-preset": "0.77.3", - "@react-native/eslint-config": "0.77.3", - "@react-native/eslint-plugin": "0.77.3", - "@react-native/metro-config": "0.77.3", - "@react-native/typescript-config": "0.77.3", - "@storybook/addon-actions": "~5.3.21", - "@storybook/addon-knobs": "~5.3.21", - "@storybook/addon-links": "~5.3.21", - "@storybook/addon-ondevice-actions": "~5.3.23", - "@storybook/addon-ondevice-knobs": "~5.3.26", - "@storybook/react-native": "~5.3.27", - "@storybook/react-native-server": "~5.3.23", + "@react-native-community/cli": "20.0.2", + "@react-native-community/cli-platform-android": "20.0.2", + "@react-native-community/cli-platform-ios": "20.0.2", + "@react-native/babel-preset": "0.81.5", + "@react-native/eslint-config": "0.81.5", + "@react-native/eslint-plugin": "0.81.5", + "@react-native/metro-config": "0.81.5", + "@react-native/typescript-config": "0.81.5", "@testing-library/jest-native": "~5.4.3", "@testing-library/react-native": "~12.3.3", "@types/eslint__js": "~8.42.3", @@ -174,14 +171,13 @@ "@types/lodash.flatten": "~4.4.9", "@types/lodash.merge": "~4.6.9", "@types/lodash.startcase": "~4.4.9", - "@types/react": "~18.2.79", - "@types/react-native": "~0.71.13", + "@types/react": "~19.1.9", "@types/react-native-vector-icons": "~6.4.18", - "@types/react-test-renderer": "~18.0.7", + "@types/react-test-renderer": "~19.1.0", "@types/readable-stream": "^4", "@typescript-eslint/eslint-plugin": "~7.18.0", "@typescript-eslint/parser": "~7.18.0", - "babel-jest": "~27.5.1", + "babel-jest": "~29.7.0", "babel-plugin-module-resolver": "~5.0.2", "commitlint": "~17.7.2", "copyfiles": "~2.4.1", @@ -195,16 +191,15 @@ "husky": "~7.0.4", "jest": "~29.6.4", "lint-staged": "~11.2.6", - "metro-react-native-babel-transformer": "~0.77.0", "mockdate": "~3.0.5", "patch-package": "^8.0.1", "pod-install": "~0.1.39", "postinstall-postinstall": "^2.1.0", "prettier": "~2.8.8", - "react-dom": "~18.3.1", - "react-native-svg-transformer": "~0.14.3", - "react-test-renderer": "~18.3.1", - "typescript": "~5.5.4", + "react-dom": "19.1.0", + "react-native-svg-transformer": "^1.5.1", + "react-test-renderer": "19.1.0", + "typescript": "~5.9.2", "typescript-eslint": "~7.18.0" } } diff --git a/app/src/components/PressableOpacity.tsx b/app/src/components/PressableOpacity.tsx new file mode 100644 index 0000000..df5f286 --- /dev/null +++ b/app/src/components/PressableOpacity.tsx @@ -0,0 +1,29 @@ +import { Pressable } from 'react-native' + +/** + * A wrapper around Pressable that mimics the opacity change of TouchableOpacity when pressed. + * + * Ported from bc-wallet-mobile. Prefer this over react-native's TouchableOpacity — + * Pressable uses the modern responder system and is reliable on the New Architecture + * (TouchableOpacity taps get dropped in some nested-list/inverted-list situations). + * + * @param props - The props for the Pressable component + * @returns A Pressable component that changes opacity when pressed, similar to TouchableOpacity + */ +export const PressableOpacity = (props: React.ComponentProps) => { + return ( + { + const style = typeof props.style === 'function' ? props.style(state) : props.style + + if (!state.pressed) { + return style + } + + return [style, { opacity: 0.2 }] // Mimics the default opacity from TouchableOpacity + }} + /> + ) +} diff --git a/app/src/constants.ts b/app/src/constants.ts index acdd141..26edb0e 100644 --- a/app/src/constants.ts +++ b/app/src/constants.ts @@ -2,6 +2,10 @@ export const autoDisableRemoteLoggingIntervalInMinutes = 60 export const surveyMonkeyUrl = 'https://www.surveymonkey.com/r/7BMHJL8' export const surveyMonkeyExitUrl = 'https://www.surveymonkey.com/survey-thanks' export const hitSlop = { top: 44, bottom: 44, left: 44, right: 44 } + +// Reserved AppError status codes (see src/errors/errorRegistry.ts) +export const UNKNOWN_APP_ERROR_STATUS_CODE = 9999 +export const FATAL_UNRECOVERABLE_ERROR_STATUS_CODE = 9998 interface AttestationRestrictionEnvironment { credDefIDs: readonly string[] invitationUrl: string diff --git a/app/src/contexts/ErrorAlertContext.tsx b/app/src/contexts/ErrorAlertContext.tsx new file mode 100644 index 0000000..5f76b22 --- /dev/null +++ b/app/src/contexts/ErrorAlertContext.tsx @@ -0,0 +1,137 @@ +import { AppError } from '@/errors' +import { AppErrorModal, ErrorModalAction, ErrorModalPayload } from '@/errors/components/ErrorModal' +import { AlertAction, showAlert } from '@/utils/alert' +import BCLogger from '@/utils/logger' + +import { createContext, PropsWithChildren, useCallback, useContext, useMemo, useState } from 'react' + +interface ErrorModalOptions { + action?: ErrorModalAction +} + +export interface AlertOptions { + /** Custom actions/buttons for the native alert */ + actions?: AlertAction[] +} + +export interface ErrorAlertContextType { + /** + * Show error via ErrorModal (default display) + */ + emitErrorModal: (title: string, description: string, error: AppError, options?: ErrorModalOptions) => void + + /** + * Show native alert with title and description + */ + emitAlert: (title: string, description: string, options?: AlertOptions) => void +} + +export const ErrorAlertContext = createContext(null) + +interface ErrorAlertProviderProps extends PropsWithChildren { + enableReport?: boolean +} + +/** + * ErrorAlertProvider - Unified error and alert handling (ported from bc-wallet-mobile). + * + * Owns the error modal state and renders AppErrorModal directly, + * eliminating DeviceEventEmitter indirection. + * + * Provides a single entry point for: + * - Error modals (via AppErrorModal, rendered internally) + * - Native alerts (via React Native Alert) + * - Error logging (remote logger / Loki) + */ +export const ErrorAlertProvider = ({ children, enableReport = true }: ErrorAlertProviderProps) => { + const [error, setError] = useState(null) + const [errorKey, setErrorKey] = useState(0) + const [errorModalOptions, setErrorModalOptions] = useState(null) + + /** + * Show error via ErrorModal + * + * @param title - The title to display in the error modal + * @param description - The description/message to display in the error modal + * @param error - The AppError instance containing error details + * @returns void + */ + const emitErrorModal = useCallback( + (title: string, description: string, error: AppError, options?: ErrorModalOptions): void => { + setErrorModalOptions(options ?? null) + + BCLogger.error(`[${error.code}] Error modal emitted`, { + title, + description, + ...error.toJSON(), + }) + + setError({ + title, + description, + message: error.fullMessage, + code: error.statusCode, + appEvent: error.appEvent, + stack: error.stack, + cause: error.cause, + screen: error.screen, + url: error.url, + method: error.method, + }) + setErrorKey((prev) => prev + 1) + }, + [] + ) + + /** + * Show native alert with title and description + */ + const emitAlert = useCallback((title: string, description: string, options?: AlertOptions): void => { + showAlert(title, description, options?.actions) + }, []) + + /** + * Dismiss the currently displayed error modal + */ + const dismissErrorModal = useCallback((): void => { + setError(null) + setErrorModalOptions(null) + }, []) + + const value: ErrorAlertContextType = useMemo( + () => ({ + emitErrorModal, + emitAlert, + }), + [emitErrorModal, emitAlert] + ) + + return ( + + {children} + + + ) +} + +/** + * Hook to access error and alert functionality + * + * @returns Error alert context with methods: emitErrorModal, emitAlert + * @throws Error if used outside of ErrorAlertProvider + */ +export const useErrorAlert = (): ErrorAlertContextType => { + const context = useContext(ErrorAlertContext) + + if (!context) { + throw new Error('useErrorAlert must be used within an ErrorAlertProvider') + } + + return context +} diff --git a/app/src/errors/appError.test.ts b/app/src/errors/appError.test.ts new file mode 100644 index 0000000..66c2d0b --- /dev/null +++ b/app/src/errors/appError.test.ts @@ -0,0 +1,130 @@ +import { AppEventCode } from '@/events/appEventCode' +import { AppError, isAppError, isHandledAppError } from './appError' +import { ErrorCategory, ErrorRegistry } from './errorRegistry' + +describe('AppError', () => { + describe('constructor', () => { + it('should create an AppError with correct properties', () => { + const identity = { + category: ErrorCategory.GENERAL, + appEvent: AppEventCode.UNKNOWN_SERVER_ERROR, + statusCode: 1234, + } + const message = 'Detailed technical message' + const error = new AppError(message, identity, { cause: new Error(message) }) + + expect(error.message).toBe(message) + expect(error.code).toBe('general.unknown_server_error.1234') + expect(error.appEvent).toBe('unknown_server_error') + expect(error.technicalMessage).toBe(message) + expect(error.cause).toBeInstanceOf(Error) + expect(error.timestamp).toBeDefined() + expect(error.handled).toBe(false) + }) + }) + + describe('technicalMessage', () => { + const identity = { + category: ErrorCategory.GENERAL, + appEvent: AppEventCode.UNKNOWN_SERVER_ERROR, + statusCode: 1234, + } + + it('should return null if there is no cause', () => { + const error = new AppError('Something went wrong', identity) + + expect(error.technicalMessage).toBeNull() + }) + + it('should return null if cause is not an Error', () => { + const error = new AppError('Something went wrong', identity, { cause: 'Not an error' }) + + expect(error.technicalMessage).toBeNull() + }) + + it('should prefix the native error code when present on the cause', () => { + const cause = Object.assign(new Error("Key pair with alias 'abc' not found."), { code: 'E_KEY_NOT_FOUND' }) + const error = new AppError('Something went wrong', identity, { cause }) + + expect(error.technicalMessage).toBe("E_KEY_NOT_FOUND: Key pair with alias 'abc' not found.") + }) + + it('should append the server response body for AxiosErrors when it is a short string', () => { + const axiosLike = Object.assign(new Error('Request failed with status code 400'), { + isAxiosError: true, + response: { data: 'email_address is invalid' }, + }) + const error = new AppError('Bad request', identity, { cause: axiosLike }) + + expect(error.technicalMessage).toBe('Request failed with status code 400: email_address is invalid') + }) + + it('should not append the response body for AxiosErrors when it is not a string', () => { + const axiosLike = Object.assign(new Error('Request failed with status code 400'), { + isAxiosError: true, + response: { data: { error: 'bad_request' } }, + }) + const error = new AppError('Bad request', identity, { cause: axiosLike }) + + expect(error.technicalMessage).toBe('Request failed with status code 400') + }) + }) + + describe('fullMessage', () => { + it('should include the debug code', () => { + const error = AppError.fromErrorDefinition(ErrorRegistry.NO_INTERNET) + + expect(error.fullMessage).toContain(error.message) + expect(error.fullMessage).toContain(`Debug: [${error.code}]`) + }) + + it('should include the technical message when a cause is present', () => { + const error = AppError.fromErrorDefinition(ErrorRegistry.NO_INTERNET, { cause: new Error('socket hang up') }) + + expect(error.fullMessage).toContain('socket hang up') + }) + }) + + describe('fromErrorDefinition', () => { + it('should build an AppError from a registry definition', () => { + const error = AppError.fromErrorDefinition(ErrorRegistry.AGENT_INITIALIZATION_ERROR) + + expect(error.statusCode).toBe(2901) + expect(error.appEvent).toBe(AppEventCode.AGENT_INITIALIZATION_ERROR) + expect(error.code).toBe('wallet.agent_initialization_error.2901') + }) + }) + + describe('toJSON', () => { + it('should serialize without exploding the cause', () => { + const cause = Object.assign(new Error('native failure'), { code: 'E_FAIL', userInfo: { detail: 1 } }) + const error = AppError.fromErrorDefinition(ErrorRegistry.UNKNOWN_ERROR, { cause }) + + const json = error.toJSON() + expect(json.code).toBe(error.code) + expect(json.cause).toEqual(expect.objectContaining({ name: 'Error', message: 'native failure', code: 'E_FAIL' })) + }) + }) + + describe('isAppError / isHandledAppError', () => { + it('should identify AppErrors', () => { + const error = AppError.fromErrorDefinition(ErrorRegistry.UNKNOWN_ERROR) + expect(isAppError(error)).toBe(true) + expect(isAppError(new Error('x'))).toBe(false) + expect(isAppError(null)).toBe(false) + }) + + it('should match on appEvent when provided', () => { + const error = AppError.fromErrorDefinition(ErrorRegistry.NO_INTERNET) + expect(isAppError(error, AppEventCode.NO_INTERNET)).toBe(true) + expect(isAppError(error, AppEventCode.SERVER_ERROR)).toBe(false) + }) + + it('should identify handled AppErrors', () => { + const error = AppError.fromErrorDefinition(ErrorRegistry.NO_INTERNET) + expect(isHandledAppError(error)).toBe(false) + error.handled = true + expect(isHandledAppError(error)).toBe(true) + }) + }) +}) diff --git a/app/src/errors/appError.ts b/app/src/errors/appError.ts new file mode 100644 index 0000000..5fa37bf --- /dev/null +++ b/app/src/errors/appError.ts @@ -0,0 +1,195 @@ +import { AppEventCode } from '@/events/appEventCode' +import { ErrorCategory, ErrorDefinition } from './errorRegistry' + +// Ported from bc-wallet-mobile; the Snowplow analytics tracking upstream does in +// the constructor was dropped — Keyring reports errors to Loki via the remote +// logger at the point they are surfaced (ErrorAlertProvider / reportProblem). + +export type ErrorIdentity = { + category: ErrorCategory + appEvent: AppEventCode + statusCode: number +} + +/** + * Reduce a `cause` to a small, safe-to-serialize summary. + * + * The raw cause of an HTTP failure is often an AxiosError whose `config.data` holds the + * full request body. Serializing it (JSON.stringify expands a Buffer to a per-byte number + * array) can exhaust memory, so toJSON() keeps only lightweight identifying fields and + * drops the nested chain/body. The live `cause` property is left untouched for runtime logic. + */ +const summarizeCause = (cause: unknown): unknown => { + if (!(cause instanceof Error)) { + return cause + } + + const { code, status, userInfo } = cause as { code?: unknown; status?: unknown; userInfo?: unknown } + const summary: Record = { name: cause.name, message: cause.message } + if (code !== undefined) { + summary.code = code + } + if (status !== undefined) { + summary.status = status + } + if (userInfo !== undefined) { + // Native-module rejections carry small, bridge-serializable diagnostics here + summary.userInfo = userInfo + } + const responseData = (cause as { response?: { data?: unknown } }).response?.data + if (typeof responseData === 'string' && responseData.length <= 500) { + summary.responseData = responseData + } + return summary +} + +/** + * Custom application error class with structured information. + * + * @extends {Error} + * @class + */ +export class AppError extends Error { + code: string // ie: network.no_internet.2100 + appEvent: AppEventCode // ie: no_internet + statusCode: number // ie: 2100 + timestamp: string // ISO timestamp of when the error was created + handled: boolean // Whether this error has been handled by a policy + screen: string | undefined // Active screen name at the time the error was created + url?: string // API endpoint URL that produced this error, if applicable + method?: string // HTTP method of the request that produced this error, if applicable + + constructor(message: string, identity: ErrorIdentity, options?: ErrorOptions) { + super(message, options) + this.name = this.constructor.name + + this.code = `${identity.category}.${identity.appEvent}.${identity.statusCode}` // ie: network.no_internet.2100 + this.appEvent = identity.appEvent + this.statusCode = identity.statusCode + this.timestamp = new Date().toISOString() + this.handled = false + this.screen = undefined + this.url = undefined + this.method = undefined + } + + /** + * Get the technical message from the original error, if available. + * + * @returns The technical message or null if not available. + */ + get technicalMessage(): string | null { + if (!(this.cause instanceof Error)) { + return null + } + + const cause = this.cause as Error & { code?: unknown; isAxiosError?: boolean; response?: { data?: unknown } } + + // AxiosErrors have their error code written into cause.code; that value is + // already captured in appEvent, so excluding it here keeps technicalMessage + // as the server description + const isAxiosError = Boolean(cause.isAxiosError) || cause.name === 'AxiosError' + + // For non-Axios errors (e.g. native module errors), cause.code is a meaningful prefix like "E_KEY_NOT_FOUND" + const code = !isAxiosError && typeof cause.code === 'string' ? cause.code : undefined + + // Include the server's response body when it's a short plain string + const responseData = isAxiosError ? cause.response?.data : undefined + const serverReason = typeof responseData === 'string' && responseData.length <= 500 ? responseData : undefined + + return [code, cause.message, serverReason].filter(Boolean).join(': ') + } + + /** + * Get the full error message, including technical details if available. + * + * This is the user-facing details string (shown behind "Show details" in the error + * modal), so it deliberately excludes the active screen and request URL — that infra + * context could alarm users. Screen/Request are appended only to the "Report this + * problem" payload sent to the remote logger, never shown to the user. + * + * @example + * `No internet connection + * Debug: [network.no_internet.2100] Failed to fetch resource` + * + * @returns The full error message string. + */ + get fullMessage(): string { + let formattedMessage = this.message + + formattedMessage += `\nDebug: [${this.code}]` + + if (this.technicalMessage) { + formattedMessage += ` ${this.technicalMessage}` + } + + return formattedMessage + } + + /** + * Create an AppError from an ErrorDefinition. + * + * @param definition - The ErrorDefinition to create the AppError from. + * @param options - Optional ErrorOptions (e.g. cause) for additional context. + * @returns An instance of AppError. + */ + static fromErrorDefinition(definition: ErrorDefinition, options?: ErrorOptions): AppError { + return new AppError( + definition.message, + { + category: definition.category, + appEvent: definition.appEvent, + statusCode: definition.statusCode, + }, + options + ) + } + + /** + * Serialize the AppError to a JSON object. Useful for logging. + * + * @return An object containing the serialized error details. + */ + toJSON() { + return { + name: this.name, + message: this.message, + technicalMessage: this.technicalMessage, + code: this.code, + timestamp: this.timestamp, + handled: this.handled, + screen: this.screen, + url: this.url, + method: this.method, + cause: summarizeCause(this.cause), + } + } +} + +/** + * Check if an error is an AppError that has already been handled by an error policy. + * + * @param error - The error to check + * @returns True if the error is an AppError and has been handled + */ +export function isHandledAppError(error: unknown): error is AppError { + return error instanceof AppError && error.handled +} + +/** + * Check if an error is an instance of AppError, and optionally if it matches a specific app event code. + * + * @param error - The error to check + * @param appEvent - Optional app event code to match against the error's appEvent property + * @returns True if the error is an AppError (and matches the app event code if provided) + */ +export function isAppError( + error: unknown, + appEvent?: TAppEventCode +): error is AppError & { appEvent: TAppEventCode } { + if (appEvent) { + return error instanceof AppError && error.appEvent === appEvent + } + + return error instanceof AppError +} diff --git a/app/src/errors/components/ErrorBoundary.tsx b/app/src/errors/components/ErrorBoundary.tsx new file mode 100644 index 0000000..8a3749f --- /dev/null +++ b/app/src/errors/components/ErrorBoundary.tsx @@ -0,0 +1,113 @@ +import { AbstractBifoldLogger } from '@bifold/core' +import React, { ReactNode } from 'react' +import { useTranslation } from 'react-i18next' +import { StyleSheet } from 'react-native' +import { SafeAreaView } from 'react-native-safe-area-context' +import { reportProblem } from '@/utils/logger' +import { toBifoldError } from '../errorHandler' +import { ErrorInfoCard } from './ErrorInfoCard' + +interface ErrorBoundaryProps { + children: ReactNode + t: (key: string) => string + logger: AbstractBifoldLogger +} + +interface ErrorBoundaryState { + hasError: boolean + error: Error | null +} + +/** + * React class error boundary that catches render errors in its subtree. + * + * Since this sits at the top of the component tree (above providers and + * ErrorModal), it renders the shared ErrorInfoCard directly in its fallback + * using hardcoded fallback colors. This avoids depending on ThemeProvider + * or any other context that lives below it. + */ +class ErrorBoundary extends React.Component { + state: ErrorBoundaryState = { hasError: false, error: null } + + static getDerivedStateFromError(error: Error): Partial { + return { hasError: true, error } + } + + componentDidCatch(error: Error): void { + this.props.logger.error(`ErrorBoundary caught an error: ${error}`) + } + + handleDismiss = (): void => { + this.setState({ hasError: false, error: null }) + } + + getReportError = (error: Error) => { + return toBifoldError(this.props.t('Error.Problem'), this.props.t('Error.ProblemDescription'), error) + } + + handleReport = (): string | undefined => { + const { error } = this.state + const { logger } = this.props + + if (!error) { + return + } + + const reportError = this.getReportError(error) + logger.error(`ErrorBoundary reported: ${error}`) + return reportProblem(reportError) + } + + render(): React.ReactNode { + const { hasError, error } = this.state + + if (hasError && error) { + const reportError = this.getReportError(error) + return ( + + + + ) + } + + return this.props.children + } +} + +const styles = StyleSheet.create({ + overlay: { + flex: 1, + backgroundColor: 'rgba(0,0,0,0.5)', + justifyContent: 'center', + alignItems: 'center', + }, +}) + +interface ErrorBoundaryWrapperProps { + children: ReactNode + logger: AbstractBifoldLogger +} + +/** + * Functional wrapper that provides useTranslation to the class-based + * ErrorBoundary. Place at the top of the component tree so it acts as + * the last-resort catch-all for unhandled render errors. + */ +export const ErrorBoundaryWrapper: React.FC = ({ children, logger }) => { + const { t } = useTranslation() + return ( + + {children} + + ) +} + +export default ErrorBoundaryWrapper diff --git a/app/src/errors/components/ErrorInfoCard.tsx b/app/src/errors/components/ErrorInfoCard.tsx new file mode 100644 index 0000000..fe46279 --- /dev/null +++ b/app/src/errors/components/ErrorInfoCard.tsx @@ -0,0 +1,416 @@ +import { PressableOpacity } from '@/components/PressableOpacity' +import { hitSlop } from '@/constants' +import { testIdWithKey } from '@bifold/core' +import Clipboard from '@react-native-clipboard/clipboard' +import React, { useEffect, useMemo, useRef, useState } from 'react' +import { useTranslation } from 'react-i18next' +import { ScrollView, StyleSheet, Text, TouchableOpacity, useWindowDimensions, View } from 'react-native' +import { getBuildNumber, getVersion } from 'react-native-device-info' +import CommunityIcon from 'react-native-vector-icons/MaterialCommunityIcons' +import Icon from 'react-native-vector-icons/MaterialIcons' +import { ErrorModalAction } from './ErrorModal' + +// This component is used outside the theme provider in many cases (e.g. the +// top-level ErrorBoundary fallback) and has style requirements the theme +// doesn't support well, so the colours are defined here (Keyring brand). +export const colors = { + cardBackground: '#FFFFFF', + cardBorder: '#D3D3D3', + shadow: '#000000', + icon: '#313132', + text: '#313132', + textSecondary: '#606060', + link: '#622C62', // Keyring brand purple + primaryButton: '#622C62', + primaryButtonDisabled: '#757575', + primaryButtonText: '#FFFFFF', + primaryButtonTextDisabled: '#FFFFFF', + successIcon: '#89CE00', + secondaryButtonBackground: '#FFFFFF', + secondaryButtonBorder: '#622C62', + secondaryButtonText: '#622C62', + destructiveButton: '#D21E30', // Keyring bright crimson + destructiveButtonText: '#FFFFFF', +} + +export interface ErrorInfoCardProps { + title: string + description: string + message?: string + code?: number + onDismiss: () => void + /** + * Invoked when the user reports the problem. May return a reference code that + * the card then surfaces for the user to share with support. + */ + onReport?: () => string | void + enableReport?: boolean + action?: ErrorModalAction +} + +export const ErrorInfoCard: React.FC = ({ + title, + description, + message, + code, + onDismiss, + onReport, + action, + enableReport = false, +}) => { + const { t } = useTranslation() + const { width } = useWindowDimensions() + const [showDetails, setShowDetails] = useState(false) + const [reported, setReported] = useState(false) + const [referenceCode, setReferenceCode] = useState(null) + const [copied, setCopied] = useState(false) + const copyResetTimeout = useRef | null>(null) + + useEffect(() => { + return () => { + if (copyResetTimeout.current) { + clearTimeout(copyResetTimeout.current) + } + } + }, []) + + const formattedDetails = message ? `${t('Error.ErrorCode')} ${code ?? 0} - ${message}` : '' + + const handleReport = () => { + setReported(true) + const reportedCode = onReport?.() + if (reportedCode) { + setReferenceCode(reportedCode) + } + } + + const handleCopy = () => { + if (!referenceCode) { + return + } + Clipboard.setString(referenceCode) + setCopied(true) + if (copyResetTimeout.current) { + clearTimeout(copyResetTimeout.current) + } + copyResetTimeout.current = setTimeout(() => setCopied(false), 2000) + } + + const containerStyle = useMemo( + () => ({ + minWidth: width - 50, + maxWidth: width - 50, + }), + [width] + ) + + return ( + + + + + + + {title} + + + + + + + + + + {description} + + + {message && ( + setShowDetails((prev) => !prev)} + activeOpacity={0.7} + > + + + {showDetails ? t('Global.HideDetails') : t('Global.ShowDetails')}{' '} + + + + + )} + + {message && showDetails && ( + + {formattedDetails} + + )} + + + {enableReport && onReport && ( + + + {reported && ( + + )} + + {reported ? t('Error.Reported') : t('Error.ReportThisProblem')} + + + + )} + + {action && ( + { + onDismiss() + action.onPress() + }} + activeOpacity={0.8} + > + + {action.text} + + + )} + + + {reported && referenceCode && ( + + {t('Error.ReferenceCode')} + + + {referenceCode} + + + + {copied ? t('Error.CodeCopied') : t('Error.CopyCode')} + + + {t('Error.ShareCodeWithSupport')} + + )} + + + {t('Settings.Version')} {getVersion()} ({getBuildNumber()}) + + + + + ) +} + +const styles = StyleSheet.create({ + card: { + backgroundColor: colors.cardBackground, + borderRadius: 8, + borderWidth: 1, + borderColor: colors.cardBorder, + padding: 16, + shadowColor: colors.shadow, + shadowOffset: { width: 0, height: 2 }, + shadowOpacity: 0.1, + shadowRadius: 8, + elevation: 4, + }, + header: { + flexDirection: 'row', + paddingHorizontal: 4, + paddingTop: 4, + }, + icon: { + marginRight: 10, + alignSelf: 'center', + }, + headerTextContainer: { + flex: 1, + alignSelf: 'center', + }, + titleText: { + fontSize: 18, + fontWeight: '700', + color: colors.text, + }, + body: { + marginTop: 8, + paddingHorizontal: 4, + paddingBottom: 8, + }, + bodyText: { + fontSize: 16, + color: colors.text, + marginVertical: 8, + lineHeight: 24, + }, + detailsText: { + fontSize: 14, + color: colors.textSecondary, + marginBottom: 4, + lineHeight: 20, + }, + showDetailsTouchable: { + marginVertical: 8, + }, + showDetailsRow: { + flexDirection: 'row', + alignItems: 'center', + }, + showDetailsText: { + fontSize: 16, + fontWeight: '500', + color: colors.link, + }, + buttons: { + paddingTop: 16, + paddingHorizontal: 4, + gap: 8, + }, + primaryButton: { + backgroundColor: colors.primaryButton, + borderRadius: 8, + paddingVertical: 14, + paddingHorizontal: 24, + alignItems: 'center', + justifyContent: 'center', + }, + primaryButtonDisabled: { + backgroundColor: colors.primaryButtonDisabled, + }, + primaryButtonContent: { + flexDirection: 'row', + alignItems: 'center', + justifyContent: 'center', + }, + reportIcon: { + marginRight: 8, + }, + primaryButtonText: { + fontSize: 16, + fontWeight: '600', + color: colors.primaryButtonText, + }, + primaryButtonTextDisabled: { + fontSize: 16, + fontWeight: '600', + color: colors.primaryButtonTextDisabled, + }, + secondaryButton: { + backgroundColor: colors.secondaryButtonBackground, + borderRadius: 8, + borderWidth: 1.5, + borderColor: colors.secondaryButtonBorder, + paddingVertical: 14, + paddingHorizontal: 24, + alignItems: 'center', + justifyContent: 'center', + }, + secondaryButtonText: { + fontSize: 16, + fontWeight: '600', + color: colors.secondaryButtonText, + }, + destructiveButton: { + backgroundColor: colors.destructiveButton, + borderRadius: 8, + paddingVertical: 14, + paddingHorizontal: 24, + alignItems: 'center', + justifyContent: 'center', + }, + destructiveButtonText: { + fontSize: 16, + fontWeight: '600', + color: colors.destructiveButtonText, + }, + referenceContainer: { + marginTop: 16, + marginHorizontal: 4, + padding: 12, + borderRadius: 8, + borderWidth: 1, + borderColor: colors.cardBorder, + backgroundColor: '#F2F2F2', + }, + referenceLabel: { + fontSize: 13, + color: colors.textSecondary, + marginBottom: 4, + }, + referenceRow: { + flexDirection: 'row', + alignItems: 'center', + justifyContent: 'space-between', + }, + referenceCode: { + fontSize: 20, + fontWeight: '700', + letterSpacing: 2, + color: colors.text, + flexShrink: 1, + }, + copyButton: { + flexDirection: 'row', + alignItems: 'center', + paddingVertical: 6, + paddingHorizontal: 10, + marginLeft: 8, + }, + copyButtonText: { + fontSize: 14, + fontWeight: '600', + color: colors.link, + marginLeft: 4, + }, + referenceHint: { + fontSize: 13, + color: colors.textSecondary, + marginTop: 8, + lineHeight: 18, + }, + footer: { + marginTop: 16, + paddingTop: 8, + alignSelf: 'center', + fontSize: 12, + color: colors.textSecondary, + }, +}) diff --git a/app/src/errors/components/ErrorModal.tsx b/app/src/errors/components/ErrorModal.tsx new file mode 100644 index 0000000..5db5f48 --- /dev/null +++ b/app/src/errors/components/ErrorModal.tsx @@ -0,0 +1,118 @@ +import { reportProblem } from '@/utils/logger' +import { BifoldError, useTheme } from '@bifold/core' +import React, { useCallback, useMemo } from 'react' +import { Modal, Pressable, StyleSheet } from 'react-native' +import { ErrorInfoCard } from './ErrorInfoCard' + +export interface ErrorModalAction { + text: string + onPress: () => void + style?: 'default' | 'destructive' +} + +export interface ErrorModalPayload { + title: string + description: string + message: string + code: number + appEvent: string + cause?: unknown + stack?: string + screen?: string + url?: string + method?: string +} + +export interface AppErrorModalProps { + error: ErrorModalPayload | null + errorKey: number + onDismiss: () => void + action?: ErrorModalAction + enableReport?: boolean +} + +/** + * Custom error modal replacing Bifold's ErrorModal for full control over + * styling and the "Report this problem" behavior. + * + * Rendered by ErrorAlertProvider and driven by its state — no event + * emitters or listeners involved. + */ +export const AppErrorModal: React.FC = ({ + error, + errorKey, + onDismiss, + action, + enableReport = true, +}) => { + const { ColorPalette } = useTheme() + + /** + * Handler for "Report this problem" action in the error modal. + * Sends a report to the remote logger (Loki) with error details. + * + * @returns the reference code the user can share with support, or undefined if there is no error + */ + const handleReport = useCallback((): string | undefined => { + if (!error) { + return + } + + // error.message is AppError.fullMessage — the user-facing details string, which + // deliberately omits the screen name and request URL so we don't surface infra + // details to the user. Append them here so they still ride along in the report. + let reportMessage = error.message + if (error.screen) { + reportMessage += `\nScreen: ${error.screen}` + } + if (error.url) { + const request = error.method ? `${error.method} ${error.url}` : error.url + reportMessage += `\nRequest: ${request}` + } + + const reportError = new BifoldError(error.title, error.description, reportMessage, error.code) + reportError.cause = error.cause + reportError.stack = error.stack + + return reportProblem(reportError) + }, [error]) + + const overlayStyle = useMemo( + () => + StyleSheet.create({ + overlay: { + flex: 1, + backgroundColor: ColorPalette.notification.popupOverlay, + justifyContent: 'center', + alignItems: 'center', + }, + }), + [ColorPalette] + ) + + if (!error) { + return null + } + + return ( + + {/* Allow presses outside of the modal to dismiss it */} + + {/* Prevent presses inside the modal from propagating to the overlay */} + e.stopPropagation()} accessible={false} importantForAccessibility="no"> + + + + + ) +} diff --git a/app/src/errors/errorHandler.test.ts b/app/src/errors/errorHandler.test.ts new file mode 100644 index 0000000..aebd015 --- /dev/null +++ b/app/src/errors/errorHandler.test.ts @@ -0,0 +1,219 @@ +import { UNKNOWN_APP_ERROR_STATUS_CODE } from '@/constants' +import { AppEventCode } from '@/events/appEventCode' +import { BifoldError } from '@bifold/core' +import { AppError } from './appError' +import { + ensureAppError, + extractErrorMessage, + getErrorDefinition, + getErrorDefinitionFromAppEventCode, + isDeviceStorageFullError, + toBifoldError, +} from './errorHandler' +import { ErrorCategory, ErrorRegistry, ErrorSeverity } from './errorRegistry' + +describe('errorHandler', () => { + describe('extractErrorMessage', () => { + it('should return empty string for null', () => { + expect(extractErrorMessage(null)).toBe('') + }) + + it('should return empty string for undefined', () => { + expect(extractErrorMessage(undefined)).toBe('') + }) + + it('should extract message from Error object', () => { + const error = new Error('Test error message') + expect(extractErrorMessage(error)).toBe('Test error message') + }) + + it('should return string directly', () => { + expect(extractErrorMessage('Direct string error')).toBe('Direct string error') + }) + + it('should extract message from object with message property', () => { + const errorObj = { message: 'Object error message' } + expect(extractErrorMessage(errorObj)).toBe('Object error message') + }) + + it('should stringify other objects', () => { + const obj = { code: 123, details: 'some details' } + expect(extractErrorMessage(obj)).toBe(JSON.stringify(obj)) + }) + + it('should handle circular references gracefully', () => { + const circular: Record = { name: 'test' } + circular.self = circular + expect(extractErrorMessage(circular)).toBe('[Non-serializable object]') + }) + }) + + describe('isDeviceStorageFullError', () => { + it('should detect the iOS NSFileWriteOutOfSpaceError message', () => { + const error = new Error( + 'An unexpected File IO error occurred! Error: You can\'t save the file "ABC123.jpg" because the volume "User" is out of space.' + ) + expect(isDeviceStorageFullError(error)).toBe(true) + }) + + it('should detect the Android/POSIX ENOSPC message', () => { + const error = new Error( + 'An unexpected File IO error occurred! Error: write failed: ENOSPC (No space left on device).' + ) + expect(isDeviceStorageFullError(error)).toBe(true) + }) + + it('should detect an ENOSPC error code even with an unrelated message', () => { + const error = new Error('write failed') as Error & { code: string } + error.code = 'ENOSPC' + expect(isDeviceStorageFullError(error)).toBe(true) + }) + + it('should detect a SQLite disk-full message', () => { + expect(isDeviceStorageFullError(new Error('database or disk is full (code 13 SQLITE_FULL)'))).toBe(true) + }) + + it('should detect a disk-full cause nested inside an AppError', () => { + const cause = new Error('You can\'t save the file "x.jpg" because the volume "User" is out of space.') + const appError = AppError.fromErrorDefinition(ErrorRegistry.STATE_LOAD_ERROR, { cause }) + expect(isDeviceStorageFullError(appError)).toBe(true) + }) + + it('should detect a plain string error', () => { + expect(isDeviceStorageFullError('No space left on device')).toBe(true) + }) + + it('should return false for a generic failure', () => { + const appError = AppError.fromErrorDefinition(ErrorRegistry.STATE_LOAD_ERROR, { + cause: new Error('keychain unavailable'), + }) + expect(isDeviceStorageFullError(appError)).toBe(false) + }) + + it('should return false for null and undefined', () => { + expect(isDeviceStorageFullError(null)).toBe(false) + expect(isDeviceStorageFullError(undefined)).toBe(false) + }) + + it('should not hang on a circular cause chain', () => { + const error = new Error('generic failure') + error.cause = error + expect(isDeviceStorageFullError(error)).toBe(false) + }) + }) + + describe('getErrorDefinition', () => { + it('should return the error definition for a valid key', () => { + const definition = getErrorDefinition('CAMERA_BROKEN') + + expect(definition).toEqual(ErrorRegistry.CAMERA_BROKEN) + expect(definition.statusCode).toBe(2000) + expect(definition.category).toBe(ErrorCategory.CAMERA) + expect(definition.severity).toBe(ErrorSeverity.ERROR) + }) + + it('should return error definitions for all error categories in the trimmed registry', () => { + expect(getErrorDefinition('NO_INTERNET').category).toBe(ErrorCategory.NETWORK) + expect(getErrorDefinition('STATE_LOAD_ERROR').category).toBe(ErrorCategory.WALLET) + expect(getErrorDefinition('PARSE_INVITATION_ERROR').category).toBe(ErrorCategory.CONNECTION) + expect(getErrorDefinition('ATTESTATION_GENERATION_ERROR').category).toBe(ErrorCategory.VERIFICATION) + expect(getErrorDefinition('ATTESTATION_UNSUPPORTED_PLATFORM').category).toBe(ErrorCategory.DEVICE) + }) + }) + + describe('getErrorDefinitionFromAppEventCode', () => { + it('should return correct error definition for known app event code', () => { + const definition = getErrorDefinitionFromAppEventCode('agent_initialization_error') + + expect(definition).toEqual(ErrorRegistry.AGENT_INITIALIZATION_ERROR) + }) + + it('should return null for unknown app event code', () => { + const definition = getErrorDefinitionFromAppEventCode('unknown_event_code') + + expect(definition).toBeNull() + }) + + it('sanity test for all error definitions', () => { + Object.values(ErrorRegistry).forEach((definition) => { + const fetchedDef = getErrorDefinitionFromAppEventCode(definition.appEvent) + expect(fetchedDef).toEqual(definition) + }) + }) + + it('should return null for empty app event code', () => { + const definition = getErrorDefinitionFromAppEventCode('') + + expect(definition).toBeNull() + }) + }) + + describe('ensureAppError', () => { + it('should return the same instance for an AppError', () => { + const appError = AppError.fromErrorDefinition(ErrorRegistry.NO_INTERNET) + expect(ensureAppError(appError)).toBe(appError) + }) + + it('should wrap a plain Error using the fallback event', () => { + const cause = new Error('boom') + const appError = ensureAppError(cause) + expect(appError).toBeInstanceOf(AppError) + expect(appError.appEvent).toBe(AppEventCode.UNKNOWN_APP_ERROR) + expect(appError.cause).toBe(cause) + }) + + it('should wrap using a specific fallback event when provided', () => { + const appError = ensureAppError(new Error('boom'), AppEventCode.AGENT_INITIALIZATION_ERROR) + expect(appError.appEvent).toBe(AppEventCode.AGENT_INITIALIZATION_ERROR) + expect(appError.statusCode).toBe(2901) + }) + }) + + describe('toBifoldError', () => { + it('should convert a plain Error into a BifoldError with UNKNOWN_APP_ERROR_STATUS_CODE', () => { + const error = new Error('something broke') + error.stack = 'fake stack' + + const result = toBifoldError('Title', 'Description', error) + + expect(result).toBeInstanceOf(BifoldError) + expect(result.title).toBe('Title') + expect(result.description).toBe('Description') + expect(result.message).toBe('something broke') + expect(result.code).toBe(UNKNOWN_APP_ERROR_STATUS_CODE) + expect(result.stack).toBe('fake stack') + }) + + it('should convert an AppError into a BifoldError with its statusCode and fullMessage', () => { + const cause = new Error('technical details') + const appError = new AppError( + 'App Error', + { + category: ErrorCategory.GENERAL, + appEvent: AppEventCode.UNKNOWN_APP_ERROR, + statusCode: 1000, + }, + { cause } + ) + + const result = toBifoldError('Display Title', 'Display Description', appError) + + expect(result).toBeInstanceOf(BifoldError) + expect(result.message).toBe(appError.fullMessage) + expect(result.title).toBe('Display Title') + expect(result.description).toBe('Display Description') + expect(result.code).toBe(1000) + expect(result.cause).toBe(cause) + }) + + it('should preserve the cause from the original error', () => { + const cause = new Error('root cause') + const error = new Error('wrapper') + error.cause = cause + + const result = toBifoldError('T', 'D', error) + + expect(result.cause).toBe(cause) + }) + }) +}) diff --git a/app/src/errors/errorHandler.ts b/app/src/errors/errorHandler.ts new file mode 100644 index 0000000..72f2dab --- /dev/null +++ b/app/src/errors/errorHandler.ts @@ -0,0 +1,148 @@ +import { UNKNOWN_APP_ERROR_STATUS_CODE } from '@/constants' +import { BifoldError } from '@bifold/core' +import { AppEventCode } from '../events/appEventCode' +import { AppError } from './appError' +import { ErrorDefinition, ErrorRegistry, ErrorRegistryAppEventMap, ErrorRegistryKey } from './errorRegistry' + +/** + * Extract a meaningful message from an unknown error value + * + * @param error - The unknown error value to extract a message from + * @returns A string message extracted from the error, or a fallback message if extraction fails + */ +export function extractErrorMessage(error: unknown): string { + if (error == null) { + return '' + } + if (error instanceof Error) { + return error.message + } + if (typeof error === 'string') { + return error + } + if (typeof error === 'object' && 'message' in error && typeof error.message === 'string') { + return error.message + } + try { + return JSON.stringify(error) + } catch { + // JSON.stringify failed (e.g., circular reference), return type info instead + return `[Non-serializable ${typeof error}]` + } +} + +/** + * Signatures emitted by the OS when a write fails because the disk is full. + * + * - iOS (NSFileWriteOutOfSpaceError): `You can't save the file "x.jpg" because the volume "User" is out of space.` + * - POSIX/Android (ENOSPC): `write failed: ENOSPC (No space left on device)` + * - SQLite (SQLITE_FULL): `database or disk is full` + */ +const OUT_OF_STORAGE_PATTERNS: RegExp[] = [ + /out of space/i, + /no space left on device/i, + /\bENOSPC\b/, + /\bSQLITE_FULL\b/i, + /database or disk is full/i, + /not enough (?:free |disk |storage )?space/i, +] + +/** + * Detect whether an error (or anything in its cause chain) was ultimately caused by + * the device running out of disk space, so callers can show actionable "free up space" + * guidance instead of a generic storage failure message. + * + * @param error - The error to inspect, including its nested `cause` chain + * @returns True if any error in the chain matches a known out-of-disk-space signature + */ +export function isDeviceStorageFullError(error: unknown): boolean { + let current: unknown = error + + // Bounded walk of the cause chain to guard against cycles + for (let depth = 0; current != null && depth < 10; depth++) { + const code = (current as { code?: unknown }).code + if (typeof code === 'string' && code.toUpperCase() === 'ENOSPC') { + return true + } + + const message = extractErrorMessage(current) + if (OUT_OF_STORAGE_PATTERNS.some((pattern) => pattern.test(message))) { + return true + } + + current = (current as { cause?: unknown }).cause + } + + return false +} + +/** + * Get error definition by key (useful for custom error handling) + * + * @param errorKey - The key of the error definition to retrieve from the ErrorRegistry. + * @returns The ErrorDefinition associated with the provided errorKey. + */ +export function getErrorDefinition(errorKey: ErrorRegistryKey): ErrorDefinition { + return ErrorRegistry[errorKey] +} + +/** + * Get error definition from app event code + * + * @param appEvent - The application event code to look up. + * @returns The corresponding ErrorDefinition or null if not found. + */ +export const getErrorDefinitionFromAppEventCode = (appEvent?: string): ErrorDefinition | null => { + return ErrorRegistryAppEventMap.get(appEvent as AppEventCode) ?? null +} + +/** + * Gets an AppError from the ErrorRegistry or fallback to `UNKNOWN_ERROR` + * + * @param event - The app event code to create the error for + * @param cause - An optional cause (e.g., an underlying error) that provides additional context for the AppError + * @returns An instance of AppError corresponding to the provided app event code and cause + */ +export const getRegistryAppError = (event: AppEventCode, cause?: unknown): AppError => { + const errorDefinition = getErrorDefinitionFromAppEventCode(event) ?? ErrorRegistry.UNKNOWN_ERROR + return AppError.fromErrorDefinition(errorDefinition, { cause }) +} + +/** + * Ensures that an unknown error is returned as an instance of AppError, using a fallback app event code if the original error is not already an AppError. + * + * @param error - The unknown error to ensure as an AppError + * @param fallbackEvent - The app event code to use for the new AppError if the provided error is not already an AppError (default: AppEventCode.UNKNOWN_APP_ERROR) + * @returns An instance of AppError + */ +export const ensureAppError = (error: unknown, fallbackEvent = AppEventCode.UNKNOWN_APP_ERROR): AppError => { + if (error instanceof AppError) { + return error + } + + return getRegistryAppError(fallbackEvent, error) +} + +/** + * Converts an Error or AppError into a BifoldError, preserving as much information as possible for display in the UI. + * + * @param title - The title to display for the error + * @param description - A user-friendly description of the error + * @param error - The original error object to convert + * @returns A BifoldError containing the provided title, description, and details from the original error + */ +export const toBifoldError = (title: string, description: string, error: Error | AppError): BifoldError => { + let bifoldError: BifoldError + + if (error instanceof AppError) { + bifoldError = new BifoldError(title, description, error.fullMessage, error.statusCode) + } else { + bifoldError = new BifoldError(title, description, error.message, UNKNOWN_APP_ERROR_STATUS_CODE) + } + + // Attach the cause and stack trace for debugging purposes + bifoldError.cause = error.cause + bifoldError.stack = error.stack + + return bifoldError +} diff --git a/app/src/errors/errorRegistry.test.ts b/app/src/errors/errorRegistry.test.ts new file mode 100644 index 0000000..f0f1761 --- /dev/null +++ b/app/src/errors/errorRegistry.test.ts @@ -0,0 +1,120 @@ +import { ErrorCategory, ErrorRegistry, ErrorRegistryKey, ErrorSeverity } from './errorRegistry' + +describe('errorRegistry', () => { + describe('ErrorSeverity', () => { + it('should have all expected severity levels', () => { + expect(ErrorSeverity.INFO).toBe('info') + expect(ErrorSeverity.WARNING).toBe('warning') + expect(ErrorSeverity.ERROR).toBe('error') + expect(ErrorSeverity.CRITICAL).toBe('critical') + }) + }) + + describe('ErrorCategory', () => { + it('should have all expected categories', () => { + expect(ErrorCategory.CAMERA).toBe('camera') + expect(ErrorCategory.NETWORK).toBe('network') + expect(ErrorCategory.CREDENTIAL).toBe('credential') + expect(ErrorCategory.PROOF).toBe('proof') + expect(ErrorCategory.CONNECTION).toBe('connection') + expect(ErrorCategory.WALLET).toBe('wallet') + expect(ErrorCategory.VERIFICATION).toBe('verification') + expect(ErrorCategory.DEVICE).toBe('device') + expect(ErrorCategory.STORAGE).toBe('storage') + expect(ErrorCategory.GENERAL).toBe('general') + }) + }) + + describe('ErrorRegistry', () => { + it('should contain no duplicate codes', () => { + const codes = Object.values(ErrorRegistry).map((error) => error.statusCode) + const uniqueCodes = new Set(codes) + expect(uniqueCodes.size).toBe(codes.length) + }) + + it('should contain no duplicate app events', () => { + const appEvents = Object.values(ErrorRegistry).map((error) => error.appEvent) + const uniqueAppEvents = new Set(appEvents) + expect(uniqueAppEvents.size).toBe(appEvents.length) + }) + + it('should contain all expected error keys', () => { + // Camera errors + expect(ErrorRegistry.CAMERA_BROKEN).toBeDefined() + expect(ErrorRegistry.INVALID_QR_CODE).toBeDefined() + + // Network errors + expect(ErrorRegistry.NO_INTERNET).toBeDefined() + expect(ErrorRegistry.SERVER_ERROR).toBeDefined() + expect(ErrorRegistry.SERVER_TIMEOUT).toBeDefined() + + // Wallet errors + expect(ErrorRegistry.STATE_LOAD_ERROR).toBeDefined() + expect(ErrorRegistry.AGENT_INITIALIZATION_ERROR).toBeDefined() + expect(ErrorRegistry.WALLET_SECRET_NOT_FOUND).toBeDefined() + + // Connection errors + expect(ErrorRegistry.PARSE_INVITATION_ERROR).toBeDefined() + expect(ErrorRegistry.RECEIVE_INVITATION_ERROR).toBeDefined() + + // Attestation errors + expect(ErrorRegistry.ATTESTATION_BAD_INVITATION).toBeDefined() + expect(ErrorRegistry.ATTESTATION_CONNECTION_ERROR).toBeDefined() + }) + + it('should have valid error definitions with all required fields', () => { + const errorKeys = Object.keys(ErrorRegistry) as ErrorRegistryKey[] + + errorKeys.forEach((key) => { + const definition = ErrorRegistry[key] + + expect(definition.statusCode).toBeDefined() + expect(typeof definition.statusCode).toBe('number') + + expect(definition.appEvent).toBeDefined() + expect(typeof definition.appEvent).toBe('string') + + expect(definition.severity).toBeDefined() + expect(Object.values(ErrorSeverity)).toContain(definition.severity) + + expect(definition.category).toBeDefined() + expect(Object.values(ErrorCategory)).toContain(definition.category) + + expect(definition.message).toBeDefined() + expect(typeof definition.message).toBe('string') + }) + }) + + it('should have error codes in correct ranges', () => { + // Camera/Scanning Errors (2000-2099) + expect(ErrorRegistry.CAMERA_BROKEN.statusCode).toBeGreaterThanOrEqual(2000) + expect(ErrorRegistry.CAMERA_BROKEN.statusCode).toBeLessThan(2100) + + // Network Errors (2100-2199) + expect(ErrorRegistry.NO_INTERNET.statusCode).toBeGreaterThanOrEqual(2100) + expect(ErrorRegistry.NO_INTERNET.statusCode).toBeLessThan(2200) + + // Wallet/Agent Errors (2900-2999) + expect(ErrorRegistry.STATE_LOAD_ERROR.statusCode).toBeGreaterThanOrEqual(2900) + expect(ErrorRegistry.STATE_LOAD_ERROR.statusCode).toBeLessThan(3000) + + // Connection/Invitation Errors (3000-3099) + expect(ErrorRegistry.PARSE_INVITATION_ERROR.statusCode).toBeGreaterThanOrEqual(3000) + expect(ErrorRegistry.PARSE_INVITATION_ERROR.statusCode).toBeLessThan(3100) + + // Attestation Errors (3100-3199) + expect(ErrorRegistry.ATTESTATION_BAD_INVITATION.statusCode).toBeGreaterThanOrEqual(3100) + expect(ErrorRegistry.ATTESTATION_BAD_INVITATION.statusCode).toBeLessThan(3200) + }) + }) + + describe('ErrorRegistryKey type', () => { + it('should allow accessing registry with valid keys', () => { + const key: ErrorRegistryKey = 'CAMERA_BROKEN' + const definition = ErrorRegistry[key] + + expect(definition).toBeDefined() + expect(definition.statusCode).toBe(2000) + }) + }) +}) diff --git a/app/src/errors/errorRegistry.ts b/app/src/errors/errorRegistry.ts new file mode 100644 index 0000000..f8ad14f --- /dev/null +++ b/app/src/errors/errorRegistry.ts @@ -0,0 +1,297 @@ +import { FATAL_UNRECOVERABLE_ERROR_STATUS_CODE, UNKNOWN_APP_ERROR_STATUS_CODE } from '@/constants' +import { AppEventCode } from '../events/appEventCode' + +/** + * Error severity levels for categorization + */ +export enum ErrorSeverity { + /** Informational - user action may be needed but no error occurred */ + INFO = 'info', + /** Warning - something unexpected happened but operation can continue */ + WARNING = 'warning', + /** Error - operation failed, user needs to take action */ + ERROR = 'error', + /** Critical - app functionality is compromised */ + CRITICAL = 'critical', +} + +/** + * Error category for grouping related errors + */ +export enum ErrorCategory { + CAMERA = 'camera', + NETWORK = 'network', + CREDENTIAL = 'credential', + PROOF = 'proof', + CONNECTION = 'connection', + WALLET = 'wallet', + VERIFICATION = 'verification', + DEVICE = 'device', + STORAGE = 'storage', + GENERAL = 'general', + UNKNOWN = 'unknown', +} + +/** + * Error definition containing all metadata for an error type + */ +export interface ErrorDefinition { + /** Unique error status code (for support reference) */ + statusCode: number + /** App event code */ + appEvent: AppEventCode + /** Error severity */ + severity: ErrorSeverity + /** Error category */ + category: ErrorCategory + /** Human-readable error message (technical, not user-facing — UI strings come from i18n) */ + message: string +} + +/** + * Master registry of Keyring app errors. + * + * Ported from bc-wallet-mobile and trimmed to the codes Keyring uses (upstream + * also carries BCSC/IAS account, token and native-module bands). The code + * ranges are kept aligned with upstream so support references stay comparable: + * + * 2000-2099: Camera/Scanning errors + * 2100-2199: Network errors + * 2900-2999: Wallet/Agent errors + * 3000-3099: Connection/Invitation errors + * 3100-3199: Attestation errors + * + * Special codes: + * 9999: Reserved for unknown/unmapped errors + * 9998: Reserved for fatal unrecoverable errors + */ +export const ErrorRegistry = { + // ============================================ + // Special Errors + // ============================================ + UNKNOWN_ERROR: { + statusCode: UNKNOWN_APP_ERROR_STATUS_CODE, // 9999 + appEvent: AppEventCode.UNKNOWN_APP_ERROR, + severity: ErrorSeverity.ERROR, + category: ErrorCategory.UNKNOWN, + message: 'An unknown error occurred', + }, + FATAL_ERROR: { + statusCode: FATAL_UNRECOVERABLE_ERROR_STATUS_CODE, // 9998 + appEvent: AppEventCode.FATAL_UNRECOVERABLE_ERROR, + severity: ErrorSeverity.CRITICAL, + category: ErrorCategory.UNKNOWN, + message: 'A fatal error occurred — app functionality may be compromised', + }, + + // ============================================ + // Camera/Scanning Errors (2000-2099) + // ============================================ + CAMERA_BROKEN: { + statusCode: 2000, + appEvent: AppEventCode.CAMERA_BROKEN, + severity: ErrorSeverity.ERROR, + category: ErrorCategory.CAMERA, + message: 'Camera hardware unavailable or failed to initialize', + }, + INVALID_QR_CODE: { + statusCode: 2001, + appEvent: AppEventCode.INVALID_QR_CODE, + severity: ErrorSeverity.WARNING, + category: ErrorCategory.CAMERA, + message: 'Scanned QR code could not be parsed or contains invalid data', + }, + + // ============================================ + // Network Errors (2100-2199) + // ============================================ + NO_INTERNET: { + statusCode: 2100, + appEvent: AppEventCode.NO_INTERNET, + severity: ErrorSeverity.ERROR, + category: ErrorCategory.NETWORK, + // NOTE: covers any transport-layer failure with no HTTP response — device + // offline, DNS failure, TLS error, or connection reset on the target host. + message: + 'Network request failed before a response was received — device offline, or DNS/TLS/connection error on the target host', + }, + SERVER_ERROR: { + statusCode: 2101, + appEvent: AppEventCode.SERVER_ERROR, + severity: ErrorSeverity.ERROR, + category: ErrorCategory.NETWORK, + message: 'Server returned a 5xx response', + }, + SERVER_TIMEOUT: { + statusCode: 2102, + appEvent: AppEventCode.SERVER_TIMEOUT, + severity: ErrorSeverity.ERROR, + category: ErrorCategory.NETWORK, + message: 'HTTP request exceeded timeout threshold — no response received', + }, + UNSECURED_NETWORK: { + statusCode: 2103, + appEvent: AppEventCode.UNSECURED_NETWORK, + severity: ErrorSeverity.WARNING, + category: ErrorCategory.NETWORK, + message: 'TLS/SSL validation failed — connection is not secure', + }, + PROBLEM_WITH_CONNECTION: { + statusCode: 2104, + appEvent: AppEventCode.PROBLEM_WITH_CONNECTION, + severity: ErrorSeverity.ERROR, + category: ErrorCategory.NETWORK, + message: 'Network connection dropped or reset during request', + }, + UNKNOWN_SERVER_ERROR: { + statusCode: 2111, + appEvent: AppEventCode.UNKNOWN_SERVER_ERROR, + severity: ErrorSeverity.ERROR, + category: ErrorCategory.NETWORK, + message: 'Server returned an unrecognized error response — could not map to a known error code', + }, + NOT_FOUND: { + statusCode: 2113, + appEvent: AppEventCode.NOT_FOUND, + severity: ErrorSeverity.ERROR, + category: ErrorCategory.NETWORK, + message: 'Server returned 404 — requested resource or endpoint was not found', + }, + + // ============================================ + // Wallet/Agent Errors (2900-2999) + // ============================================ + STATE_LOAD_ERROR: { + statusCode: 2900, + appEvent: AppEventCode.STATE_LOAD_ERROR, + severity: ErrorSeverity.ERROR, + category: ErrorCategory.WALLET, + message: 'Wallet state deserialization from persistent storage failed', + }, + AGENT_INITIALIZATION_ERROR: { + statusCode: 2901, + appEvent: AppEventCode.AGENT_INITIALIZATION_ERROR, + severity: ErrorSeverity.CRITICAL, + category: ErrorCategory.WALLET, + message: 'Aries agent initialization failed — check wallet key, mediator config, and ledger connectivity', + }, + WALLET_SECRET_NOT_FOUND: { + statusCode: 2902, + appEvent: AppEventCode.WALLET_SECRET_NOT_FOUND, + severity: ErrorSeverity.CRITICAL, + category: ErrorCategory.WALLET, + message: 'Wallet secret not found in secure storage — wallet may need to be re-created', + }, + + // ============================================ + // Connection/Invitation Errors (3000-3099) + // ============================================ + PARSE_INVITATION_ERROR: { + statusCode: 3000, + appEvent: AppEventCode.PARSE_INVITATION_ERROR, + severity: ErrorSeverity.ERROR, + category: ErrorCategory.CONNECTION, + message: 'Connection invitation URL/payload could not be parsed — invalid format', + }, + RECEIVE_INVITATION_ERROR: { + statusCode: 3001, + appEvent: AppEventCode.RECEIVE_INVITATION_ERROR, + severity: ErrorSeverity.ERROR, + category: ErrorCategory.CONNECTION, + message: 'Agent failed to process and accept the connection invitation', + }, + LEGACY_DID_ERROR: { + statusCode: 3002, + appEvent: AppEventCode.LEGACY_DID_ERROR, + severity: ErrorSeverity.ERROR, + category: ErrorCategory.CONNECTION, + message: 'Legacy DID resolution or conversion failed — unsupported DID method', + }, + APP_TO_APP_URL_ERROR: { + statusCode: 3003, + appEvent: AppEventCode.APP_TO_APP_URL_ERROR, + severity: ErrorSeverity.ERROR, + category: ErrorCategory.CONNECTION, + message: 'App-to-app deep link URL is malformed or missing required parameters', + }, + + // ============================================ + // Attestation Errors (3100-3199) + // ============================================ + ATTESTATION_BAD_INVITATION: { + statusCode: 3100, + appEvent: AppEventCode.ATTESTATION_BAD_INVITATION, + severity: ErrorSeverity.ERROR, + category: ErrorCategory.VERIFICATION, + message: 'Attestation invitation failed validation — malformed or expired', + }, + ATTESTATION_CONNECTION_ERROR: { + statusCode: 3101, + appEvent: AppEventCode.ATTESTATION_CONNECTION_ERROR, + severity: ErrorSeverity.ERROR, + category: ErrorCategory.VERIFICATION, + message: 'Failed to establish agent connection for attestation exchange', + }, + ATTESTATION_NONCE_ERROR: { + statusCode: 3102, + appEvent: AppEventCode.ATTESTATION_NONCE_ERROR, + severity: ErrorSeverity.ERROR, + category: ErrorCategory.VERIFICATION, + message: 'Attestation nonce generation or validation failed', + }, + ATTESTATION_GENERATION_ERROR: { + statusCode: 3103, + appEvent: AppEventCode.ATTESTATION_GENERATION_ERROR, + severity: ErrorSeverity.ERROR, + category: ErrorCategory.VERIFICATION, + message: 'Platform attestation generation failed — Play Integrity or App Attest error', + }, + ATTESTATION_VALIDATION_ERROR: { + statusCode: 3104, + appEvent: AppEventCode.ATTESTATION_VALIDATION_ERROR, + severity: ErrorSeverity.ERROR, + category: ErrorCategory.VERIFICATION, + message: 'Server-side attestation validation rejected the token', + }, + ATTESTATION_AGENT_UNDEFINED: { + statusCode: 3105, + appEvent: AppEventCode.ATTESTATION_AGENT_UNDEFINED, + severity: ErrorSeverity.CRITICAL, + category: ErrorCategory.VERIFICATION, + message: 'Attestation requires an initialized agent but agent reference is undefined', + }, + ATTESTATION_INTEGRITY_UNAVAILABLE: { + statusCode: 3106, + appEvent: AppEventCode.ATTESTATION_INTEGRITY_UNAVAILABLE, + severity: ErrorSeverity.ERROR, + category: ErrorCategory.VERIFICATION, + message: 'Platform integrity API (Play Integrity / App Attest) is not available on this device', + }, + ATTESTATION_GENERAL_PROOF_ERROR: { + statusCode: 3107, + appEvent: AppEventCode.ATTESTATION_GENERAL_PROOF_ERROR, + severity: ErrorSeverity.ERROR, + category: ErrorCategory.VERIFICATION, + message: 'Attestation proof presentation failed — agent could not construct or send proof', + }, + ATTESTATION_REQUEST_ERROR: { + statusCode: 3108, + appEvent: AppEventCode.ATTESTATION_REQUEST_ERROR, + severity: ErrorSeverity.ERROR, + category: ErrorCategory.VERIFICATION, + message: 'Attestation request to verification service failed — network or server error', + }, + ATTESTATION_UNSUPPORTED_PLATFORM: { + statusCode: 3109, + appEvent: AppEventCode.ATTESTATION_UNSUPPORTED_PLATFORM, + severity: ErrorSeverity.ERROR, + category: ErrorCategory.DEVICE, + message: 'Current platform does not support attestation — requires iOS 14+ or Android with Play Services', + }, +} as const satisfies Record + +export const ErrorRegistryAppEventMap = new Map( + Object.values(ErrorRegistry).map((definition) => [definition.appEvent, definition]) +) + +export type ErrorRegistryKey = keyof typeof ErrorRegistry diff --git a/app/src/errors/index.ts b/app/src/errors/index.ts new file mode 100644 index 0000000..a198322 --- /dev/null +++ b/app/src/errors/index.ts @@ -0,0 +1,52 @@ +/** + * Keyring Wallet Error Handling Module (ported from bc-wallet-mobile) + * + * This module provides a centralized error handling framework that: + * - Uses a registry of predefined errors with technical messages + * - Integrates with the ErrorModal for user-facing error display + * - Supports native alerts via ErrorAlertContext + * - Provides remote logging via the app logger (Loki) + * + * ## Recommended Usage (React Components) + * + * Use the `useErrorAlert()` hook for the cleanest API: + * + * ```typescript + * import { useErrorAlert } from '@/contexts/ErrorAlertContext' + * + * const MyComponent = () => { + * const { emitErrorModal, emitAlert } = useErrorAlert() + * + * // Show error via ErrorModal + * emitErrorModal('Error Title', 'Something went wrong', appErrorInstance) + * + * // Show informational native alert + * emitAlert('Update available', 'A new version is ready', { + * actions: [{ text: 'Update Now', onPress: updateApp }], + * }) + * } + * ``` + */ + +// AppError class +export { AppError, isAppError, isHandledAppError } from './appError' + +// Error registry and types +export { + ErrorCategory, + ErrorRegistry, + ErrorSeverity, + type ErrorDefinition, + type ErrorRegistryKey, +} from './errorRegistry' + +// Error handler utilities +export { + ensureAppError, + extractErrorMessage, + getErrorDefinition, + getErrorDefinitionFromAppEventCode, + getRegistryAppError, + isDeviceStorageFullError, + toBifoldError, +} from './errorHandler' diff --git a/app/src/events/appEventCode.ts b/app/src/events/appEventCode.ts new file mode 100644 index 0000000..530e46e --- /dev/null +++ b/app/src/events/appEventCode.ts @@ -0,0 +1,49 @@ +/** + * Stable, machine-readable event codes attached to AppErrors. + * + * Ported from bc-wallet-mobile (trimmed to the codes Keyring uses — the + * upstream file also carries ~150 BCSC/IAS-specific codes we dropped). + * Codes are snake_case strings so they stay greppable in remote logs. + */ +export enum AppEventCode { + // Special + UNKNOWN_APP_ERROR = 'unknown_app_error', + FATAL_UNRECOVERABLE_ERROR = 'fatal_unrecoverable_error', + UNKNOWN_ERROR_BOUNDARY_ERROR = 'unknown_error_boundary_error', + + // Camera / scanning + CAMERA_BROKEN = 'camera_broken', + INVALID_QR_CODE = 'invalid_qr_code', + + // Network + NO_INTERNET = 'no_internet', + SERVER_ERROR = 'server_error', + UNKNOWN_SERVER_ERROR = 'unknown_server_error', + SERVER_TIMEOUT = 'server_timeout', + UNSECURED_NETWORK = 'unsecured_network', + PROBLEM_WITH_CONNECTION = 'problem_with_connection', + NOT_FOUND = 'not_found', + + // Wallet / agent + STATE_LOAD_ERROR = 'state_load_error', + AGENT_INITIALIZATION_ERROR = 'agent_initialization_error', + WALLET_SECRET_NOT_FOUND = 'wallet_secret_not_found', + + // Connections / invitations + PARSE_INVITATION_ERROR = 'parse_invitation_error', + RECEIVE_INVITATION_ERROR = 'receive_invitation_error', + LEGACY_DID_ERROR = 'legacy_did_error', + APP_TO_APP_URL_ERROR = 'app_to_app_url_error', + + // Attestation + ATTESTATION_BAD_INVITATION = 'attestation_bad_invitation', + ATTESTATION_CONNECTION_ERROR = 'attestation_connection_error', + ATTESTATION_NONCE_ERROR = 'attestation_nonce_error', + ATTESTATION_GENERATION_ERROR = 'attestation_generation_error', + ATTESTATION_VALIDATION_ERROR = 'attestation_validation_error', + ATTESTATION_AGENT_UNDEFINED = 'attestation_agent_undefined', + ATTESTATION_INTEGRITY_UNAVAILABLE = 'attestation_integrity_unavailable', + ATTESTATION_GENERAL_PROOF_ERROR = 'attestation_general_proof_error', + ATTESTATION_REQUEST_ERROR = 'attestation_request_error', + ATTESTATION_UNSUPPORTED_PLATFORM = 'attestation_unsupported_platform', +} diff --git a/app/src/hooks/notifications.ts b/app/src/hooks/notifications.ts index f0e1b81..baf2232 100644 --- a/app/src/hooks/notifications.ts +++ b/app/src/hooks/notifications.ts @@ -1,12 +1,6 @@ -import { AnonCredsCredentialMetadataKey } from '@credo-ts/anoncreds/build/utils/metadata' -import { - BasicMessageRecord, - CredentialExchangeRecord as CredentialRecord, - CredentialState, - ProofExchangeRecord, - ProofState, -} from '@credo-ts/core' -import { useCredentialByState, useProofByState, useBasicMessages, useAgent } from '@credo-ts/react-hooks' +import { AnonCredsCredentialMetadataKey } from '@credo-ts/anoncreds' +import { DidCommBasicMessageRecord, DidCommCredentialExchangeRecord, DidCommCredentialState, DidCommProofExchangeRecord, DidCommProofState } from '@credo-ts/didcomm' +import { useCredentialByState, useProofByState, useBasicMessages, useAgent } from '@bifold/react-hooks' import { BifoldAgent, useStore, @@ -32,22 +26,22 @@ function isProtocolMessage(content: string): boolean { } } -export const useNotifications = (): Array => { +export const useNotifications = (): Array => { const { agent } = useAgent() const [store] = useStore() - const offers = useCredentialByState(CredentialState.OfferReceived) - const proofsRequested = useProofByState(ProofState.RequestReceived) - const [nonAttestationProofs, setNonAttestationProofs] = useState([]) + const offers = useCredentialByState(DidCommCredentialState.OfferReceived) + const proofsRequested = useProofByState(DidCommProofState.RequestReceived) + const [nonAttestationProofs, setNonAttestationProofs] = useState([]) const [notifications, setNotifications] = useState([]) const { records: basicMessages } = useBasicMessages() - const credsReceived = useCredentialByState(CredentialState.CredentialReceived) - const credsDone = useCredentialByState(CredentialState.Done) - const proofsDone = useProofByState([ProofState.Done, ProofState.PresentationReceived]) + const credsReceived = useCredentialByState(DidCommCredentialState.CredentialReceived) + const credsDone = useCredentialByState(DidCommCredentialState.Done) + const proofsDone = useProofByState([DidCommProofState.Done, DidCommProofState.PresentationReceived]) useEffect(() => { // get all unseen messages, excluding protocol/witness messages - const unseenMessages: BasicMessageRecord[] = basicMessages.filter((msg) => { + const unseenMessages: DidCommBasicMessageRecord[] = basicMessages.filter((msg) => { if (isProtocolMessage(msg.content)) return false const meta = msg.metadata.get(BasicMessageMetadata.customMetadata) as basicMessageCustomMetadata return !meta?.seen @@ -55,7 +49,7 @@ export const useNotifications = (): Array { if (!contactsWithUnseenMessages.includes(msg.connectionId)) { contactsWithUnseenMessages.push(msg.connectionId) @@ -63,7 +57,7 @@ export const useNotifications = (): Array { + const revoked = credsDone.filter((cred: DidCommCredentialExchangeRecord) => { // eslint-disable-next-line @typescript-eslint/no-non-null-assertion const metadata = cred!.metadata.get(CredentialMetadata.customMetadata) as credentialCustomMetadata if (cred?.revocationNotification && metadata?.revoked_seen == undefined) { @@ -85,7 +79,7 @@ export const useNotifications = (): Array { return ( - ![ProofState.Done, ProofState.PresentationReceived].includes(proof.state) || + ![DidCommProofState.Done, DidCommProofState.PresentationReceived].includes(proof.state) || (proof.isVerified !== undefined && !(proof.metadata.data[ProofMetadata.customMetadata] as ProofCustomMetadata)?.details_seen) ) @@ -107,7 +101,7 @@ export const useNotifications = (): Array { Promise.all( - [...proofsRequested, ...proofsDone].map(async (proof: ProofExchangeRecord) => { + [...proofsRequested, ...proofsDone].map(async (proof: DidCommProofExchangeRecord) => { const isAttestation = await isProofRequestingAttestation(proof, agent as BifoldAgent, AttestationRestrictions) return { value: proof, diff --git a/app/src/hooks/useAutoRequestPermission.ts b/app/src/hooks/useAutoRequestPermission.ts new file mode 100644 index 0000000..740c38c --- /dev/null +++ b/app/src/hooks/useAutoRequestPermission.ts @@ -0,0 +1,50 @@ +import { useEffect, useRef, useState } from 'react' + +/** + * Automatically requests a permission once on mount if not already granted. + * Ensures the permission is only requested once per component lifecycle. + * Returns a loading state to prevent UI flicker during permission requests. + * Ported from bc-wallet-mobile. + * + * @param hasPermission - Whether the permission is currently granted + * @param requestPermission - Function to request the permission + * @param enabled - Optional flag to delay the permission request (useful for sequencing multiple permissions) + * @returns Object with `isLoading` - true while the initial permission request is pending + * + * @example + * // Single permission + * const { hasPermission, requestPermission } = useCameraPermission() + * const { isLoading } = useAutoRequestPermission(hasPermission, requestPermission) + * + * @example + * // Multiple permissions (sequenced to avoid dialog conflicts) + * const { isLoading: isCameraLoading } = useAutoRequestPermission(hasCameraPermission, requestCameraPermission) + * const { isLoading: isMicLoading } = useAutoRequestPermission(hasMicPermission, requestMicPermission, !isCameraLoading) + */ +export const useAutoRequestPermission = ( + hasPermission: boolean, + requestPermission: () => Promise, + enabled: boolean = true +): { isLoading: boolean } => { + const hasRequested = useRef(false) + const [isLoading, setIsLoading] = useState(!hasPermission) + + useEffect(() => { + const request = async () => { + if (!enabled) { + return + } + if (!hasPermission && !hasRequested.current) { + hasRequested.current = true + setIsLoading(true) + await requestPermission() + setIsLoading(false) + } else if (hasPermission) { + setIsLoading(false) + } + } + request() + }, [hasPermission, requestPermission, enabled]) + + return { isLoading } +} diff --git a/app/src/hooks/useBCAgentSetup.ts b/app/src/hooks/useBCAgentSetup.ts index ee15300..ebd174b 100644 --- a/app/src/hooks/useBCAgentSetup.ts +++ b/app/src/hooks/useBCAgentSetup.ts @@ -1,6 +1,7 @@ import { createLinkSecretIfRequired, DispatchAction, + migrateRCardTemplateProofs, migrateToAskar, PersistentStorage, TOKENS, @@ -9,21 +10,22 @@ import { WalletSecret, setupVrcConnectionHandler, } from '@bifold/core' -import { Agent, HttpOutboundTransport, MediatorPickupStrategy, WsOutboundTransport } from '@credo-ts/core' -import { IndyVdrPoolConfig, IndyVdrPoolService } from '@credo-ts/indy-vdr/build/pool' +import { Agent } from '@credo-ts/core' +import { + DidCommHttpOutboundTransport, + DidCommMediatorPickupStrategy, + DidCommWsOutboundTransport, +} from '@credo-ts/didcomm' +import { IndyVdrPoolConfig, IndyVdrPoolService } from '@credo-ts/indy-vdr' import { agentDependencies } from '@credo-ts/react-native' import { GetCredentialDefinitionRequest, GetSchemaRequest } from '@hyperledger/indy-vdr-shared' import moment from 'moment' import { useCallback, useRef, useState } from 'react' -import { Config } from 'react-native-config' import { CachesDirectoryPath } from 'react-native-fs' // DISABLED: Push notifications disabled — no server backend yet // import { activate } from '@/utils/PushNotificationsHelper' import { getBCAgentModules } from '@/utils/bc-agent-modules' import { BCState, BCLocalStorageKeys } from '@/store' -import { batchPickup, startPeriodicTrustPing } from '@/utils/mediator' - -const PERIODIC_PICKUP_INTERVAL_MS = 5000 const loadCachedLedgers = async (): Promise => { // eslint-disable-next-line @typescript-eslint/no-explicit-any @@ -34,17 +36,20 @@ const loadCachedLedgers = async (): Promise => } } +// Live mode holds a WebSocket open to the mediator, which pushes messages as +// they arrive (upstream bc-wallet-mobile approach). This replaced the previous +// batch-pickup + 5s trust-ping polling loop; our hosted mediator advertises a +// wss endpoint so the socket-based delivery works without polling. const configureMessagePickup = async (agent: Agent): Promise => { - if (Config.MEDIATOR_USE_V2_BATCH_PICKUP === 'true') { - await agent.mediationRecipient.initiateMessagePickup(undefined, MediatorPickupStrategy.PickUpV2LiveMode) - batchPickup(agent) - } + await agent.modules.didcomm.mediationRecipient.initiateMessagePickup( + undefined, + DidCommMediatorPickupStrategy.PickUpV2LiveMode + ) } const useBCAgentSetup = () => { const [agent, setAgent] = useState(null) const agentInstanceRef = useRef(null) - const periodicPickupCleanupRef = useRef<(() => void) | null>(null) const [store, dispatch] = useStore() const [logger, indyLedgers, attestationMonitor, credDefs, schemas] = useServices([ TOKENS.UTIL_LOGGER, @@ -63,12 +68,10 @@ const useBCAgentSetup = () => { ) const restartExistingAgent = useCallback( - async (agent: Agent, walletSecret: WalletSecret): Promise => { + async (agent: Agent): Promise => { try { - await agent.wallet.open({ - id: walletSecret.id, - key: walletSecret.key, - }) + // credo 0.6: the askar store config (id/key) lives on the AskarModule, + // so re-initializing reopens the wallet await agent.initialize() } catch (error) { logger.warn(`Agent restart failed with error ${error}`) @@ -86,19 +89,15 @@ const useBCAgentSetup = () => { async (ledgers: IndyVdrPoolConfig[], walletSecret: WalletSecret, mediatorUrl: string): Promise => { const options = { config: { - label: store.preferences.walletName || 'Keyring', - walletConfig: { - id: walletSecret.id, - key: walletSecret.key, - }, logger, - mediatorPickupStrategy: MediatorPickupStrategy.Implicit, autoUpdateStorageOnStartup: true, - autoAcceptConnections: true, + // credo 0.6: wallet id/key live on the AskarModule store config, + // mediation + auto-accept live on the DidCommModule (see bc-agent-modules.ts) // Document loader is configured in W3cCredentialsModule (see bc-agent-modules.ts) }, dependencies: agentDependencies, modules: getBCAgentModules({ + walletSecret, indyNetworks: ledgers, mediatorInvitationUrl: mediatorUrl, txnCache: { @@ -106,27 +105,19 @@ const useBCAgentSetup = () => { expiryOffsetMs: 1000 * 60 * 60 * 24 * 7, path: CachesDirectoryPath + '/txn-cache', }, - enableProxy: store.developer.enableProxy, - proxyBaseUrl: Config.INDY_VDR_PROXY_URL, - proxyCacheSettings: { - allowCaching: false, - cacheDurationInSeconds: 60 * 60 * 24 * 7, - }, }), } - logger.info(store.developer.enableProxy && Config.INDY_VDR_PROXY_URL ? 'VDR Proxy enabled' : 'VDR Proxy disabled') - const newAgent = new Agent(options) - const wsTransport = new WsOutboundTransport() - const httpTransport = new HttpOutboundTransport() + const wsTransport = new DidCommWsOutboundTransport() + const httpTransport = new DidCommHttpOutboundTransport() - newAgent.registerOutboundTransport(wsTransport) - newAgent.registerOutboundTransport(httpTransport) + newAgent.modules.didcomm.registerOutboundTransport(wsTransport) + newAgent.modules.didcomm.registerOutboundTransport(httpTransport) return newAgent }, - [store.preferences.walletName, logger, store.developer.enableProxy] + [logger] ) const migrateIfRequired = useCallback( @@ -145,8 +136,11 @@ const useBCAgentSetup = () => { const warmUpCache = useCallback( async (newAgent: Agent, cachedLedgers?: IndyVdrPoolConfig[]) => { const poolService = newAgent.dependencyManager.resolve(IndyVdrPoolService) - if (!cachedLedgers) { - // these escapes can be removed once Indy VDR has been upgraded and the patch is no longer needed + // refreshPoolConnections/getAllPoolTransactions came from the BC indy-vdr + // patch (credo 0.5); the unpatched 0.6.3 pool service does not have them + // eslint-disable-next-line @typescript-eslint/ban-ts-comment + // @ts-ignore:next-line + if (!cachedLedgers && typeof poolService.refreshPoolConnections === 'function') { // eslint-disable-next-line @typescript-eslint/ban-ts-comment // @ts-ignore:next-line await poolService.refreshPoolConnections() @@ -194,12 +188,10 @@ const useBCAgentSetup = () => { const mediatorUrl = store.preferences.selectedMediator logger.info('Checking for existing agent...') if (agentInstanceRef.current) { - const restartedAgent = await restartExistingAgent(agentInstanceRef.current, walletSecret) + const restartedAgent = await restartExistingAgent(agentInstanceRef.current) if (restartedAgent) { logger.info('Successfully restarted existing agent...') await configureMessagePickup(restartedAgent) - periodicPickupCleanupRef.current?.() - periodicPickupCleanupRef.current = startPeriodicTrustPing(restartedAgent, PERIODIC_PICKUP_INTERVAL_MS) refreshAttestationMonitor(restartedAgent) agentInstanceRef.current = restartedAgent setAgent(restartedAgent) @@ -220,10 +212,12 @@ const useBCAgentSetup = () => { logger.info('Initializing agent...') await newAgent.initialize() + // Fix up R-Card template records stored by pre-credo-0.6 versions (no + // proof) before any UI provider reads W3C credential records + await migrateRCardTemplateProofs(newAgent) + logger.info(`configuring message pickup for ${mediatorUrl}`) await configureMessagePickup(newAgent) - periodicPickupCleanupRef.current?.() - periodicPickupCleanupRef.current = startPeriodicTrustPing(newAgent, PERIODIC_PICKUP_INTERVAL_MS) logger.info('Warming up cache...') await warmUpCache(newAgent, cachedLedgers) @@ -262,8 +256,6 @@ const useBCAgentSetup = () => { ) const shutdownAndClearAgentIfExists = useCallback(async () => { - periodicPickupCleanupRef.current?.() - periodicPickupCleanupRef.current = null if (agent) { try { await agent.shutdown() diff --git a/app/src/hooks/useDeclineCredentialOffer.ts b/app/src/hooks/useDeclineCredentialOffer.ts new file mode 100644 index 0000000..7021b5f --- /dev/null +++ b/app/src/hooks/useDeclineCredentialOffer.ts @@ -0,0 +1,35 @@ +import { useAgent } from '@bifold/react-hooks' +import { DidCommCredentialExchangeRecord } from '@credo-ts/didcomm' +import { useCallback } from 'react' +import { useTranslation } from 'react-i18next' + +/** + * Declines a credential offer and, when the offer came over a live connection, + * sends a problem report so the issuer knows. Ported from bc-wallet-mobile. + */ +export const useDeclineCredentialOffer = (credential: DidCommCredentialExchangeRecord) => { + const { agent } = useAgent() + const { t } = useTranslation() + + return useCallback(async () => { + if (!agent) { + return + } + try { + await agent.modules.didcomm.credentials.declineOffer({ credentialExchangeRecordId: credential.id }) + + const connectionId = credential.connectionId ?? '' + if (connectionId) { + const connection = await agent.modules.didcomm.connections.findById(connectionId) + if (connection) { + await agent.modules.didcomm.credentials.sendProblemReport({ + credentialExchangeRecordId: credential.id, + description: t('CredentialOffer.Declined'), + }) + } + } + } catch (err) { + agent.config.logger.error(`Failed to decline credential offer: ${err}`) + } + }, [agent, credential.id, credential.connectionId, t]) +} diff --git a/app/src/hooks/useDeclineProofRequest.ts b/app/src/hooks/useDeclineProofRequest.ts new file mode 100644 index 0000000..67dcbfd --- /dev/null +++ b/app/src/hooks/useDeclineProofRequest.ts @@ -0,0 +1,35 @@ +import { useAgent } from '@bifold/react-hooks' +import { DidCommProofExchangeRecord } from '@credo-ts/didcomm' +import { useCallback } from 'react' +import { useTranslation } from 'react-i18next' + +/** + * Declines a proof request and, when it came over a live connection, sends a + * problem report so the verifier knows. Ported from bc-wallet-mobile. + */ +export const useDeclineProofRequest = (proof: DidCommProofExchangeRecord) => { + const { agent } = useAgent() + const { t } = useTranslation() + + return useCallback(async () => { + if (!agent) { + return + } + try { + const connectionId = proof.connectionId ?? '' + if (connectionId) { + const connection = await agent.modules.didcomm.connections.findById(connectionId) + if (connection) { + await agent.modules.didcomm.proofs.sendProblemReport({ + proofExchangeRecordId: proof.id, + description: t('ProofRequest.Declined'), + }) + } + } + + await agent.modules.didcomm.proofs.declineRequest({ proofExchangeRecordId: proof.id }) + } catch (err) { + agent.config.logger.error(`Failed to decline proof request: ${err}`) + } + }, [agent, proof.id, proof.connectionId, t]) +} diff --git a/app/src/hooks/usePreventGestureBack.ts b/app/src/hooks/usePreventGestureBack.ts new file mode 100644 index 0000000..a83f843 --- /dev/null +++ b/app/src/hooks/usePreventGestureBack.ts @@ -0,0 +1,26 @@ +import { useFocusEffect, useNavigation } from '@react-navigation/native' +import { useCallback } from 'react' + +/** + * Prevents gesture-based back navigation (Android hardware back, swipe) while + * still allowing programmatic navigation (e.g. navigation.goBack()). + * + * gestureEnabled: false handles iOS; this hook handles Android's beforeRemove. + * Ported from bc-wallet-mobile. + */ +const usePreventGestureBack = () => { + const navigation = useNavigation() + + useFocusEffect( + useCallback(() => { + const unsubscribe = navigation.addListener('beforeRemove', (event) => { + if (!event.data.action.source) { + event.preventDefault() + } + }) + return unsubscribe + }, [navigation]) + ) +} + +export default usePreventGestureBack diff --git a/app/src/keyring-theme/components/AddCredentialSlider.tsx b/app/src/keyring-theme/components/AddCredentialSlider.tsx index b166dec..0216565 100644 --- a/app/src/keyring-theme/components/AddCredentialSlider.tsx +++ b/app/src/keyring-theme/components/AddCredentialSlider.tsx @@ -1,7 +1,7 @@ import { SafeAreaModal, Screens, Stacks, testIdForAccessabilityLabel, testIdWithKey } from '@bifold/core' -import { AnonCredsCredentialMetadataKey } from '@credo-ts/anoncreds/build/utils/metadata' -import { CredentialState } from '@credo-ts/core' -import { useCredentialByState } from '@credo-ts/react-hooks' +import { AnonCredsCredentialMetadataKey } from '@credo-ts/anoncreds' +import { DidCommCredentialState } from '@credo-ts/didcomm' +import { useCredentialByState } from '@bifold/react-hooks' import { useNavigation } from '@react-navigation/native' import React, { useCallback, useEffect, useState } from 'react' import { useTranslation } from 'react-i18next' @@ -21,8 +21,8 @@ export default function AddCredentialSlider() { const [addCredentialPressed, setAddCredentialPressed] = useState(false) const [showGetPersonCredential, setShowGetPersonCredential] = useState(false) - const credentialsReceived = useCredentialByState(CredentialState.CredentialReceived) - const credentialsDone = useCredentialByState(CredentialState.Done) + const credentialsReceived = useCredentialByState(DidCommCredentialState.CredentialReceived) + const credentialsDone = useCredentialByState(DidCommCredentialState.Done) const deactivateSlider = useCallback(() => { DeviceEventEmitter.emit(KeyRingEventTypes.ADD_CREDENTIAL_PRESSED, false) diff --git a/app/src/keyring-theme/components/HomeHeaderView.tsx b/app/src/keyring-theme/components/HomeHeaderView.tsx index 2a1c2c5..396f2e0 100644 --- a/app/src/keyring-theme/components/HomeHeaderView.tsx +++ b/app/src/keyring-theme/components/HomeHeaderView.tsx @@ -1,4 +1,4 @@ -import { useAgent } from '@credo-ts/react-hooks' +import { useAgent } from '@bifold/react-hooks' import { Screens, Stacks, testIdWithKey, useTheme } from '@bifold/core' import { RemoteLogger } from '@bifold/remote-logs' import { useNavigation } from '@react-navigation/native' diff --git a/app/src/keyring-theme/features/person-flow/screens/PersonCredential.tsx b/app/src/keyring-theme/features/person-flow/screens/PersonCredential.tsx index e6ce940..c3574b9 100644 --- a/app/src/keyring-theme/features/person-flow/screens/PersonCredential.tsx +++ b/app/src/keyring-theme/features/person-flow/screens/PersonCredential.tsx @@ -1,4 +1,4 @@ -import { useAgent } from '@credo-ts/react-hooks' +import { useAgent } from '@bifold/react-hooks' import { useStore, useTheme, diff --git a/app/src/keyring-theme/features/person-flow/screens/PersonCredentialLoading.tsx b/app/src/keyring-theme/features/person-flow/screens/PersonCredentialLoading.tsx index 61a319f..ce6af6e 100644 --- a/app/src/keyring-theme/features/person-flow/screens/PersonCredentialLoading.tsx +++ b/app/src/keyring-theme/features/person-flow/screens/PersonCredentialLoading.tsx @@ -14,8 +14,8 @@ import { useStore, useTheme, } from '@bifold/core' -import { CredentialState } from '@credo-ts/core' -import { useAgent, useCredentialByState } from '@credo-ts/react-hooks' +import { DidCommCredentialState } from '@credo-ts/didcomm' +import { useAgent, useCredentialByState } from '@bifold/react-hooks' import { StackScreenProps } from '@react-navigation/stack' import React, { useCallback, useEffect, useMemo, useRef, useState } from 'react' import { useTranslation } from 'react-i18next' @@ -38,9 +38,9 @@ const PersonCredentialLoading: React.FC = ({ navigation }) => { const { ColorPalette, TextTheme, Spacing } = useTheme() const [store] = useStore() const [remoteAgentDetails, setRemoteAgentDetails] = useState() - const timer = useRef() + const timer = useRef(undefined) const [logger] = useServices([TOKENS.UTIL_LOGGER]) - const receivedCredentialOffers = useCredentialByState(CredentialState.OfferReceived) + const receivedCredentialOffers = useCredentialByState(DidCommCredentialState.OfferReceived) const [stepText, setStepText] = useState('Starting process...') const [progressPercent, setProgressPercent] = useState(0) const { agent } = useAgent() @@ -224,7 +224,7 @@ const PersonCredentialLoading: React.FC = ({ navigation }) => { useEffect(() => { for (const credential of receivedCredentialOffers) { if ( - credential.state == CredentialState.OfferReceived && + credential.state == DidCommCredentialState.OfferReceived && credential.connectionId === remoteAgentDetails?.connectionId ) { goToCredentialOffer(credential.id) diff --git a/app/src/keyring-theme/features/person-flow/utils/BCIDHelper.ts b/app/src/keyring-theme/features/person-flow/utils/BCIDHelper.ts index af5676d..37a3328 100644 --- a/app/src/keyring-theme/features/person-flow/utils/BCIDHelper.ts +++ b/app/src/keyring-theme/features/person-flow/utils/BCIDHelper.ts @@ -52,7 +52,7 @@ export const connectToIASAgent = async ( ): Promise => { // connect to the agent, this will re-format the legacy invite // until we have OOB working in ACA-py. - const invite = await agent.oob.parseInvitation(iasAgentInviteUrl) + const invite = await agent.modules.didcomm.oob.parseInvitation(iasAgentInviteUrl) if (!invite) { throw new BifoldError(t('Error.Title2020'), t('Error.Message2020'), t('Error.NoMessage'), ErrorCodes.BadInvitation) @@ -60,7 +60,7 @@ export const connectToIASAgent = async ( await removeExistingInvitationsById(agent, invite.id) - const record = await agent.oob.receiveInvitation(invite) + const record = await agent.modules.didcomm.oob.receiveInvitation(invite) if (!record) { throw new BifoldError( diff --git a/app/src/keyring-theme/theme.ts b/app/src/keyring-theme/theme.ts index 3daa88b..54b7eea 100644 --- a/app/src/keyring-theme/theme.ts +++ b/app/src/keyring-theme/theme.ts @@ -158,6 +158,13 @@ export const BrandColors: IBrandColors = { tabBarInactive: MEDIUM_GRAY, // #666666 inlineError: SemanticColors.error, inlineWarning: NotificationColors.warnText, + // New in bifold 3.x IBrandColors + credentialCardPlaceholderBackground: GrayscaleColors.veryLightGrey, + credentialCardStatusBadgeErrorBackground: '#FDECEA', + credentialCardStatusBadgeErrorIcon: BKC_BLACK, + credentialCardStatusBadgeWarningBackground: '#FFF8E1', + credentialCardStatusBadgeWarningIcon: BKC_BLACK, + loadingIcon: GrayscaleColors.white, } export const ColorPalette: IColorPalette = { diff --git a/app/src/localization/en/index.ts b/app/src/localization/en/index.ts index 7d2ed68..92c5936 100644 --- a/app/src/localization/en/index.ts +++ b/app/src/localization/en/index.ts @@ -28,6 +28,15 @@ const translation = { "Title2032": "Unable to open app-to-app URL", "Message2032": "There was a problem while opening the app-to-app URL.", "NoMessage": "No Message", + "ReferenceCode": "Reference code", + "CopyCode": "Copy", + "CodeCopied": "Copied", + "ShareCodeWithSupport": "Share this code with support when you contact us.", + "Problem": "Something went wrong", + "ProblemDescription": "An unexpected error occurred. Please report this error and try again.", + }, + "Global": { + "HideDetails": "Hide Details", }, "CameraDisclosure": { "AllowCameraUse": "Allow camera use", diff --git a/app/src/localization/fr/index.ts b/app/src/localization/fr/index.ts index 7249624..f7746a4 100644 --- a/app/src/localization/fr/index.ts +++ b/app/src/localization/fr/index.ts @@ -28,6 +28,15 @@ const translation = { "Title2032": "Unable to open app-to-app URL (FR)", "Message2032": "There was a problem while opening the app-to-app URL. (FR)", "NoMessage": "Aucun message", + "ReferenceCode": "Code de référence", + "CopyCode": "Copier", + "CodeCopied": "Copié", + "ShareCodeWithSupport": "Communiquez ce code au soutien lorsque vous nous contactez.", + "Problem": "Un problème est survenu", + "ProblemDescription": "Une erreur inattendue s'est produite. Veuillez signaler cette erreur et réessayer.", + }, + "Global": { + "HideDetails": "Masquer les détails", }, "CameraDisclosure": { "AllowCameraUse": "Autoriser l'utilisation de la caméra", diff --git a/app/src/localization/pt-br/index.ts b/app/src/localization/pt-br/index.ts index 9da55db..66c1f67 100644 --- a/app/src/localization/pt-br/index.ts +++ b/app/src/localization/pt-br/index.ts @@ -28,6 +28,15 @@ const translation = { "Title2032": "Unable to open app-to-app URL (PT-BR)", "Message2032": "There was a problem while opening the app-to-app URL. (PT-BR)", "NoMessage": "No Message (PT-BR)", + "ReferenceCode": "Código de referência", + "CopyCode": "Copiar", + "CodeCopied": "Copiado", + "ShareCodeWithSupport": "Compartilhe este código com o suporte ao entrar em contato.", + "Problem": "Algo deu errado", + "ProblemDescription": "Ocorreu um erro inesperado. Reporte este erro e tente novamente.", + }, + "Global": { + "HideDetails": "Ocultar detalhes", }, "CameraDisclosure": { "AllowCameraUse": "Allow camera use (PT-BR)", diff --git a/app/src/screens/Developer.tsx b/app/src/screens/Developer.tsx index f6fa961..999f213 100644 --- a/app/src/screens/Developer.tsx +++ b/app/src/screens/Developer.tsx @@ -11,7 +11,7 @@ import { clearTestContacts, } from '@bifold/core' import { RemoteLogger, RemoteLoggerEventTypes } from '@bifold/remote-logs' -import { useAgent } from '@credo-ts/react-hooks' +import { useAgent } from '@bifold/react-hooks' import { useNavigation } from '@react-navigation/native' import React, { useState } from 'react' import { useTranslation } from 'react-i18next' @@ -106,7 +106,7 @@ const Developer: React.FC = () => { setEnvironmentModalVisible(false) } - const SectionHeader = ({ icon, title }: { icon: string; title: string }): JSX.Element => ( + const SectionHeader = ({ icon, title }: { icon: string; title: string }): React.JSX.Element => ( {title} @@ -117,9 +117,9 @@ const Developer: React.FC = () => { title: string accessibilityLabel?: string testID?: string - children: JSX.Element + children: React.JSX.Element showRowSeparator?: boolean - subContent?: JSX.Element + subContent?: React.JSX.Element onPress?: () => void } const SectionRow = ({ diff --git a/app/src/services/attestation.ts b/app/src/services/attestation.ts index 97c7e90..99291c5 100644 --- a/app/src/services/attestation.ts +++ b/app/src/services/attestation.ts @@ -4,34 +4,20 @@ import { AttestationMonitor as AttestationMonitorI, BifoldAgent, BifoldError, - removeExistingInvitationsById, } from '@bifold/core' +import { Agent, BaseEvent } from '@credo-ts/core' import { - appleAttestation, - generateKey, - googleAttestation, - isPlayIntegrityAvailable, -} from '@bifold/react-native-attestation' -import { AnonCredsCredentialOffer } from '@credo-ts/anoncreds' -import { - Agent, - BaseEvent, - ConnectionRecord, - CredentialEventTypes, - CredentialExchangeRecord, - CredentialState, - ProofEventTypes, - ProofExchangeRecord, - ProofState, -} from '@credo-ts/core' -import { DeviceEventEmitter, Platform } from 'react-native' -import { getBuildNumber, getSystemName, getSystemVersion, getVersion } from 'react-native-device-info' + DidCommCredentialEventTypes, + DidCommCredentialExchangeRecord, + DidCommCredentialState, + DidCommProofEventTypes, + DidCommProofExchangeRecord, + DidCommProofState, +} from '@credo-ts/didcomm' +import { DeviceEventEmitter } from 'react-native' import { AttestationRestrictions } from '@/constants' import { credentialsMatchForProof } from '@utils/credentials' -import { AttestationRequestParams, AttestationResult, requestAttestationDrpc, requestNonceDrpc } from '@utils/drpc' - -const defaultResponseTimeoutInMs = 10000 // DRPC response timeout // subscription type from agent events (TODO: add type export from Credo) type AgentSubscription = ReturnType['subscribe']> @@ -100,11 +86,11 @@ const findCredDefIDs = (restrictions: [Restriction]): Array => { } const invitationUrlFromRestrictions = async ( - proof: ProofExchangeRecord, + proof: DidCommProofExchangeRecord, agent: BifoldAgent, restrictions: AttestationRestrictionsType ): Promise => { - const format = (await agent.proofs.getFormatData(proof.id)) as unknown as AttestationProofRequestFormat + const format = (await agent.modules.didcomm.proofs.getFormatData(proof.id)) as unknown as AttestationProofRequestFormat const formatToUse = format.request?.anoncreds ? 'anoncreds' : 'indy' const restrictionsArePresent = format.request?.[formatToUse]?.requested_attributes?.attestationInfo?.restrictions @@ -127,7 +113,7 @@ const invitationUrlFromRestrictions = async ( } export const isProofRequestingAttestation = async ( - proof: ProofExchangeRecord, + proof: DidCommProofExchangeRecord, agent: BifoldAgent, restrictions: AttestationRestrictionsType ): Promise => { @@ -156,7 +142,7 @@ export class AttestationMonitor implements AttestationMonitorI { private log?: AbstractBifoldLogger private _attestationWorkflowInProgress = false private _shouldHandleProofRequestAutomatically = false - private _proofRequest?: ProofExchangeRecord + private _proofRequest?: DidCommProofExchangeRecord // private _currentWorkflowState?: typeof AttestationEventTypes // take in options, agent, and logger. Options should include the attestation service URL @@ -184,11 +170,11 @@ export class AttestationMonitor implements AttestationMonitorI { this.agent = agent this.proofSubscription = this.agent?.events - .observable(ProofEventTypes.ProofStateChanged) + .observable(DidCommProofEventTypes.ProofStateChanged) .subscribe(this.handleProofStateChanged) this.offerSubscription = this.agent?.events - .observable(CredentialEventTypes.CredentialStateChanged) + .observable(DidCommCredentialEventTypes.DidCommCredentialStateChanged) .subscribe(this.handleCredentialStateChanged) } @@ -198,74 +184,21 @@ export class AttestationMonitor implements AttestationMonitorI { } public requestAttestationCredential = async (): Promise => { - if (!this.agent || !this._proofRequest) { - throw new BifoldError( + // The BC Wallet implementation fetched a fresh attestation credential from + // BC's attestation service over DRPC. Keyring does not run that service + // (and @credo-ts/drpc has no stable credo 0.6 release), so we surface a + // failure event instead. Keyring hardware attestation for VRC lives in + // @bifold/react-native-attestation and the VRC module. + this.log?.warn('Remote attestation credential issuance is not available in Keyring') + this.stopWorkflow( + AttestationEventTypes.FailedRequestCredential, + new BifoldError( 'Attestation Service', - 'There was a problem with the remote attestation service.', - 'The agent cannot be undefined.', - AttestationErrorCodes.FailedToFetchNonceForAttestation + 'Remote attestation credential issuance is not available.', + 'This wallet does not use the BC attestation service.', + AttestationErrorCodes.FailedToRequestAttestation ) - } - - this.log?.info('Fetching attestation credential') - - this.startWorkflow() - - try { - const invitationUrl = await invitationUrlFromRestrictions(this._proofRequest, this.agent, AttestationRestrictions) - if (!invitationUrl) { - throw new BifoldError( - 'Attestation Service', - 'Unable to connect to the attestation service.', - 'No details provided.', - AttestationErrorCodes.FailedToConnectToAttestationAgent - ) - } - - const connection = await this.connectToAttestationAgent(invitationUrl) - if (!connection) { - throw new BifoldError( - 'Attestation Service', - 'Unable to connect to the attestation service.', - 'No details provided.', - AttestationErrorCodes.FailedToConnectToAttestationAgent - ) - } - - const nonce = await this.fetchNonceForAttestation(connection) - if (!nonce) { - throw new BifoldError( - 'Attestation Service', - 'There was a problem with the attestation service.', - 'No details provided.', - AttestationErrorCodes.FailedToFetchNonceForAttestation - ) - } - - const attestationObj = await this.generateAttestation(nonce) - if (!attestationObj) { - throw new BifoldError( - 'Attestation Service', - 'There was a problem with the attestation service.', - 'No details provided.', - AttestationErrorCodes.FailedToGenerateAttestation - ) - } - - const result = await this.requestAttestation(connection, attestationObj) - if (result.status !== 'success') { - throw new BifoldError( - 'Attestation Service', - 'There was a problem with the attestation service.', - 'No details provided.', - AttestationErrorCodes.FailedToValidateAttestation - ) - } - } catch (error) { - this.log?.error('Failed to fetch attestation credential', error as Error) - - this.stopWorkflow(AttestationEventTypes.FailedRequestCredential, error as Error) - } + ) } private startWorkflow = () => { @@ -279,20 +212,20 @@ export class AttestationMonitor implements AttestationMonitorI { DeviceEventEmitter.emit(eventType, error) } - private handleProofRequest = async (proofRequest: ProofExchangeRecord): Promise => { + private handleProofRequest = async (proofRequest: DidCommProofExchangeRecord): Promise => { if (!this.agent) { return false } this.log?.info('Selecting credentials for attestation proof request') // This will throw if we don't have the necessary credentials - const credentials = await this.agent.proofs.selectCredentialsForRequest({ - proofRecordId: proofRequest.id, + const credentials = await this.agent.modules.didcomm.proofs.selectCredentialsForRequest({ + proofExchangeRecordId: proofRequest.id, }) this.log?.info('Accepting attestation proof request') - await this.agent.proofs.acceptRequest({ - proofRecordId: proofRequest.id, + await this.agent.modules.didcomm.proofs.acceptRequest({ + proofExchangeRecordId: proofRequest.id, proofFormats: credentials.proofFormats, }) @@ -309,14 +242,14 @@ export class AttestationMonitor implements AttestationMonitorI { ) } - const { credentialRecord } = event.payload - const credential = credentialRecord as CredentialExchangeRecord + const { credentialExchangeRecord } = event.payload + const credential = credentialExchangeRecord as DidCommCredentialExchangeRecord this.log?.info('Handling credential offer') try { - const { offer } = await this.agent.credentials.getFormatData(credential.id) - const offerData = (offer?.anoncreds ?? offer?.indy) as AnonCredsCredentialOffer + const { offer } = await this.agent.modules.didcomm.credentials.getFormatData(credential.id) + const offerData = (offer?.anoncreds ?? offer?.indy) as { cred_def_id?: string } | undefined // do nothing if not an attestation credential const offerIsForAttestation = await isOfferingAttestation(offerData?.cred_def_id ?? '', AttestationRestrictions) @@ -325,20 +258,20 @@ export class AttestationMonitor implements AttestationMonitorI { } // if it's a new offer, automatically accept - if (credential.state === CredentialState.OfferReceived) { + if (credential.state === DidCommCredentialState.OfferReceived) { this.log?.info('Accepting credential offer') - await this.agent.credentials.acceptOffer({ - credentialRecordId: credential.id, + await this.agent.modules.didcomm.credentials.acceptOffer({ + credentialExchangeRecordId: credential.id, }) } // only finish loading state once credential is fully accepted - if (credential.state === CredentialState.Done) { + if (credential.state === DidCommCredentialState.Done) { // TODO: credential.offer in flight completed this.log?.info('Credential accepted') if (this._shouldHandleProofRequestAutomatically && this._proofRequest) { - if (this._proofRequest.state === ProofState.RequestReceived) { + if (this._proofRequest.state === DidCommProofState.RequestReceived) { const result = await this.handleProofRequest(this._proofRequest) if (result) { this.stopWorkflow(AttestationEventTypes.Completed) @@ -366,11 +299,11 @@ export class AttestationMonitor implements AttestationMonitorI { } const { proofRecord } = event.payload - const proof = proofRecord as ProofExchangeRecord + const proof = proofRecord as DidCommProofExchangeRecord this.log?.info('Handling proof received') - if (proof.state !== ProofState.RequestReceived) { + if (proof.state !== DidCommProofState.RequestReceived) { return } @@ -419,232 +352,9 @@ export class AttestationMonitor implements AttestationMonitorI { } } - private async connectToAttestationAgent(invitationUrl: string): Promise { - if (!this.agent) { - throw new BifoldError( - 'Attestation Service', - 'There was a problem with the remote attestation service.', - 'The agent cannot be undefined.', - AttestationErrorCodes.FailedToFetchNonceForAttestation - ) - } - - const invite = await this.agent.oob.parseInvitation(invitationUrl) - - if (!invite) { - this.log?.error('Unable to parse attestation agent invitation') - - throw new BifoldError( - 'Attestation Service', - 'Unable to parse the attestation agent invitation', - 'No details provided.', - AttestationErrorCodes.BadInvitation - ) - } - - this.log?.info('Removing any existing duplicate invitations if they exist') - await removeExistingInvitationsById(this.agent, invite.id) - - this.log?.info('Receiving invitation') - const { connectionRecord } = await this.agent.oob.receiveInvitation(invite) - if (!connectionRecord) { - throw new BifoldError( - 'Attestation Service', - 'Unable to accept attestation agent invitation', - 'No details provided.', - AttestationErrorCodes.BadInvitation - ) - } - - // this step will fail if there is more than one active connection record between a given wallet and - // the traction instance which is why we need to `removeExistingInvitationsById` above - return await this.agent.connections.returnWhenIsConnected(connectionRecord.id) - } - - private async fetchNonceForAttestation(connection: ConnectionRecord): Promise { - if (!this.agent) { - throw new BifoldError( - 'Attestation Service', - 'There was a problem with the remote attestation service.', - 'The agent cannot be undefined.', - AttestationErrorCodes.FailedToFetchNonceForAttestation - ) - } - - this.log?.info('Requesting nonce from controller') - - const requestNonceCb = await requestNonceDrpc(this.agent, connection) - const nonceResponse = await requestNonceCb(defaultResponseTimeoutInMs) - - if (!nonceResponse) { - this.log?.error('Failed to fetch nonce for attestation, code = none, reason = timeout occurred.') - - throw new BifoldError( - 'Attestation Service', - 'There was a problem with the remote attestation service.', - 'Timeout occurred.', - AttestationErrorCodes.FailedToFetchNonceForAttestation - ) - } - - this.log?.info('DRPC nonce response received') - - if (nonceResponse.error) { - this.log?.error( - `Failed to fetch nonce for attestation, code = ${nonceResponse.error.code}, reason = ${nonceResponse.error.message}` - ) - - throw new BifoldError( - 'Attestation Service', - 'There was a problem with the remote attestation service.', - nonceResponse.error.message ?? 'No details provided.', - AttestationErrorCodes.FailedToFetchNonceForAttestation - ) - } - - const nonce = nonceResponse.result.nonce - - return nonce - } - - private async requestAttestation( - connection: ConnectionRecord, - attestationObj: AttestationRequestParams - ): Promise { - if (!this.agent) { - throw new BifoldError( - 'Attestation Service', - 'There was a problem with the remote attestation service.', - 'No details provided.', - AttestationErrorCodes.FailedToFetchNonceForAttestation - ) - } - - this.log?.info('Requesting attestation credential from controller') - - const requestAttestationCb = await requestAttestationDrpc(this.agent, connection, attestationObj) - const attestationResponse = await requestAttestationCb(defaultResponseTimeoutInMs) - - if (!attestationResponse) { - this.log?.error('Failed to request attestation, code = none, reason = timeout occurred.') - - throw new BifoldError( - 'Attestation Service', - 'There was a problem with the remote attestation service.', - 'Timeout occurred.', - AttestationErrorCodes.FailedToRequestAttestation - ) - } - - this.log?.info('DRPC attestation response received') - - if (attestationResponse.error) { - this.log?.error( - `Failed to request attestation, code = ${attestationResponse.error.code}, reason = ${attestationResponse.error.message}` - ) - - throw new BifoldError( - 'Attestation Service', - 'There was a problem with the remote attestation service.', - attestationResponse.error.message ?? 'No details provided.', - AttestationErrorCodes.FailedToRequestAttestation - ) - } - - return attestationResponse.result - } - - private commonAttestationMessageComponent() { - const common: Partial = { - app_version: `${getVersion()}-${getBuildNumber()}`, - os_version: `${getSystemName()} ${getSystemVersion()}`, - } - - return common - } - - private async generateAttestation(nonce: string) { - switch (Platform.OS) { - case 'ios': - return this.generateAppleAttestation(nonce) - case 'android': - return this.generateGoogleAttestation(nonce) - - default: - // TODO(jl): throw unsupported platform error - break - } - } - - private async generateAppleAttestation(nonce: string) { - const common = this.commonAttestationMessageComponent() - const shouldCacheKey = false - - this.log?.info('Generating key for Apple') - const keyId = await generateKey(shouldCacheKey) - - this.log?.info('Using Apple on-device attestation') - const attestationAsBuffer = await appleAttestation(keyId, nonce) - const attestationRequest = { - ...common, - platform: 'apple', - key_id: keyId, - attestation_object: attestationAsBuffer.toString('base64'), - } as AttestationRequestParams - - this.log?.info('On-device Apple attestation complete') - - return attestationRequest - } - - private async generateGoogleAttestation(nonce: string) { - const common = this.commonAttestationMessageComponent() - - this.log?.info('Checking if Play Integrity is available') - - const available = await isPlayIntegrityAvailable() - if (!available) { - this.log?.error('Google Play Integrity is unavailable') - - const error = new BifoldError( - 'Google Play Integrity Unavailable', - 'Google Play Integrity is required for device attestation but is not available on this device.', - 'The device attestation process cannot be completed without Google Play Integrity services.', - AttestationErrorCodes.IntegrityUnavailable - ) - - throw error - } else { - this.log?.info('Google Play Integrity is available') - } - - this.log?.info('Using Google on-device attestation') - - let tokenString: string - try { - tokenString = await googleAttestation(nonce) - } catch (error) { - const bifoldError = new BifoldError( - 'Google Attestation Error', - 'There was a problem with the Google Integrity API.', - (error as Error)?.message || 'No details provided.', - AttestationErrorCodes.IntegrityUnavailable - ) - throw bifoldError - } - const attestationRequest = { - ...common, - platform: 'google', - attestation_object: tokenString, - } as AttestationRequestParams - this.log?.info('On-device Google attestation complete') - - return attestationRequest - } - private attestationCredentialRequired = async (agent: BifoldAgent, proofId: string): Promise => { agent.config.logger.info('Fetching proof by id') - const proof = await agent?.proofs.getById(proofId) + const proof = await agent?.modules.didcomm.proofs.getById(proofId) agent.config.logger.info('Second check if proof is requesting attestation') agent.config.logger.info('Checking if credentials match for proof request') diff --git a/app/src/utils/PushNotificationsHelper.ts b/app/src/utils/PushNotificationsHelper.ts index 8727a86..c3d6aaa 100644 --- a/app/src/utils/PushNotificationsHelper.ts +++ b/app/src/utils/PushNotificationsHelper.ts @@ -1,4 +1,5 @@ -import { Agent, ConnectionRecord, ConnectionType } from '@credo-ts/core' +import { Agent } from '@credo-ts/core' +import { DidCommConnectionRecord, DidCommConnectionType } from '@credo-ts/didcomm' import { PersistentStorage } from '@bifold/core' import messaging, { FirebaseMessagingTypes } from '@react-native-firebase/messaging' import { Platform } from 'react-native' @@ -68,9 +69,9 @@ const requestPermission = async (): Promise => { * Helper Functions Section */ -const getMediatorConnection = async (agent: Agent): Promise => { - const connections: ConnectionRecord[] = await agent.connections.getAll() - const mediators = connections.filter((r) => r.connectionTypes.includes(ConnectionType.Mediator)) +const getMediatorConnection = async (agent: Agent): Promise => { + const connections: DidCommConnectionRecord[] = await agent.modules.didcomm.connections.getAll() + const mediators = connections.filter((r) => r.connectionTypes.includes(DidCommConnectionType.Mediator)) if (mediators.length < 1) { agent.config.logger.warn(`Mediator connection not found`) return undefined @@ -117,7 +118,7 @@ const isMediatorCapable = async (agent: Agent): Promise => const mediator = await getMediatorConnection(agent) if (!mediator) return - const response = await agent.discovery.queryFeatures({ + const response = await agent.modules.didcomm.discovery.queryFeatures({ awaitDisclosures: true, connectionId: mediator.id, protocolVersion: 'v1', diff --git a/app/src/utils/alert.ts b/app/src/utils/alert.ts new file mode 100644 index 0000000..0adfa82 --- /dev/null +++ b/app/src/utils/alert.ts @@ -0,0 +1,23 @@ +import i18n from 'i18next' +import { Alert, AlertButton } from 'react-native' + +// Extends AlertButton to require text property +export type AlertAction = AlertButton & { text: string } + +// Default OK action - evaluated at call time to get current translation +const getDefaultOkAction = (): AlertAction => ({ + text: i18n.t('Global.Okay'), + onPress: () => {}, +}) + +/** + * Displays a native alert with pre-translated title and body. + * Use this when you have already translated the strings. + * + * @param title - The alert title (already translated) + * @param body - The alert body/message (already translated) + * @param actions - Optional array of AlertButton actions. If not provided, a default 'OK' button will be used. + */ +export const showAlert = (title: string, body: string, actions?: AlertAction[]): void => { + Alert.alert(title, body, actions ?? [getDefaultOkAction()]) +} diff --git a/app/src/utils/bc-agent-modules.ts b/app/src/utils/bc-agent-modules.ts index 6ce9960..1c70bd9 100644 --- a/app/src/utils/bc-agent-modules.ts +++ b/app/src/utils/bc-agent-modules.ts @@ -1,72 +1,61 @@ import { - AnonCredsCredentialFormatService, + AnonCredsDidCommCredentialFormatService, + AnonCredsDidCommProofFormatService, AnonCredsModule, - AnonCredsProofFormatService, - DataIntegrityCredentialFormatService, - LegacyIndyCredentialFormatService, - LegacyIndyProofFormatService, - V1CredentialProtocol, - V1ProofProtocol, + DataIntegrityDidCommCredentialFormatService, + DidCommCredentialV1Protocol, + DidCommProofV1Protocol, + LegacyIndyDidCommCredentialFormatService, + LegacyIndyDidCommProofFormatService, } from '@credo-ts/anoncreds' -import { AskarModule } from '@credo-ts/askar' +import { AskarKeyManagementService, AskarModule } from '@credo-ts/askar' import { Agent, - AutoAcceptCredential, - AutoAcceptProof, - ConnectionsModule, - CredentialsModule, DidsModule, - DifPresentationExchangeProofFormatService, - JsonLdCredentialFormatService, - MediationRecipientModule, - MediatorPickupStrategy, - ProofsModule, - V2CredentialProtocol, - V2ProofProtocol, + JwkDidResolver, + KeyDidResolver, + Kms, + PeerDidResolver, W3cCredentialsModule, + WebDidResolver, } from '@credo-ts/core' -import { DrpcModule } from '@credo-ts/drpc' +import { + DidCommAutoAcceptCredential, + DidCommAutoAcceptProof, + DidCommCredentialV2Protocol, + DidCommDifPresentationExchangeProofFormatService, + DidCommJsonLdCredentialFormatService, + DidCommMediatorPickupStrategy, + DidCommModule, + DidCommProofV2Protocol, +} from '@credo-ts/didcomm' import { IndyVdrAnonCredsRegistry, IndyVdrModule, IndyVdrPoolConfig } from '@credo-ts/indy-vdr' -// DISABLED: Push notifications disabled — no server backend yet -// import { PushNotificationsApnsModule, PushNotificationsFcmModule } from '@credo-ts/push-notifications' -import { WebVhAnonCredsRegistry, WebvhDidResolver } from '@credo-ts/webvh' +import { SecureEnvironmentKeyManagementService } from '@credo-ts/react-native' +import { WebVhAnonCredsRegistry, WebVhDidResolver } from '@credo-ts/webvh' import { anoncreds } from '@hyperledger/anoncreds-react-native' -import { ariesAskar } from '@hyperledger/aries-askar-react-native' import { indyVdr } from '@hyperledger/indy-vdr-react-native' -import { CacheSettings, IndyVdrProxyAnonCredsRegistry, IndyVdrProxyDidResolver } from 'credo-ts-indy-vdr-proxy-client' +import { askar } from '@openwallet-foundation/askar-react-native' import * as BifoldCore from '@bifold/core' export type BCAgent = Agent> interface GetBCAgentModulesOptions { + walletSecret: { id: string; key: string } indyNetworks: IndyVdrPoolConfig[] mediatorInvitationUrl?: string txnCache?: { capacity: number; expiryOffsetMs: number; path?: string } - enableProxy?: boolean - proxyBaseUrl?: string - proxyCacheSettings?: CacheSettings } /** - * Constructs the modules to be used in the agent setup - * @param indyNetworks - * @param mediatorInvitationUrl determine which mediator to use - * @param txnCache optional local cache config for indyvdr - * @param enableProxy boolean from the store to determine if proxy should be used - * @param proxyBaseUrl URL of indy vdr proxy - * @param proxyCacheSettings settings for above mentioned proxy client caching + * Constructs the modules to be used in the agent setup (credo 0.6). + * Mirrors @bifold/core getAgentModules, plus the Keyring additions: + * JSON-LD credential format (VRC), VRC document loader, RelationshipDidModule + * and AttestationStorageModule. * @returns modules to be used in agent setup */ -export function getBCAgentModules({ - indyNetworks, - mediatorInvitationUrl, - txnCache, - enableProxy, - proxyBaseUrl, - proxyCacheSettings, -}: GetBCAgentModulesOptions) { - const indyCredentialFormat = new LegacyIndyCredentialFormatService() - const indyProofFormat = new LegacyIndyProofFormatService() +export function getBCAgentModules({ walletSecret, indyNetworks, mediatorInvitationUrl, txnCache }: GetBCAgentModulesOptions) { + const indyCredentialFormat = new LegacyIndyDidCommCredentialFormatService() + const indyProofFormat = new LegacyIndyDidCommProofFormatService() if (txnCache) { indyVdr.setLedgerTxnCache({ @@ -80,7 +69,16 @@ export function getBCAgentModules({ const modules = { askar: new AskarModule({ - ariesAskar, + enableKms: false, + askar, + store: { id: walletSecret.id, key: walletSecret.key }, + }), + kms: new Kms.KeyManagementModule({ + backends: [ + new AskarKeyManagementService(), + new SecureEnvironmentKeyManagementService({ biometricsBacked: false }), + ], + defaultBackend: 'askar', }), anoncreds: new AnonCredsModule({ anoncreds, @@ -90,66 +88,58 @@ export function getBCAgentModules({ indyVdr, networks: indyNetworks as [IndyVdrPoolConfig], }), - connections: new ConnectionsModule({ - autoAcceptConnections: true, - }), - credentials: new CredentialsModule({ - autoAcceptCredentials: AutoAcceptCredential.ContentApproved, - credentialProtocols: [ - new V1CredentialProtocol({ indyCredentialFormat }), - new V2CredentialProtocol({ - credentialFormats: [ - indyCredentialFormat, - new AnonCredsCredentialFormatService(), - new DataIntegrityCredentialFormatService(), - new JsonLdCredentialFormatService(), - ], - }), - ], - }), - proofs: new ProofsModule({ - autoAcceptProofs: AutoAcceptProof.ContentApproved, - proofProtocols: [ - new V1ProofProtocol({ indyProofFormat }), - new V2ProofProtocol({ - proofFormats: [ - indyProofFormat, - new AnonCredsProofFormatService(), - new DifPresentationExchangeProofFormatService(), - ], - }), - ], - }), - mediationRecipient: new MediationRecipientModule({ - mediatorInvitationUrl: mediatorInvitationUrl, - mediatorPickupStrategy: MediatorPickupStrategy.Implicit, + didcomm: new DidCommModule({ + useDidSovPrefixWhereAllowed: true, + connections: { + autoAcceptConnections: true, + }, + credentials: { + autoAcceptCredentials: DidCommAutoAcceptCredential.ContentApproved, + credentialProtocols: [ + new DidCommCredentialV1Protocol({ indyCredentialFormat }), + new DidCommCredentialV2Protocol({ + credentialFormats: [ + indyCredentialFormat, + new AnonCredsDidCommCredentialFormatService(), + new DataIntegrityDidCommCredentialFormatService(), + new DidCommJsonLdCredentialFormatService(), + ], + }), + ], + }, + proofs: { + autoAcceptProofs: DidCommAutoAcceptProof.ContentApproved, + proofProtocols: [ + new DidCommProofV1Protocol({ indyProofFormat }), + new DidCommProofV2Protocol({ + proofFormats: [ + indyProofFormat, + new AnonCredsDidCommProofFormatService(), + new DidCommDifPresentationExchangeProofFormatService(), + ], + }), + ], + }, + mediationRecipient: { + mediatorInvitationUrl: mediatorInvitationUrl, + mediatorPickupStrategy: DidCommMediatorPickupStrategy.Implicit, + }, }), - // DISABLED: Push notifications disabled — no server backend yet - // pushNotificationsFcm: new PushNotificationsFcmModule(), - // pushNotificationsApns: new PushNotificationsApnsModule(), dids: new DidsModule({ - resolvers: [new WebvhDidResolver()], + resolvers: [ + new WebVhDidResolver(), + new WebDidResolver(), + new JwkDidResolver(), + new KeyDidResolver(), + new PeerDidResolver(), + ], }), w3cCredentials: new W3cCredentialsModule({ documentLoader: (BifoldCore as any).createVrcDocumentLoader, }), - drpc: new DrpcModule(), relationshipDid: new RelationshipDidModule(), attestationStorage: new AttestationStorageModule(), } - if (enableProxy && proxyBaseUrl) { - modules.anoncreds = new AnonCredsModule({ - anoncreds, - registries: [ - new IndyVdrProxyAnonCredsRegistry({ proxyBaseUrl, cacheOptions: proxyCacheSettings }), - new WebVhAnonCredsRegistry(), - ], - }) - modules.dids = new DidsModule({ - resolvers: [new IndyVdrProxyDidResolver({ proxyBaseUrl }), new WebvhDidResolver()], - }) - } - return modules } diff --git a/app/src/utils/credentials.ts b/app/src/utils/credentials.ts index ce6c19c..12127ce 100644 --- a/app/src/utils/credentials.ts +++ b/app/src/utils/credentials.ts @@ -4,7 +4,7 @@ import { AnonCredsRequestedAttributeMatch, AnonCredsRequestedPredicateMatch, } from '@credo-ts/anoncreds' -import { CredentialExchangeRecord, ProofExchangeRecord, GetCredentialsForProofRequestReturn } from '@credo-ts/core' +import { DidCommCredentialExchangeRecord, DidCommProofExchangeRecord, GetCredentialsForProofRequestReturn } from '@credo-ts/didcomm' import { BifoldAgent } from '@bifold/core' import { Attribute, Predicate } from '@bifold/oca/build/legacy' @@ -14,7 +14,7 @@ export type ProofCredentialItems = ProofCredentialAttributes & ProofCredentialPr export type ProofCredentialAttributes = { altCredentials?: string[] - credExchangeRecord?: CredentialExchangeRecord + credExchangeRecord?: DidCommCredentialExchangeRecord credId: string credDefId?: string proofCredDefId?: string @@ -26,7 +26,7 @@ export type ProofCredentialAttributes = { export type ProofCredentialPredicates = { altCredentials?: string[] - credExchangeRecord?: CredentialExchangeRecord + credExchangeRecord?: DidCommCredentialExchangeRecord credId: string credDefId?: string proofCredDefId?: string @@ -124,7 +124,7 @@ export const evaluatePredicates = * @returns The Anoncreds or Indy proof format object */ const formatForProofWithId = async (agent: BifoldAgent, proofId: string, filterByNonRevocationRequirements = false) => { - const format = await agent.proofs.getFormatData(proofId) + const format = await agent.modules.didcomm.proofs.getFormatData(proofId) const proofIsAnoncredsFormat = format.request?.anoncreds !== undefined const proofIsIndycredsFormat = format.request?.indy !== undefined const proofFormats = { @@ -168,12 +168,12 @@ const formatForProofWithId = async (agent: BifoldAgent, proofId: string, filterB */ export const credentialsMatchForProof = async ( agent: BifoldAgent, - proof: ProofExchangeRecord, + proof: DidCommProofExchangeRecord, filterByNonRevocationRequirements = true ): Promise => { const proofFormats = await formatForProofWithId(agent, proof.id, filterByNonRevocationRequirements) - const credentials = await agent.proofs.getCredentialsForRequest({ - proofRecordId: proof.id, + const credentials = await agent.modules.didcomm.proofs.getCredentialsForRequest({ + proofExchangeRecordId: proof.id, proofFormats, }) diff --git a/app/src/utils/drpc.ts b/app/src/utils/drpc.ts deleted file mode 100644 index c647bd1..0000000 --- a/app/src/utils/drpc.ts +++ /dev/null @@ -1,68 +0,0 @@ -import { Agent, ConnectionRecord } from '@credo-ts/core' -import { DrpcRequest, DrpcResponseObject } from '@credo-ts/drpc' - -export type DrpcResponsePromise = (responseTimeout: number) => Promise - -export type AttestationRequestParams = { - attestation_object: string - platform: 'apple' | 'google' - os_version: string - app_version: string - key_id?: string // Apple only -} - -export type NonceDrpcResponse = DrpcResponseObject & { - result?: { - nonce: string - } -} - -export type AttestationResult = { - status: 'success' | 'failure' -} - -export type AttestationDrpcResponse = DrpcResponseObject & { - result?: AttestationResult -} - -// These are the methods that the DRPC server supports. They -// should map to a handler on the controller. -const DrpcMethod = { - RequestNonceV2: 'request_nonce_v2', - RequestAttestationV2: 'request_attestation_v2', -} as const - -export const sendDrpcRequest = async ( - agent: Agent, - connectionId: string, - request: Partial - // eslint-disable-next-line @typescript-eslint/no-explicit-any -): Promise> => { - const requestWithId = { jsonrpc: '2.0', id: Math.floor(Math.random() * 900000) + 100000, ...request } - - return await agent.modules.drpc.sendRequest(connectionId, requestWithId) -} - -export const requestNonceDrpc = async ( - agent: Agent, - connectionRecord: ConnectionRecord -): Promise> => { - const request: Partial = { - method: DrpcMethod.RequestNonceV2, - } - - return await sendDrpcRequest(agent, connectionRecord.id, request) -} - -export const requestAttestationDrpc = async ( - agent: Agent, - connectionRecord: ConnectionRecord, - params: AttestationRequestParams -): Promise> => { - const request: Partial = { - method: DrpcMethod.RequestAttestationV2, - params, - } - - return await sendDrpcRequest(agent, connectionRecord.id, request) -} diff --git a/app/src/utils/logger.ts b/app/src/utils/logger.ts index c1fd06f..d443a9f 100644 --- a/app/src/utils/logger.ts +++ b/app/src/utils/logger.ts @@ -1,4 +1,5 @@ -import { RemoteLogger, RemoteLoggerOptions } from '@bifold/remote-logs' +import type { BifoldError } from '@bifold/core' +import { RemoteLogger, RemoteLoggerOptions, lokiTransport } from '@bifold/remote-logs' import Config from 'react-native-config' import { getApplicationName, @@ -8,6 +9,7 @@ import { getVersion, } from 'react-native-device-info' import { autoDisableRemoteLoggingIntervalInMinutes } from '../constants' +import { generateReferenceCode } from './reference-code' const logOptions: RemoteLoggerOptions = { lokiUrl: Config.REMOTE_LOGGING_URL, @@ -21,4 +23,52 @@ const logOptions: RemoteLoggerOptions = { const BCLogger = new RemoteLogger(logOptions) +/** + * Sends a problem report to Loki and returns a user-facing reference code. + * + * Ported from bc-wallet-mobile. The reference code is embedded in the report + * payload as `report_id`, so support can locate the incident later by searching + * the `incident-report` job for it (e.g. in Grafana: + * `{job="incident-report"} |= ""`). It is intentionally placed in the log + * body rather than as a Loki label to avoid high label cardinality. + * + * Reporting is best-effort: any transport failure is swallowed so the user is + * always given a code to share, even when the network/Loki is unavailable. + * + * @param error - the error being reported + * @returns the reference code to surface to the user + */ +export const reportProblem = (error: BifoldError): string => { + const referenceCode = generateReferenceCode() + const { title, description, code, message, stack } = error + + try { + if (logOptions.lokiUrl) { + lokiTransport({ + msg: title, + // Only attach `stack` when the error actually carries one — user-initiated + // reports have no real trace, so the field is omitted rather than logging + // meaningless construction frames. + rawMsg: [ + { + message: title, + data: { description, code, message, ...(stack ? { stack } : {}), report_id: referenceCode }, + }, + ], + level: { severity: 3, text: 'error' }, + options: { + lokiUrl: logOptions.lokiUrl, + lokiLabels: logOptions.lokiLabels, + job: 'incident-report', + }, + }) + } + } catch (e) { + // Never let a reporting failure prevent the user from getting their code. + BCLogger.error?.(`Failed to send problem report to Loki: ${e}`) + } + + return referenceCode +} + export default BCLogger diff --git a/app/src/utils/mediator.ts b/app/src/utils/mediator.ts deleted file mode 100644 index eede53b..0000000 --- a/app/src/utils/mediator.ts +++ /dev/null @@ -1,31 +0,0 @@ -import { Agent, MediatorPickupStrategy } from '@credo-ts/core' - -export const batchPickup = async (agent: Agent): Promise => { - try { - for (let i = 0; i < 2; i++) { - agent.config.logger.debug(`Batch pickup attempt ${i + 1}`) - agent.mediationRecipient.initiateMessagePickup(undefined, MediatorPickupStrategy.Implicit) - await new Promise((resolve) => setTimeout(resolve, 50)) - } - } catch (error) { - agent.config.logger.error(`Error during batch pickup: ${error}`) - } -} - -export const startPeriodicTrustPing = (agent: Agent, intervalMs: number): (() => void) => { - const id = setInterval(async () => { - try { - const mediator = await agent.mediationRecipient.findDefaultMediator() - if (!mediator) return - - await agent.connections.sendPing(mediator.connectionId, { - responseRequested: false, - withReturnRouting: true, - }) - } catch (error) { - agent.config.logger.error(`Periodic trust ping failed: ${error}`) - } - }, intervalMs) - - return () => clearInterval(id) -} diff --git a/app/src/utils/reference-code.ts b/app/src/utils/reference-code.ts new file mode 100644 index 0000000..1555908 --- /dev/null +++ b/app/src/utils/reference-code.ts @@ -0,0 +1,25 @@ +/** + * Characters used to build a user-facing reference code. Visually ambiguous + * glyphs (0/O, 1/I/L, and U) are excluded so the code can be read aloud over the + * phone and typed back without confusion. + */ +const REFERENCE_CODE_ALPHABET = '23456789ABCDEFGHJKMNPQRSTVWXYZ' +const REFERENCE_CODE_LENGTH = 8 +const REFERENCE_CODE_GROUP_SIZE = 4 + +/** + * Generates a short, human-readable reference code, e.g. "7K2P-9XQF". + * + * It is grouped with a dash for readability and drawn from an ambiguity-free + * alphabet so a user can relay it to support without transcription errors. + */ +export const generateReferenceCode = (): string => { + let code = '' + for (let i = 0; i < REFERENCE_CODE_LENGTH; i++) { + if (i > 0 && i % REFERENCE_CODE_GROUP_SIZE === 0) { + code += '-' + } + code += REFERENCE_CODE_ALPHABET.charAt(Math.floor(Math.random() * REFERENCE_CODE_ALPHABET.length)) + } + return code +} diff --git a/app/storybook/addons.ts b/app/storybook/addons.ts deleted file mode 100644 index 429196c..0000000 --- a/app/storybook/addons.ts +++ /dev/null @@ -1,4 +0,0 @@ -/* eslint-disable import/no-extraneous-dependencies */ -import '@storybook/addon-actions' -import '@storybook/addon-links' -import '@storybook/addon-knobs' diff --git a/app/storybook/index.ts b/app/storybook/index.ts deleted file mode 100644 index 0efc575..0000000 --- a/app/storybook/index.ts +++ /dev/null @@ -1,28 +0,0 @@ -/* eslint-disable import/no-extraneous-dependencies */ -// if you use expo remove this line -import { withKnobs } from '@storybook/addon-knobs' -import { getStorybookUI, configure, addDecorator } from '@storybook/react-native' -import { Platform } from 'react-native' - -import './rn-addons' - -// enables knobs for all stories -addDecorator(withKnobs) - -// import stories -configure(() => { - require('./stories') -}, module) - -// Refer to https://github.com/storybookjs/react-native/tree/master/app/react-native#getstorybookui-options -// To find allowed options for getStorybookUI -const StorybookUIRoot = getStorybookUI({ - host: Platform.OS === 'android' ? '10.0.2.2' : '0.0.0.0', - asyncStorage: null, -}) - -// If you are using React Native vanilla and after installation you don't see your app name here, write it manually. -// If you use Expo you should remove this line. -//AppRegistry.registerComponent('%APP_NAME%', () => StorybookUIRoot) - -export default StorybookUIRoot diff --git a/app/storybook/rn-addons.ts b/app/storybook/rn-addons.ts deleted file mode 100644 index 88595a3..0000000 --- a/app/storybook/rn-addons.ts +++ /dev/null @@ -1,3 +0,0 @@ -/* eslint-disable import/no-extraneous-dependencies */ -import '@storybook/addon-ondevice-actions/register' -import '@storybook/addon-ondevice-knobs/register' diff --git a/app/storybook/stories/Brandings/Brandings.stories.tsx b/app/storybook/stories/Brandings/Brandings.stories.tsx deleted file mode 100644 index ce3a5c0..0000000 --- a/app/storybook/stories/Brandings/Brandings.stories.tsx +++ /dev/null @@ -1,295 +0,0 @@ -import { - components, - ContainerProvider, - contexts, - MainContainer, - StoreContext, - ThemeProvider, - TOKENS, -} from '@bifold/core' -import { BrandingOverlayType, RemoteOCABundleResolver } from '@bifold/oca/build/legacy' -import { AnonCredsCredentialMetadataKey } from '@credo-ts/anoncreds/build/utils/metadata' -import { - CredentialExchangeRecord, - CredentialExchangeRecordProps, - CredentialPreviewAttribute, - CredentialRole, - CredentialState, - RevocationNotification, -} from '@credo-ts/core' -import { select } from '@storybook/addon-knobs' -import { storiesOf } from '@storybook/react-native' -import React, { Dispatch, PropsWithChildren, useEffect, useMemo, useState } from 'react' -import { useTranslation } from 'react-i18next' -import { FlatList, ListRenderItem, View } from 'react-native' -import { Config } from 'react-native-config' -import { container } from 'tsyringe' - -import { KeyRingThemeNames } from '@/constants' -import { themes } from '@/theme' - -const OCABundleResolver = new RemoteOCABundleResolver(Config.OCA_URL ?? '', { - brandingOverlayType: BrandingOverlayType.Branding10, -}) -const BasicAppContext: React.FC = ({ children }) => { - const context = useMemo(() => new MainContainer(container.createChildContainer()).init(), []) - context.container.registerInstance(TOKENS.UTIL_OCA_RESOLVER, OCABundleResolver) - return {children} -} - -enum CREDENTIALS { - LSBC_TEST = 'AuJrigKQGRLJajKAebTgWu:3:CL:209526:default', - LSBC_PROD = '4xE68b6S5VRFrKMMG1U95M:3:CL:59232:default', - SHOWCASE_LAWYER_DEV = 'L6ASjmDDbDH7yPL1t2yFj9:2:member_card:1.53', - SHOWCASE_LAWYER_TEST = 'M6dhuFj5UwbhWkSLmvYSPc:2:member_card:1.53', - SHOWCASE_LAWYER_PROD = 'QEquAHkM35w4XVT3Ku5yat:2:member_card:1.53', - SHOWCASE_STUDENT_DEV = 'L6ASjmDDbDH7yPL1t2yFj9:2:student_card:1.2', - SHOWCASE_STUDENT_TEST = 'M6dhuFj5UwbhWkSLmvYSPc:2:student_card:1.2', - SHOWCASE_STUDENT_PROD = 'QEquAHkM35w4XVT3Ku5yat:2:student_card:1.2', - SHOWCASE_LAWYER2_PERSON_DEV = 'L6ASjmDDbDH7yPL1t2yFj9:2:Person:1.2', - SHOWCASE_LAWYER2_PERSON_TEST = 'M6dhuFj5UwbhWkSLmvYSPc:2:Person:1.2', - SHOWCASE_LAWYER2_PERSON_PROD = 'QEquAHkM35w4XVT3Ku5yat:2:Person:1.2', - UNVERIFIED_PERSON_DEV = 'Ui6HA36FvN83cEtmYYHxrn:2:unverified_person:0.1.0', - UNVERIFIED_PERSON_TEST = 'HTkhhCW1bAXWnxC1u3YVoa:2:unverified_person:0.1.0', - UNVERIFIED_PERSON_PROD = 'YXCtXE4YhVjULgj5hrk4ML:2:unverified_person:0.1.0', - PILOT_INVITE_DEV = 'Mp2pDQqS2eSjNVA7kXc8ut:2:BC VC Pilot Certificate:1.0.1', - PILOT_INVITE_TEST = '4zBepKVWZcGTzug4X49vAN:2:BC VC Pilot Certificate:1.0.1', - PILOT_INVITE_PROD = 'E2h4RUJxyh48PLJ1CtGJrq:2:BC VC Pilot Certificate:1.0.1', - BC_DIGITAL_ID_QA = 'KCxVC8GkKywjhWJnUfCmkW:3:CL:20:PersonQA', - BC_DIGITAL_ID_SIT = '7xjfawcnyTUcduWVysLww5:3:CL:28075:PersonSIT', - BC_DIGITAL_ID_DEV = 'XpgeQa93eZvGSZBZef3PHn:3:CL:28075:PersonDEV', - BC_DIGITAL_ID_PROD = 'RGjWbW1eycP7FrMf4QJvX8:3:CL:13:Person', -} - -enum CREDENTIAL_DEFINITION { - Generic = 'asdasdasd:2:generic:1.0:Generic', -} - -const { - misc: { CredentialCard }, -} = components - -type CredentialProps = { - credentialRecordId: string - revoked?: boolean - credentialDefinitionId: string - connectionId?: string -} - -const CredentialWrapper = ({ - revoked = false, - credentialRecordId, - credentialDefinitionId, - connectionId, -}: CredentialProps) => { - const indyCredential = { credentialRecordType: 'indy', credentialRecordId } - const props: CredentialExchangeRecordProps = { - role: CredentialRole.Issuer, - connectionId: connectionId, - threadId: '', - state: CredentialState.CredentialIssued, - protocolVersion: '1.0', - credentials: [indyCredential], - } - const credDefIdParts = credentialDefinitionId.split(':') - if (credDefIdParts[2] === 'CL' && credDefIdParts[4] === 'Person') { - props.credentialAttributes = [ - new CredentialPreviewAttribute({ name: 'given_names', value: 'John' }), - new CredentialPreviewAttribute({ name: 'family_name', value: 'Doe' }), - ] - } - const credential: CredentialExchangeRecord = new CredentialExchangeRecord(props) - credential.metadata.set(AnonCredsCredentialMetadataKey, { - credentialDefinitionId: credentialDefinitionId, - schemaId: '', - }) - if (revoked) { - credential.revocationNotification = new RevocationNotification() - } - return -} - -type ListItem = { - credentialDefinitionId: string - credentialRecordId: string - revoked: boolean - connectionId?: string -} - -type CredentialsProps = { items: ListItem[] } - -const ItemDivider = () => { - return ( - - ) -} - -const Credentials = ({ items }: CredentialsProps) => { - const lang = select('Language', ['en', 'fr', 'pt'], 'en') - const { i18n } = useTranslation() - const [isLoaded, setLoaded] = useState(false) - const renderItem: ListRenderItem = ({ item, index }): JSX.Element => { - return ( - - ) - } - useEffect(() => { - async function changeFlag() { - await i18n.changeLanguage(lang) - setLoaded(true) - } - changeFlag() - }, [lang, i18n]) - return ( - <> - {isLoaded && ( - - )} - - ) -} - -storiesOf('Brandings', module) - .add('All', () => { - const state = contexts.store.defaultState - // eslint-disable-next-line @typescript-eslint/no-explicit-any - const dispatch: Dispatch = () => { - return - } - const list: ListItem[] = [ - { - credentialDefinitionId: CREDENTIALS.BC_DIGITAL_ID_PROD, - credentialRecordId: 'PersonCredential_default', - revoked: false, - }, - { - credentialDefinitionId: CREDENTIALS.BC_DIGITAL_ID_PROD, - credentialRecordId: 'PersonCredential_Revoked', - revoked: true, - }, - { - credentialDefinitionId: CREDENTIALS.SHOWCASE_STUDENT_PROD, - credentialRecordId: 'StudentCredential_default', - revoked: false, - }, - { - credentialDefinitionId: CREDENTIALS.SHOWCASE_STUDENT_PROD, - credentialRecordId: 'StudentCredential_Revoked', - revoked: true, - }, - { credentialDefinitionId: CREDENTIALS.LSBC_PROD, credentialRecordId: 'Lawyer_default', revoked: false }, - { credentialDefinitionId: CREDENTIALS.LSBC_PROD, credentialRecordId: 'Lawyer_Revoked', revoked: true }, - { - credentialDefinitionId: CREDENTIALS.PILOT_INVITE_PROD, - credentialRecordId: 'Pilot_default', - revoked: false, - }, - { - credentialDefinitionId: CREDENTIALS.PILOT_INVITE_PROD, - credentialRecordId: 'Pilot_Revoked', - revoked: true, - }, - { - credentialDefinitionId: CREDENTIALS.UNVERIFIED_PERSON_PROD, - credentialRecordId: 'unverified_person_default', - revoked: false, - }, - { - credentialDefinitionId: CREDENTIALS.UNVERIFIED_PERSON_PROD, - credentialRecordId: 'unverified_person_Revoked', - revoked: true, - }, - { credentialDefinitionId: CREDENTIAL_DEFINITION.Generic, credentialRecordId: 'Generic_default', revoked: false }, - { - credentialDefinitionId: CREDENTIAL_DEFINITION.Generic, - credentialRecordId: 'Generic_Revoked', - revoked: true, - connectionId: 'ACME', - }, - { - credentialDefinitionId: CREDENTIAL_DEFINITION.Generic, - credentialRecordId: 'Generic_Revoked', - revoked: true, - connectionId: 'ab2c9305-282e-42da-82d9-70d3e99ecb02', - }, - { - credentialDefinitionId: CREDENTIAL_DEFINITION.Generic, - credentialRecordId: 'Generic_Revoked', - revoked: true, - connectionId: 'ab2c9305-282e-42da-82d9-70d3e99ecb02-70d3e99ecb02', - }, - { - credentialDefinitionId: CREDENTIAL_DEFINITION.Generic, - credentialRecordId: 'Generic_Revoked', - revoked: true, - connectionId: 'ab2c9305-282e-42da-82d9-70d3e99ecb02-70d3e99ecb02-282e-42da-82d9-70d3e99ecb02-70d3e99ecb02', - }, - ] - return ( - - - - - - - - ) - }) - .add('Person: Default', (): React.ReactNode => { - const state = contexts.store.defaultState - // eslint-disable-next-line @typescript-eslint/no-explicit-any - const dispatch: Dispatch = () => { - return - } - const list: ListItem[] = [ - { - credentialDefinitionId: CREDENTIALS.BC_DIGITAL_ID_PROD, - credentialRecordId: 'PersonCredential_default', - revoked: false, - }, - ] - return ( - <> - - - - - - - - - ) - }) - .add('Person: Revoked', (): React.ReactNode => { - const state = contexts.store.defaultState - // eslint-disable-next-line @typescript-eslint/no-explicit-any - const dispatch: Dispatch = () => { - return - } - const list: ListItem[] = [ - { - credentialDefinitionId: CREDENTIALS.BC_DIGITAL_ID_PROD, - credentialRecordId: 'PersonCredential_Revoked', - revoked: true, - }, - ] - return ( - - - - - - ) - }) diff --git a/app/storybook/stories/Button/Button.stories.tsx b/app/storybook/stories/Button/Button.stories.tsx deleted file mode 100644 index 6049ec9..0000000 --- a/app/storybook/stories/Button/Button.stories.tsx +++ /dev/null @@ -1,46 +0,0 @@ -/* eslint-disable import/no-extraneous-dependencies */ -import { components, ThemeProvider } from '@bifold/core' -import { storiesOf } from '@storybook/react-native' -import React from 'react' -import { ScrollView, Text, View } from 'react-native' -import { SafeAreaView } from 'react-native-safe-area-context' - -import { KeyRingThemeNames } from '@/constants' -import { themes } from '@/theme' - -const Button = components.buttons.Button.default -const ButtonType = components.buttons.Button.ButtonType - -storiesOf('Button', module) - //.addDecorator((getStory) => {getStory()}) - .add('All', () => { - const items = [] - for (const buttonType of [ButtonType.Primary, ButtonType.Secondary, ButtonType.Critical]) { - let title = 'Primary' - switch (buttonType) { - case ButtonType.Secondary: - title = 'Secondary' - break - case ButtonType.Critical: - title = 'Critical' - break - } - for (const enabled of [true, false]) { - items.push( - - {title} (enabled={`${enabled}`}) - - ) - items.push(