diff --git a/.vscode/settings.json b/.vscode/settings.json new file mode 100644 index 00000000..e0f15db2 --- /dev/null +++ b/.vscode/settings.json @@ -0,0 +1,3 @@ +{ + "java.configuration.updateBuildConfiguration": "automatic" +} \ No newline at end of file diff --git a/package.json b/package.json index b90d909a..4aa912c0 100644 --- a/package.json +++ b/package.json @@ -57,6 +57,10 @@ "@aries-framework/react-hooks": "patch:@aries-framework/react-hooks@npm:0.4.2#./.yarn/patches/@aries-framework-react-hooks-npm-0.4.2-84b7eb8764.patch" }, "dependencies": { + "lottie-react-native": "^6.6.0", + "react-native-ble-manager": "^11.5.3", + "react-native-ble-plx": "^3.1.2", + "react-native-maps": "^1.15.4", "react-native-qrcode-svg": "^6.2.0", "react-native-svg": "^14.1.0" } diff --git a/packages/legacy/app/android/app/build.gradle b/packages/legacy/app/android/app/build.gradle index 9dce9ed5..ec1d11a6 100644 --- a/packages/legacy/app/android/app/build.gradle +++ b/packages/legacy/app/android/app/build.gradle @@ -143,7 +143,23 @@ dependencies { } else { implementation jscFlavor } + implementation 'com.polidea.rxandroidble2:dagger-library-shadow:1.17.2' + implementation 'org.reactivestreams:reactive-streams:1.0.3' + implementation 'io.reactivex.rxjava2:rxjava:2.2.17' + implementation 'com.jakewharton.rxrelay2:rxrelay:2.1.1' + implementation 'com.polidea.rxandroidble2:rxandroidble:1.17.2' } apply from: project(':react-native-config').projectDir.getPath() + "/dotenv.gradle" apply from: file("../../node_modules/@react-native-community/cli-platform-android/native_modules.gradle"); applyNativeModulesAppBuildGradle(project) + +tasks.withType(JavaCompile) { + options.compilerArgs << "-Xlint:unchecked" << "-Xlint:deprecation" +} + +// Explicitly declare the dependency between lintAnalyzeDebug and copyReactNativeVectorIconFonts +tasks.whenTaskAdded { task -> + if (task.name.startsWith("lintAnalyze")) { + task.dependsOn("copyReactNativeVectorIconFonts") + } +} diff --git a/packages/legacy/app/android/app/src/main/AndroidManifest.xml b/packages/legacy/app/android/app/src/main/AndroidManifest.xml index 8685f74d..bf0bc061 100644 --- a/packages/legacy/app/android/app/src/main/AndroidManifest.xml +++ b/packages/legacy/app/android/app/src/main/AndroidManifest.xml @@ -1,6 +1,22 @@ + xmlns:tools="http://schemas.android.com/tools" + package="com.ariesbifold"> + + + + + + + + + + + + @@ -9,25 +25,27 @@ - - - - - - + android:icon="@mipmap/basic_swish" + android:allowBackup="false" + android:resizeableActivity="false" + android:theme="@style/AppTheme" + android:usesCleartextTraffic="true" + tools:replace="android:label, android:icon, android:allowBackup, android:resizeableActivity, android:theme, android:usesCleartextTraffic"> + + + + + + diff --git a/packages/legacy/app/android/app/src/main/java/com/ariesbifold/BleAdvertiseModule.java b/packages/legacy/app/android/app/src/main/java/com/ariesbifold/BleAdvertiseModule.java new file mode 100644 index 00000000..73a36b7a --- /dev/null +++ b/packages/legacy/app/android/app/src/main/java/com/ariesbifold/BleAdvertiseModule.java @@ -0,0 +1,312 @@ +package com.ariesbifold; + +import com.facebook.react.common.StandardCharsets; +import com.facebook.react.bridge.*; +import com.facebook.react.modules.core.DeviceEventManagerModule; + +import android.bluetooth.BluetoothGattCharacteristic; +import android.bluetooth.BluetoothGattServer; +import android.bluetooth.BluetoothGattServerCallback; +import android.bluetooth.BluetoothGattService; +import android.content.Context; +import android.util.Log; +import android.bluetooth.BluetoothAdapter; +import android.bluetooth.BluetoothManager; +import android.bluetooth.le.AdvertiseCallback; +import android.bluetooth.le.AdvertiseData; +import android.bluetooth.le.AdvertiseSettings; +import android.bluetooth.le.BluetoothLeAdvertiser; +import android.content.BroadcastReceiver; +import android.content.Intent; +import android.content.IntentFilter; +import android.os.ParcelUuid; + +import com.facebook.react.bridge.WritableMap; +import com.facebook.react.bridge.Arguments; + +import java.util.UUID; +import java.util.HashMap; +import java.util.Map; +import java.lang.Object; +import java.util.Hashtable; +import java.util.Set; + +public class BleAdvertiseModule extends ReactContextBaseJavaModule { + private static final UUID CHARACTERISTIC_UUID = UUID.fromString("d918d942-8516-4165-922f-dd6823d32b2f"); + public static final String TAG = "BleAdvertise"; + private BluetoothManager mBluetoothManager; + private BluetoothAdapter mBluetoothAdapter; + private BluetoothGattServer gattServer; + private static Hashtable mAdvertiserList; + private static Hashtable mAdvertiserCallbackList; + private int companyId; + private Boolean mObservedState; + + //Constructor + public BleAdvertiseModule(ReactApplicationContext reactContext) { + super(reactContext); + + mAdvertiserList = new Hashtable(); + mAdvertiserCallbackList = new Hashtable(); + + mBluetoothManager = (BluetoothManager) reactContext.getApplicationContext() + .getSystemService(Context.BLUETOOTH_SERVICE); + if (mBluetoothManager != null) { + mBluetoothAdapter = mBluetoothManager.getAdapter(); + } + + if (mBluetoothAdapter != null) { + mObservedState = mBluetoothAdapter.isEnabled(); + } + + this.companyId = 0x0000; + + IntentFilter filter = new IntentFilter(BluetoothAdapter.ACTION_STATE_CHANGED); + reactContext.registerReceiver(mReceiver, filter); + } + + private final BluetoothGattServerCallback gattServerCallback = new BluetoothGattServerCallback() { + @Override + public void onCharacteristicWriteRequest(android.bluetooth.BluetoothDevice device, int requestId, BluetoothGattCharacteristic characteristic, boolean preparedWrite, boolean responseNeeded, int offset, byte[] value) { + if (CHARACTERISTIC_UUID.equals(characteristic.getUuid())) { + characteristic.setValue(value); + if (responseNeeded) { + gattServer.sendResponse(device, requestId, android.bluetooth.BluetoothGatt.GATT_SUCCESS, offset, value); + } + WritableMap map = Arguments.createMap(); + map.putString("data", new String(value, StandardCharsets.UTF_8)); + Log.d(TAG, "data:" + value + "_________" + new String(value, StandardCharsets.UTF_8)); + sendEvent("onRead", map); + } + } + }; + + @Override + public String getName() { + return "BleAdvertise"; + } + + @Override + public Map getConstants() { + final Map constants = new HashMap<>(); + constants.put("ADVERTISE_MODE_BALANCED", AdvertiseSettings.ADVERTISE_MODE_BALANCED); + constants.put("ADVERTISE_MODE_LOW_LATENCY", AdvertiseSettings.ADVERTISE_MODE_LOW_LATENCY); + constants.put("ADVERTISE_MODE_LOW_POWER", AdvertiseSettings.ADVERTISE_MODE_LOW_POWER); + constants.put("ADVERTISE_TX_POWER_HIGH", AdvertiseSettings.ADVERTISE_TX_POWER_HIGH); + constants.put("ADVERTISE_TX_POWER_LOW", AdvertiseSettings.ADVERTISE_TX_POWER_LOW); + constants.put("ADVERTISE_TX_POWER_MEDIUM", AdvertiseSettings.ADVERTISE_TX_POWER_MEDIUM); + constants.put("ADVERTISE_TX_POWER_ULTRA_LOW", AdvertiseSettings.ADVERTISE_TX_POWER_ULTRA_LOW); + + return constants; + } + + @ReactMethod + public void setCompanyId(int companyId) { + this.companyId = companyId; + } + + @ReactMethod + public void broadcast(String uid, String cuid, ReadableMap options, Promise promise) { + ReactApplicationContext reactContext = getReactApplicationContext(); + + if (companyId == 0x0000) { + Log.w("BleAdvertiseModule", "Invalid company id"); + promise.reject("Invalid company id"); + return; + } + + if (mBluetoothAdapter == null) { + Log.w("BleAdvertiseModule", "mBluetoothAdapter unavailable"); + promise.reject("mBluetoothAdapter unavailable"); + return; + } + + if (mObservedState != null && !mObservedState) { + Log.w("BleAdvertiseModule", "Bluetooth disabled"); + promise.reject("Bluetooth disabled"); + return; + } + + BluetoothGattService service = new BluetoothGattService(UUID.fromString(uid), BluetoothGattService.SERVICE_TYPE_PRIMARY); + BluetoothGattCharacteristic characteristic = new BluetoothGattCharacteristic( + UUID.fromString(cuid), + BluetoothGattCharacteristic.PROPERTY_READ | BluetoothGattCharacteristic.PROPERTY_WRITE, + BluetoothGattCharacteristic.PERMISSION_READ | BluetoothGattCharacteristic.PERMISSION_WRITE + ); + service.addCharacteristic(characteristic); + gattServer = mBluetoothManager.openGattServer(reactContext, gattServerCallback); + gattServer.addService(service); + + BluetoothLeAdvertiser tempAdvertiser; + AdvertiseCallback tempCallback; + + if (mAdvertiserList.containsKey(uid)) { + tempAdvertiser = mAdvertiserList.remove(uid); + tempCallback = mAdvertiserCallbackList.remove(uid); + + tempAdvertiser.stopAdvertising(tempCallback); + } else { + tempAdvertiser = mBluetoothAdapter.getBluetoothLeAdvertiser(); + tempCallback = new BleAdvertiseModule.SimpleAdvertiseCallback(promise); + } + + if (tempAdvertiser == null) { + Log.w("BleAdvertiseModule", "Advertiser Not Available unavailable"); + promise.reject("Advertiser unavailable on this device"); + return; + } + + AdvertiseSettings settings = buildAdvertiseSettings(); + AdvertiseData data = buildAdvertiseData(ParcelUuid.fromString(uid), options); + + tempAdvertiser.startAdvertising(settings, data, tempCallback); + + mAdvertiserList.put(uid, tempAdvertiser); + mAdvertiserCallbackList.put(uid, tempCallback); + } + + @ReactMethod + public void stopBroadcast(final Promise promise) { + Log.w("BleAdvertiseModule", "Stop Broadcast call"); + + if (mBluetoothAdapter == null) { + Log.w("BleAdvertiseModule", "mBluetoothAdapter unavailable"); + promise.reject("mBluetoothAdapter unavailable"); + return; + } + + if (mObservedState != null && !mObservedState) { + Log.w("BleAdvertiseModule", "Bluetooth disabled"); + promise.reject("Bluetooth disabled"); + return; + } + + WritableArray promiseArray = Arguments.createArray(); + + Set keys = mAdvertiserList.keySet(); + for (String key : keys) { + BluetoothLeAdvertiser tempAdvertiser = mAdvertiserList.remove(key); + AdvertiseCallback tempCallback = mAdvertiserCallbackList.remove(key); + if (tempAdvertiser != null) { + tempAdvertiser.stopAdvertising(tempCallback); + promiseArray.pushString(key); + } + } + + promise.resolve(promiseArray); + } + + @ReactMethod + public void addListener(String eventName) { + + } + + @ReactMethod + public void removeListeners(Integer count) { + + } + + private AdvertiseSettings buildAdvertiseSettings() { + AdvertiseSettings.Builder settingsBuilder = new AdvertiseSettings.Builder() + .setAdvertiseMode(AdvertiseSettings.ADVERTISE_MODE_LOW_LATENCY) + .setTxPowerLevel(AdvertiseSettings.ADVERTISE_TX_POWER_HIGH) + .setConnectable(true); + + return settingsBuilder.build(); + } + + private AdvertiseData buildAdvertiseData(ParcelUuid uuid, ReadableMap options) { + AdvertiseData.Builder dataBuilder = new AdvertiseData.Builder() + .setIncludeDeviceName(true) + .setIncludeTxPowerLevel(false) + .addServiceUuid(uuid); + + return dataBuilder.build(); + } + + private class SimpleAdvertiseCallback extends AdvertiseCallback { + Promise promise; + + public SimpleAdvertiseCallback () { + } + + public SimpleAdvertiseCallback (Promise promise) { + this.promise = promise; + } + + @Override + public void onStartFailure(int errorCode) { + super.onStartFailure(errorCode); + Log.i(TAG, "Advertising failed with code "+ errorCode); + + if (promise == null) return; + + switch (errorCode) { + case ADVERTISE_FAILED_FEATURE_UNSUPPORTED: + promise.reject("This feature is not supported on this platform."); break; + case ADVERTISE_FAILED_TOO_MANY_ADVERTISERS: + promise.reject("Failed to start advertising because no advertising instance is available."); break; + case ADVERTISE_FAILED_ALREADY_STARTED: + promise.reject("Failed to start advertising as the advertising is already started."); break; + case ADVERTISE_FAILED_DATA_TOO_LARGE: + promise.reject("Failed to start advertising as the advertise data to be broadcasted is larger than 31 bytes."); break; + case ADVERTISE_FAILED_INTERNAL_ERROR: + promise.reject("Operation failed due to an internal error."); break; + } + } + + @Override + public void onStartSuccess(AdvertiseSettings settingsInEffect) { + super.onStartSuccess(settingsInEffect); + Log.i(TAG, "Advertising successful"); + + if (promise == null) return; + promise.resolve(settingsInEffect.toString()); + } + } + + private final BroadcastReceiver mReceiver = new BroadcastReceiver() { + @Override + public void onReceive(Context context, Intent intent) { + final String action = intent.getAction(); + + if (action.equals(BluetoothAdapter.ACTION_STATE_CHANGED)) { + final int state = intent.getIntExtra(BluetoothAdapter.EXTRA_STATE, BluetoothAdapter.ERROR); + final int prevState = intent.getIntExtra(BluetoothAdapter.EXTRA_PREVIOUS_STATE, BluetoothAdapter.ERROR); + + Log.d(TAG, String.valueOf(state)); + switch (state) { + case BluetoothAdapter.STATE_OFF: + mObservedState = false; + break; + case BluetoothAdapter.STATE_TURNING_OFF: + mObservedState = false; + break; + case BluetoothAdapter.STATE_ON: + mObservedState = true; + break; + case BluetoothAdapter.STATE_TURNING_ON: + mObservedState = true; + break; + } + + // Only send enabled when fully ready. Turning on and Turning OFF are seen as disabled. + if (state == BluetoothAdapter.STATE_ON && prevState != BluetoothAdapter.STATE_ON) { + WritableMap params = Arguments.createMap(); + params.putBoolean("enabled", true); + sendEvent("onBTStatusChange", params); + } else if (state != BluetoothAdapter.STATE_ON && prevState == BluetoothAdapter.STATE_ON ) { + WritableMap params = Arguments.createMap(); + params.putBoolean("enabled", false); + sendEvent("onBTStatusChange", params); + } + } + } + }; + + private void sendEvent(String eventName, WritableMap params) { + getReactApplicationContext() + .getJSModule(DeviceEventManagerModule.RCTDeviceEventEmitter.class) + .emit(eventName, params); + } +} diff --git a/packages/legacy/app/android/app/src/main/java/com/ariesbifold/BleAdvertisePackage.java b/packages/legacy/app/android/app/src/main/java/com/ariesbifold/BleAdvertisePackage.java new file mode 100644 index 00000000..19534116 --- /dev/null +++ b/packages/legacy/app/android/app/src/main/java/com/ariesbifold/BleAdvertisePackage.java @@ -0,0 +1,26 @@ +package com.ariesbifold; + +import java.util.Arrays; +import java.util.Collections; +import java.util.List; +import java.util.ArrayList; +import com.facebook.react.ReactPackage; +import com.facebook.react.bridge.JavaScriptModule; +import com.facebook.react.bridge.NativeModule; +import com.facebook.react.bridge.ReactApplicationContext; +import com.facebook.react.uimanager.ViewManager; + +public class BleAdvertisePackage implements ReactPackage { + + @Override + public List createNativeModules(ReactApplicationContext reactContext) { + List modules = new ArrayList<>(); + modules.add(new BleAdvertiseModule(reactContext)); + return modules; + } + + @Override + public List createViewManagers(ReactApplicationContext reactContext) { + return Arrays.asList(); + } +} diff --git a/packages/legacy/app/android/app/src/main/java/com/ariesbifold/MainActivity.java b/packages/legacy/app/android/app/src/main/java/com/ariesbifold/MainActivity.java index 8c147abc..9e5fb122 100644 --- a/packages/legacy/app/android/app/src/main/java/com/ariesbifold/MainActivity.java +++ b/packages/legacy/app/android/app/src/main/java/com/ariesbifold/MainActivity.java @@ -27,7 +27,7 @@ public void onConfigurationChanged(Configuration newConfig) { */ @Override protected String getMainComponentName() { - return "aries-bifold"; + return "fhwa-wallet"; } /** diff --git a/packages/legacy/app/android/app/src/main/java/com/ariesbifold/MainApplication.java b/packages/legacy/app/android/app/src/main/java/com/ariesbifold/MainApplication.java index edd91dfd..0f81905b 100644 --- a/packages/legacy/app/android/app/src/main/java/com/ariesbifold/MainApplication.java +++ b/packages/legacy/app/android/app/src/main/java/com/ariesbifold/MainApplication.java @@ -10,6 +10,7 @@ import com.facebook.soloader.SoLoader; import java.util.List; import org.wonday.orientation.OrientationActivityLifecycle; +import com.ariesbifold.BleAdvertisePackage; public class MainApplication extends Application implements ReactApplication { @@ -24,6 +25,7 @@ public boolean getUseDeveloperSupport() { protected List getPackages() { @SuppressWarnings("UnnecessaryLocalVariable") List packages = new PackageList(this).getPackages(); + packages.add(new BleAdvertisePackage()); // Packages that cannot be autolinked yet can be added manually here, for example: // packages.add(new MyReactNativePackage()); return packages; diff --git a/packages/legacy/app/android/build.gradle b/packages/legacy/app/android/build.gradle index 736e0c37..d87845d4 100644 --- a/packages/legacy/app/android/build.gradle +++ b/packages/legacy/app/android/build.gradle @@ -37,11 +37,11 @@ allprojects { } subprojects { configurations.all { - it.resolutionStrategy.activateDependencyLocking() + // it.resolutionStrategy.activateDependencyLocking() } } dependencyLocking { - lockAllConfigurations() + // lockAllConfigurations() } diff --git a/packages/legacy/app/android/settings.gradle b/packages/legacy/app/android/settings.gradle index 25abc3d7..a04584fb 100644 --- a/packages/legacy/app/android/settings.gradle +++ b/packages/legacy/app/android/settings.gradle @@ -1,4 +1,9 @@ -rootProject.name = 'aries-bifold' +rootProject.name = 'fhwa-wallet' apply from: file("../node_modules/@react-native-community/cli-platform-android/native_modules.gradle"); applyNativeModulesSettingsGradle(settings) include ':app' -includeBuild('../node_modules/@react-native/gradle-plugin') \ No newline at end of file +includeBuild('../node_modules/@react-native/gradle-plugin') +include ':react-native-onesignal' +project(':react-native-onesignal').projectDir = new File(rootProject.projectDir, '../node_modules/react-native-onesignal/android') + +include ':react-native-maps' +project(':react-native-maps').projectDir = new File(rootProject.projectDir, '../node_modules/react-native-maps/android') diff --git a/packages/legacy/app/app.json b/packages/legacy/app/app.json index 97ddb286..a5e16238 100644 --- a/packages/legacy/app/app.json +++ b/packages/legacy/app/app.json @@ -1,4 +1,4 @@ { - "name": "aries-bifold", - "displayName": "Aries Bifold" + "name": "fhwa-wallet", + "displayName": "FHWA Wallet" } diff --git a/packages/legacy/app/ios/AriesBifold-Bridging-Header.h b/packages/legacy/app/ios/AriesBifold-Bridging-Header.h index 1b2cb5d6..4380265e 100644 --- a/packages/legacy/app/ios/AriesBifold-Bridging-Header.h +++ b/packages/legacy/app/ios/AriesBifold-Bridging-Header.h @@ -2,3 +2,5 @@ // Use this file to import your target's public headers that you would like to expose to Swift. // +#import "React/RCTBridgeModule.h" +#import diff --git a/packages/legacy/app/ios/AriesBifoldTests-Bridging-Header.h b/packages/legacy/app/ios/AriesBifoldTests-Bridging-Header.h new file mode 100644 index 00000000..1b2cb5d6 --- /dev/null +++ b/packages/legacy/app/ios/AriesBifoldTests-Bridging-Header.h @@ -0,0 +1,4 @@ +// +// Use this file to import your target's public headers that you would like to expose to Swift. +// + diff --git a/packages/legacy/app/ios/BLEPeripheralManager.h b/packages/legacy/app/ios/BLEPeripheralManager.h new file mode 100644 index 00000000..75b08dbd --- /dev/null +++ b/packages/legacy/app/ios/BLEPeripheralManager.h @@ -0,0 +1,18 @@ +// +// BLEPeripheralManager.h +// ariesbifold +// +// Created by amishfaldu on 6/7/24. +// + +//#import +#import +#import + +NS_ASSUME_NONNULL_BEGIN + +@interface BleAdvertise : RCTEventEmitter + +@end + +NS_ASSUME_NONNULL_END diff --git a/packages/legacy/app/ios/BLEPeripheralManager.m b/packages/legacy/app/ios/BLEPeripheralManager.m new file mode 100644 index 00000000..f442e76b --- /dev/null +++ b/packages/legacy/app/ios/BLEPeripheralManager.m @@ -0,0 +1,15 @@ +// +// BLEPeripheralManager.m +// ariesbifold +// +// Created by amishfaldu on 6/7/24. +// + +#import +#import + +@interface RCT_EXTERN_MODULE(BleAdvertise, NSObject) +RCT_EXTERN_METHOD(setCompanyId:(NSInteger *)companyId) +RCT_EXTERN_METHOD(broadcast:(NSString *)serviceUUID characteristicUUID:(NSString *)characteristicUUID config:(NSDictionary *)config resolver:(RCTPromiseResolveBlock)resolve rejecter:(RCTPromiseRejectBlock)reject) +RCT_EXTERN_METHOD(stopBroadcast) +@end diff --git a/packages/legacy/app/ios/BLEPeripheralManager.swift b/packages/legacy/app/ios/BLEPeripheralManager.swift new file mode 100644 index 00000000..689dc560 --- /dev/null +++ b/packages/legacy/app/ios/BLEPeripheralManager.swift @@ -0,0 +1,132 @@ +// +// BLEPeripheralManager.swift +// ariesbifold +// +// Created by amishfaldu on 6/7/24. +// + +import Foundation +import CoreBluetooth +import UIKit + +@objc(BleAdvertise) +class BleAdvertise: RCTEventEmitter, CBPeripheralManagerDelegate { + + var peripheralManager: CBPeripheralManager! + var customService: CBMutableService! + + // Define your Service and Characteristic UUIDs + var serviceUUID: CBUUID! + var characteristicUUID: CBUUID! + var deviceName: String! + + var startAdvertisePromise: RCTPromiseResolveBlock? + var startAdvertiseReject: RCTPromiseRejectBlock? + +// @objc +// static var sharedInstance: BleAdvertise? + + override init() { + deviceName = UIDevice.current.name // Fetch the device name + super.init() + peripheralManager = CBPeripheralManager(delegate: self, queue: nil) +// BleAdvertise.sharedInstance = self + } + + func peripheralManagerDidUpdateState(_ peripheral: CBPeripheralManager) { + if peripheral.state == .poweredOn { + print("Bluetooth is powered on and ready to use") +// startAdvertising() + } else { + print("Bluetooth is not available") + } + } + + @objc func setCompanyId(_ companyId: Int64) { + + } + + @objc(broadcast:characteristicUUID:config:resolver:rejecter:) + func broadcast(serviceUUIDString: String, characteristicUUIDString: String, config: NSDictionary, resolve: @escaping RCTPromiseResolveBlock, reject: @escaping RCTPromiseRejectBlock) { + serviceUUID = CBUUID(string: serviceUUIDString) + characteristicUUID = CBUUID(string: characteristicUUIDString) + let characteristic = CBMutableCharacteristic( + type: characteristicUUID, + properties: [.read, .write, .notify], + value: nil, + permissions: [.readable, .writeable] + ) + + customService = CBMutableService(type: serviceUUID, primary: true) + customService.characteristics = [characteristic] + + peripheralManager.add(customService) + + let advertisementData: [String: Any] = [ + CBAdvertisementDataServiceUUIDsKey: [serviceUUID], + CBAdvertisementDataLocalNameKey: deviceName + ] + peripheralManager.startAdvertising(advertisementData) + + print("Started advertising service with UUID: \(String(describing: serviceUUID))") + } + + @objc(stopBroadcast) + func stopBroadcast() { + peripheralManager.stopAdvertising() + print("Stopped advertising") + } + + func peripheralManager(_ peripheral: CBPeripheralManager, didAdd service: CBService, error: Error?) { + if let error = error { + print("Error adding service: \(error.localizedDescription)") + } else { + print("Service added successfully") + } + } + + func peripheralManagerDidStartAdvertising(_ peripheral: CBPeripheralManager, error: Error?) { + if let error = error { + print("Error starting advertising: \(error.localizedDescription)") + } else { + print("Started advertising successfully") + } + } + + func peripheralManager(_ peripheral: CBPeripheralManager, didReceiveRead request: CBATTRequest) { + // Handle read request + if request.characteristic.uuid == characteristicUUID { + // request.value = characteristic.value + peripheralManager.respond(to: request, withResult: .success) + } + } + + func peripheralManager(_ peripheral: CBPeripheralManager, didReceiveWrite requests: [CBATTRequest]) { + // Handle write requests + for request in requests { + if request.characteristic.uuid == characteristicUUID { + if let value = request.value { +// characteristic.value = value + // Notify React Native about the received data + sendEvent(withName: "onRead", body: ["data": String(decoding:value, as: UTF8.self)]) + peripheralManager.respond(to: request, withResult: .success) + } + } + } + } + + override func supportedEvents() -> [String]! { + return ["onRead"] + } + + override class func requiresMainQueueSetup() -> Bool { + return true + } + + } + + extension Data { + var hexString: String { + return map { String(format: "%02x", $0) }.joined() + } + } diff --git a/packages/legacy/app/ios/Media.xcassets/AppIcon.appiconset/1024.png b/packages/legacy/app/ios/Media.xcassets/AppIcon.appiconset/1024.png new file mode 100644 index 00000000..140cec68 Binary files /dev/null and b/packages/legacy/app/ios/Media.xcassets/AppIcon.appiconset/1024.png differ diff --git a/packages/legacy/app/ios/Media.xcassets/AppIcon.appiconset/120 1.png b/packages/legacy/app/ios/Media.xcassets/AppIcon.appiconset/120 1.png new file mode 100644 index 00000000..82fbded6 Binary files /dev/null and b/packages/legacy/app/ios/Media.xcassets/AppIcon.appiconset/120 1.png differ diff --git a/packages/legacy/app/ios/Media.xcassets/AppIcon.appiconset/120.png b/packages/legacy/app/ios/Media.xcassets/AppIcon.appiconset/120.png new file mode 100644 index 00000000..82fbded6 Binary files /dev/null and b/packages/legacy/app/ios/Media.xcassets/AppIcon.appiconset/120.png differ diff --git a/packages/legacy/app/ios/Media.xcassets/AppIcon.appiconset/180.png b/packages/legacy/app/ios/Media.xcassets/AppIcon.appiconset/180.png new file mode 100644 index 00000000..2e73d08e Binary files /dev/null and b/packages/legacy/app/ios/Media.xcassets/AppIcon.appiconset/180.png differ diff --git a/packages/legacy/app/ios/Media.xcassets/AppIcon.appiconset/40.png b/packages/legacy/app/ios/Media.xcassets/AppIcon.appiconset/40.png new file mode 100644 index 00000000..5f5e179b Binary files /dev/null and b/packages/legacy/app/ios/Media.xcassets/AppIcon.appiconset/40.png differ diff --git a/packages/legacy/app/ios/Media.xcassets/AppIcon.appiconset/58.png b/packages/legacy/app/ios/Media.xcassets/AppIcon.appiconset/58.png new file mode 100644 index 00000000..9b679956 Binary files /dev/null and b/packages/legacy/app/ios/Media.xcassets/AppIcon.appiconset/58.png differ diff --git a/packages/legacy/app/ios/Media.xcassets/AppIcon.appiconset/60.png b/packages/legacy/app/ios/Media.xcassets/AppIcon.appiconset/60.png new file mode 100644 index 00000000..4a211c22 Binary files /dev/null and b/packages/legacy/app/ios/Media.xcassets/AppIcon.appiconset/60.png differ diff --git a/packages/legacy/app/ios/Media.xcassets/AppIcon.appiconset/80.png b/packages/legacy/app/ios/Media.xcassets/AppIcon.appiconset/80.png new file mode 100644 index 00000000..27951d49 Binary files /dev/null and b/packages/legacy/app/ios/Media.xcassets/AppIcon.appiconset/80.png differ diff --git a/packages/legacy/app/ios/Media.xcassets/AppIcon.appiconset/87.png b/packages/legacy/app/ios/Media.xcassets/AppIcon.appiconset/87.png new file mode 100644 index 00000000..d3865e3d Binary files /dev/null and b/packages/legacy/app/ios/Media.xcassets/AppIcon.appiconset/87.png differ diff --git a/packages/legacy/app/ios/Media.xcassets/AppIcon.appiconset/Contents.json b/packages/legacy/app/ios/Media.xcassets/AppIcon.appiconset/Contents.json index 866813af..fd81fca2 100644 --- a/packages/legacy/app/ios/Media.xcassets/AppIcon.appiconset/Contents.json +++ b/packages/legacy/app/ios/Media.xcassets/AppIcon.appiconset/Contents.json @@ -1,62 +1,62 @@ { - "images": [ + "images" : [ { - "filename": "Icon-20@2x.png", - "idiom": "iphone", - "scale": "2x", - "size": "20x20" + "filename" : "40.png", + "idiom" : "iphone", + "scale" : "2x", + "size" : "20x20" }, { - "filename": "Icon-20@3x.png", - "idiom": "iphone", - "scale": "3x", - "size": "20x20" + "filename" : "60.png", + "idiom" : "iphone", + "scale" : "3x", + "size" : "20x20" }, { - "filename": "Icon-29@2x.png", - "idiom": "iphone", - "scale": "2x", - "size": "29x29" + "filename" : "58.png", + "idiom" : "iphone", + "scale" : "2x", + "size" : "29x29" }, { - "filename": "Icon-29@3x.png", - "idiom": "iphone", - "scale": "3x", - "size": "29x29" + "filename" : "87.png", + "idiom" : "iphone", + "scale" : "3x", + "size" : "29x29" }, { - "filename": "Icon-40@2x.png", - "idiom": "iphone", - "scale": "2x", - "size": "40x40" + "filename" : "80.png", + "idiom" : "iphone", + "scale" : "2x", + "size" : "40x40" }, { - "filename": "Icon-40@3x.png", - "idiom": "iphone", - "scale": "3x", - "size": "40x40" + "filename" : "120 1.png", + "idiom" : "iphone", + "scale" : "3x", + "size" : "40x40" }, { - "filename": "Icon-60@2x.png", - "idiom": "iphone", - "scale": "2x", - "size": "60x60" + "filename" : "120.png", + "idiom" : "iphone", + "scale" : "2x", + "size" : "60x60" }, { - "filename": "Icon-60@3x-1.png", - "idiom": "iphone", - "scale": "3x", - "size": "60x60" + "filename" : "180.png", + "idiom" : "iphone", + "scale" : "3x", + "size" : "60x60" }, { - "filename": "iTunesArtwork.png", - "idiom": "ios-marketing", - "scale": "1x", - "size": "1024x1024" + "filename" : "1024.png", + "idiom" : "ios-marketing", + "scale" : "1x", + "size" : "1024x1024" } ], - "info": { - "author": "xcode", - "version": 1 + "info" : { + "author" : "xcode", + "version" : 1 } } diff --git a/packages/legacy/app/ios/Media.xcassets/AppIcon.appiconset/Icon-20@2x.png b/packages/legacy/app/ios/Media.xcassets/AppIcon.appiconset/Icon-20@2x.png deleted file mode 100644 index 8d36cd84..00000000 Binary files a/packages/legacy/app/ios/Media.xcassets/AppIcon.appiconset/Icon-20@2x.png and /dev/null differ diff --git a/packages/legacy/app/ios/Media.xcassets/AppIcon.appiconset/Icon-20@3x.png b/packages/legacy/app/ios/Media.xcassets/AppIcon.appiconset/Icon-20@3x.png deleted file mode 100644 index 69e1f04e..00000000 Binary files a/packages/legacy/app/ios/Media.xcassets/AppIcon.appiconset/Icon-20@3x.png and /dev/null differ diff --git a/packages/legacy/app/ios/Media.xcassets/AppIcon.appiconset/Icon-29@2x.png b/packages/legacy/app/ios/Media.xcassets/AppIcon.appiconset/Icon-29@2x.png deleted file mode 100644 index a0c6eac2..00000000 Binary files a/packages/legacy/app/ios/Media.xcassets/AppIcon.appiconset/Icon-29@2x.png and /dev/null differ diff --git a/packages/legacy/app/ios/Media.xcassets/AppIcon.appiconset/Icon-29@3x.png b/packages/legacy/app/ios/Media.xcassets/AppIcon.appiconset/Icon-29@3x.png deleted file mode 100644 index 6ae6ac4a..00000000 Binary files a/packages/legacy/app/ios/Media.xcassets/AppIcon.appiconset/Icon-29@3x.png and /dev/null differ diff --git a/packages/legacy/app/ios/Media.xcassets/AppIcon.appiconset/Icon-40@2x.png b/packages/legacy/app/ios/Media.xcassets/AppIcon.appiconset/Icon-40@2x.png deleted file mode 100644 index 9154036d..00000000 Binary files a/packages/legacy/app/ios/Media.xcassets/AppIcon.appiconset/Icon-40@2x.png and /dev/null differ diff --git a/packages/legacy/app/ios/Media.xcassets/AppIcon.appiconset/Icon-40@3x.png b/packages/legacy/app/ios/Media.xcassets/AppIcon.appiconset/Icon-40@3x.png deleted file mode 100644 index a00ec476..00000000 Binary files a/packages/legacy/app/ios/Media.xcassets/AppIcon.appiconset/Icon-40@3x.png and /dev/null differ diff --git a/packages/legacy/app/ios/Media.xcassets/AppIcon.appiconset/Icon-60@2x.png b/packages/legacy/app/ios/Media.xcassets/AppIcon.appiconset/Icon-60@2x.png deleted file mode 100644 index a00ec476..00000000 Binary files a/packages/legacy/app/ios/Media.xcassets/AppIcon.appiconset/Icon-60@2x.png and /dev/null differ diff --git a/packages/legacy/app/ios/Media.xcassets/AppIcon.appiconset/Icon-60@3x-1.png b/packages/legacy/app/ios/Media.xcassets/AppIcon.appiconset/Icon-60@3x-1.png deleted file mode 100644 index 4c153938..00000000 Binary files a/packages/legacy/app/ios/Media.xcassets/AppIcon.appiconset/Icon-60@3x-1.png and /dev/null differ diff --git a/packages/legacy/app/ios/Media.xcassets/AppIcon.appiconset/iTunesArtwork.png b/packages/legacy/app/ios/Media.xcassets/AppIcon.appiconset/iTunesArtwork.png deleted file mode 100644 index 6614f667..00000000 Binary files a/packages/legacy/app/ios/Media.xcassets/AppIcon.appiconset/iTunesArtwork.png and /dev/null differ diff --git a/packages/legacy/app/ios/Podfile b/packages/legacy/app/ios/Podfile index 54fc58f6..5de716eb 100644 --- a/packages/legacy/app/ios/Podfile +++ b/packages/legacy/app/ios/Podfile @@ -1,9 +1,34 @@ source 'https://cdn.cocoapods.org' require_relative '../node_modules/react-native/scripts/react_native_pods' +require_relative '../node_modules/react-native-permissions/scripts/setup' platform :ios, min_ios_version_supported prepare_react_native_project! +# ⬇️ uncomment wanted permissions +setup_permissions([ + # 'AppTrackingTransparency', + 'Bluetooth', + # 'Calendars', + # 'CalendarsWriteOnly', + 'Camera', + # 'Contacts', + 'FaceID', + # 'LocationAccuracy', + 'LocationAlways', + 'LocationWhenInUse', + # 'MediaLibrary', + # 'Microphone', + # 'Motion', + # 'Notifications', + # 'PhotoLibrary', + # 'PhotoLibraryAddOnly', + # 'Reminders', + # 'Siri', + # 'SpeechRecognition', + # 'StoreKit', +]) + # If you are using a `react-native-flipper` your iOS build will fail when `NO_FLIPPER=1` is set. # because `react-native-flipper` depends on (FlipperKit,...) that will be excluded # diff --git a/packages/legacy/app/ios/Podfile.lock b/packages/legacy/app/ios/Podfile.lock index d09fcb86..45d43cf4 100644 --- a/packages/legacy/app/ios/Podfile.lock +++ b/packages/legacy/app/ios/Podfile.lock @@ -29,6 +29,7 @@ PODS: - React-callinvoker - React-Core - libevent (2.1.12) + - MultiplatformBleAdapter (0.2.0) - RCT-Folly (2021.07.22.00): - boost - DoubleConversion @@ -329,13 +330,11 @@ PODS: - React-jsinspector (0.72.5) - React-logger (0.72.5): - glog - - react-native-camera (3.44.3): + - react-native-ble-manager (11.5.3): - React-Core - - react-native-camera/RCT (= 3.44.3) - - react-native-camera/RN (= 3.44.3) - - react-native-camera/RCT (3.44.3): - - React-Core - - react-native-camera/RN (3.44.3): + - react-native-ble-plx (3.1.2): + - MultiplatformBleAdapter (= 0.2.0) + - RCT-Folly (= 2021.07.22.00) - React-Core - react-native-config (1.5.0): - react-native-config/App (= 1.5.0) @@ -347,6 +346,8 @@ PODS: - React-Core - react-native-netinfo (9.3.7): - React-Core + - react-native-orientation-locker (1.6.0): + - React-Core - react-native-safe-area-context (3.4.1): - React-Core - react-native-splash-screen (3.3.0): @@ -483,37 +484,8 @@ PODS: - React-Core - RNLocalize (2.2.6): - React-Core - - RNPermissions (3.9.2): - - React-Core - - RNReanimated (3.5.4): - - DoubleConversion - - FBLazyVector - - glog - - hermes-engine - - RCT-Folly - - RCTRequired - - RCTTypeSafety - - React-callinvoker + - RNPermissions (4.1.5): - React-Core - - React-Core/DevSupport - - React-Core/RCTWebSocket - - React-CoreModules - - React-cxxreact - - React-hermes - - React-jsi - - React-jsiexecutor - - React-jsinspector - - React-RCTActionSheet - - React-RCTAnimation - - React-RCTAppDelegate - - React-RCTBlob - - React-RCTImage - - React-RCTLinking - - React-RCTNetwork - - React-RCTSettings - - React-RCTText - - ReactCommon/turbomodule/core - - Yoga - RNScreens (3.25.0): - React-Core - React-RCTImage @@ -522,6 +494,10 @@ PODS: - RNVectorIcons (10.0.0): - React-Core - SocketRocket (0.6.1) + - VisionCamera (3.6.16): + - React + - React-callinvoker + - React-Core - Yoga (1.14.0) DEPENDENCIES: @@ -551,11 +527,13 @@ DEPENDENCIES: - React-jsiexecutor (from `../node_modules/react-native/ReactCommon/jsiexecutor`) - React-jsinspector (from `../node_modules/react-native/ReactCommon/jsinspector`) - React-logger (from `../node_modules/react-native/ReactCommon/logger`) - - react-native-camera (from `../node_modules/react-native-camera`) + - react-native-ble-manager (from `../node_modules/react-native-ble-manager`) + - react-native-ble-plx (from `../node_modules/react-native-ble-plx`) - react-native-config (from `../node_modules/react-native-config`) - 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-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`) - react-native-splash-screen (from `../node_modules/react-native-splash-screen`) - react-native-tcp-socket (from `../node_modules/react-native-tcp-socket`) @@ -586,10 +564,10 @@ 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`) + - VisionCamera (from `../node_modules/react-native-vision-camera`) - Yoga (from `../node_modules/react-native/ReactCommon/yoga`) SPEC REPOS: @@ -598,6 +576,7 @@ SPEC REPOS: - CocoaAsyncSocket - fmt - libevent + - MultiplatformBleAdapter - SocketRocket EXTERNAL SOURCES: @@ -650,8 +629,10 @@ EXTERNAL SOURCES: :path: "../node_modules/react-native/ReactCommon/jsinspector" React-logger: :path: "../node_modules/react-native/ReactCommon/logger" - react-native-camera: - :path: "../node_modules/react-native-camera" + react-native-ble-manager: + :path: "../node_modules/react-native-ble-manager" + react-native-ble-plx: + :path: "../node_modules/react-native-ble-plx" react-native-config: :path: "../node_modules/react-native-config" react-native-encrypted-storage: @@ -660,6 +641,8 @@ EXTERNAL SOURCES: :path: "../node_modules/react-native-get-random-values" react-native-netinfo: :path: "../node_modules/@react-native-community/netinfo" + react-native-orientation-locker: + :path: "../node_modules/react-native-orientation-locker" react-native-safe-area-context: :path: "../node_modules/react-native-safe-area-context" react-native-splash-screen: @@ -720,14 +703,14 @@ 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: :path: "../node_modules/react-native-svg" RNVectorIcons: :path: "../node_modules/react-native-vector-icons" + VisionCamera: + :path: "../node_modules/react-native-vision-camera" Yoga: :path: "../node_modules/react-native/ReactCommon/yoga" @@ -745,6 +728,7 @@ SPEC CHECKSUMS: hermes-engine: f6cf92a471053245614d9d8097736f6337d5b86c indy-vdr: 85cd66089f151256581323440e78988891f4082e libevent: 4049cae6c81cdb3654a443be001fb9bdceff7913 + MultiplatformBleAdapter: b1fddd0d499b96b607e00f0faa8e60648343dc1d RCT-Folly: 424b8c9a7a0b9ab2886ffe9c3b041ef628fd4fb1 RCTRequired: df81ab637d35fac9e6eb94611cfd20f0feb05455 RCTTypeSafety: 4636e4a36c7c2df332bda6d59b19b41c443d4287 @@ -760,11 +744,13 @@ SPEC CHECKSUMS: React-jsiexecutor: ff70a72027dea5cc7d71cfcc6fad7f599f63987a React-jsinspector: aef73cbd43b70675f572214d10fa438c89bf11ba React-logger: 2e4aee3e11b3ec4fa6cfd8004610bbb3b8d6cca4 - react-native-camera: b8cc03e2feec0c04403d0998e37cf519d8fd4c6f + react-native-ble-manager: d63955f48a45306ae02b3d313ca46ad928a4645a + react-native-ble-plx: 669899d2fd4d360d541b05ce19c6ee77d95853bf react-native-config: 5330c8258265c1e5fdb8c009d2cabd6badd96727 react-native-encrypted-storage: db300a3f2f0aba1e818417c1c0a6be549038deb7 react-native-get-random-values: a6ea6a8a65dc93e96e24a11105b1a9c8cfe1d72a react-native-netinfo: 2517ad504b3d303e90d7a431b0fcaef76d207983 + react-native-orientation-locker: 4409c5b12b65f942e75449872b4f078b6f27af81 react-native-safe-area-context: 9e40fb181dac02619414ba1294d6c2a807056ab9 react-native-splash-screen: 4312f786b13a81b5169ef346d76d33bc0c6dc457 react-native-tcp-socket: e724380c910c2e704816ec817ed28f1342246ff7 @@ -794,14 +780,14 @@ SPEC CHECKSUMS: RNGestureHandler: a479ebd5ed4221a810967000735517df0d2db211 RNKeychain: ff836453cba46938e0e9e4c22e43d43fa2c90333 RNLocalize: d4b8af4e442d4bcca54e68fc687a2129b4d71a81 - RNPermissions: 7f93fea75d6ea684fe600b08e2c244098a49244b - RNReanimated: ab2e96c6d5591c3dfbb38a464f54c8d17fb34a87 + RNPermissions: 2ce48c298b55586f6ad873ddda0a5fe65d251e8d RNScreens: 85d3880b52d34db7b8eeebe2f1a0e807c05e69fa RNSVG: d7d7bc8229af3842c9cfc3a723c815a52cdd1105 RNVectorIcons: 8b5bb0fa61d54cd2020af4f24a51841ce365c7e9 SocketRocket: f32cd54efbe0f095c4d7594881e52619cfe80b17 + VisionCamera: b236f548d6507923857dade542c7e0a148ed3492 Yoga: 86fed2e4d425ee4c6eab3813ba1791101ee153c6 -PODFILE CHECKSUM: 702646d9563d22bf09e336926a5fb0e2d3239409 +PODFILE CHECKSUM: 4749f46ac279359c9f99a5af9e25e8db7aa3264c -COCOAPODS: 1.13.0 +COCOAPODS: 1.15.2 diff --git a/packages/legacy/app/ios/ariesbifold.xcodeproj/project.pbxproj b/packages/legacy/app/ios/ariesbifold.xcodeproj/project.pbxproj index 02181965..4b1b5fb8 100644 --- a/packages/legacy/app/ios/ariesbifold.xcodeproj/project.pbxproj +++ b/packages/legacy/app/ios/ariesbifold.xcodeproj/project.pbxproj @@ -8,6 +8,10 @@ /* Begin PBXBuildFile section */ 00E356F31AD99517003FC87E /* AriesBifoldTests.m in Sources */ = {isa = PBXBuildFile; fileRef = 00E356F21AD99517003FC87E /* AriesBifoldTests.m */; }; + 0BE4E0DD2C140BCD00636F44 /* BLEPeripheralManager.swift in Sources */ = {isa = PBXBuildFile; fileRef = 0BE4E0DC2C140BCD00636F44 /* BLEPeripheralManager.swift */; }; + 0BE4E0DE2C140BCD00636F44 /* BLEPeripheralManager.swift in Sources */ = {isa = PBXBuildFile; fileRef = 0BE4E0DC2C140BCD00636F44 /* BLEPeripheralManager.swift */; }; + 0BE4E0E12C140C1800636F44 /* BLEPeripheralManager.m in Sources */ = {isa = PBXBuildFile; fileRef = 0BE4E0E02C140C1800636F44 /* BLEPeripheralManager.m */; }; + 0BE4E0E22C140C1800636F44 /* BLEPeripheralManager.m in Sources */ = {isa = PBXBuildFile; fileRef = 0BE4E0E02C140C1800636F44 /* BLEPeripheralManager.m */; }; 13B07FBC1A68108700A75B9A /* AppDelegate.m in Sources */ = {isa = PBXBuildFile; fileRef = 13B07FB01A68108700A75B9A /* AppDelegate.m */; }; 13B07FBF1A68108700A75B9A /* Images.xcassets in Resources */ = {isa = PBXBuildFile; fileRef = 13B07FB51A68108700A75B9A /* Images.xcassets */; }; 13B07FC11A68108700A75B9A /* main.m in Sources */ = {isa = PBXBuildFile; fileRef = 13B07FB71A68108700A75B9A /* main.m */; }; @@ -45,7 +49,12 @@ 00E356EE1AD99517003FC87E /* AriesBifoldTests.xctest */ = {isa = PBXFileReference; explicitFileType = wrapper.cfbundle; includeInIndex = 0; path = AriesBifoldTests.xctest; sourceTree = BUILT_PRODUCTS_DIR; }; 00E356F11AD99517003FC87E /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = ""; }; 00E356F21AD99517003FC87E /* AriesBifoldTests.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = AriesBifoldTests.m; sourceTree = ""; }; - 13B07F961A680F5B00A75B9A /* AriesBifold.app */ = {isa = PBXFileReference; explicitFileType = wrapper.application; includeInIndex = 0; path = AriesBifold.app; sourceTree = BUILT_PRODUCTS_DIR; }; + 0BE4E0DA2C140BCD00636F44 /* AriesBifold-Bridging-Header.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = "AriesBifold-Bridging-Header.h"; sourceTree = ""; }; + 0BE4E0DB2C140BCD00636F44 /* AriesBifoldTests-Bridging-Header.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = "AriesBifoldTests-Bridging-Header.h"; sourceTree = ""; }; + 0BE4E0DC2C140BCD00636F44 /* BLEPeripheralManager.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = BLEPeripheralManager.swift; sourceTree = ""; }; + 0BE4E0DF2C140C1800636F44 /* BLEPeripheralManager.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = BLEPeripheralManager.h; sourceTree = ""; }; + 0BE4E0E02C140C1800636F44 /* BLEPeripheralManager.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = BLEPeripheralManager.m; sourceTree = ""; }; + 13B07F961A680F5B00A75B9A /* FHWA.app */ = {isa = PBXFileReference; explicitFileType = wrapper.application; includeInIndex = 0; path = FHWA.app; sourceTree = BUILT_PRODUCTS_DIR; }; 13B07FAF1A68108700A75B9A /* AppDelegate.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = AppDelegate.h; path = AriesBifold/AppDelegate.h; sourceTree = ""; }; 13B07FB01A68108700A75B9A /* AppDelegate.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = AppDelegate.m; path = AriesBifold/AppDelegate.m; sourceTree = ""; }; 13B07FB51A68108700A75B9A /* Images.xcassets */ = {isa = PBXFileReference; lastKnownFileType = folder.assetcatalog; name = Images.xcassets; path = AriesBifold/Images.xcassets; sourceTree = ""; }; @@ -144,6 +153,9 @@ 83CBB9F61A601CBA00E9B192 = { isa = PBXGroup; children = ( + 0BE4E0DC2C140BCD00636F44 /* BLEPeripheralManager.swift */, + 0BE4E0DF2C140C1800636F44 /* BLEPeripheralManager.h */, + 0BE4E0E02C140C1800636F44 /* BLEPeripheralManager.m */, 566FB1F1273B158E003E9BEE /* Media.xcassets */, 13B07FAE1A68108700A75B9A /* AriesBifold */, 00E356EF1AD99517003FC87E /* AriesBifoldTests */, @@ -152,6 +164,8 @@ 2D16E6871FA4F8E400B85C8A /* Frameworks */, 56A83D5927D95BBF002FE8FE /* Resources */, 8ACF6F3B2962FE31C0EE5408 /* Pods */, + 0BE4E0DA2C140BCD00636F44 /* AriesBifold-Bridging-Header.h */, + 0BE4E0DB2C140BCD00636F44 /* AriesBifoldTests-Bridging-Header.h */, ); indentWidth = 2; sourceTree = ""; @@ -161,7 +175,7 @@ 83CBBA001A601CBA00E9B192 /* Products */ = { isa = PBXGroup; children = ( - 13B07F961A680F5B00A75B9A /* AriesBifold.app */, + 13B07F961A680F5B00A75B9A /* FHWA.app */, 00E356EE1AD99517003FC87E /* AriesBifoldTests.xctest */, ); name = Products; @@ -222,7 +236,7 @@ ); name = AriesBifold; productName = AriesBifold; - productReference = 13B07F961A680F5B00A75B9A /* AriesBifold.app */; + productReference = 13B07F961A680F5B00A75B9A /* FHWA.app */; productType = "com.apple.product-type.application"; }; /* End PBXNativeTarget section */ @@ -235,10 +249,11 @@ TargetAttributes = { 00E356ED1AD99517003FC87E = { CreatedOnToolsVersion = 6.2; + LastSwiftMigration = 1540; TestTargetID = 13B07F861A680F5B00A75B9A; }; 13B07F861A680F5B00A75B9A = { - LastSwiftMigration = 1120; + LastSwiftMigration = 1540; }; }; }; @@ -284,7 +299,7 @@ /* Begin PBXShellScriptBuildPhase section */ 00DD1BFF1BD5951E006B06BC /* Bundle React Native code and images */ = { isa = PBXShellScriptBuildPhase; - buildActionMask = 2147483647; + buildActionMask = 12; files = ( ); inputPaths = ( @@ -294,7 +309,7 @@ ); runOnlyForDeploymentPostprocessing = 0; shellPath = /bin/sh; - shellScript = "set -e\n\nexport NODE_BINARY=node\n../node_modules/react-native/scripts/react-native-xcode.sh\n"; + shellScript = "\nset -e\n\nif [[ -s \"$HOME/.nvm/nvm.sh\" ]]; then\n. \"$HOME/.nvm/nvm.sh\"\nelif [[ -x \"$(command -v brew)\" && -s \"$(brew --prefix nvm)/nvm.sh\" ]]; then\n. \"$(brew --prefix nvm)/nvm.sh\"\nfi\n\nexport NODE_BINARY=node\n../node_modules/react-native/scripts/react-native-xcode.sh\n"; }; 04A23698871F60D02E13ACB0 /* [CP] Embed Pods Frameworks */ = { isa = PBXShellScriptBuildPhase; @@ -435,6 +450,8 @@ buildActionMask = 2147483647; files = ( 00E356F31AD99517003FC87E /* AriesBifoldTests.m in Sources */, + 0BE4E0E22C140C1800636F44 /* BLEPeripheralManager.m in Sources */, + 0BE4E0DE2C140BCD00636F44 /* BLEPeripheralManager.swift in Sources */, ); runOnlyForDeploymentPostprocessing = 0; }; @@ -442,8 +459,10 @@ isa = PBXSourcesBuildPhase; buildActionMask = 2147483647; files = ( + 0BE4E0DD2C140BCD00636F44 /* BLEPeripheralManager.swift in Sources */, 13B07FBC1A68108700A75B9A /* AppDelegate.m in Sources */, 13B07FC11A68108700A75B9A /* main.m in Sources */, + 0BE4E0E12C140C1800636F44 /* BLEPeripheralManager.m in Sources */, ); runOnlyForDeploymentPostprocessing = 0; }; @@ -462,7 +481,9 @@ isa = XCBuildConfiguration; baseConfigurationReference = 9337C17A2E512FDE0E677F2E /* Pods-AriesBifold-AriesBifoldTests.debug.xcconfig */; buildSettings = { + ALWAYS_EMBED_SWIFT_STANDARD_LIBRARIES = YES; BUNDLE_LOADER = "$(TEST_HOST)"; + CLANG_ENABLE_MODULES = YES; DEVELOPMENT_TEAM = ""; GCC_PREPROCESSOR_DEFINITIONS = ( "DEBUG=1", @@ -482,6 +503,9 @@ ); PRODUCT_BUNDLE_IDENTIFIER = "org.reactjs.native.example.$(PRODUCT_NAME:rfc1034identifier)"; PRODUCT_NAME = "$(TARGET_NAME)"; + SWIFT_OBJC_BRIDGING_HEADER = "AriesBifoldTests-Bridging-Header.h"; + SWIFT_OPTIMIZATION_LEVEL = "-Onone"; + SWIFT_VERSION = 5.0; TEST_HOST = "$(BUILT_PRODUCTS_DIR)/AriesBifold.app/AriesBifold"; }; name = Debug; @@ -490,7 +514,9 @@ isa = XCBuildConfiguration; baseConfigurationReference = 65B4BCEABB8190F24B4588BC /* Pods-AriesBifold-AriesBifoldTests.release.xcconfig */; buildSettings = { + ALWAYS_EMBED_SWIFT_STANDARD_LIBRARIES = YES; BUNDLE_LOADER = "$(TEST_HOST)"; + CLANG_ENABLE_MODULES = YES; COPY_PHASE_STRIP = NO; DEVELOPMENT_TEAM = ""; INFOPLIST_FILE = AriesBifoldTests/Info.plist; @@ -507,6 +533,8 @@ ); PRODUCT_BUNDLE_IDENTIFIER = "org.reactjs.native.example.$(PRODUCT_NAME:rfc1034identifier)"; PRODUCT_NAME = "$(TARGET_NAME)"; + SWIFT_OBJC_BRIDGING_HEADER = "AriesBifoldTests-Bridging-Header.h"; + SWIFT_VERSION = 5.0; TEST_HOST = "$(BUILT_PRODUCTS_DIR)/AriesBifold.app/AriesBifold"; }; name = Release; @@ -518,7 +546,7 @@ ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon; CLANG_ENABLE_MODULES = YES; CURRENT_PROJECT_VERSION = 1; - DEVELOPMENT_TEAM = G9667JTP83; + DEVELOPMENT_TEAM = X4AZ3Y5536; ENABLE_BITCODE = NO; FRAMEWORK_SEARCH_PATHS = "$(inherited)"; INFOPLIST_FILE = AriesBifold/Info.plist; @@ -535,11 +563,12 @@ "-ObjC", "-lc++", ); - PRODUCT_BUNDLE_IDENTIFIER = org.reactjs.native.example.AriesBifold; - PRODUCT_NAME = AriesBifold; + PRODUCT_BUNDLE_IDENTIFIER = org.reactjs.native.example.AriesBifoldNJIT; + PRODUCT_NAME = FHWA; SUPPORTED_PLATFORMS = "iphoneos iphonesimulator"; SUPPORTS_MACCATALYST = NO; SUPPORTS_MAC_DESIGNED_FOR_IPHONE_IPAD = YES; + SWIFT_OBJC_BRIDGING_HEADER = "AriesBifold-Bridging-Header.h"; SWIFT_OPTIMIZATION_LEVEL = "-Onone"; SWIFT_VERSION = 5.0; TARGETED_DEVICE_FAMILY = "1,2"; @@ -554,7 +583,7 @@ ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon; CLANG_ENABLE_MODULES = YES; CURRENT_PROJECT_VERSION = 1; - DEVELOPMENT_TEAM = G9667JTP83; + DEVELOPMENT_TEAM = X4AZ3Y5536; ENABLE_BITCODE = NO; FRAMEWORK_SEARCH_PATHS = "$(inherited)"; INFOPLIST_FILE = AriesBifold/Info.plist; @@ -571,11 +600,12 @@ "-ObjC", "-lc++", ); - PRODUCT_BUNDLE_IDENTIFIER = org.reactjs.native.example.AriesBifold; - PRODUCT_NAME = AriesBifold; + PRODUCT_BUNDLE_IDENTIFIER = org.reactjs.native.example.AriesBifoldNJIT; + PRODUCT_NAME = FHWA; SUPPORTED_PLATFORMS = "iphoneos iphonesimulator"; SUPPORTS_MACCATALYST = NO; SUPPORTS_MAC_DESIGNED_FOR_IPHONE_IPAD = YES; + SWIFT_OBJC_BRIDGING_HEADER = "AriesBifold-Bridging-Header.h"; SWIFT_VERSION = 5.0; TARGETED_DEVICE_FAMILY = "1,2"; VERSIONING_SYSTEM = "apple-generic"; @@ -648,7 +678,13 @@ OTHER_CPLUSPLUSFLAGS = "$(inherited)"; OTHER_LDFLAGS = ( "$(inherited)", - " ", + "-Wl", + "-ld_classic", + "-Wl", + "-ld_classic", + "-Wl", + "-ld_classic", + "-Wl -ld_classic ", ); REACT_NATIVE_PATH = "${PODS_ROOT}/../../node_modules/react-native"; SDKROOT = iphoneos; @@ -716,7 +752,13 @@ OTHER_CPLUSPLUSFLAGS = "$(inherited)"; OTHER_LDFLAGS = ( "$(inherited)", - " ", + "-Wl", + "-ld_classic", + "-Wl", + "-ld_classic", + "-Wl", + "-ld_classic", + "-Wl -ld_classic ", ); REACT_NATIVE_PATH = "${PODS_ROOT}/../../node_modules/react-native"; SDKROOT = iphoneos; diff --git a/packages/legacy/app/ios/ariesbifold.xcodeproj/xcshareddata/xcschemes/AriesBifold.xcscheme b/packages/legacy/app/ios/ariesbifold.xcodeproj/xcshareddata/xcschemes/AriesBifold.xcscheme index c4acecf8..2a567b21 100644 --- a/packages/legacy/app/ios/ariesbifold.xcodeproj/xcshareddata/xcschemes/AriesBifold.xcscheme +++ b/packages/legacy/app/ios/ariesbifold.xcodeproj/xcshareddata/xcschemes/AriesBifold.xcscheme @@ -15,9 +15,9 @@ + ReferencedContainer = "container:ariesbifold.xcodeproj"> @@ -35,7 +35,7 @@ BlueprintIdentifier = "00E356ED1AD99517003FC87E" BuildableName = "AriesBifoldTests.xctest" BlueprintName = "AriesBifoldTests" - ReferencedContainer = "container:AriesBifold.xcodeproj"> + ReferencedContainer = "container:ariesbifold.xcodeproj"> @@ -55,9 +55,9 @@ + ReferencedContainer = "container:ariesbifold.xcodeproj"> @@ -72,9 +72,9 @@ + ReferencedContainer = "container:ariesbifold.xcodeproj"> diff --git a/packages/legacy/app/ios/ariesbifold/AppDelegate.m b/packages/legacy/app/ios/ariesbifold/AppDelegate.m index 6e2e9b64..7abb2f92 100644 --- a/packages/legacy/app/ios/ariesbifold/AppDelegate.m +++ b/packages/legacy/app/ios/ariesbifold/AppDelegate.m @@ -7,7 +7,7 @@ @implementation AppDelegate - (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions { - self.moduleName = @"aries-bifold"; + self.moduleName = @"fhwa-wallet"; // You can add your custom initial props in the dictionary below. // They will be passed down to the ViewController used by React Native. self.initialProps = @{}; diff --git a/packages/legacy/app/ios/ariesbifold/Info.plist b/packages/legacy/app/ios/ariesbifold/Info.plist index 765de7a0..f7fe8ef0 100644 --- a/packages/legacy/app/ios/ariesbifold/Info.plist +++ b/packages/legacy/app/ios/ariesbifold/Info.plist @@ -5,7 +5,7 @@ CFBundleDevelopmentRegion en CFBundleDisplayName - AriesBifold + FHWA CFBundleExecutable $(EXECUTABLE_NAME) CFBundleIdentifier @@ -37,6 +37,10 @@ + NSBluetoothAlwaysUsageDescription + $(PRODUCT_NAME) wants to use Bluetooth + NSBluetoothPeripheralUsageDescription + $(PRODUCT_NAME) wants to use Bluetooth NSCameraUsageDescription Camera used for in-app QR Code scanning NSFaceIDUsageDescription @@ -48,6 +52,11 @@ MaterialIcons.ttf MaterialCommunityIcons.ttf + UIBackgroundModes + + bluetooth-central + location + UILaunchStoryboardName LaunchScreen UIRequiredDeviceCapabilities @@ -70,4 +79,4 @@ UIViewControllerBasedStatusBarAppearance - + \ No newline at end of file diff --git a/packages/legacy/app/package.json b/packages/legacy/app/package.json index 23b562a2..935ab6b0 100644 --- a/packages/legacy/app/package.json +++ b/packages/legacy/app/package.json @@ -2,7 +2,7 @@ "name": "aries-bifold-app", "version": "1.0.0", "private": true, - "description": "Aries Bifold Wallet App", + "description": "FHWA Wallet App", "scripts": { "android": "react-native run-android", "gradle": "./android/gradlew --project-dir=./android --no-daemon", @@ -56,6 +56,8 @@ "react-native": "*", "react-native-animated-pagination-dots": "^0.1.72", "react-native-argon2": "^2.0.1", + "react-native-ble-manager": "^11.5.3", + "react-native-ble-plx": "^3.1.2", "react-native-bouncy-checkbox": "^3.0.5", "react-native-collapsible": "^1.6.1", "react-native-config": "^1.4.2", diff --git a/packages/legacy/core/.prettierrc b/packages/legacy/core/.prettierrc index cbe842ac..f547d59a 100644 --- a/packages/legacy/core/.prettierrc +++ b/packages/legacy/core/.prettierrc @@ -1,5 +1,6 @@ { "printWidth": 120, "semi": false, - "singleQuote": true + "singleQuote": true, + "endOfLine": "auto" } diff --git a/packages/legacy/core/App/assets/img/FHWA-Logo.svg b/packages/legacy/core/App/assets/img/FHWA-Logo.svg new file mode 100644 index 00000000..2cfba0b8 --- /dev/null +++ b/packages/legacy/core/App/assets/img/FHWA-Logo.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/packages/legacy/core/App/assets/img/activity-indicator-circle.svg b/packages/legacy/core/App/assets/img/activity-indicator-circle.svg index 439aa184..dad219a0 100644 --- a/packages/legacy/core/App/assets/img/activity-indicator-circle.svg +++ b/packages/legacy/core/App/assets/img/activity-indicator-circle.svg @@ -1,90 +1,17 @@ - + - - - - - - - - - - - - - - - - - - - - - - + + + + + + + + - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + + + + \ No newline at end of file diff --git a/packages/legacy/core/App/assets/img/car.svg b/packages/legacy/core/App/assets/img/car.svg new file mode 100644 index 00000000..a0a7e634 --- /dev/null +++ b/packages/legacy/core/App/assets/img/car.svg @@ -0,0 +1,9 @@ + + + + + + + + + diff --git a/packages/legacy/core/App/assets/img/carfront.svg b/packages/legacy/core/App/assets/img/carfront.svg new file mode 100644 index 00000000..fa017655 --- /dev/null +++ b/packages/legacy/core/App/assets/img/carfront.svg @@ -0,0 +1,559 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/packages/legacy/core/App/assets/img/carside.svg b/packages/legacy/core/App/assets/img/carside.svg new file mode 100644 index 00000000..2720eb9c --- /dev/null +++ b/packages/legacy/core/App/assets/img/carside.svg @@ -0,0 +1,194 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/packages/legacy/core/App/assets/img/check-in-circle.svg b/packages/legacy/core/App/assets/img/check-in-circle.svg index 51351025..fcdb83e4 100644 --- a/packages/legacy/core/App/assets/img/check-in-circle.svg +++ b/packages/legacy/core/App/assets/img/check-in-circle.svg @@ -1,18 +1,11 @@ - + - - - - \ No newline at end of file + + + diff --git a/packages/legacy/core/App/assets/img/default-photo.png b/packages/legacy/core/App/assets/img/default-photo.png new file mode 100644 index 00000000..5d67ba3f Binary files /dev/null and b/packages/legacy/core/App/assets/img/default-photo.png differ diff --git a/packages/legacy/core/App/assets/img/default-photo.svg b/packages/legacy/core/App/assets/img/default-photo.svg new file mode 100644 index 00000000..f4c604b7 --- /dev/null +++ b/packages/legacy/core/App/assets/img/default-photo.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/packages/legacy/core/App/assets/img/line.svg b/packages/legacy/core/App/assets/img/line.svg new file mode 100644 index 00000000..61ce43ac --- /dev/null +++ b/packages/legacy/core/App/assets/img/line.svg @@ -0,0 +1,3 @@ + + + diff --git a/packages/legacy/core/App/assets/img/logo.png b/packages/legacy/core/App/assets/img/logo.png new file mode 100644 index 00000000..db57f0ea Binary files /dev/null and b/packages/legacy/core/App/assets/img/logo.png differ diff --git a/packages/legacy/core/App/assets/img/sending.svg b/packages/legacy/core/App/assets/img/sending.svg new file mode 100644 index 00000000..bce670f7 --- /dev/null +++ b/packages/legacy/core/App/assets/img/sending.svg @@ -0,0 +1,13 @@ + + + + + + + + + + + + + diff --git a/packages/legacy/core/App/assets/img/sent.svg b/packages/legacy/core/App/assets/img/sent.svg new file mode 100644 index 00000000..54ddf1e8 --- /dev/null +++ b/packages/legacy/core/App/assets/img/sent.svg @@ -0,0 +1,13 @@ + + + + + + + + + + + + + diff --git a/packages/legacy/core/App/assets/img/shield.svg b/packages/legacy/core/App/assets/img/shield.svg new file mode 100644 index 00000000..cca5fd0c --- /dev/null +++ b/packages/legacy/core/App/assets/img/shield.svg @@ -0,0 +1,9 @@ + + + + + + + + + diff --git a/packages/legacy/core/App/components/animated/ConnectionLoading.tsx b/packages/legacy/core/App/components/animated/ConnectionLoading.tsx index e3850d0e..d06b12c2 100644 --- a/packages/legacy/core/App/components/animated/ConnectionLoading.tsx +++ b/packages/legacy/core/App/components/animated/ConnectionLoading.tsx @@ -2,7 +2,7 @@ import React, { useEffect, useRef } from 'react' import { View, StyleSheet, Animated } from 'react-native' import ActivityIndicator from '../../assets/img/activity-indicator-circle.svg' -import Wallet from '../../assets/img/wallet.svg' +import Car from '../../assets/img/carfront.svg' import { useTheme } from '../../contexts/theme' const ConnectionLoading: React.FC = () => { @@ -24,15 +24,15 @@ const ConnectionLoading: React.FC = () => { }, animation: { position: 'absolute', + top: 70, }, }) const credentialInHandDisplayOptions = { fill: ColorPallet.notification.infoText, - height: 130, - width: 130, + height: 150, + width: 150, } const animatedCircleDisplayOptions = { - fill: ColorPallet.notification.infoText, height: 250, width: 250, } @@ -43,7 +43,7 @@ const ConnectionLoading: React.FC = () => { return ( - + diff --git a/packages/legacy/core/App/components/animated/CredentialAdded.tsx b/packages/legacy/core/App/components/animated/CredentialAdded.tsx index 2ab77809..c7f37c3d 100644 --- a/packages/legacy/core/App/components/animated/CredentialAdded.tsx +++ b/packages/legacy/core/App/components/animated/CredentialAdded.tsx @@ -1,23 +1,21 @@ import React, { useEffect, useRef } from 'react' import { View, StyleSheet, Animated } from 'react-native' -import CheckInCircle from '../../assets/img/check-in-circle.svg' -import CredentialCard from '../../assets/img/credential-card.svg' -import WalletBack from '../../assets/img/wallet-back.svg' -import WalletFront from '../../assets/img/wallet-front.svg' +import CarImage from '../../assets/img/carfront.svg' +import ShieldImage from '../../assets/img/shield.svg' const CredentialAdded: React.FC = () => { const cardFadeAnim = useRef(new Animated.Value(0)).current const checkFadeAnim = useRef(new Animated.Value(0)).current - const tranAnim = useRef(new Animated.Value(-90)).current + const tranAnim = useRef(new Animated.Value(0)).current // Start the shield above the screen const slideTiming: Animated.TimingAnimationConfig = { - toValue: -15, - duration: 1200, + toValue: 60, // Slide the shield down by 90 units + duration: 200, useNativeDriver: true, } const fadeTiming: Animated.TimingAnimationConfig = { toValue: 1, - duration: 600, + duration: 200, useNativeDriver: true, } const style = StyleSheet.create({ @@ -39,7 +37,8 @@ const CredentialAdded: React.FC = () => { }, check: { alignItems: 'center', - marginBottom: 10, + marginRight: -180, + zIndex: 100, }, }) @@ -49,7 +48,7 @@ const CredentialAdded: React.FC = () => { setTimeout(() => { Animated.sequence([ Animated.timing(cardFadeAnim, fadeTiming), - Animated.timing(tranAnim, slideTiming), + Animated.timing(tranAnim, slideTiming), // Apply the slide timing animation here Animated.timing(checkFadeAnim, fadeTiming), ]).start() }, animationDelay) @@ -57,15 +56,11 @@ const CredentialAdded: React.FC = () => { return ( - - + + - - - - - + ) diff --git a/packages/legacy/core/App/components/animated/CredentialPending.tsx b/packages/legacy/core/App/components/animated/CredentialPending.tsx index 19434aad..b2e295d7 100644 --- a/packages/legacy/core/App/components/animated/CredentialPending.tsx +++ b/packages/legacy/core/App/components/animated/CredentialPending.tsx @@ -1,16 +1,14 @@ import React, { useEffect, useRef } from 'react' import { View, StyleSheet, Animated } from 'react-native' -import CredentialCard from '../../assets/img/credential-card.svg' -import WalletBack from '../../assets/img/wallet-back.svg' -import WalletFront from '../../assets/img/wallet-front.svg' +import CarImage from '../../assets/img/carside.svg' const CredentialPending: React.FC = () => { const fadeAnim = useRef(new Animated.Value(0)).current - const tranAnim = useRef(new Animated.Value(-90)).current + const tranAnim = useRef(new Animated.Value(0)).current const slideTiming: Animated.TimingAnimationConfig = { - toValue: -15, - duration: 1400, + toValue: 1100, + duration: 2200, useNativeDriver: true, } const fadeTiming: Animated.TimingAnimationConfig = { @@ -22,23 +20,13 @@ const CredentialPending: React.FC = () => { container: { flexDirection: 'column', }, - back: { - backgroundColor: 'transparent', - position: 'absolute', - marginTop: -30, - }, - front: { - backgroundColor: 'transparent', - }, card: { - backgroundColor: 'transparent', - position: 'absolute', - marginLeft: 10, + marginLeft: -550, }, }) useEffect(() => { - const animationDelay = 300 + const animationDelay = 200 setTimeout(() => { Animated.loop( @@ -49,11 +37,9 @@ const CredentialPending: React.FC = () => { return ( - - - + + - ) } diff --git a/packages/legacy/core/App/components/animated/LoadingIndicator.tsx b/packages/legacy/core/App/components/animated/LoadingIndicator.tsx index 4e1d0729..6785e08a 100644 --- a/packages/legacy/core/App/components/animated/LoadingIndicator.tsx +++ b/packages/legacy/core/App/components/animated/LoadingIndicator.tsx @@ -6,7 +6,7 @@ import { useTheme } from '../../contexts/theme' import { testIdWithKey } from '../../utils/testable' const LoadingIndicator: React.FC = () => { - const { ColorPallet, Assets } = useTheme() + const { Assets } = useTheme() const rotationAnim = useRef(new Animated.Value(0)).current const timing: Animated.TimingAnimationConfig = { toValue: 1, @@ -23,7 +23,6 @@ const LoadingIndicator: React.FC = () => { }, }) const imageDisplayOptions = { - fill: ColorPallet.notification.infoText, height: 200, width: 200, } @@ -34,12 +33,8 @@ const LoadingIndicator: React.FC = () => { return ( - - + + diff --git a/packages/legacy/core/App/components/animated/SendingProof.tsx b/packages/legacy/core/App/components/animated/SendingProof.tsx index 08424bc9..c4fbe4f8 100644 --- a/packages/legacy/core/App/components/animated/SendingProof.tsx +++ b/packages/legacy/core/App/components/animated/SendingProof.tsx @@ -2,11 +2,11 @@ import React, { useEffect, useRef } from 'react' import { View, StyleSheet, Animated } from 'react-native' import ActivityIndicator from '../../assets/img/activity-indicator-circle.svg' -import CredentialInHand from '../../assets/img/credential-in-hand.svg' -import { useTheme } from '../../contexts/theme' +import CarImage from '../../assets/img/carfront.svg' +// import { useTheme } from '../../contexts/theme' const SendingProof: React.FC = () => { - const { ColorPallet } = useTheme() + // const { ColorPallet } = useTheme() const rotationAnim = useRef(new Animated.Value(0)).current const timing: Animated.TimingAnimationConfig = { toValue: 1, @@ -24,15 +24,14 @@ const SendingProof: React.FC = () => { }, animation: { position: 'absolute', + top: 70, }, }) const credentialInHandDisplayOptions = { - fill: ColorPallet.notification.infoText, - height: 130, - width: 130, + height: 150, + width: 150, } const animatedCircleDisplayOptions = { - fill: ColorPallet.notification.infoText, height: 250, width: 250, } @@ -43,10 +42,11 @@ const SendingProof: React.FC = () => { return ( - + + ) } diff --git a/packages/legacy/core/App/components/animated/SentProof.tsx b/packages/legacy/core/App/components/animated/SentProof.tsx index a9f10e3c..38fc5d97 100644 --- a/packages/legacy/core/App/components/animated/SentProof.tsx +++ b/packages/legacy/core/App/components/animated/SentProof.tsx @@ -1,17 +1,17 @@ import React, { useEffect, useRef } from 'react' import { View, StyleSheet, Animated } from 'react-native' -import ActivityIndicator from '../../assets/img/activity-indicator-circle.svg' -import CheckInCircle from '../../assets/img/check-in-circle.svg' -import CredentialInHand from '../../assets/img/credential-in-hand.svg' +import CarImage from '../../assets/img/carfront.svg' +import Line from '../../assets/img/line.svg' // Import the Line SVG component +import Sent from '../../assets/img/sent.svg' import { useTheme } from '../../contexts/theme' const SentProof: React.FC = () => { const { ColorPallet } = useTheme() - const ringFadeAnim = useRef(new Animated.Value(1)).current + const ringFadeAnim = useRef(new Animated.Value(0)).current const checkFadeAnim = useRef(new Animated.Value(0)).current const ringFadeTiming: Animated.TimingAnimationConfig = { - toValue: 0, + toValue: 1, duration: 600, useNativeDriver: true, } @@ -23,55 +23,53 @@ const SentProof: React.FC = () => { const style = StyleSheet.create({ container: { alignItems: 'center', - justifyContent: 'center', - // backgroundColor: 'red', + justifyContent: 'space-between', + flexDirection: 'row', + marginTop: 30, // Added marginTop for space }, - credential: { - marginTop: 25, + carContainer: { + // Adjusted margin to create space between cars + marginHorizontal: 70, + zIndex: 2, }, - ring: { - flexGrow: 3, + sentContainer: { + // Adjusted position to place the Sent SVG between cars + backgroundColor: ColorPallet.brand.modalPrimaryBackground, position: 'absolute', - // backgroundColor: 'yellow', + left: '61%', // Position the Sent SVG in the center horizontally + zIndex: 2, }, - check: { + lineContainer: { position: 'absolute', + top: '3%', + left: '40%', + zIndex: 1, }, }) - const credentialInHandDisplayOptions = { - fill: ColorPallet.notification.infoText, - height: 130, - width: 130, - } - const animatedCircleDisplayOptions = { - fill: ColorPallet.notification.infoText, - height: 250, - width: 250, - } useEffect(() => { - // Animated.loop( Animated.parallel([ Animated.timing(ringFadeAnim, ringFadeTiming), Animated.timing(checkFadeAnim, checkFadeTiming), ]).start() - // ).start() - // Animated.loop(Animated.timing(rotationAnim, rotationTiming)).start() }, []) return ( - - - - - + + + + + - - - + + + + + + ) } diff --git a/packages/legacy/core/App/components/inputs/LimitedTextInput.tsx b/packages/legacy/core/App/components/inputs/LimitedTextInput.tsx index 1ecb20b6..22884174 100644 --- a/packages/legacy/core/App/components/inputs/LimitedTextInput.tsx +++ b/packages/legacy/core/App/components/inputs/LimitedTextInput.tsx @@ -12,7 +12,7 @@ interface Props extends TextInputProps { const LimitedTextInput: React.FC = ({ label, limit, handleChangeText, ...textInputProps }) => { const [focused, setFocused] = useState(false) const [characterCount, setCharacterCount] = useState(0) - const { Inputs, TextTheme } = useTheme() + const { Inputs, TextTheme, ColorPallet } = useTheme() const styles = StyleSheet.create({ container: { marginVertical: 10, @@ -23,6 +23,8 @@ const LimitedTextInput: React.FC = ({ label, limit, handleChangeText, ... }, textInput: { ...Inputs.textInput, + color: TextTheme.normal.color, + borderColor: ColorPallet.brand.primary, }, limitCounter: { color: TextTheme.normal.color, diff --git a/packages/legacy/core/App/components/misc/BLEScanner.tsx b/packages/legacy/core/App/components/misc/BLEScanner.tsx new file mode 100644 index 00000000..5ae79148 --- /dev/null +++ b/packages/legacy/core/App/components/misc/BLEScanner.tsx @@ -0,0 +1,351 @@ +/* eslint-disable no-console */ +import React from 'react' +import { DidExchangeState } from '@aries-framework/core' +import { useAgent } from '@aries-framework/react-hooks' +import { useIsFocused } from '@react-navigation/native' +import { useEffect, useState } from 'react' +import { useTranslation } from 'react-i18next' +import { + SafeAreaView, + View, + Text, + Pressable, + Switch, + FlatList, + StyleSheet, + NativeEventEmitter, + NativeModules, + Alert, + AppState, + AppStateStatus, +} from 'react-native' +import BleManager from 'react-native-ble-manager' + +import ButtonLoading from '../../components/animated/ButtonLoading' +import ConnectionLoading from '../../components/animated/ConnectionLoading' +import Button, { ButtonType } from '../../components/buttons/Button' +import { domain } from '../../constants' +import { useTheme } from '../../contexts/theme' +import { useConnectionByOutOfBandId } from '../../hooks/connections' +import { ScanProps } from '../../screens/Scan' +import { Stacks, Screens } from '../../types/navigators' +import { createConnectionInvitation, stringToBytes } from '../../utils/helpers' +import { handleInvitation } from '../../utils/invitation' +import { testIdWithKey } from '../../utils/testable' + +const { BleAdvertise } = NativeModules + +// Define the local device interface for TypeScript +interface LocalDevice { + id: string + name?: string + rssi?: number + advertising?: Advertising +} + +interface Advertising { + serviceUUIDs: string[] +} + +// Styling for the component +const styles = StyleSheet.create({ + container: { + flex: 1, + padding: 20, + }, + device: { + marginVertical: 5, + flexDirection: 'row', + justifyContent: 'space-between', + alignItems: 'center', + }, + deviceName: { + fontWeight: 'bold', + }, + noDevicesText: { + textAlign: 'center', + marginTop: 20, + }, +}) + +const BLEScanner: React.FC = ({ navigation, route }) => { + const [isScanning, setIsScanning] = useState(false) + const [recordId, setRecordId] = useState(undefined) + const [devices, setDevices] = useState([]) + const [isConnecting, setIsConnecting] = useState(false) + const [discoverable, setDiscoverable] = useState() + const [isBluetoothEnabled, setIsBluetoothEnabled] = useState(false) + const [appState, setAppState] = useState(AppState.currentState) + const { ColorPallet, TextTheme } = useTheme() + const bleManagerModule = NativeModules.BleManager + const bleManagerEmitter = new NativeEventEmitter(bleManagerModule) + const bleAdvertiseEmitter = new NativeEventEmitter(NativeModules.BleAdvertise) + const { agent } = useAgent() + const { t } = useTranslation() + const isFocused = useIsFocused() + + const record = useConnectionByOutOfBandId(recordId || '') + const uuid = '1357d860-1eb6-11ef-9e35-0800200c9a66' + const cuuid = 'd918d942-8516-4165-922f-dd6823d32b2f' + let receivedInvitation = '' + + BleAdvertise.setCompanyId(0x00e0) + + const handleBleManagerDidUpdateState = (args: { state: string }) => { + if (args.state === 'on') { + setIsBluetoothEnabled(true) + } else { + setIsBluetoothEnabled(false) + } + } + + const handleDiscoverPeripheral = (peripheral: LocalDevice) => { + console.log(peripheral) + if (peripheral && peripheral.id && peripheral.name) { + setDevices((prevDevices) => { + const deviceExists = prevDevices.some((device) => device.id === peripheral.id) + if (!deviceExists) console.log(peripheral) + return deviceExists + ? prevDevices + : [...prevDevices, { id: peripheral.id, name: peripheral.name, rssi: peripheral.rssi }] + }) + } + } + + const handleRead = async ({ data }: { data: string }) => { + setIsConnecting(true) + console.log('Received data from', cuuid, 'in service', uuid) + console.log('Data:', data) + + receivedInvitation += data + + if (data.includes('\n')) { + receivedInvitation.replace('\n', '') + await handleInvitation(navigation, route, agent, receivedInvitation) + } + } + + // Stop advertising BLE + const stopAdvertising = async () => { + setDiscoverable(false) + try { + await BleAdvertise.stopBroadcast() + console.log('Stopped advertising') + } catch (error) { + console.error('Failed to stop advertising:', error) + } + } + + useEffect(() => { + BleManager.start({ showAlert: false }).catch((error) => { + console.error('BleManager initialization error:', error) + }) + + const stopListener = bleManagerEmitter.addListener('BleManagerStopScan', () => { + setIsScanning(false) + console.log('Scan is stopped') + }) + + const updateListener = bleManagerEmitter.addListener('BleManagerDidUpdateState', handleBleManagerDidUpdateState) + const discoverListener = bleManagerEmitter.addListener('BleManagerDiscoverPeripheral', handleDiscoverPeripheral) + const readListener = bleAdvertiseEmitter.addListener('onRead', handleRead) + BleManager.checkState() + + console.log("Added listeners") + + return () => { + console.log("Removed listeners") + updateListener.remove() + stopListener.remove() + discoverListener.remove() + readListener.remove() + } + }, []) + + useEffect(() => { + console.log(record) + if (record?.state === DidExchangeState.Completed) { + navigation.getParent()?.navigate(Stacks.ConnectionStack, { + screen: Screens.Connection, + params: { connectionId: record.id }, + }) + } + }, [record]) + + // When app is pushed to the background, stop advertising + useEffect(() => { + const handleAppStateChange = (nextAppState: AppStateStatus) => { + console.log("stop from app state change") + if (nextAppState.match(/inactive|background/)) { + stopAdvertising() + } + setAppState(nextAppState) + } + + const appStateListener = AppState.addEventListener('change', handleAppStateChange) + + return () => { + appStateListener.remove() + } + }, [appState]) + + // When screen is unfocused, stop advertising + useEffect(() => { + console.log("Stop from is focus") + if (!isFocused) { + stopAdvertising() + } + }, [isFocused]) + + // Scan for other BLE connections, use a custom UUID so only devices advertising through the app are visible. + const startScan = async () => { + setDevices([]) // Clear devices list before scanning + BleManager.scan([uuid], 10, true) + .then(() => { + setIsScanning(true) + }) + .catch((err: any) => { + console.error('Scan failed', err) + setIsScanning(false) + }) + } + + const createInvitation = async (): Promise => { + const result = await createConnectionInvitation(agent) + setRecordId(result.record.id) + return result.record.outOfBandInvitation.toUrl({ domain }) + '\n' // Add delimiter \n to detect completion in bluetooth send + } + + const disconnectDevice = (deviceId: string) => { + BleManager.disconnect(deviceId) + .then(() => { + // Success code + console.log('Disconnected') + }) + .catch((error) => { + // Failure code + console.log(error) + }) + } + + const sendInvitation = async (deviceId: string) => { + const invitationURL = await createInvitation() + + console.log(invitationURL) + await BleManager.write(deviceId, uuid, cuuid, stringToBytes(invitationURL)) + .then(() => { + console.log('Invitation URL sent successfully') + }) + .catch((error) => { + console.error(error) + }) + } + + const connectToDevice = (deviceId: string) => { + setIsConnecting(true) + BleManager.connect(deviceId) + .then(async () => { + console.log('Connected to', deviceId) + return BleManager.retrieveServices(deviceId) + }) + .then(async (peripheralInfo) => { + console.log('Peripheral info:', peripheralInfo) + return sendInvitation(deviceId) + }) + .then(() => { + disconnectDevice(deviceId) + }) + .catch((err: any) => { + setIsConnecting(false) + console.error('Connection failed', err) + Alert.alert('Connection Failed', `Failed to connect to device ${deviceId}`) + }) + } + + const startAdvertising = async () => { + setDiscoverable(true) + try { + BleAdvertise.broadcast(uuid, cuuid, {}) + .then((success: any) => { + console.log(success) + }) + .catch((error: string) => { + console.log('broadcast failed with: ' + error) + }) + } catch (error) { + console.log('Broadcast failed with: ' + error) + Alert.alert('Broadcast Failed', `Failed to start broadcasting: ${error}`) + } + } + + const renderItem = ({ item }: { item: LocalDevice }) => ( + + {item.name} + + ) + + if (!isBluetoothEnabled) { + return ( + + + {t('ScanBLE.BluetoothText')} + + + ) + } else if (isConnecting) { + return ( + + + + ) + } else { + return ( + + + + {t('ScanBLE.MakeDiscoverable')} + + + + (value ? startAdvertising() : stopAdvertising())} + value={discoverable} + // disabled={!biometryAvailable} + /> + + + + + {t('ScanBLE.Text1')} + + {!isScanning && devices.length === 0 && No devices found.} + item.id} /> + + + ) + } +} + +export default BLEScanner diff --git a/packages/legacy/core/App/components/misc/CredentialCard11.tsx b/packages/legacy/core/App/components/misc/CredentialCard11.tsx index b9771993..722ad65b 100644 --- a/packages/legacy/core/App/components/misc/CredentialCard11.tsx +++ b/packages/legacy/core/App/components/misc/CredentialCard11.tsx @@ -124,10 +124,10 @@ const CredentialCard11: React.FC = ({ } const [dimensions, setDimensions] = useState({ cardWidth: 0, cardHeight: 0 }) - const styles = StyleSheet.create({ container: { - backgroundColor: overlay.brandingOverlay?.primaryBackgroundColor, + backgroundColor: '#113B51', //hardcode overlay.brandingOverlay?.primaryBackgroundColor, + borderRadius: borderRadius, }, cardContainer: { @@ -138,7 +138,7 @@ const CredentialCard11: React.FC = ({ width: logoHeight, borderTopLeftRadius: borderRadius, borderBottomLeftRadius: borderRadius, - backgroundColor: getSecondaryBackgroundColor() ?? overlay.brandingOverlay?.primaryBackgroundColor, + backgroundColor: '#0D2D3E', //hardcode getSecondaryBackgroundColor() ?? overlay.brandingOverlay?.primaryBackgroundColor }, primaryBodyContainer: { flex: 1, @@ -440,7 +440,7 @@ const CredentialCard11: React.FC = ({ }, ]} > - {overlay.metaOverlay?.name} + {overlay.metaOverlay?.name?.toUpperCase()} diff --git a/packages/legacy/core/App/components/misc/QRRenderer.tsx b/packages/legacy/core/App/components/misc/QRRenderer.tsx index e1697220..2b0b1b70 100644 --- a/packages/legacy/core/App/components/misc/QRRenderer.tsx +++ b/packages/legacy/core/App/components/misc/QRRenderer.tsx @@ -39,11 +39,20 @@ const QRRenderer: React.FC = ({ value, onError, size }) => { } }, [onError]) - const qrSize = size ?? width - 80 + const qrSize = (size ?? width - 80) > 500 ? 500 : size ?? width - 80 return ( - {} + {isInvalidQR && {t('QRRender.GenerationError')}} ) diff --git a/packages/legacy/core/App/components/modals/DismissiblePopupModal.tsx b/packages/legacy/core/App/components/modals/DismissiblePopupModal.tsx index fd6da561..0128c383 100644 --- a/packages/legacy/core/App/components/modals/DismissiblePopupModal.tsx +++ b/packages/legacy/core/App/components/modals/DismissiblePopupModal.tsx @@ -74,7 +74,7 @@ const DismissiblePopupModal: React.FC = ({ headerText: { ...TextTheme.bold, alignSelf: 'flex-start', - color: ColorPallet.notification.infoText, + color: ColorPallet.grayscale.black, }, bodyText: { ...TextTheme.normal, diff --git a/packages/legacy/core/App/components/modals/ImageModal.tsx b/packages/legacy/core/App/components/modals/ImageModal.tsx index eca46c52..721d0f91 100644 --- a/packages/legacy/core/App/components/modals/ImageModal.tsx +++ b/packages/legacy/core/App/components/modals/ImageModal.tsx @@ -11,6 +11,7 @@ import { } from 'react-native' import Icon from 'react-native-vector-icons/MaterialIcons' +import Default from '../../assets/img/default-photo.svg' import { hitSlop } from '../../constants' import { useTheme } from '../../contexts/theme' import { GenericFn } from '../../types/fn' @@ -75,7 +76,11 @@ const ImageModal: React.FC = ({ uri, onDismissPressed }) => { - + {uri === '*' ? ( + + ) : ( + + )} diff --git a/packages/legacy/core/App/components/modals/CameraDisclosureModal.tsx b/packages/legacy/core/App/components/modals/PermissionDisclosureModal.tsx similarity index 72% rename from packages/legacy/core/App/components/modals/CameraDisclosureModal.tsx rename to packages/legacy/core/App/components/modals/PermissionDisclosureModal.tsx index bba9c3a0..d3ee4c81 100644 --- a/packages/legacy/core/App/components/modals/CameraDisclosureModal.tsx +++ b/packages/legacy/core/App/components/modals/PermissionDisclosureModal.tsx @@ -6,17 +6,20 @@ import { Modal, ScrollView, StyleSheet, Text, View, Linking } from 'react-native import { SafeAreaView } from 'react-native-safe-area-context' import { useTheme } from '../../contexts/theme' -import { Screens, HomeStackParams, TabStacks } from '../../types/navigators' +import { Screens, HomeStackParams, TabStacks, Stacks } from '../../types/navigators' import { testIdWithKey } from '../../utils/testable' import Button, { ButtonType } from '../buttons/Button' import DismissiblePopupModal from './DismissiblePopupModal' -interface CameraDisclosureModalProps { - requestCameraUse: () => Promise +export type DisclosureTypes = 'CameraDisclosure' | 'NearbyDevicesDisclosure' | 'LocationDisclosure' + +interface PermissionDisclosureModalProps { + type: DisclosureTypes + requestUse: () => Promise } -const CameraDisclosureModal: React.FC = ({ requestCameraUse }) => { +const PermissionDisclosureModal: React.FC = ({ type, requestUse }) => { const { t } = useTranslation() const navigation = useNavigation>() const [modalVisible, setModalVisible] = useState(true) @@ -45,7 +48,7 @@ const CameraDisclosureModal: React.FC = ({ requestCa const onContinueTouched = async () => { setRequestInProgress(true) - const granted = await requestCameraUse() + const granted = await requestUse() if (!granted) { setShowSettingsPopup(true) } @@ -55,12 +58,20 @@ const CameraDisclosureModal: React.FC = ({ requestCa const onOpenSettingsTouched = async () => { setModalVisible(false) await Linking.openSettings() - navigation.getParent()?.navigate(TabStacks.HomeStack, { screen: Screens.Home }) + if (type == 'CameraDisclosure') { + navigation.getParent()?.navigate(TabStacks.HomeStack, { screen: Screens.Home }) + } else { + navigation.getParent()?.navigate(Stacks.SettingStack, { screen: Screens.ScanBLE }) + } } const onNotNowTouched = () => { setModalVisible(false) - navigation.getParent()?.navigate(TabStacks.HomeStack, { screen: Screens.Home }) + if (type == 'CameraDisclosure') { + navigation.getParent()?.navigate(TabStacks.HomeStack, { screen: Screens.Home }) + } else { + navigation.getParent()?.navigate(Stacks.SettingStack, { screen: Screens.ScanBLE }) + } } const onOpenSettingsDismissed = () => { @@ -71,20 +82,20 @@ const CameraDisclosureModal: React.FC = ({ requestCa {showSettingsPopup && ( )} - - {t('CameraDisclosure.AllowCameraUse')} + + {t(`${type}.AllowUse`)} - {t('CameraDisclosure.CameraDisclosure')} - {t('CameraDisclosure.ToContinueUsing')} + {t(`${type}.Disclosure`)} + {t(`${type}.ToContinueUsing`)} @@ -112,4 +123,4 @@ const CameraDisclosureModal: React.FC = ({ requestCa ) } -export default CameraDisclosureModal +export default PermissionDisclosureModal diff --git a/packages/legacy/core/App/components/record/Record.tsx b/packages/legacy/core/App/components/record/Record.tsx index 3f0040d9..31f77133 100644 --- a/packages/legacy/core/App/components/record/Record.tsx +++ b/packages/legacy/core/App/components/record/Record.tsx @@ -55,7 +55,7 @@ const Record: React.FC = ({ header, footer, fields, hideFieldValues return ( (a.name ?? '').localeCompare(b.name ?? ''))} keyExtractor={({ name }, index) => name || index.toString()} renderItem={({ item: attr, index }) => field ? ( diff --git a/packages/legacy/core/App/components/record/RecordBinaryField.tsx b/packages/legacy/core/App/components/record/RecordBinaryField.tsx index b6ffd24c..c1ef4080 100644 --- a/packages/legacy/core/App/components/record/RecordBinaryField.tsx +++ b/packages/legacy/core/App/components/record/RecordBinaryField.tsx @@ -2,6 +2,7 @@ import React, { useState } from 'react' import { useTranslation } from 'react-i18next' import { Image, StyleSheet, Text, TouchableOpacity, View } from 'react-native' +import Default from '../../assets/img/default-photo.svg' import ImageModal from '../../components/modals/ImageModal' import { hiddenFieldValue } from '../../constants' import { useTheme } from '../../contexts/theme' @@ -18,6 +19,10 @@ const RecordBinaryField: React.FC = ({ attributeValue, s const { t } = useTranslation() const [showImageModal, setShowImageModal] = useState(false) + // const actualValue = attributeValue === '*' ? Default : attributeValue + // eslint-disable-next-line no-console + // console.log(actualValue) + const styles = StyleSheet.create({ text: { ...ListItems.recordAttributeText, @@ -38,7 +43,11 @@ const RecordBinaryField: React.FC = ({ attributeValue, s testID={testIdWithKey('zoom')} onPress={() => setShowImageModal(true)} > - + {attributeValue === '*' ? ( + + ) : ( + + )} ) : ( diff --git a/packages/legacy/core/App/components/record/RecordField.tsx b/packages/legacy/core/App/components/record/RecordField.tsx index abf013ea..3b72a640 100644 --- a/packages/legacy/core/App/components/record/RecordField.tsx +++ b/packages/legacy/core/App/components/record/RecordField.tsx @@ -7,6 +7,7 @@ import { StyleSheet, Text, TouchableOpacity, View } from 'react-native' import { hiddenFieldValue } from '../../constants' import { useTheme } from '../../contexts/theme' +import { DateToString } from '../../utils/credential' import { isDataUrl } from '../../utils/helpers' import { testIdWithKey } from '../../utils/testable' @@ -41,13 +42,20 @@ export const AttributeValue: React.FC = ({ field, style, s }) if ( (field.encoding == validEncoding && field.format && validFormat.test(field.format) && field.value) || - isDataUrl(field.value) + isDataUrl(field.value) || + field.name?.toLowerCase().includes('photo') ) { return } if (field.type == CaptureBaseAttributeType.DateInt || field.type == CaptureBaseAttributeType.DateTime) { return } + if (field.name?.toLowerCase().includes('date')) + return ( + + {shown ? DateToString(field.value as string) : hiddenFieldValue} + + ) return ( {shown ? field.value : hiddenFieldValue} @@ -92,6 +100,9 @@ const RecordField: React.FC = ({ }, }) + // // eslint-disable-next-line no-console + // console.log(field) + return ( diff --git a/packages/legacy/core/App/configs/ledgers/indy/ledgers.json b/packages/legacy/core/App/configs/ledgers/indy/ledgers.json index 956e108f..3c80c5db 100644 --- a/packages/legacy/core/App/configs/ledgers/indy/ledgers.json +++ b/packages/legacy/core/App/configs/ledgers/indy/ledgers.json @@ -4,6 +4,6 @@ "indyNamespace": "bcovrin:test", "isProduction": false, "connectOnStartup": true, - "genesisTransactions": "{\"reqSignature\":{},\"txn\":{\"data\":{\"data\":{\"alias\":\"Node1\",\"blskey\":\"4N8aUNHSgjQVgkpm8nhNEfDf6txHznoYREg9kirmJrkivgL4oSEimFF6nsQ6M41QvhM2Z33nves5vfSn9n1UwNFJBYtWVnHYMATn76vLuL3zU88KyeAYcHfsih3He6UHcXDxcaecHVz6jhCYz1P2UZn2bDVruL5wXpehgBfBaLKm3Ba\",\"blskey_pop\":\"RahHYiCvoNCtPTrVtP7nMC5eTYrsUA8WjXbdhNc8debh1agE9bGiJxWBXYNFbnJXoXhWFMvyqhqhRoq737YQemH5ik9oL7R4NTTCz2LEZhkgLJzB3QRQqJyBNyv7acbdHrAT8nQ9UkLbaVL9NBpnWXBTw4LEMePaSHEw66RzPNdAX1\",\"client_ip\":\"3.145.42.89\",\"client_port\":9702,\"node_ip\":\"3.145.42.89\",\"node_port\":9701,\"services\":[\"VALIDATOR\"]},\"dest\":\"Gw6pDLhcBcoQesN72qfotTgFa7cbuqZpkX3Xo6pLhPhv\"},\"metadata\":{\"from\":\"Th7MpTaRZVRYnPiabds81Y\"},\"type\":\"0\"},\"txnMetadata\":{\"seqNo\":1,\"txnId\":\"fea82e10e894419fe2bea7d96296a6d46f50f93f9eeda954ec461b2ed2950b62\"},\"ver\":\"1\"}\n {\"reqSignature\":{},\"txn\":{\"data\":{\"data\":{\"alias\":\"Node2\",\"blskey\":\"37rAPpXVoxzKhz7d9gkUe52XuXryuLXoM6P6LbWDB7LSbG62Lsb33sfG7zqS8TK1MXwuCHj1FKNzVpsnafmqLG1vXN88rt38mNFs9TENzm4QHdBzsvCuoBnPH7rpYYDo9DZNJePaDvRvqJKByCabubJz3XXKbEeshzpz4Ma5QYpJqjk\",\"blskey_pop\":\"Qr658mWZ2YC8JXGXwMDQTzuZCWF7NK9EwxphGmcBvCh6ybUuLxbG65nsX4JvD4SPNtkJ2w9ug1yLTj6fgmuDg41TgECXjLCij3RMsV8CwewBVgVN67wsA45DFWvqvLtu4rjNnE9JbdFTc1Z4WCPA3Xan44K1HoHAq9EVeaRYs8zoF5\",\"client_ip\":\"3.145.42.89\",\"client_port\":9704,\"node_ip\":\"3.145.42.89\",\"node_port\":9703,\"services\":[\"VALIDATOR\"]},\"dest\":\"8ECVSk179mjsjKRLWiQtssMLgp6EPhWXtaYyStWPSGAb\"},\"metadata\":{\"from\":\"EbP4aYNeTHL6q385GuVpRV\"},\"type\":\"0\"},\"txnMetadata\":{\"seqNo\":2,\"txnId\":\"1ac8aece2a18ced660fef8694b61aac3af08ba875ce3026a160acbc3a3af35fc\"},\"ver\":\"1\"}\n {\"reqSignature\":{},\"txn\":{\"data\":{\"data\":{\"alias\":\"Node3\",\"blskey\":\"3WFpdbg7C5cnLYZwFZevJqhubkFALBfCBBok15GdrKMUhUjGsk3jV6QKj6MZgEubF7oqCafxNdkm7eswgA4sdKTRc82tLGzZBd6vNqU8dupzup6uYUf32KTHTPQbuUM8Yk4QFXjEf2Usu2TJcNkdgpyeUSX42u5LqdDDpNSWUK5deC5\",\"blskey_pop\":\"QwDeb2CkNSx6r8QC8vGQK3GRv7Yndn84TGNijX8YXHPiagXajyfTjoR87rXUu4G4QLk2cF8NNyqWiYMus1623dELWwx57rLCFqGh7N4ZRbGDRP4fnVcaKg1BcUxQ866Ven4gw8y4N56S5HzxXNBZtLYmhGHvDtk6PFkFwCvxYrNYjh\",\"client_ip\":\"3.145.42.89\",\"client_port\":9706,\"node_ip\":\"3.145.42.89\",\"node_port\":9705,\"services\":[\"VALIDATOR\"]},\"dest\":\"DKVxG2fXXTU8yT5N7hGEbXB3dfdAnYv1JczDUHpmDxya\"},\"metadata\":{\"from\":\"4cU41vWW82ArfxJxHkzXPG\"},\"type\":\"0\"},\"txnMetadata\":{\"seqNo\":3,\"txnId\":\"7e9f355dffa78ed24668f0e0e369fd8c224076571c51e2ea8be5f26479edebe4\"},\"ver\":\"1\"}\n {\"reqSignature\":{},\"txn\":{\"data\":{\"data\":{\"alias\":\"Node4\",\"blskey\":\"2zN3bHM1m4rLz54MJHYSwvqzPchYp8jkHswveCLAEJVcX6Mm1wHQD1SkPYMzUDTZvWvhuE6VNAkK3KxVeEmsanSmvjVkReDeBEMxeDaayjcZjFGPydyey1qxBHmTvAnBKoPydvuTAqx5f7YNNRAdeLmUi99gERUU7TD8KfAa6MpQ9bw\",\"blskey_pop\":\"RPLagxaR5xdimFzwmzYnz4ZhWtYQEj8iR5ZU53T2gitPCyCHQneUn2Huc4oeLd2B2HzkGnjAff4hWTJT6C7qHYB1Mv2wU5iHHGFWkhnTX9WsEAbunJCV2qcaXScKj4tTfvdDKfLiVuU2av6hbsMztirRze7LvYBkRHV3tGwyCptsrP\",\"client_ip\":\"3.145.42.89\",\"client_port\":9708,\"node_ip\":\"3.145.42.89\",\"node_port\":9707,\"services\":[\"VALIDATOR\"]},\"dest\":\"4PS3EDQ3dW1tci1Bp6543CfuuebjFrg36kLAUcskGfaA\"},\"metadata\":{\"from\":\"TWwCRQRZ2ZHMJFn9TzLp7W\"},\"type\":\"0\"},\"txnMetadata\":{\"seqNo\":4,\"txnId\":\"aa5e817d7cc626170eca175822029339a444eb0ee8f0bd20d3b0b76e566fb008\"},\"ver\":\"1\"}" + "genesisTransactions": "{\"reqSignature\":{},\"txn\":{\"data\":{\"data\":{\"alias\":\"Node1\",\"blskey\":\"4N8aUNHSgjQVgkpm8nhNEfDf6txHznoYREg9kirmJrkivgL4oSEimFF6nsQ6M41QvhM2Z33nves5vfSn9n1UwNFJBYtWVnHYMATn76vLuL3zU88KyeAYcHfsih3He6UHcXDxcaecHVz6jhCYz1P2UZn2bDVruL5wXpehgBfBaLKm3Ba\",\"blskey_pop\":\"RahHYiCvoNCtPTrVtP7nMC5eTYrsUA8WjXbdhNc8debh1agE9bGiJxWBXYNFbnJXoXhWFMvyqhqhRoq737YQemH5ik9oL7R4NTTCz2LEZhkgLJzB3QRQqJyBNyv7acbdHrAT8nQ9UkLbaVL9NBpnWXBTw4LEMePaSHEw66RzPNdAX1\",\"client_ip\":\"107.20.28.166\",\"client_port\":9702,\"node_ip\":\"107.20.28.166\",\"node_port\":9701,\"services\":[\"VALIDATOR\"]},\"dest\":\"Gw6pDLhcBcoQesN72qfotTgFa7cbuqZpkX3Xo6pLhPhv\"},\"metadata\":{\"from\":\"Th7MpTaRZVRYnPiabds81Y\"},\"type\":\"0\"},\"txnMetadata\":{\"seqNo\":1,\"txnId\":\"fea82e10e894419fe2bea7d96296a6d46f50f93f9eeda954ec461b2ed2950b62\"},\"ver\":\"1\"}\n{\"reqSignature\":{},\"txn\":{\"data\":{\"data\":{\"alias\":\"Node2\",\"blskey\":\"37rAPpXVoxzKhz7d9gkUe52XuXryuLXoM6P6LbWDB7LSbG62Lsb33sfG7zqS8TK1MXwuCHj1FKNzVpsnafmqLG1vXN88rt38mNFs9TENzm4QHdBzsvCuoBnPH7rpYYDo9DZNJePaDvRvqJKByCabubJz3XXKbEeshzpz4Ma5QYpJqjk\",\"blskey_pop\":\"Qr658mWZ2YC8JXGXwMDQTzuZCWF7NK9EwxphGmcBvCh6ybUuLxbG65nsX4JvD4SPNtkJ2w9ug1yLTj6fgmuDg41TgECXjLCij3RMsV8CwewBVgVN67wsA45DFWvqvLtu4rjNnE9JbdFTc1Z4WCPA3Xan44K1HoHAq9EVeaRYs8zoF5\",\"client_ip\":\"107.20.28.166\",\"client_port\":9704,\"node_ip\":\"107.20.28.166\",\"node_port\":9703,\"services\":[\"VALIDATOR\"]},\"dest\":\"8ECVSk179mjsjKRLWiQtssMLgp6EPhWXtaYyStWPSGAb\"},\"metadata\":{\"from\":\"EbP4aYNeTHL6q385GuVpRV\"},\"type\":\"0\"},\"txnMetadata\":{\"seqNo\":2,\"txnId\":\"1ac8aece2a18ced660fef8694b61aac3af08ba875ce3026a160acbc3a3af35fc\"},\"ver\":\"1\"}\n{\"reqSignature\":{},\"txn\":{\"data\":{\"data\":{\"alias\":\"Node3\",\"blskey\":\"3WFpdbg7C5cnLYZwFZevJqhubkFALBfCBBok15GdrKMUhUjGsk3jV6QKj6MZgEubF7oqCafxNdkm7eswgA4sdKTRc82tLGzZBd6vNqU8dupzup6uYUf32KTHTPQbuUM8Yk4QFXjEf2Usu2TJcNkdgpyeUSX42u5LqdDDpNSWUK5deC5\",\"blskey_pop\":\"QwDeb2CkNSx6r8QC8vGQK3GRv7Yndn84TGNijX8YXHPiagXajyfTjoR87rXUu4G4QLk2cF8NNyqWiYMus1623dELWwx57rLCFqGh7N4ZRbGDRP4fnVcaKg1BcUxQ866Ven4gw8y4N56S5HzxXNBZtLYmhGHvDtk6PFkFwCvxYrNYjh\",\"client_ip\":\"107.20.28.166\",\"client_port\":9706,\"node_ip\":\"107.20.28.166\",\"node_port\":9705,\"services\":[\"VALIDATOR\"]},\"dest\":\"DKVxG2fXXTU8yT5N7hGEbXB3dfdAnYv1JczDUHpmDxya\"},\"metadata\":{\"from\":\"4cU41vWW82ArfxJxHkzXPG\"},\"type\":\"0\"},\"txnMetadata\":{\"seqNo\":3,\"txnId\":\"7e9f355dffa78ed24668f0e0e369fd8c224076571c51e2ea8be5f26479edebe4\"},\"ver\":\"1\"}\n{\"reqSignature\":{},\"txn\":{\"data\":{\"data\":{\"alias\":\"Node4\",\"blskey\":\"2zN3bHM1m4rLz54MJHYSwvqzPchYp8jkHswveCLAEJVcX6Mm1wHQD1SkPYMzUDTZvWvhuE6VNAkK3KxVeEmsanSmvjVkReDeBEMxeDaayjcZjFGPydyey1qxBHmTvAnBKoPydvuTAqx5f7YNNRAdeLmUi99gERUU7TD8KfAa6MpQ9bw\",\"blskey_pop\":\"RPLagxaR5xdimFzwmzYnz4ZhWtYQEj8iR5ZU53T2gitPCyCHQneUn2Huc4oeLd2B2HzkGnjAff4hWTJT6C7qHYB1Mv2wU5iHHGFWkhnTX9WsEAbunJCV2qcaXScKj4tTfvdDKfLiVuU2av6hbsMztirRze7LvYBkRHV3tGwyCptsrP\",\"client_ip\":\"107.20.28.166\",\"client_port\":9708,\"node_ip\":\"107.20.28.166\",\"node_port\":9707,\"services\":[\"VALIDATOR\"]},\"dest\":\"4PS3EDQ3dW1tci1Bp6543CfuuebjFrg36kLAUcskGfaA\"},\"metadata\":{\"from\":\"TWwCRQRZ2ZHMJFn9TzLp7W\"},\"type\":\"0\"},\"txnMetadata\":{\"seqNo\":4,\"txnId\":\"aa5e817d7cc626170eca175822029339a444eb0ee8f0bd20d3b0b76e566fb008\"},\"ver\":\"1\"}" } -] +] \ No newline at end of file diff --git a/packages/legacy/core/App/contexts/configuration.tsx b/packages/legacy/core/App/contexts/configuration.tsx index 03036567..303d50af 100644 --- a/packages/legacy/core/App/contexts/configuration.tsx +++ b/packages/legacy/core/App/contexts/configuration.tsx @@ -43,7 +43,7 @@ export interface ConfigurationContext { supportedLanguages: Locales[] connectionTimerDelay?: number autoRedirectConnectionToHome?: boolean - proofRequestTemplates?: (useDevTemplates: boolean) => Array + proofRequestTemplates?: (useDevTemplates: boolean, attributes: string[]) => Array enableTours?: boolean enableImplicitInvitations?: boolean enableReuseConnections?: boolean diff --git a/packages/legacy/core/App/localization/en/index.ts b/packages/legacy/core/App/localization/en/index.ts index 56558b4e..65d68380 100644 --- a/packages/legacy/core/App/localization/en/index.ts +++ b/packages/legacy/core/App/localization/en/index.ts @@ -142,8 +142,8 @@ const translation = { "Attestation": "I have read, understand and accept the terms and conditions.", }, "Tour": { - "GuideTitle": "Welcome to Aries Bifold", - "WouldYouLike": "Would you like some guidance on how to use Aries Bifold?", + "GuideTitle": "Welcome to FHWA", + "WouldYouLike": "Would you like some guidance on how to use FHWA?", "UseAppGuides": "Use app guides", "DoNotUseAppGuides": "Don't use app guides", "AddAndShare": "Add and share credentials", @@ -164,9 +164,21 @@ const translation = { "Done": "Done", }, "CameraDisclosure": { - "AllowCameraUse": "Allow camera use", - "CameraDisclosure": "The camera is used to scan QR codes that initiate a credential offer or credential request. No information about the images is stored, used for analytics, or shared.", - "ToContinueUsing": "To continue using the Aries Bifold scan feature, please allow camera permissions.", + "AllowUse": "Allow camera use", + "Disclosure": "The camera is used to scan QR codes that initiate a credential offer or credential request. No information about the images is stored, used for analytics, or shared.", + "ToContinueUsing": "To continue using the FHWA scan feature, please allow camera permissions.", + "OpenSettings": "Open settings", + }, + "NearbyDevicesDisclosure": { + "AllowUse": "Allow nearby devices use", + "Disclosure": "The nearby devices is used to discover other devices.", + "ToContinueUsing": "To continue using the FHWA bluetooth feature, please allow nearby devices permissions.", + "OpenSettings": "Open settings", + }, + "LocationDisclosure": { + "AllowUse": "Allow location use", + "Disclosure": "The location is used to discover other devices.", + "ToContinueUsing": "To continue using the FHWA bluetooth feature, please allow location permissions.", "OpenSettings": "Open settings", }, "PINCreate": { @@ -218,6 +230,14 @@ const translation = { "Continue": "Continue", "EnterYourCurrentPIN": "Enter your current PIN" }, + "ScanBLE": { + "Connect": "Connect", + "BluetoothText": "Please turn on Bluetooth to continue.", + "Text1": "Ensure Bluetooth is enabled on both devices. Use the button below to scan for available devices and send and invitation to connect.", + "Toggle": "Toggle Bluetooth discovery", + "ScanDevices": "Scan for devices", + "MakeDiscoverable": "Make Discoverable" + }, "PINEnter": { "EnterPIN": "Enter your wallet PIN", "Unlock": "Unlock", @@ -353,12 +373,12 @@ const translation = { "ScanHelp": "Scan Help", "ScanNow": "Scan Now", "WhatToScan": "What QR Codes can be scanned?", - "ScanOnySpecial": "Only special QR codes can be scanned by Bifold Wallet.", + "ScanOnySpecial": "Only special QR codes can be scanned by FHWA Wallet.", "ScanOnlySpecial2": "These are presented by participating services or people to receive a credential offer, request for information or to connect.", - "ScanOnlySpecial3": "Bifold Wallet currently doesn't support adding digital credential by scanning or taking photos of physical ones.", - "WhereToUseLink": "See where you can use Bifold Wallet", + "ScanOnlySpecial3": "FHWA Wallet currently doesn't support adding digital credential by scanning or taking photos of physical ones.", + "WhereToUseLink": "See where you can use FHWA Wallet", "BadQRCode": "QR Code Not Recognized", - "BadQRCodeDescription": "Ths QR code scanned doesn't work with Bifold Wallet. Bifold Wallet only works with participating services.\n\nIt currently can't add digital credentials by taking photos of physical ones.", + "BadQRCodeDescription": "This QR code scanned doesn't work with FHWA Wallet. FHWA Wallet only works with participating services.\n\nIt currently can't add digital credentials by taking photos of physical ones.", }, "Connection": { "JustAMoment": "Just a moment while we make a secure connection...", @@ -487,6 +507,8 @@ const translation = { "Build": "Build", "WhatAreContacts": "What are Contacts?", "QRCodeGen": "Generate QR Code", + "ScanBLE": "Bluetooth", + "ProofRequestDetails":"Proof Request Details", "ScanMyQR": "Scan my QR code", "Help": "Help", "MoreInformation": "More information", @@ -521,7 +543,7 @@ const translation = { "Screens": { "Splash": "Splash", "Onboarding": "Onboarding", - "Preface": "Aries Bifold", + "Preface": "FHWA", "Terms": "Terms & Conditions", "CreatePIN": "Create a PIN", "EnterPIN": "Enter PIN", @@ -548,6 +570,7 @@ const translation = { "ChangePIN": "Change PIN", "CommonDecline": "Decline", "ProofRequests": "Proof requests", + "SelectProofRequest": "Select proof request", "SendProofRequest": "Send a proof request", "ChooseProofRequest": "Choose a proof request", "ProofRequestUsageHistory": "Usage History", @@ -586,16 +609,16 @@ const translation = { }, "NetInfo": { "NoInternetConnectionTitle": "No internet connection", - "NoInternetConnectionMessage": "You're unable to access services using Bifold or receive credentials until you're back online.\n\nPlease check your internet connection.", + "NoInternetConnectionMessage": "You're unable to access services using FHWA or receive credentials until you're back online.\n\nPlease check your internet connection.", "LedgerConnectivityIssueTitle": "Wallet Services", "LedgerConnectivityIssueMessage": "A firewall may be preventing you from connecting to wallet related services.", }, "Onboarding": { - "SkipA11y": "Skip introduction to Aries Bifold", + "SkipA11y": "Skip introduction to FHWA", }, "Preface": { "PrimaryHeading": "Is this app for you?", - "Paragraph1": "Most people will not have a need for Aries Bifold because very few digital credentials are currently available.", + "Paragraph1": "Most people will not have a need for FHWA because very few digital credentials are currently available.", "Confirmed": "I have confirmed that this app is for me.", }, "Chat": { diff --git a/packages/legacy/core/App/localization/fr/index.ts b/packages/legacy/core/App/localization/fr/index.ts index c4b73dc1..819b6e4c 100644 --- a/packages/legacy/core/App/localization/fr/index.ts +++ b/packages/legacy/core/App/localization/fr/index.ts @@ -142,8 +142,8 @@ const translation = { "Attestation": "J'ai lu, je comprends et j'accepte les conditions." }, "Tour": { - "GuideTitle": "Bienvenue à Aries Bifold", - "WouldYouLike": "Souhaitez-vous des conseils sur la façon d'utiliser Aries Bifold?", + "GuideTitle": "Bienvenue à FHWA", + "WouldYouLike": "Souhaitez-vous des conseils sur la façon d'utiliser FHWA?", "UseAppGuides": "Utiliser les conseils", "DoNotUseAppGuides": "Ne pas utiliser les conseils", "AddAndShare": "Ajouter et partager des justificatifs d'identité", @@ -164,8 +164,20 @@ const translation = { "Done": "Terminer", }, "CameraDisclosure": { - "AllowCameraUse": "Autoriser l'utilisation de la caméra", - "CameraDisclosure": "La caméra est utilisée pour capturer les codes QR qui initient une offre de justificatifs d'identité ou une demande de preuve. Aucune information de l'image n'est sauvegardée, utilisée pour les analyses, ou partagée.", + "AllowUse": "Autoriser l'utilisation de la caméra", + "Disclosure": "La caméra est utilisée pour capturer les codes QR qui initient une offre de justificatifs d'identité ou une demande de preuve. Aucune information de l'image n'est sauvegardée, utilisée pour les analyses, ou partagée.", + "ToContinueUsing": "Pour continuer à utiliser la fonction de balayage du Portefeuille QC, autoriser l'utilisation de caméra.", + "OpenSettings": "Ourvir Paramètres", + }, + "NearbyDevicesDisclosure": { + "AllowUse": "Autoriser l'utilisation de la caméra", + "Disclosure": "La caméra est utilisée pour capturer les codes QR qui initient une offre de justificatifs d'identité ou une demande de preuve. Aucune information de l'image n'est sauvegardée, utilisée pour les analyses, ou partagée.", + "ToContinueUsing": "Pour continuer à utiliser la fonction de balayage du Portefeuille QC, autoriser l'utilisation de caméra.", + "OpenSettings": "Ourvir Paramètres", + }, + "LocationDisclosure": { + "AllowUse": "Autoriser l'utilisation de la caméra", + "Disclosure": "La caméra est utilisée pour capturer les codes QR qui initient une offre de justificatifs d'identité ou une demande de preuve. Aucune information de l'image n'est sauvegardée, utilisée pour les analyses, ou partagée.", "ToContinueUsing": "Pour continuer à utiliser la fonction de balayage du Portefeuille QC, autoriser l'utilisation de caméra.", "OpenSettings": "Ourvir Paramètres", }, @@ -217,6 +229,13 @@ const translation = { "Continue": "Continuer", "EnterYourCurrentPIN": "Entrez votre NIP actuel" }, + "ScanBLE": { + "BluetoothText": "Please turn on Bluetooth to continue.", + "Text1": "Assurez-vous que Bluetooth est activé sur les deux appareils. Utilisez le bouton ci-dessous pour rechercher les appareils disponibles et envoyer une invitation à vous connecter.", + "Toggle": "Activer/Désactiver la découverte Bluetooth", + "ScanDevices": "Rechercher des appareils", + "MakeDiscoverable": "Rendre visible" + }, "PINEnter": { "EnterPIN": "Veuillez saisir votre NIP", "Unlock": "Déverrouiller", @@ -351,12 +370,12 @@ const translation = { "Torch": "Flash", "ScanHelp": "Scan Help (FR)", "ScanNow": "Scan Now (FR)", - "ScanOnySpecial": "Only special QR codes can be scanned by Bifold Wallet. (FR)", + "ScanOnySpecial": "Only special QR codes can be scanned by FHWA Wallet. (FR)", "ScanOnlySpecial2": "These are presented by participating services or people to receive a credential offer, request for information or to connect. (FR)", - "ScanOnlySpecial3": "Bifold Wallet currently doesn't support adding digital credential by scanning or taking photos of physical ones. (FR)", - "WhereToUseLink": "See where you can use Bifold Wallet (FR)", + "ScanOnlySpecial3": "FHWA Wallet currently doesn't support adding digital credential by scanning or taking photos of physical ones. (FR)", + "WhereToUseLink": "See where you can use FHWA Wallet (FR)", "BadQRCode": "QR Code Not Recognized (FR)", - "BadQRCodeDescription": "Ths QR code scanned doesn't work with Bifold Wallet. Bifold Wallet only works with participating services.\n\nIt currently can't add digital credentials by taking photos of physical ones. (FR)", + "BadQRCodeDescription": "This QR code scanned doesn't work with FHWA Wallet. FHWA Wallet only works with participating services.\n\nIt currently can't add digital credentials by taking photos of physical ones. (FR)", }, "Connection": { "JustAMoment": "Veuillez patienter pendant que nous établissons une connexion sécurisée...", @@ -506,7 +525,7 @@ const translation = { "Screens": { "Splash": "Page de garde", "Onboarding": "Inscription", - "Preface": "Aries Bifold", + "Preface": "FHWA", "Terms": "Conditions d'utilisation", "CreatePIN": "Créer un NIP à 6 chiffres", "EnterPIN": "Saisir le NIP", @@ -567,16 +586,16 @@ const translation = { }, "NetInfo": { "NoInternetConnectionTitle": "Aucune connexion Internet", - "NoInternetConnectionMessage": "Vous ne pouvez pas accéder aux services à l'aide de Bifold ou recevoir des informations d'identification tant que vous n'êtes pas de nouveau en ligne.\n\nS'il vous plait, vérifiez votre connexion internet.", + "NoInternetConnectionMessage": "Vous ne pouvez pas accéder aux services à l'aide de FHWA ou recevoir des informations d'identification tant que vous n'êtes pas de nouveau en ligne.\n\nS'il vous plait, vérifiez votre connexion internet.", "LedgerConnectivityIssueTitle": "Services de portefeuille", "LedgerConnectivityIssueMessage": "Il se peut qu'un pare-feu vous empêche de vous connecter aux services liés au portefeuille.", }, "Onboarding": { - "SkipA11y": "Skip introduction to Aries Bifold (FR)", + "SkipA11y": "Skip introduction to FHWA (FR)", }, "Preface": { "PrimaryHeading": "Is this app for you? (FR)", - "Paragraph1": "Most people will not have a need for Aries Bifold because very few digital credentials are currently available. (FR)", + "Paragraph1": "Most people will not have a need for FHWA because very few digital credentials are currently available. (FR)", "Confirmed": "I have confirmed that this app is for me. (FR)", }, "Chat": { diff --git a/packages/legacy/core/App/localization/pt-br/index.ts b/packages/legacy/core/App/localization/pt-br/index.ts index 1b2105e6..59be2911 100644 --- a/packages/legacy/core/App/localization/pt-br/index.ts +++ b/packages/legacy/core/App/localization/pt-br/index.ts @@ -136,8 +136,8 @@ const translation = { "Attestation": "Eu li, entendo e aceito os termos e condições.", }, "Tour": { - "GuideTitle": "Bem-vindo a Aries Bifold", - "WouldYouLike": "Gostaria de ver algumas instruções sobre como usar a Aries Bifold?", + "GuideTitle": "Bem-vindo a FHWA", + "WouldYouLike": "Gostaria de ver algumas instruções sobre como usar a FHWA?", "UseAppGuides": "Usar o guia do app", "DoNotUseAppGuides": "Não usar o guia do app", "AddAndShare": "Adicionar e compartilhar credenciais", @@ -158,9 +158,21 @@ const translation = { "Done": "Terminar", }, "CameraDisclosure": { - "AllowCameraUse": "Permitir uso da câmera", - "CameraDisclosure": "A câmera é usada para escanear QR Codes para processamento imediato no dispositivo. Nenhuma informação sobre as imagens é armazenada, usada para análise, ou compartilhada.", - "ToContinueUsing": "Para continuar usando a funcionalidade de scan da Aries Bifold, favor permitir o uso da câmera.", + "AllowUse": "Permitir uso da câmera", + "Disclosure": "A câmera é usada para escanear QR Codes para processamento imediato no dispositivo. Nenhuma informação sobre as imagens é armazenada, usada para análise, ou compartilhada.", + "ToContinueUsing": "Para continuar usando a funcionalidade de scan da FHWA, favor permitir o uso da câmera.", + "OpenSettings": "Abrir as configurações", + }, + "NearbyDevicesDisclosure": { + "AllowUse": "Permitir uso da câmera", + "Disclosure": "A câmera é usada para escanear QR Codes para processamento imediato no dispositivo. Nenhuma informação sobre as imagens é armazenada, usada para análise, ou compartilhada.", + "ToContinueUsing": "Para continuar usando a funcionalidade de scan da FHWA, favor permitir o uso da câmera.", + "OpenSettings": "Abrir as configurações", + }, + "LocationDisclosure": { + "AllowUse": "Permitir uso da câmera", + "Disclosure": "A câmera é usada para escanear QR Codes para processamento imediato no dispositivo. Nenhuma informação sobre as imagens é armazenada, usada para análise, ou compartilhada.", + "ToContinueUsing": "Para continuar usando a funcionalidade de scan da FHWA, favor permitir o uso da câmera.", "OpenSettings": "Abrir as configurações", }, "PINCreate": { @@ -211,6 +223,13 @@ const translation = { "Continue": "Continuar", "EnterYourCurrentPIN": "Digite seu PIN atual." }, + "ScanBLE": { + "BluetoothText": "Please turn on Bluetooth to continue.", + "Text1": "Certifique-se de que o Bluetooth esteja ativado em ambos os dispositivos. Use o botão abaixo para procurar dispositivos disponíveis e enviar um convite para conexão.", + "Toggle": "Alternar descoberta de Bluetooth", + "ScanDevices": "Procurar dispositivos", + "MakeDiscoverable": "Tornar detectável" + }, "PINEnter": { "EnterPIN": "Digitar PIN", "Unlock": "Destravar", @@ -333,12 +352,12 @@ const translation = { "Torch": "Flash", "ScanHelp": "Scan Help (PB)", "ScanNow": "Scan Now (PB)", - "ScanOnySpecial": "Only special QR codes can be scanned by Bifold Wallet. (PB)", + "ScanOnySpecial": "Only special QR codes can be scanned by FHWA Wallet. (PB)", "ScanOnlySpecial2": "These are presented by participating services or people to receive a credential offer, request for information or to connect. (PB)", - "ScanOnlySpecial3": "Bifold Wallet currently doesn't support adding digital credential by scanning or taking photos of physical ones. (PB)", - "WhereToUseLink": "See where you can use Bifold Wallet (PB)", + "ScanOnlySpecial3": "FHWA Wallet currently doesn't support adding digital credential by scanning or taking photos of physical ones. (PB)", + "WhereToUseLink": "See where you can use FHWA Wallet (PB)", "BadQRCode": "QR Code Not Recognized (PB)", - "BadQRCodeDescription": "Ths QR code scanned doesn't work with Bifold Wallet. Bifold Wallet only works with participating services.\n\nIt currently can't add digital credentials by taking photos of physical ones. (PB)", + "BadQRCodeDescription": "This QR code scanned doesn't work with FHWA Wallet. FHWA Wallet only works with participating services.\n\nIt currently can't add digital credentials by taking photos of physical ones. (PB)", }, "Connection": { "JustAMoment": "Aguarde um momento enquanto fazemos uma conexão segura...", @@ -491,7 +510,7 @@ const translation = { "Screens": { "Splash": "Splash", "Onboarding": "Onboarding", - "Preface": "Aries Bifold", + "Preface": "FHWA", "Terms": "Termos & Condições", "CreatePIN": "Criar um PIN", "EnterPIN": "Digitar o PIN", @@ -545,16 +564,16 @@ const translation = { }, "NetInfo": { "NoInternetConnectionTitle": "Sem conexão com a internet", - "NoInternetConnectionMessage": "Não é possivel acessar serviços utilizando a Bifold ou receber credenciais até você voltar a estar online.\n\nFavor checkar sua conexão com a internet.", + "NoInternetConnectionMessage": "Não é possivel acessar serviços utilizando a FHWA ou receber credenciais até você voltar a estar online.\n\nFavor checkar sua conexão com a internet.", "LedgerConnectivityIssueTitle": "Serviços de Carteira", "LedgerConnectivityIssueMessage": "Um firewall pode estar te impedindo de conectar-se a serviços relacionados a carteira.", }, "Onboarding": { - "SkipA11y": "Pular introdução a Aries Bifold", + "SkipA11y": "Pular introdução a FHWA", }, "Preface": { "PrimaryHeading": "Is this app for you? (PT-BR)", - "Paragraph1": "Most people will not have a need for Aries Bifold because very few digital credentials are currently available. (PT-BR)", + "Paragraph1": "Most people will not have a need for FHWA because very few digital credentials are currently available. (PT-BR)", "Confirmed": "I have confirmed that this app is for me. (PT-BR)", }, "Chat": { diff --git a/packages/legacy/core/App/navigators/ContactStack.tsx b/packages/legacy/core/App/navigators/ContactStack.tsx index e47290f9..c71dd16d 100644 --- a/packages/legacy/core/App/navigators/ContactStack.tsx +++ b/packages/legacy/core/App/navigators/ContactStack.tsx @@ -11,8 +11,11 @@ import CredentialOffer from '../screens/CredentialOffer' import ListContacts from '../screens/ListContacts' import ProofDetails from '../screens/ProofDetails' import ProofRequest from '../screens/ProofRequest' +import ProofRequestDetails from '../screens/ProofRequestDetails' import QRCodeGen from '../screens/QRCodeGen' import RenameContact from '../screens/RenameContact' +import ScanBLE from '../screens/ScanBLE' +import SelectProofRequest from '../screens/SelectProofRequest' import WhatAreContacts from '../screens/WhatAreContacts' import { ContactStackParams, Screens } from '../types/navigators' @@ -39,8 +42,19 @@ const ContactStack: React.FC = () => { component={RenameContact} options={{ title: t('Screens.RenameContact') }} /> + + + { component={ListProofRequests} options={{ title: t('Screens.ChooseProofRequest') }} /> + = ({ route }) => { const navigation = useNavigation>() const connection = useConnectionById(connectionId) const basicMessages = useBasicMessagesByConnectionId(connectionId) + + // eslint-disable-next-line no-console + // console.error(basicMessages) const credentials = useCredentialsByConnectionId(connectionId) const proofs = useProofsByConnectionId(connectionId) const isFocused = useIsFocused() @@ -63,7 +66,6 @@ const Chat: React.FC = ({ route }) => { const { ColorPallet } = useTheme() const [theirLabel, setTheirLabel] = useState(getConnectionName(connection, store.preferences.alternateContactNames)) - // This useEffect is for properly rendering changes to the alt contact name, useMemo did not pick them up useEffect(() => { setTheirLabel(getConnectionName(connection, store.preferences.alternateContactNames)) }, [isFocused, connection, store.preferences.alternateContactNames]) @@ -111,7 +113,7 @@ const Chat: React.FC = ({ route }) => { if (i < links.length) { const link = links[i] return ( - <> + {split} handleLinkPress(link)} @@ -120,13 +122,14 @@ const Chat: React.FC = ({ route }) => { > {link} - + ) } return {split} })} ) + return { _id: record.id, text: record.content, @@ -270,6 +273,8 @@ const Chat: React.FC = ({ route }) => { const onSend = useCallback( async (messages: IMessage[]) => { + // eslint-disable-next-line no-console + // console.error(messages) await agent?.basicMessages.sendMessage(connectionId, messages[0].text) }, [agent, connectionId] @@ -277,24 +282,23 @@ const Chat: React.FC = ({ route }) => { const onSendRequest = useCallback(async () => { navigation.navigate(Stacks.ProofRequestsStack as any, { - screen: Screens.ProofRequests, + // screen: Screens.ProofRequests, + screen: Screens.SelectProofRequest, params: { navigation: navigation, connectionId }, }) }, [navigation, connectionId]) const actions = useMemo(() => { - return store.preferences.useVerifierCapability - ? [ - { - text: t('Verifier.SendProofRequest'), - onPress: () => { - setShowActionSlider(false) - onSendRequest() - }, - icon: () => , - }, - ] - : undefined + return [ + { + text: t('Verifier.SendProofRequest'), + onPress: () => { + setShowActionSlider(false) + onSendRequest() + }, + icon: () => , + }, + ] }, [t, store.preferences.useVerifierCapability, onSendRequest]) const onDismiss = () => { @@ -309,7 +313,7 @@ const Chat: React.FC = ({ route }) => { alignTop renderAvatar={() => null} messageIdGenerator={(msg) => msg?._id.toString() || '0'} - renderMessage={(props) => } + renderMessage={(props) => } renderInputToolbar={(props) => renderInputToolbar(props, theme)} renderSend={(props) => renderSend(props, theme)} renderComposer={(props) => renderComposer(props, theme, t('Contacts.TypeHere'))} diff --git a/packages/legacy/core/App/screens/Connection.tsx b/packages/legacy/core/App/screens/Connection.tsx index 6f83a430..b8da00d6 100644 --- a/packages/legacy/core/App/screens/Connection.tsx +++ b/packages/legacy/core/App/screens/Connection.tsx @@ -64,6 +64,7 @@ const Connection: React.FC = ({ navigation, route }) => { }, messageText: { fontWeight: TextTheme.normal.fontWeight, + color: ColorPallet.grayscale.black, textAlign: 'center', marginTop: 30, }, diff --git a/packages/legacy/core/App/screens/ContactDetails.tsx b/packages/legacy/core/App/screens/ContactDetails.tsx index b58848b6..b01527c0 100644 --- a/packages/legacy/core/App/screens/ContactDetails.tsx +++ b/packages/legacy/core/App/screens/ContactDetails.tsx @@ -13,6 +13,7 @@ import { ToastType } from '../components/toast/BaseToast' import { EventTypes } from '../constants' import { useStore } from '../contexts/store' import { useTheme } from '../contexts/theme' +// import { useConnectionByOutOfBandId } from '../hooks/connections' import { BifoldError } from '../types/error' import { ContactStackParams, Screens, TabStacks } from '../types/navigators' import { ModalUsage } from '../types/remove' @@ -22,6 +23,7 @@ import { testIdWithKey } from '../utils/testable' type ContactDetailsProps = StackScreenProps const ContactDetails: React.FC = ({ route }) => { + // eslint-disable-next-line no-unsafe-optional-chaining const { connectionId } = route?.params const { agent } = useAgent() const { t } = useTranslation() @@ -91,7 +93,13 @@ const ContactDetails: React.FC = ({ route }) => { navigation.navigate(Screens.RenameContact, { connectionId }) } + const handleGoToSelect = () => { + navigation.navigate(Screens.SelectProofRequest, { connectionId }) + // useConnectionByOutOfBandId() + } + const callGoToRename = useCallback(() => handleGoToRename(), []) + const callGoToProofSelection = useCallback(() => handleGoToSelect(), []) const callOnRemove = useCallback(() => handleOnRemove(), []) const callSubmitRemove = useCallback(() => handleSubmitRemove(), []) const callCancelRemove = useCallback(() => handleCancelRemove(), []) @@ -122,6 +130,15 @@ const ContactDetails: React.FC = ({ route }) => { > {t('Screens.RenameContact')} + + {t('Screens.SelectProofRequest')} + = ({ navigation, route const styles = StyleSheet.create({ container: { - backgroundColor: overlay.brandingOverlay?.primaryBackgroundColor, + backgroundColor: '#113B51', //hardcode overlay.brandingOverlay?.primaryBackgroundColor, display: 'flex', }, secondaryHeaderContainer: { height: 1.5 * logoHeight, - backgroundColor: - (overlay.brandingOverlay?.backgroundImage - ? 'rgba(0, 0, 0, 0)' - : overlay.brandingOverlay?.secondaryBackgroundColor) ?? 'rgba(0, 0, 0, 0.24)', + backgroundColor: '#0D2D3E', //hardcode (overlay.brandingOverlay?.backgroundImage ? 'rgba(0, 0, 0, 0)' : overlay.brandingOverlay?.secondaryBackgroundColor) ?? 'rgba(0, 0, 0, 0.24)', }, primaryHeaderContainer: { paddingHorizontal, @@ -256,10 +254,11 @@ const CredentialDetails: React.FC = ({ navigation, route styles.textContainer, { lineHeight: 24, + fontWeight: 'bold', }, ]} > - {overlay.metaOverlay?.name} + {overlay.metaOverlay?.name?.toUpperCase()} diff --git a/packages/legacy/core/App/screens/CredentialOffer.tsx b/packages/legacy/core/App/screens/CredentialOffer.tsx index 25ad0c0b..af2562e9 100644 --- a/packages/legacy/core/App/screens/CredentialOffer.tsx +++ b/packages/legacy/core/App/screens/CredentialOffer.tsx @@ -114,6 +114,7 @@ const CredentialOffer: React.FC = ({ navigation, route }) } const updateCredentialPreview = async () => { + // eslint-disable-next-line no-unsafe-optional-chaining const { ...formatData } = await agent?.credentials.getFormatData(credential.id) const { offer, offerAttributes } = formatData const offerData = offer?.anoncreds ?? offer?.indy diff --git a/packages/legacy/core/App/screens/CredentialOfferAccept.tsx b/packages/legacy/core/App/screens/CredentialOfferAccept.tsx index 1d5bea98..bc8b5559 100644 --- a/packages/legacy/core/App/screens/CredentialOfferAccept.tsx +++ b/packages/legacy/core/App/screens/CredentialOfferAccept.tsx @@ -33,7 +33,7 @@ const CredentialOfferAccept: React.FC = ({ visible, const [timer, setTimer] = useState() const credential = useCredentialById(credentialId) const navigation = useNavigation() - const { ListItems } = useTheme() + const { ListItems, ColorPallet } = useTheme() const { CredentialAdded, CredentialPending } = useAnimatedComponents() const { connectionTimerDelay } = useConfiguration() const connTimerDelay = connectionTimerDelay ?? 10000 // in ms @@ -52,6 +52,7 @@ const CredentialOfferAccept: React.FC = ({ visible, messageText: { textAlign: 'center', marginTop: 30, + color: ColorPallet.grayscale.black, }, controlsContainer: { marginTop: 'auto', diff --git a/packages/legacy/core/App/screens/ListContacts.tsx b/packages/legacy/core/App/screens/ListContacts.tsx index d70d3ad6..107c57ab 100644 --- a/packages/legacy/core/App/screens/ListContacts.tsx +++ b/packages/legacy/core/App/screens/ListContacts.tsx @@ -38,6 +38,16 @@ const ListContacts: React.FC = ({ navigation }) => { connections = records.filter((r) => !r.connectionTypes.includes(ConnectionType.Mediator)) } + // Sort connections by updatedAt + connections.sort((a, b) => { + // Convert updatedAt to Date objects, handling potential undefined values + const dateA = a.updatedAt ? new Date(a.updatedAt) : new Date(0) + const dateB = b.updatedAt ? new Date(b.updatedAt) : new Date(0) + + // Compare dates + return dateB.getTime() - dateA.getTime() + }) + const onPressAddContact = () => { navigation.getParent()?.navigate(Stacks.ConnectStack, { screen: Screens.Scan, params: { defaultToConnect: true } }) } diff --git a/packages/legacy/core/App/screens/ListCredentials.tsx b/packages/legacy/core/App/screens/ListCredentials.tsx index 32f77fb3..26ba80e0 100644 --- a/packages/legacy/core/App/screens/ListCredentials.tsx +++ b/packages/legacy/core/App/screens/ListCredentials.tsx @@ -46,7 +46,6 @@ const ListCredentials: React.FC = () => { return stop }, [screenIsFocused]) - return ( { + const { ColorPallet } = useTheme() + const styles = StyleSheet.create({ + container: { + flex: 1, + backgroundColor: ColorPallet.brand.secondaryBackground, + }, + map: { + width: '100%', + height: '100%', + }, + }) + + return ( + + + + + + ) +} + +export default Maps diff --git a/packages/legacy/core/App/screens/ProofDetails.tsx b/packages/legacy/core/App/screens/ProofDetails.tsx index 9e32ec4e..ad474e65 100644 --- a/packages/legacy/core/App/screens/ProofDetails.tsx +++ b/packages/legacy/core/App/screens/ProofDetails.tsx @@ -1,3 +1,4 @@ +/* eslint-disable no-unsafe-optional-chaining */ import type { StackScreenProps } from '@react-navigation/stack' import { ProofExchangeRecord, ProofState } from '@aries-framework/core' diff --git a/packages/legacy/core/App/screens/ProofRequest.tsx b/packages/legacy/core/App/screens/ProofRequest.tsx index 117debc6..966ca57a 100644 --- a/packages/legacy/core/App/screens/ProofRequest.tsx +++ b/packages/legacy/core/App/screens/ProofRequest.tsx @@ -1,3 +1,5 @@ +/* eslint-disable import/no-named-as-default-member */ +/* eslint-disable no-unsafe-optional-chaining */ import type { StackScreenProps } from '@react-navigation/stack' import { diff --git a/packages/legacy/core/App/screens/ProofRequestDetails.tsx b/packages/legacy/core/App/screens/ProofRequestDetails.tsx index 6a3e07c4..e69141dc 100644 --- a/packages/legacy/core/App/screens/ProofRequestDetails.tsx +++ b/packages/legacy/core/App/screens/ProofRequestDetails.tsx @@ -207,7 +207,7 @@ const ProofRequestAttributesCard: React.FC = ( ) } -const ProofRequestDetails: React.FC = ({ route, navigation }) => { +const ProofRequestDetails: React.FC = ({ navigation }) => { const { ColorPallet, TextTheme } = useTheme() const [store] = useStore() const { t } = useTranslation() @@ -218,6 +218,7 @@ const ProofRequestDetails: React.FC = ({ route, naviga if (!agent) { throw new Error('Unable to fetch agent from AFJ') } + const templateId = 'Aries:5:VerifiedFullName:0.0.1:indy' const style = StyleSheet.create({ container: { @@ -245,7 +246,7 @@ const ProofRequestDetails: React.FC = ({ route, naviga }, }) - const { templateId, connectionId } = route?.params + const connectionId = '4449b08e-b3f8-4c5d-98c2-91e0f9093328' const [meta, setMeta] = useState(undefined) const [attributes, setAttributes] = useState | undefined>(undefined) diff --git a/packages/legacy/core/App/screens/QRCodeGen.tsx b/packages/legacy/core/App/screens/QRCodeGen.tsx index 3ce41e6b..8dc6dc65 100644 --- a/packages/legacy/core/App/screens/QRCodeGen.tsx +++ b/packages/legacy/core/App/screens/QRCodeGen.tsx @@ -1,50 +1,156 @@ -import { NavigationProp, ParamListBase } from '@react-navigation/native' -import React from 'react' -import { useTranslation } from 'react-i18next' -import { SafeAreaView, ScrollView, StyleSheet, Text, View } from 'react-native' -import QRCode from 'react-native-qrcode-svg' - -import Link from '../components/texts/Link' -import { useTheme } from '../contexts/theme' -import { Screens, Stacks } from '../types/navigators' - -interface WhatAreContactsProps { - navigation: NavigationProp -} - -const QRCodeGen: React.FC = () => { - const { ColorPallet, TextTheme } = useTheme() - const { t } = useTranslation() - const styles = StyleSheet.create({ - container: { - flex: 1, - alignItems: 'center', - backgroundColor: ColorPallet.brand.primaryBackground, - }, - title: { - ...TextTheme.headingTwo, - marginBottom: 15, - }, - pageContent: { - marginTop: 30, - paddingLeft: 25, - paddingRight: 25, - }, - }) - - return ( - - - Scan the QR Code - - - - ) -} - -export default QRCodeGen +import { DidExchangeState } from '@aries-framework/core' +import { useAgent } from '@aries-framework/react-hooks' +import { StackScreenProps } from '@react-navigation/stack' +import React, { useCallback, useEffect, useState } from 'react' +import { useTranslation } from 'react-i18next' +import { View, StyleSheet, Text, ScrollView, useWindowDimensions } from 'react-native' +import { TouchableOpacity } from 'react-native-gesture-handler' +import { SafeAreaView } from 'react-native-safe-area-context' +import Icon from 'react-native-vector-icons/MaterialIcons' + +import LoadingIndicator from '../components/animated/LoadingIndicator' +import QRRenderer from '../components/misc/QRRenderer' +import { domain } from '../constants' +import { useStore } from '../contexts/store' +import { useTheme } from '../contexts/theme' +import { useConnectionByOutOfBandId } from '../hooks/connections' +import { QrCodeScanError } from '../types/error' +import { Screens, Stacks, ConnectStackParams } from '../types/navigators' +import { createConnectionInvitation } from '../utils/helpers' +import { testIdWithKey } from '../utils/testable' + +type ConnectProps = StackScreenProps + +interface Props extends ConnectProps { + defaultToConnect: boolean + handleCodeScan: (value: string) => Promise + error?: QrCodeScanError | null + enableCameraOnError?: boolean +} + +const QRCodeGen: React.FC = ({ navigation }) => { + const { width } = useWindowDimensions() + const qrSize = width - 40 + const [store] = useStore() + const [invitation, setInvitation] = useState(undefined) + const [recordId, setRecordId] = useState(undefined) + const { t } = useTranslation() + const { ColorPallet, TextTheme, TabTheme } = useTheme() + const { agent } = useAgent() + + const styles = StyleSheet.create({ + container: { + flex: 1, + backgroundColor: ColorPallet.brand.secondaryBackground, + }, + camera: { + flex: 1, + justifyContent: 'center', + alignItems: 'center', + }, + cameraViewContainer: { + alignItems: 'center', + flex: 1, + width: '100%', + }, + viewFinder: { + width: 250, + height: 250, + borderRadius: 24, + borderWidth: 2, + borderColor: ColorPallet.grayscale.white, + }, + viewFinderContainer: { + flex: 1, + width: '100%', + justifyContent: 'center', + alignItems: 'center', + }, + errorContainer: { + flexDirection: 'row', + alignItems: 'center', + marginTop: 20, + paddingHorizontal: 20, + }, + icon: { + color: ColorPallet.grayscale.white, + padding: 4, + }, + tabContainer: { + flexDirection: 'row', + ...TabTheme.tabBarStyle, + }, + qrContainer: { + marginTop: 10, + flex: 1, + }, + walletName: { + ...TextTheme.headingTwo, + textAlign: 'center', + marginBottom: 20, + }, + secondaryText: { + ...TextTheme.normal, + textAlign: 'center', + }, + editButton: { ...TextTheme.headingTwo, marginBottom: 20, marginLeft: 10, color: ColorPallet.brand.primary }, + }) + + const createInvitation = useCallback(async () => { + setInvitation(undefined) + const result = await createConnectionInvitation(agent) + if (result) { + setRecordId(result.record.id) + setInvitation(result.record.outOfBandInvitation.toUrl({ domain })) + } + }, []) + + const handleEdit = () => { + navigation.navigate(Screens.NameWallet) + } + + useEffect(() => { + createInvitation() + }, []) + + const record = useConnectionByOutOfBandId(recordId || '') + + useEffect(() => { + if (record?.state === DidExchangeState.Completed) { + navigation.getParent()?.navigate(Stacks.ConnectionStack, { + screen: Screens.Connection, + params: { connectionId: record.id }, + }) + } + }, [record]) + + return ( + + + + + {!invitation && } + {invitation && } + + + + + {store.preferences.walletName} + + + + + + {t('Connection.ShareQR')} + + + + + ) +} + +export default QRCodeGen diff --git a/packages/legacy/core/App/screens/Scan.tsx b/packages/legacy/core/App/screens/Scan.tsx index b0de4e2f..4f8413d6 100644 --- a/packages/legacy/core/App/screens/Scan.tsx +++ b/packages/legacy/core/App/screens/Scan.tsx @@ -8,14 +8,14 @@ import Toast from 'react-native-toast-message' import NewQRView from '../components/misc/NewQRView' import QRScanner from '../components/misc/QRScanner' -import CameraDisclosureModal from '../components/modals/CameraDisclosureModal' +import PermissionDisclosureModal from '../components/modals/PermissionDisclosureModal' import { ToastType } from '../components/toast/BaseToast' import LoadingView from '../components/views/LoadingView' import { useStore } from '../contexts/store' -import { BifoldError, QrCodeScanError } from '../types/error' -import { ConnectStackParams, Screens, Stacks } from '../types/navigators' +import { QrCodeScanError } from '../types/error' +import { ConnectStackParams } from '../types/navigators' import { PermissionContract } from '../types/permissions' -import { connectFromInvitation, getJson, getUrl, receiveMessageFromUrlRedirect } from '../utils/helpers' +import { handleInvitation } from '../utils/invitation' export type ScanProps = StackScreenProps @@ -30,74 +30,12 @@ const Scan: React.FC = ({ navigation, route }) => { if (route?.params && route.params['defaultToConnect']) { defaultToConnect = route.params['defaultToConnect'] } - let implicitInvitations = false - if (route?.params && route.params['implicitInvitations']) { - implicitInvitations = route.params['implicitInvitations'] - } - let reuseConnections = false - if (route?.params && route.params['reuseConnections']) { - reuseConnections = route.params['reuseConnections'] - } - - const handleInvitation = async (value: string): Promise => { - try { - const receivedInvitation = await connectFromInvitation(value, agent, implicitInvitations, reuseConnections) - if (receivedInvitation?.connectionRecord?.id) { - // not connectionless - navigation.getParent()?.navigate(Stacks.ConnectionStack, { - screen: Screens.Connection, - params: { connectionId: receivedInvitation.connectionRecord.id }, - }) - } else { - //connectionless - navigation.navigate(Stacks.ConnectionStack as any, { - screen: Screens.Connection, - params: { threadId: receivedInvitation?.outOfBandRecord.outOfBandInvitation.threadId }, - }) - } - } catch (err: unknown) { - // [Error: Connection does not have an ID] - // [AriesFrameworkError: An out of band record with invitation 05fe3693-2c12-4165-a3b6-370280ccd43b has already been received. Invitations should have a unique id.] - try { - // if scanned value is json -> pass into AFJ as is - const json = getJson(value) - if (json) { - await agent?.receiveMessage(json) - navigation.getParent()?.navigate(Stacks.ConnectionStack, { - screen: Screens.Connection, - params: { threadId: json['@id'] }, - }) - return - } - - // if scanned value is url -> receive message from it - const url = getUrl(value) - if (url) { - const message = await receiveMessageFromUrlRedirect(value, agent) - navigation.getParent()?.navigate(Stacks.ConnectionStack, { - screen: Screens.Connection, - params: { threadId: message['@id'] }, - }) - return - } - } catch (err: unknown) { - const error = new BifoldError( - t('Error.Title1031'), - t('Error.Message1031'), - (err as Error)?.message ?? err, - 1031 - ) - // throwing for QrCodeScanError - throw error - } - } - } const handleCodeScan = async (value: string) => { setQrCodeScanError(null) try { const uri = value - await handleInvitation(uri) + await handleInvitation(navigation, route, agent, uri) } catch (e: unknown) { const error = new QrCodeScanError(t('Scan.InvalidQrCode'), value) setQrCodeScanError(error) @@ -156,7 +94,7 @@ const Scan: React.FC = ({ navigation, route }) => { } if (showDisclosureModal) { - return + return } if (store.preferences.useConnectionInviterCapability) { diff --git a/packages/legacy/core/App/screens/ScanBLE.tsx b/packages/legacy/core/App/screens/ScanBLE.tsx new file mode 100644 index 00000000..ec105532 --- /dev/null +++ b/packages/legacy/core/App/screens/ScanBLE.tsx @@ -0,0 +1,102 @@ +/* eslint-disable no-console */ +import React, { useEffect, useState } from 'react' +import { useTranslation } from 'react-i18next' +import { Platform } from 'react-native' +import { PERMISSIONS, Permission, RESULTS, Rationale, checkMultiple, requestMultiple } from 'react-native-permissions' +import Toast from 'react-native-toast-message' + +import BLEScanner from '../components/misc/BLEScanner' +import PermissionDisclosureModal, { DisclosureTypes } from '../components/modals/PermissionDisclosureModal' +import { ToastType } from '../components/toast/BaseToast' +import LoadingView from '../components/views/LoadingView' +import { MultiplePermissionContract } from '../types/permissions' + +import { ScanProps } from './Scan' + +const ScanBLE: React.FC = ({ navigation, route }) => { + const [loading, setLoading] = useState(true) + const [showDisclosureModal, setShowDisclosureModal] = useState(true) + const [disclosureType, setDisclosureType] = useState('NearbyDevicesDisclosure') + const { t } = useTranslation() + + const permissionFlow = async ( + method: MultiplePermissionContract, + permission: Permission[], + rationale?: Rationale + ): Promise => { + try { + const permissionResult = await method(permission, rationale) + let allPermissionsGranted = false + if (Object.values(permissionResult).length) { + allPermissionsGranted = Object.values(permissionResult).every((permission) => permission === RESULTS.GRANTED) + } + + if (allPermissionsGranted) { + setShowDisclosureModal(false) + return true + } + } catch (error: unknown) { + Toast.show({ + type: ToastType.Error, + text1: t('Global.Failure'), + text2: (error as Error)?.message || t('Error.Unknown'), + visibilityTime: 2000, + position: 'bottom', + }) + } + + return false + } + + useEffect(() => { + const asyncEffect = async () => { + if (Platform.OS === 'android') { + const isAndroid12OrAbove = Platform.Version >= 31 + + const permissions = [ + PERMISSIONS.ANDROID.BLUETOOTH_SCAN, + PERMISSIONS.ANDROID.BLUETOOTH_CONNECT, + PERMISSIONS.ANDROID.BLUETOOTH_ADVERTISE, + ] + + setDisclosureType(isAndroid12OrAbove ? 'NearbyDevicesDisclosure' : 'LocationDisclosure') + await permissionFlow(checkMultiple, permissions) + } else if (Platform.OS === 'ios') { + await permissionFlow(checkMultiple, [PERMISSIONS.IOS.BLUETOOTH_PERIPHERAL]) + } + setLoading(false) + } + + asyncEffect() + }, []) + + const requestBLEUse = async (rationale?: Rationale): Promise => { + if (Platform.OS === 'android') { + const isAndroid12OrAbove = Platform.Version >= 31 + + const permissions = [ + PERMISSIONS.ANDROID.BLUETOOTH_SCAN, + PERMISSIONS.ANDROID.BLUETOOTH_CONNECT, + PERMISSIONS.ANDROID.BLUETOOTH_ADVERTISE, + ] + + return await permissionFlow(requestMultiple, permissions, rationale) + } else if (Platform.OS === 'ios') { + return await permissionFlow(requestMultiple, [PERMISSIONS.IOS.BLUETOOTH_PERIPHERAL], rationale) + } + + return false + } + + if (loading) { + return + } + + if (showDisclosureModal) { + return + } else { + return + } +} + +export default ScanBLE diff --git a/packages/legacy/core/App/screens/SelectProofRequest.tsx b/packages/legacy/core/App/screens/SelectProofRequest.tsx new file mode 100644 index 00000000..c8a18355 --- /dev/null +++ b/packages/legacy/core/App/screens/SelectProofRequest.tsx @@ -0,0 +1,170 @@ +/* eslint-disable no-console */ +import { useAgent } from '@aries-framework/react-hooks' +import { linkProofWithTemplate, sendProofRequest, useProofRequestTemplates } from '@hyperledger/aries-bifold-verifier' +// import { useNavigation } from '@react-navigation/core' +import React, { useState } from 'react' +import { useTranslation } from 'react-i18next' +import { View, StyleSheet, ScrollView } from 'react-native' +import { SafeAreaView } from 'react-native-safe-area-context' + +import Button, { ButtonType } from '../components/buttons/Button' +import CheckBoxRow from '../components/inputs/CheckBoxRow' +import { useTheme } from '../contexts/theme' +import { Screens } from '../types/navigators' +import { testIdWithKey } from '../utils/testable' + +const initialState = false + +const SelectProofRequest = ({ navigation, route }: { navigation: any; route: any }) => { + const { OnboardingTheme } = useTheme() + // const navigation = useNavigation() + + if (!route?.params) { + throw new Error('ProofRequest route prams were not set properly') + } + + const { connectionId } = route.params + // const templateId = 1 + + // const [selectedFields, setSelectedFields] = useState(initialState) + const [vehicleName, setvehicleName] = useState(initialState) + const [vehicleOwner, setvehicleOwner] = useState(initialState) + const [expiryDate, setexpiryDate] = useState(initialState) + const [stateIssued, setstateIssued] = useState(initialState) + + console.log(connectionId) + console.log(vehicleName) + const { t } = useTranslation() + + const style = StyleSheet.create({ + container: { + ...OnboardingTheme.container, + padding: 20, + }, + controlsContainer: { + marginTop: 'auto', + marginBottom: 20, + }, + marginView: { + marginTop: 10, + marginBottom: 10, + }, + }) + + const { agent } = useAgent() + if (!agent) { + throw new Error('Unable to fetch agent from AFJ') + } + + // const [customPredicateValues, setCustomPredicateValues] = useState>>({}) + + const useProofRequest = () => { + const selectedArray = [] + if (vehicleName) selectedArray.push('vehicle_information') + + if (vehicleOwner) selectedArray.push('vehicle_owner') + + if (stateIssued) selectedArray.push('state_issued') + + if (connectionId) { + if (!expiryDate) { + sendProofRequest(agent, useProofRequestTemplates(false, selectedArray)[0], connectionId, {}).then((result) => { + if (result?.proofRecord) linkProofWithTemplate(agent, result.proofRecord, '1') + }) + } else { + sendProofRequest(agent, useProofRequestTemplates(false, selectedArray)[1], connectionId, {}).then((result) => { + if (result?.proofRecord) linkProofWithTemplate(agent, result.proofRecord, '2') + }) + } + setvehicleName(false) + setvehicleOwner(false) + setexpiryDate(false) + navigation.getParent()?.navigate(Screens.Chat, { connectionId }) + // } else { + // Else redirect to the screen with connectionless request + // navigation.navigate(Screens.ProofRequesting, { templateId, predicateValues: customPredicateValues }) + } + } + + return ( + + + + + { + setvehicleName(!vehicleName) + }} + // onPress={() => + // setSelectedFields((prevVal) => { + // return { + // ...prevVal, + // vehicleName: !prevVal.vehicleName, + // } + // }) + // } + /> + + + setvehicleOwner(!vehicleOwner)} + // onPress={() => + // setSelectedFields((prevVal) => { + // return { + // ...prevVal, + // vehicleOwner: !prevVal.vehicleOwner, + // } + // }) + // } + /> + + + setstateIssued((prev) => !prev)} + // onPress={() => + // setSelectedFields((prevVal) => { + // return { + // ...prevVal, + // expiry_date: !prevVal.expiry_date, + // } + // }) + // } + /> + + + setexpiryDate((prev) => !prev)} + // onPress={() => + // setSelectedFields((prevVal) => { + // return { + // ...prevVal, + // expiry_date: !prevVal.expiry_date, + // } + // }) + // } + /> + + + + + + + ) +} + +export default SelectProofRequest diff --git a/packages/legacy/core/App/screens/Settings.tsx b/packages/legacy/core/App/screens/Settings.tsx index f7b9d30a..69ba49de 100644 --- a/packages/legacy/core/App/screens/Settings.tsx +++ b/packages/legacy/core/App/screens/Settings.tsx @@ -1,5 +1,5 @@ import { StackScreenProps } from '@react-navigation/stack' -import React, { useRef } from 'react' +import React from 'react' import { useTranslation } from 'react-i18next' import { ScrollView, @@ -15,7 +15,7 @@ import { SafeAreaView } from 'react-native-safe-area-context' import Icon from 'react-native-vector-icons/MaterialIcons' import { useConfiguration } from '../contexts/configuration' -import { DispatchAction } from '../contexts/reducers/store' +// import { DispatchAction } from '../contexts/reducers/store' import { useStore } from '../contexts/store' import { useTheme } from '../contexts/theme' import { Locales } from '../localization' @@ -26,12 +26,12 @@ import { testIdWithKey } from '../utils/testable' type SettingsProps = StackScreenProps -const touchCountToEnableBiometrics = 9 +// const touchCountToEnableBiometrics = 9 const Settings: React.FC = ({ navigation }) => { const { t, i18n } = useTranslation() - const [store, dispatch] = useStore() - const developerOptionCount = useRef(0) + const [store /*, dispatch*/] = useStore() + // const developerOptionCount = useRef(0) const { SettingsTheme, TextTheme, ColorPallet, Assets } = useTheme() const { settings, enableTours } = useConfiguration() const defaultIconSize = 24 @@ -80,19 +80,19 @@ const Settings: React.FC = ({ navigation }) => { const currentLanguage = i18n.t('Language.code', { context: i18n.language as Locales }) - const incrementDeveloperMenuCounter = () => { - if (developerOptionCount.current >= touchCountToEnableBiometrics) { - developerOptionCount.current = 0 - dispatch({ - type: DispatchAction.ENABLE_DEVELOPER_MODE, - payload: [true], - }) + // const incrementDeveloperMenuCounter = () => { + // if (developerOptionCount.current >= touchCountToEnableBiometrics) { + // developerOptionCount.current = 0 + // dispatch({ + // type: DispatchAction.ENABLE_DEVELOPER_MODE, + // payload: [true], + // }) - return - } + // return + // } - developerOptionCount.current = developerOptionCount.current + 1 - } + // developerOptionCount.current = developerOptionCount.current + 1 + // } const settingsSections: SettingSection[] = [ { @@ -134,6 +134,20 @@ const Settings: React.FC = ({ navigation }) => { onPress: () => navigation.getParent()?.navigate(Stacks.ContactStack, { screen: Screens.QRCodeGen }), value: undefined, }, + { + title: t('Settings.ScanBLE'), + accessibilityLabel: t('Settings.ScanBLE'), + testID: testIdWithKey('ScanBLE'), + onPress: () => navigation.getParent()?.navigate(Stacks.ContactStack, { screen: Screens.ScanBLE }), + value: undefined, + }, + // { + // title: t('Screens.ProofRequestDetails'), + // accessibilityLabel: t('Screens.ProofRequestDetails'), + // testID: testIdWithKey('ProofRequestDetails'), + // onPress: () => navigation.getParent()?.navigate(Stacks.ContactStack, { screen: Screens.ProofRequestDetails }), + // value: undefined, + // }, ], }, { @@ -215,7 +229,7 @@ const Settings: React.FC = ({ navigation }) => { testID: testIdWithKey('ProofRequests'), onPress: () => navigation.getParent()?.navigate(Stacks.ProofRequestsStack, { - screen: Screens.ProofRequests, + screen: Screens.SelectProofRequest, params: { navigation: navigation }, }), }, @@ -353,7 +367,7 @@ const Settings: React.FC = ({ navigation }) => { ListFooterComponent={() => ( diff --git a/packages/legacy/core/App/screens/Splash.tsx b/packages/legacy/core/App/screens/Splash.tsx index 00924b9a..05b59961 100644 --- a/packages/legacy/core/App/screens/Splash.tsx +++ b/packages/legacy/core/App/screens/Splash.tsx @@ -246,7 +246,7 @@ const Splash: React.FC = () => { const newAgent = new Agent({ config: { - label: store.preferences.walletName || 'Aries Bifold', + label: store.preferences.walletName || 'FHWA', walletConfig: { id: credentials.id, key: credentials.key, diff --git a/packages/legacy/core/App/theme.ts b/packages/legacy/core/App/theme.ts index 786cc107..23c68151 100644 --- a/packages/legacy/core/App/theme.ts +++ b/packages/legacy/core/App/theme.ts @@ -16,7 +16,8 @@ import IconInfoSentDark from './assets/img/icon-info-sent-dark.svg' import IconInfoSentLight from './assets/img/icon-info-sent-light.svg' import IconProofRequestDark from './assets/img/icon-proof-request-dark.svg' import IconProofRequestLight from './assets/img/icon-proof-request-light.svg' -import Logo from './assets/img/logo.svg' +import Logo from './assets/img/FHWA-Logo.svg' +import NoInfoShared from './assets/img/no_information_shared.svg' import Preface from './assets/img/preface.svg' import ProofRequestDeclined from './assets/img/proof-declined.svg' import VerifierRequestDeclined from './assets/img/verifier-request-declined.svg' @@ -186,28 +187,28 @@ const GrayscaleColors: IGrayscaleColors = { } const BrandColors: IBrandColors = { - primary: '#42803E', - primaryDisabled: `rgba(53, 130, 63, ${lightOpacity})`, + primary: '#1C6DA5', + primaryDisabled: `rgba(28,109,165, ${lightOpacity})`, secondary: '#FFFFFFFF', - secondaryDisabled: `rgba(53, 130, 63, ${heavyOpacity})`, - primaryLight: `rgba(53, 130, 63, ${lightOpacity})`, + secondaryDisabled: `rgba(28,109,165, ${heavyOpacity})`, + primaryLight: `rgba(28,109,165, ${lightOpacity})`, highlight: '#FCBA19', - primaryBackground: '#000000', - secondaryBackground: '#313132', - modalPrimary: '#42803E', + primaryBackground: '#F5F5F5', + secondaryBackground: '#F5F5F5', + modalPrimary: '#1C6DA5', modalSecondary: '#FFFFFFFF', - modalPrimaryBackground: '#000000', - modalSecondaryBackground: '#313132', - modalIcon: GrayscaleColors.white, - unorderedList: GrayscaleColors.white, - unorderedListModal: GrayscaleColors.white, - link: GrayscaleColors.white, - text: GrayscaleColors.white, - icon: GrayscaleColors.white, + modalPrimaryBackground: '#F5F5F5', + modalSecondaryBackground: '#F5F5F5', + modalIcon: GrayscaleColors.black, + unorderedList: GrayscaleColors.black, + unorderedListModal: GrayscaleColors.black, + link: GrayscaleColors.black, + text: GrayscaleColors.black, + icon: GrayscaleColors.black, headerIcon: GrayscaleColors.white, headerText: GrayscaleColors.white, buttonText: GrayscaleColors.white, - tabBarInactive: GrayscaleColors.white, + tabBarInactive: GrayscaleColors.black, } const SemanticColors: ISemanticColors = { @@ -217,22 +218,22 @@ const SemanticColors: ISemanticColors = { } const NotificationColors: INotificationColors = { - success: '#313132', + success: '#ffffff', successBorder: '#2E8540', successIcon: '#2E8540', - successText: '#FFFFFF', - info: '#313132', + successText: '#000000', + info: '#ffffff', infoBorder: '#0099FF', infoIcon: '#0099FF', - infoText: '#FFFFFF', - warn: '#313132', + infoText: '#000000', + warn: '#ffffff', warnBorder: '#FCBA19', warnIcon: '#FCBA19', - warnText: '#FFFFFF', - error: '#313132', + warnText: '#000000', + error: '#ffffff', errorBorder: '#D8292F', errorIcon: '#D8292F', - errorText: '#FFFFFF', + errorText: '#000000', popupOverlay: `rgba(0, 0, 0, ${mediumOpacity})`, } @@ -313,22 +314,22 @@ export const TextTheme: ITextTheme = { modalNormal: { fontSize: 18, fontWeight: 'normal', - color: ColorPallet.grayscale.white, + color: ColorPallet.grayscale.black, }, modalTitle: { fontSize: 24, fontWeight: 'bold', - color: ColorPallet.grayscale.white, + color: ColorPallet.grayscale.black, }, modalHeadingOne: { fontSize: 38, fontWeight: 'bold', - color: ColorPallet.grayscale.white, + color: ColorPallet.grayscale.black, }, modalHeadingThree: { fontSize: 26, fontWeight: 'bold', - color: ColorPallet.grayscale.white, + color: ColorPallet.grayscale.black, }, popupModalText: { fontSize: 18, @@ -351,7 +352,7 @@ export const Inputs: IInputs = StyleSheet.create({ borderRadius, fontSize: 16, backgroundColor: ColorPallet.brand.primaryBackground, - color: ColorPallet.notification.infoText, + color: '#fff', borderWidth: 2, borderColor: ColorPallet.brand.secondary, }, @@ -433,9 +434,11 @@ export const Buttons = StyleSheet.create({ padding: 16, borderRadius: 4, backgroundColor: ColorPallet.brand.modalPrimary, + color: ColorPallet.brand.secondary, }, modalPrimaryText: { ...TextTheme.bold, + color: ColorPallet.grayscale.white, textAlign: 'center', }, modalSecondary: { @@ -646,7 +649,7 @@ export const ChatTheme = { alignSelf: 'flex-end', }, leftBubble: { - backgroundColor: ColorPallet.brand.secondaryBackground, + backgroundColor: ColorPallet.brand.secondary, borderRadius: 4, padding: 16, marginLeft: 16, @@ -658,30 +661,30 @@ export const ChatTheme = { marginRight: 16, }, timeStyleLeft: { - color: ColorPallet.grayscale.lightGrey, + color: ColorPallet.grayscale.darkGrey, fontSize: 12, marginTop: 8, }, timeStyleRight: { - color: ColorPallet.grayscale.lightGrey, + color: ColorPallet.grayscale.darkGrey, fontSize: 12, marginTop: 8, }, leftText: { - color: ColorPallet.brand.secondary, + color: ColorPallet.grayscale.black, fontSize: TextTheme.normal.fontSize, }, leftTextHighlighted: { ...TextTheme.bold, - color: ColorPallet.brand.secondary, + color: ColorPallet.grayscale.black, }, rightText: { - color: ColorPallet.brand.secondary, + color: ColorPallet.grayscale.black, fontSize: TextTheme.normal.fontSize, }, rightTextHighlighted: { ...TextTheme.bold, - color: ColorPallet.brand.secondary, + color: ColorPallet.grayscale.black, }, inputToolbar: { backgroundColor: ColorPallet.brand.secondary, @@ -689,6 +692,7 @@ export const ChatTheme = { borderRadius: 10, }, inputText: { + color: ColorPallet.grayscale.black, lineHeight: undefined, fontWeight: '500', fontSize: TextTheme.normal.fontSize, @@ -795,7 +799,7 @@ const PINEnterTheme = { const PINInputTheme = { cell: { backgroundColor: ColorPallet.brand.secondaryBackground, - borderColor: ColorPallet.brand.secondary, + borderColor: ColorPallet.brand.primary, borderWidth: 1, }, focussedCell: { @@ -805,7 +809,7 @@ const PINInputTheme = { color: ColorPallet.brand.text, }, icon: { - color: ColorPallet.brand.headerIcon, + color: ColorPallet.grayscale.black, }, } @@ -833,14 +837,14 @@ export const Assets = { }, img: { logoPrimary: { - src: require('./assets/img/logo-large.png'), + src: require('./assets/img/logo.png'), aspectRatio: 1, height: '33%', width: '33%', resizeMode: 'contain', }, logoSecondary: { - src: require('./assets/img/logo-large.png'), + src: require('./assets/img/logo.png'), aspectRatio: 1, height: 120, width: 120, diff --git a/packages/legacy/core/App/types/navigators.ts b/packages/legacy/core/App/types/navigators.ts index f1b18371..0c9baef7 100644 --- a/packages/legacy/core/App/types/navigators.ts +++ b/packages/legacy/core/App/types/navigators.ts @@ -33,12 +33,15 @@ export enum Screens { CustomNotification = 'Custom Notification', ProofChangeCredential = 'Choose a credential', ProofRequests = 'Proof Requests', + SelectProofRequest = 'Select Proof Requests', + SendProofRequest = 'Send a proof request', ProofRequesting = 'Proof Requesting', ProofDetails = 'Proof Details', NameWallet = 'Name Wallet', RenameContact = 'Rename Contact', ScanHelp = 'Scan Help', QRCodeGen = 'Generate QR Code', + ScanBLE = 'Bluetooth', } export enum Stacks { @@ -93,12 +96,16 @@ export type OnboardingStackParams = { } export type ContactStackParams = { + [Screens.ProofRequestDetails]: { templateId: string; connectionId?: string } [Screens.Contacts]: undefined [Screens.Chat]: { connectionId: string } [Screens.ContactDetails]: { connectionId: string } [Screens.RenameContact]: { connectionId: string } + [Screens.SelectProofRequest]: { connectionId: string } + [Screens.SendProofRequest]: { connectionId: string } [Screens.WhatAreContacts]: undefined [Screens.QRCodeGen]: undefined + [Screens.ScanBLE]: undefined [Screens.CredentialDetails]: { credentialId: string } [Screens.CredentialOffer]: { credentialId: string } [Screens.ProofDetails]: { recordId: string; isHistory?: boolean } @@ -107,6 +114,7 @@ export type ContactStackParams = { export type ProofRequestsStackParams = { [Screens.ProofRequests]: { connectionId?: string } + [Screens.SelectProofRequest]: { connectionId?: string } [Screens.ProofRequesting]: { templateId: string; predicateValues?: Record> } [Screens.ProofDetails]: { recordId: string; isHistory?: boolean; senderReview?: boolean } [Screens.ProofRequestDetails]: { templateId: string; connectionId?: string } diff --git a/packages/legacy/core/App/types/permissions.ts b/packages/legacy/core/App/types/permissions.ts index d9a2ab76..597be9f3 100644 --- a/packages/legacy/core/App/types/permissions.ts +++ b/packages/legacy/core/App/types/permissions.ts @@ -1,2 +1,6 @@ import { Permission, PermissionStatus, Rationale } from 'react-native-permissions' export type PermissionContract = (permission: Permission, rationale?: Rationale) => Promise +export type MultiplePermissionContract = ( + permission: Permission[], + rationale?: Rationale +) => Promise> diff --git a/packages/legacy/core/App/utils/credential.ts b/packages/legacy/core/App/utils/credential.ts index cbb42fda..ad341b8d 100644 --- a/packages/legacy/core/App/utils/credential.ts +++ b/packages/legacy/core/App/utils/credential.ts @@ -6,6 +6,8 @@ import { ImageSourcePropType } from 'react-native' import { luminanceForHexColor } from './luminance' export const isValidAnonCredsCredential = (credential: CredentialExchangeRecord) => { + // eslint-disable-next-line no-console + console.error(credential) return ( credential && (credential.state === CredentialState.OfferReceived || @@ -35,3 +37,7 @@ export const getCredentialIdentifiers = (credential: CredentialExchangeRecord) = schemaId: credential.metadata.get(AnonCredsCredentialMetadataKey)?.schemaId, } } + +export function DateToString(value: string) { + return value.substring(0, 4) + '-' + value.substring(4, 6) + '-' + value.substring(6, 8) +} diff --git a/packages/legacy/core/App/utils/helpers.ts b/packages/legacy/core/App/utils/helpers.ts index 79932cde..95f2aa9d 100644 --- a/packages/legacy/core/App/utils/helpers.ts +++ b/packages/legacy/core/App/utils/helpers.ts @@ -1,3 +1,4 @@ +/* eslint-disable no-console */ import { AnonCredsCredentialInfo, AnonCredsCredentialsForProofRequest, @@ -870,7 +871,7 @@ export const createConnectionInvitation = async (agent: Agent | undefined, goalC throw new Error('Could not create new invitation') } const invitationUrl = record.outOfBandInvitation.toUrl({ domain }) - + console.log(record) return { record, invitation: record.outOfBandInvitation, @@ -1023,3 +1024,11 @@ export function generateRandomWalletName() { } return name } + +export function stringToBytes(str: string) { + const bytes = [] + for (let i = 0; i < str.length; i++) { + bytes.push(str.charCodeAt(i)) + } + return bytes +} diff --git a/packages/legacy/core/App/utils/invitation.ts b/packages/legacy/core/App/utils/invitation.ts new file mode 100644 index 00000000..60d41855 --- /dev/null +++ b/packages/legacy/core/App/utils/invitation.ts @@ -0,0 +1,72 @@ +import { Agent } from '@aries-framework/core' +import { RouteProp } from '@react-navigation/core' +import { StackNavigationProp } from '@react-navigation/stack' + +import { BifoldError } from '../types/error' +import { ConnectStackParams, Screens, Stacks } from '../types/navigators' + +import { connectFromInvitation, getJson, getUrl, receiveMessageFromUrlRedirect } from './helpers' +import { t } from 'i18next' + +export const handleInvitation = async ( + navigation: StackNavigationProp, + route: RouteProp, + agent: Agent | undefined, + value: string +): Promise => { + let implicitInvitations = false + if (route?.params && route.params['implicitInvitations']) { + implicitInvitations = route.params['implicitInvitations'] + } + let reuseConnections = false + if (route?.params && route.params['reuseConnections']) { + reuseConnections = route.params['reuseConnections'] + } + + try { + const receivedInvitation = await connectFromInvitation(value, agent, implicitInvitations, reuseConnections) + if (receivedInvitation?.connectionRecord?.id) { + // not connectionless + navigation.getParent()?.navigate(Stacks.ConnectionStack, { + screen: Screens.Connection, + params: { connectionId: receivedInvitation.connectionRecord.id }, + }) + } else { + //connectionless + navigation.navigate(Stacks.ConnectionStack as any, { + screen: Screens.Connection, + params: { threadId: receivedInvitation?.outOfBandRecord.outOfBandInvitation.threadId }, + }) + } + } catch (err: unknown) { + // [Error: Connection does not have an ID] + // [AriesFrameworkError: An out of band record with invitation 05fe3693-2c12-4165-a3b6-370280ccd43b has already been received. Invitations should have a unique id.] + try { + // if scanned value is json -> pass into AFJ as is + const json = getJson(value) + if (json) { + await agent?.receiveMessage(json) + navigation.getParent()?.navigate(Stacks.ConnectionStack, { + screen: Screens.Connection, + params: { threadId: json['@id'] }, + }) + return + } + + // if scanned value is url -> receive message from it + const url = getUrl(value) + if (url) { + const message = await receiveMessageFromUrlRedirect(value, agent) + navigation.getParent()?.navigate(Stacks.ConnectionStack, { + screen: Screens.Connection, + params: { threadId: message['@id'] }, + }) + return + } + } catch (err: unknown) { + const error = new BifoldError(t('Error.Title1031'), t('Error.Message1031'), (err as Error)?.message ?? err, 1031) + // throwing for QrCodeScanError + throw error + } + } +} diff --git a/packages/legacy/core/App/utils/ledger.tsx b/packages/legacy/core/App/utils/ledger.tsx index a4cbd5d5..7ef99d18 100644 --- a/packages/legacy/core/App/utils/ledger.tsx +++ b/packages/legacy/core/App/utils/ledger.tsx @@ -30,6 +30,7 @@ export const canConnectToLedgerNode = async (node: { host: string; port: number client.setTimeout(socketTimeoutInMs) }) +// eslint-disable-next-line @typescript-eslint/no-unused-vars export const fetchLedgerNodes = (indyNamespace = 'sovrin'): Array<{ host: string; port: number }> => { // const [pool] = pools.filter((p) => p.indyNamespace === indyNamespace) const [pool] = pools diff --git a/packages/legacy/core/App/utils/migration.ts b/packages/legacy/core/App/utils/migration.ts index af33faa3..5190ff6e 100644 --- a/packages/legacy/core/App/utils/migration.ts +++ b/packages/legacy/core/App/utils/migration.ts @@ -19,7 +19,7 @@ export const migrateToAskar = async (walletId: string, key: string, agent?: Agen agent ?? new Agent({ config: { - label: 'Aries Bifold', + label: 'FHWA', walletConfig: { id: walletId, key, diff --git a/packages/legacy/core/App/utils/proofBundle.ts b/packages/legacy/core/App/utils/proofBundle.ts index cf2497e3..740ff2c0 100644 --- a/packages/legacy/core/App/utils/proofBundle.ts +++ b/packages/legacy/core/App/utils/proofBundle.ts @@ -127,14 +127,14 @@ export class DefaultProofBundleResolver implements ProofBundleResolverType { this.proofRequestTemplates = proofRequestTemplates ?? useProofRequestTemplates } public async resolve(acceptDevRestrictions: boolean): Promise { - return Promise.resolve(this.proofRequestTemplates(acceptDevRestrictions)) + return Promise.resolve(this.proofRequestTemplates(acceptDevRestrictions, [])) } public async resolveById( templateId: string, acceptDevRestrictions: boolean ): Promise { return Promise.resolve( - this.proofRequestTemplates(acceptDevRestrictions).find((template) => template.id === templateId) + this.proofRequestTemplates(acceptDevRestrictions, []).find((template) => template.id === templateId) ) } } diff --git a/packages/legacy/core/__tests__/components/CameraDisclosureModal.test.tsx b/packages/legacy/core/__tests__/components/PermissionDisclosureModal.test.tsx similarity index 70% rename from packages/legacy/core/__tests__/components/CameraDisclosureModal.test.tsx rename to packages/legacy/core/__tests__/components/PermissionDisclosureModal.test.tsx index 0e087441..4c1a0c2a 100644 --- a/packages/legacy/core/__tests__/components/CameraDisclosureModal.test.tsx +++ b/packages/legacy/core/__tests__/components/PermissionDisclosureModal.test.tsx @@ -2,7 +2,7 @@ import { useNavigation } from '@react-navigation/core' import { render, fireEvent, act } from '@testing-library/react-native' import React from 'react' -import CameraDisclosureModal from '../../App/components/modals/CameraDisclosureModal' +import PermissionDisclosureModal from '../../App/components/modals/PermissionDisclosureModal' import { testIdWithKey } from '../../App/utils/testable' let requestCameraUse = jest.fn(() => Promise.resolve(true)) @@ -13,11 +13,11 @@ jest.mock('@react-navigation/native', () => { return require('../../__mocks__/custom/@react-navigation/native') }) -describe('CameraDisclosureModal Component', () => { - beforeAll(()=>{ +describe('PermissionDisclosureModal Component', () => { + beforeAll(() => { jest.useFakeTimers() }) - afterAll(()=>{ + afterAll(() => { jest.useRealTimers() }) beforeEach(() => { @@ -26,12 +26,14 @@ describe('CameraDisclosureModal Component', () => { }) test('Renders correctly', () => { - const tree = render() + const tree = render() expect(tree).toMatchSnapshot() }) test('Pressing "Continue" triggers requestCameraUse callback', async () => { - const { getByTestId } = render() + const { getByTestId } = render( + + ) const continueButton = getByTestId(testIdWithKey('Continue')) await act(async () => { fireEvent(continueButton, 'press') @@ -41,7 +43,9 @@ describe('CameraDisclosureModal Component', () => { test('Pressing "Not now" navigates correctly', async () => { const navigation = useNavigation() - const { getByTestId } = render() + const { getByTestId } = render( + + ) const notNowButton = getByTestId(testIdWithKey('NotNow')) await act(async () => { fireEvent(notNowButton, 'press') diff --git a/packages/legacy/core/__tests__/screens/ListProofRequests.test.tsx b/packages/legacy/core/__tests__/screens/ListProofRequests.test.tsx index 5de462cd..4f7b51a7 100644 --- a/packages/legacy/core/__tests__/screens/ListProofRequests.test.tsx +++ b/packages/legacy/core/__tests__/screens/ListProofRequests.test.tsx @@ -60,7 +60,7 @@ describe('ListProofRequests Component', () => { fireEvent(templateItemInstance, 'press') expect(navigation.navigate).toBeCalledWith('Proof Request Details', { - templateId: useProofRequestTemplates(false)[0].id, + templateId: useProofRequestTemplates(false, [])[0].id, }) }) }) diff --git a/packages/legacy/core/__tests__/screens/ProofRequesting.test.tsx b/packages/legacy/core/__tests__/screens/ProofRequesting.test.tsx index aebb99d3..1969c298 100644 --- a/packages/legacy/core/__tests__/screens/ProofRequesting.test.tsx +++ b/packages/legacy/core/__tests__/screens/ProofRequesting.test.tsx @@ -53,7 +53,7 @@ jest.mock('react-native-vision-camera', () => { jest.useFakeTimers({ legacyFakeTimers: true }) jest.spyOn(global, 'setTimeout') -const templates = useProofRequestTemplates(true) +const templates = useProofRequestTemplates(true, []) const template = templates[0] const templateId = template.id diff --git a/packages/legacy/core/package.json b/packages/legacy/core/package.json index 5192b5bb..1bb9f882 100644 --- a/packages/legacy/core/package.json +++ b/packages/legacy/core/package.json @@ -221,5 +221,8 @@ "module", "typescript" ] + }, + "dependencies": { + "react-native-ble-manager": "^11.5.3" } } diff --git a/packages/verifier/src/__tests__/verifier/proof-request.test.ts b/packages/verifier/src/__tests__/verifier/proof-request.test.ts index 92313c7c..57aa6372 100644 --- a/packages/verifier/src/__tests__/verifier/proof-request.test.ts +++ b/packages/verifier/src/__tests__/verifier/proof-request.test.ts @@ -9,7 +9,7 @@ describe('Helpers', () => { beforeAll(() => { spy = jest.spyOn(Date, 'now').mockImplementation(() => 1677766511505) }) - const templates = useProofRequestTemplates(false) + const templates = useProofRequestTemplates(false, []) test('Build anoncreds proof request from template containing two requested attributes', async () => { const template = templates[0] diff --git a/packages/verifier/src/request-templates.ts b/packages/verifier/src/request-templates.ts index e594453d..f5b383c1 100644 --- a/packages/verifier/src/request-templates.ts +++ b/packages/verifier/src/request-templates.ts @@ -1,27 +1,30 @@ import { ProofRequestTemplate, ProofRequestType } from './types/proof-reqeust-template' -export const useProofRequestTemplates = (useDevRestrictions: boolean) => { - const studentRestrictions = [{ cred_def_id: 'XUxBrVSALWHLeycAUhrNr9:3:CL:26293:student_card' }] - const studentDevRestrictions = [{ schema_name: 'student_card' }] +export const useProofRequestTemplates = (useDevRestrictions: boolean, attributes: string[]) => { + const currentDate = new Date().toLocaleDateString('en-US').split('/') + const todayDate = parseInt( + currentDate[2] + + (currentDate[0].length === 1 ? '0' + currentDate[0] : currentDate[0]) + + (currentDate[1].length === 1 ? '0' + currentDate[1] : currentDate[1]) + ) + const studentRestrictions = [{ cred_def_id: 'PpeCJT3zbNck91wFivyY8N:3:CL:16:fhwa-vdkms-ca' }] + const schema_id = 'PpeCJT3zbNck91wFivyY8N:2:vehicle_credential:0.1.0' + const studentDevRestrictions = [{ schema_name: 'vehicle_credential' }] const restrictions = useDevRestrictions ? studentDevRestrictions : studentRestrictions const defaultProofRequestTemplates: Array = [ { - id: 'Aries:5:StudentFullName:0.0.1:indy', - name: 'Student full name', - description: 'Verify the full name of a student', + id: '1', + name: 'Full Name', + description: 'Verify the details of a verified car', version: '0.0.1', payload: { type: ProofRequestType.AnonCreds, data: [ { - schema: 'XUxBrVSALWHLeycAUhrNr9:3:CL:26293:Student Card', + schema: schema_id, requestedAttributes: [ { - name: 'student_first_name', - restrictions, - }, - { - name: 'student_last_name', + names: attributes, restrictions, }, ], @@ -30,18 +33,18 @@ export const useProofRequestTemplates = (useDevRestrictions: boolean) => { }, }, { - id: 'Aries:5:StudentFullNameAndExpirationDate:0.0.1:indy', - name: 'Student full name and expiration date', - description: 'Verify that full name of a student and that he/she has a not expired student card.', + id: '2', + name: 'Full Name', + description: 'Verify the details of a verified car', version: '0.0.1', payload: { type: ProofRequestType.AnonCreds, data: [ { - schema: 'XUxBrVSALWHLeycAUhrNr9:3:CL:26293:Student Card', + schema: schema_id, requestedAttributes: [ { - names: ['student_first_name', 'student_last_name'], + names: attributes, restrictions, }, ], @@ -49,7 +52,7 @@ export const useProofRequestTemplates = (useDevRestrictions: boolean) => { { name: 'expiry_date', predicateType: '>=', - predicateValue: 20240101, + predicateValue: todayDate, restrictions, }, ], diff --git a/packages/verifier/src/utils/proof.ts b/packages/verifier/src/utils/proof.ts index 4f68094a..8282f74f 100644 --- a/packages/verifier/src/utils/proof.ts +++ b/packages/verifier/src/utils/proof.ts @@ -69,6 +69,7 @@ export const parseAnonCredsProof = (request: AnonCredsProofRequest, proof: AnonC } for (const [referent, requestedPredicate] of Object.entries(request.requested_predicates)) { + // eslint-disable-next-line @typescript-eslint/ban-ts-comment // @ts-ignore Mistake in AFJ type definition const shared = proof.requested_proof.predicates[referent] if (shared) { diff --git a/yarn.lock b/yarn.lock index e2554dec..b1c8f3e7 100644 --- a/yarn.lock +++ b/yarn.lock @@ -231,6 +231,15 @@ __metadata: languageName: node linkType: hard +"@babel/code-frame@npm:~7.10.4": + version: 7.10.4 + resolution: "@babel/code-frame@npm:7.10.4" + dependencies: + "@babel/highlight": ^7.10.4 + checksum: feb4543c8a509fe30f0f6e8d7aa84f82b41148b963b826cd330e34986f649a85cb63b2f13dd4effdf434ac555d16f14940b8ea5f4433297c2f5ff85486ded019 + languageName: node + linkType: hard + "@babel/compat-data@npm:^7.17.7, @babel/compat-data@npm:^7.20.1, @babel/compat-data@npm:^7.20.5": version: 7.21.0 resolution: "@babel/compat-data@npm:7.21.0" @@ -965,6 +974,13 @@ __metadata: languageName: node linkType: hard +"@babel/helper-validator-identifier@npm:^7.24.5": + version: 7.24.5 + resolution: "@babel/helper-validator-identifier@npm:7.24.5" + checksum: 75d6f9f475c08f3be87bae4953e9b8d8c72983e16ed2860870b328d048cb20dccb4fcbf85eacbdd817ea1efbb38552a6db9046e2e37bfe13bdec44ac8939024c + languageName: node + linkType: hard + "@babel/helper-validator-option@npm:^7.18.6, @babel/helper-validator-option@npm:^7.21.0": version: 7.21.0 resolution: "@babel/helper-validator-option@npm:7.21.0" @@ -1035,6 +1051,18 @@ __metadata: languageName: node linkType: hard +"@babel/highlight@npm:^7.10.4": + version: 7.24.5 + resolution: "@babel/highlight@npm:7.24.5" + dependencies: + "@babel/helper-validator-identifier": ^7.24.5 + chalk: ^2.4.2 + js-tokens: ^4.0.0 + picocolors: ^1.0.0 + checksum: eece0e63e9210e902f1ee88f15cabfa31d2693bd2e56806eb849478b859d274c24477081c649cee6a241c4aed7da6f3e05c7afa5c3cd70094006ed095292b0d0 + languageName: node + linkType: hard + "@babel/highlight@npm:^7.18.6": version: 7.18.6 resolution: "@babel/highlight@npm:7.18.6" @@ -3754,6 +3782,77 @@ __metadata: languageName: node linkType: hard +"@expo/config-plugins@npm:^7.2.5": + version: 7.9.2 + resolution: "@expo/config-plugins@npm:7.9.2" + dependencies: + "@expo/config-types": ^50.0.0-alpha.1 + "@expo/fingerprint": ^0.6.0 + "@expo/json-file": ~8.3.0 + "@expo/plist": ^0.1.0 + "@expo/sdk-runtime-versions": ^1.0.0 + "@react-native/normalize-color": ^2.0.0 + chalk: ^4.1.2 + debug: ^4.3.1 + find-up: ~5.0.0 + getenv: ^1.0.0 + glob: 7.1.6 + resolve-from: ^5.0.0 + semver: ^7.5.3 + slash: ^3.0.0 + slugify: ^1.6.6 + xcode: ^3.0.1 + xml2js: 0.6.0 + checksum: cd3440558a6cb757626a21a945781bd1d43ed1b4ab268673c29a8eb2f6ed95217bf8a94b6093a0238c3ce6481c8c963598aab6334e10f72a594ce8d5b9f87505 + languageName: node + linkType: hard + +"@expo/config-types@npm:^50.0.0-alpha.1": + version: 50.0.1 + resolution: "@expo/config-types@npm:50.0.1" + checksum: f803730a5a56fb0b1ddc4385d7ac930935c88be4e5a5dfaa9b7733444ba4d6d784946ecdc1e414528e5f642a473ff01a1533b8c4174e87b35d15cdd88c96bf49 + languageName: node + linkType: hard + +"@expo/fingerprint@npm:^0.6.0": + version: 0.6.1 + resolution: "@expo/fingerprint@npm:0.6.1" + dependencies: + "@expo/spawn-async": ^1.5.0 + chalk: ^4.1.2 + debug: ^4.3.4 + find-up: ^5.0.0 + minimatch: ^3.0.4 + p-limit: ^3.1.0 + resolve-from: ^5.0.0 + bin: + fingerprint: bin/cli.js + checksum: 8398d466a232604b54fc1438ece486753f6e8e65933ab270377b6f8ed1c4409a886031f0dff56b7f34d17774f71f9fd800e6b78f79fedceb2a6d4a3fdd9f490d + languageName: node + linkType: hard + +"@expo/json-file@npm:~8.3.0": + version: 8.3.3 + resolution: "@expo/json-file@npm:8.3.3" + dependencies: + "@babel/code-frame": ~7.10.4 + json5: ^2.2.2 + write-file-atomic: ^2.3.0 + checksum: 49fcb3581ac21c1c223459f32e9e931149b56a7587318f666303a62e719e3d0f122ff56a60d47ee31fac937c297a66400a00fcee63a17bebbf4b8cd30c5138c1 + languageName: node + linkType: hard + +"@expo/plist@npm:^0.1.0": + version: 0.1.3 + resolution: "@expo/plist@npm:0.1.3" + dependencies: + "@xmldom/xmldom": ~0.7.7 + base64-js: ^1.2.3 + xmlbuilder: ^14.0.0 + checksum: 8abe78bed4d1849f2cddddd1a238c6fe5c2549a9dee40158224ff70112f31503db3f17a522b6e21f16eea66b5f4b46cc49d22f2b369067d00a88ef6d301a50cd + languageName: node + linkType: hard + "@expo/react-native-action-sheet@npm:4.0.1": version: 4.0.1 resolution: "@expo/react-native-action-sheet@npm:4.0.1" @@ -3766,6 +3865,22 @@ __metadata: languageName: node linkType: hard +"@expo/sdk-runtime-versions@npm:^1.0.0": + version: 1.0.0 + resolution: "@expo/sdk-runtime-versions@npm:1.0.0" + checksum: 0942d5a356f590e8dc795761456cc48b3e2d6a38ad2a02d6774efcdc5a70424e05623b4e3e5d2fec0cdc30f40dde05c14391c781607eed3971bf8676518bfd9d + languageName: node + linkType: hard + +"@expo/spawn-async@npm:^1.5.0": + version: 1.7.2 + resolution: "@expo/spawn-async@npm:1.7.2" + dependencies: + cross-spawn: ^7.0.3 + checksum: d99e5ff6d303ec9b0105f97c4fa6c65bca526c7d4d0987997c35cc745fa8224adf009942d01808192ebb9fa30619a53316641958631e85cf17b773d9eeda2597 + languageName: node + linkType: hard + "@formatjs/ecma402-abstract@npm:1.9.9": version: 1.9.9 resolution: "@formatjs/ecma402-abstract@npm:1.9.9" @@ -4047,6 +4162,7 @@ __metadata: react-native: ~0.72.5 react-native-animated-pagination-dots: ^0.1.72 react-native-argon2: ^2.0.1 + react-native-ble-manager: ^11.5.3 react-native-bouncy-checkbox: ^3.0.5 react-native-builder-bob: ^0.21.3 react-native-collapsible: ^1.6.1 @@ -5892,6 +6008,13 @@ __metadata: languageName: node linkType: hard +"@react-native/normalize-color@npm:^2.0.0": + version: 2.1.0 + resolution: "@react-native/normalize-color@npm:2.1.0" + checksum: 8ccbd40b3c7629f1dc97b3e9aadd95fd3507fcf2e37535a6299a70436ab891c34cbdc4240b07380553d6e85dd909e23d5773b5be1da2906b026312e0b0768838 + languageName: node + linkType: hard + "@react-native/normalize-colors@npm:*": version: 0.73.0 resolution: "@react-native/normalize-colors@npm:0.73.0" @@ -6538,6 +6661,13 @@ __metadata: languageName: node linkType: hard +"@types/geojson@npm:^7946.0.13": + version: 7946.0.14 + resolution: "@types/geojson@npm:7946.0.14" + checksum: ae511bee6488ae3bd5a3a3347aedb0371e997b14225b8983679284e22fa4ebd88627c6e3ff8b08bf4cc35068cb29310c89427311ffc9322c255615821a922e71 + languageName: node + linkType: hard + "@types/git-raw-commits@npm:*": version: 2.0.1 resolution: "@types/git-raw-commits@npm:2.0.1" @@ -7083,6 +7213,20 @@ __metadata: languageName: node linkType: hard +"@xmldom/xmldom@npm:^0.8.8": + version: 0.8.10 + resolution: "@xmldom/xmldom@npm:0.8.10" + checksum: 4c136aec31fb3b49aaa53b6fcbfe524d02a1dc0d8e17ee35bd3bf35e9ce1344560481cd1efd086ad1a4821541482528672306d5e37cdbd187f33d7fadd3e2cf0 + languageName: node + linkType: hard + +"@xmldom/xmldom@npm:~0.7.7": + version: 0.7.13 + resolution: "@xmldom/xmldom@npm:0.7.13" + checksum: b4054078530e5fa8ede9677425deff0fce6d965f4c477ca73f8490d8a089e60b8498a15560425a1335f5ff99ecb851ed2c734b0a9a879299a5694302f212f37a + languageName: node + linkType: hard + "@yarnpkg/lockfile@npm:^1.1.0": version: 1.1.0 resolution: "@yarnpkg/lockfile@npm:1.1.0" @@ -7515,6 +7659,8 @@ __metadata: react-native: "*" react-native-animated-pagination-dots: ^0.1.72 react-native-argon2: ^2.0.1 + react-native-ble-manager: ^11.5.3 + react-native-ble-plx: ^3.1.2 react-native-bouncy-checkbox: ^3.0.5 react-native-collapsible: ^1.6.1 react-native-config: ^1.4.2 @@ -7562,8 +7708,12 @@ __metadata: eslint-plugin-import: ^2.28.1 eslint-plugin-prettier: ^4.0.0 lerna: ^6.6.2 + lottie-react-native: ^6.6.0 npm-run-all: ^4.1.5 prettier: ^2.8.4 + react-native-ble-manager: ^11.5.3 + react-native-ble-plx: ^3.1.2 + react-native-maps: ^1.15.4 react-native-qrcode-svg: ^6.2.0 react-native-svg: ^14.1.0 ts-node: ^10.0.0 @@ -8152,7 +8302,7 @@ __metadata: languageName: node linkType: hard -"base64-js@npm:*, base64-js@npm:^1.1.2, base64-js@npm:^1.3.0, base64-js@npm:^1.3.1": +"base64-js@npm:*, base64-js@npm:^1.1.2, base64-js@npm:^1.2.3, base64-js@npm:^1.3.0, base64-js@npm:^1.3.1, base64-js@npm:^1.5.1": version: 1.5.1 resolution: "base64-js@npm:1.5.1" checksum: 669632eb3745404c2f822a18fc3a0122d2f9a7a13f7fb8b5823ee19d1d2ff9ee5b52c53367176ea4ad093c332fd5ab4bd0ebae5a8e27917a4105a4cfc86b1005 @@ -8173,6 +8323,13 @@ __metadata: languageName: node linkType: hard +"big-integer@npm:1.6.x": + version: 1.6.52 + resolution: "big-integer@npm:1.6.52" + checksum: 6e86885787a20fed96521958ae9086960e4e4b5e74d04f3ef7513d4d0ad631a9f3bde2730fc8aaa4b00419fc865f6ec573e5320234531ef37505da7da192c40b + languageName: node + linkType: hard + "big-integer@npm:^1.6.44, big-integer@npm:^1.6.51": version: 1.6.51 resolution: "big-integer@npm:1.6.51" @@ -8291,6 +8448,24 @@ __metadata: languageName: node linkType: hard +"bplist-creator@npm:0.1.1": + version: 0.1.1 + resolution: "bplist-creator@npm:0.1.1" + dependencies: + stream-buffers: 2.2.x + checksum: b0d40d1d1623f1afdbb575cfc8075d742d2c4f0eb458574be809e3857752d1042a39553b3943d2d7f505dde92bcd43e1d7bdac61c9cd44475d696deb79f897ce + languageName: node + linkType: hard + +"bplist-parser@npm:0.3.2": + version: 0.3.2 + resolution: "bplist-parser@npm:0.3.2" + dependencies: + big-integer: 1.6.x + checksum: fad0f6eb155a9b636b4096a1725ce972a0386490d7d38df7be11a3a5645372446b7c44aacbc6626d24d2c17d8b837765361520ebf2960aeffcaf56765811620e + languageName: node + linkType: hard + "bplist-parser@npm:^0.2.0": version: 0.2.0 resolution: "bplist-parser@npm:0.2.0" @@ -9885,7 +10060,7 @@ __metadata: languageName: node linkType: hard -"debug@npm:4, debug@npm:^4.1.0, debug@npm:^4.1.1, debug@npm:^4.3.2, debug@npm:^4.3.3, debug@npm:^4.3.4": +"debug@npm:4, debug@npm:^4.1.0, debug@npm:^4.1.1, debug@npm:^4.3.1, debug@npm:^4.3.2, debug@npm:^4.3.3, debug@npm:^4.3.4": version: 4.3.4 resolution: "debug@npm:4.3.4" dependencies: @@ -12203,6 +12378,13 @@ __metadata: languageName: node linkType: hard +"getenv@npm:^1.0.0": + version: 1.0.0 + resolution: "getenv@npm:1.0.0" + checksum: 19ae5cad603a1cf1bcb8fa3bed48e00d062eb0572a4404c02334b67f3b3499f238383082b064bb42515e9e25c2b08aef1a3e3d2b6852347721aa8b174825bd56 + languageName: node + linkType: hard + "git-raw-commits@npm:^2.0.0, git-raw-commits@npm:^2.0.11, git-raw-commits@npm:^2.0.8": version: 2.0.11 resolution: "git-raw-commits@npm:2.0.11" @@ -12300,6 +12482,20 @@ __metadata: languageName: node linkType: hard +"glob@npm:7.1.6": + version: 7.1.6 + resolution: "glob@npm:7.1.6" + dependencies: + fs.realpath: ^1.0.0 + inflight: ^1.0.4 + inherits: 2 + minimatch: ^3.0.4 + once: ^1.3.0 + path-is-absolute: ^1.0.0 + checksum: 351d549dd90553b87c2d3f90ce11aed9e1093c74130440e7ae0592e11bbcd2ce7f0ebb8ba6bfe63aaf9b62166a7f4c80cb84490ae5d78408bb2572bf7d4ee0a6 + languageName: node + linkType: hard + "glob@npm:^10.2.2, glob@npm:^10.2.5": version: 10.2.6 resolution: "glob@npm:10.2.6" @@ -15352,6 +15548,26 @@ __metadata: languageName: node linkType: hard +"lottie-react-native@npm:^6.6.0": + version: 6.6.0 + resolution: "lottie-react-native@npm:6.6.0" + peerDependencies: + "@dotlottie/react-player": ^1.6.1 + "@lottiefiles/react-lottie-player": ^3.5.3 + react: "*" + react-native: ">=0.46" + react-native-windows: ">=0.63.x" + peerDependenciesMeta: + "@dotlottie/react-player": + optional: true + "@lottiefiles/react-lottie-player": + optional: true + react-native-windows: + optional: true + checksum: c989a1765caf7d6a80d72eb1c4702648cc744b07c13f1085f6f4233992264686191d84ff88233b6083ae2548261fccd9375cb9de1f81364f3f2477928d6f5c3b + languageName: node + linkType: hard + "lowercase-keys@npm:^3.0.0": version: 3.0.0 resolution: "lowercase-keys@npm:3.0.0" @@ -17895,6 +18111,17 @@ __metadata: languageName: node linkType: hard +"plist@npm:^3.0.5": + version: 3.1.0 + resolution: "plist@npm:3.1.0" + dependencies: + "@xmldom/xmldom": ^0.8.8 + base64-js: ^1.5.1 + xmlbuilder: ^15.1.1 + checksum: c8ea013da8646d4c50dff82f9be39488054621cc229957621bb00add42b5d4ce3657cf58d4b10c50f7dea1a81118f825838f838baeb4e6f17fab453ecf91d424 + languageName: node + linkType: hard + "pngjs@npm:^5.0.0": version: 5.0.0 resolution: "pngjs@npm:5.0.0" @@ -18425,6 +18652,27 @@ __metadata: languageName: node linkType: hard +"react-native-ble-manager@npm:^11.5.3": + version: 11.5.3 + resolution: "react-native-ble-manager@npm:11.5.3" + peerDependencies: + react-native: ">=0.60.0" + checksum: 1e69c4e19c19d1800dc4ac0656a254bc66b0fec7f0a93b710864054455331093e9851c7f46de48102837f945becf53fcfc4061dd106e629b7b23b0637eaf9fcb + languageName: node + linkType: hard + +"react-native-ble-plx@npm:^3.1.2": + version: 3.1.2 + resolution: "react-native-ble-plx@npm:3.1.2" + dependencies: + "@expo/config-plugins": ^7.2.5 + peerDependencies: + react: "*" + react-native: "*" + checksum: 6a35269d4e65c3b8a52469db9a628b4519f28fe4009f90c96ba017b84408d63751c708391901219ec0a4cac3c560defba4fa504ded0b8a4a4b5b2c8c307a1841 + languageName: node + linkType: hard + "react-native-bouncy-checkbox@npm:^3.0.5": version: 3.0.7 resolution: "react-native-bouncy-checkbox@npm:3.0.7" @@ -18642,6 +18890,22 @@ __metadata: languageName: node linkType: hard +"react-native-maps@npm:^1.15.4": + version: 1.15.4 + resolution: "react-native-maps@npm:1.15.4" + dependencies: + "@types/geojson": ^7946.0.13 + peerDependencies: + react: ">= 17.0.1" + react-native: ">= 0.64.3" + react-native-web: ">= 0.11" + peerDependenciesMeta: + react-native-web: + optional: true + checksum: 377c4631b6bc5d2671936eccb37ee69898778ff907df08c56fab85dd7ea14051d57e5a3bf5213b2dc7421f5661f963a25f73f6a65b70893d997bed8640f8b391 + languageName: node + linkType: hard + "react-native-orientation-locker@npm:^1.6.0": version: 1.6.0 resolution: "react-native-orientation-locker@npm:1.6.0" @@ -19801,6 +20065,13 @@ __metadata: languageName: node linkType: hard +"sax@npm:>=0.6.0": + version: 1.3.0 + resolution: "sax@npm:1.3.0" + checksum: 238ab3a9ba8c8f8aaf1c5ea9120386391f6ee0af52f1a6a40bbb6df78241dd05d782f2359d614ac6aae08c4c4125208b456548a6cf68625aa4fe178486e63ecd + languageName: node + linkType: hard + "sax@npm:~1.2.4": version: 1.2.4 resolution: "sax@npm:1.2.4" @@ -20121,6 +20392,17 @@ __metadata: languageName: node linkType: hard +"simple-plist@npm:^1.1.0": + version: 1.4.0 + resolution: "simple-plist@npm:1.4.0" + dependencies: + bplist-creator: 0.1.1 + bplist-parser: 0.3.2 + plist: ^3.0.5 + checksum: fa8086f6b781c289f1abad21306481dda4af6373b32a5d998a70e53c2b7218a1d21ebb5ae3e736baae704c21d311d3d39d01d0e6a2387eda01b4020b9ebd909e + languageName: node + linkType: hard + "simple-swizzle@npm:^0.2.2": version: 0.2.2 resolution: "simple-swizzle@npm:0.2.2" @@ -20191,6 +20473,13 @@ __metadata: languageName: node linkType: hard +"slugify@npm:^1.6.6": + version: 1.6.6 + resolution: "slugify@npm:1.6.6" + checksum: 04773c2d3b7aea8d2a61fa47cc7e5d29ce04e1a96cbaec409da57139df906acb3a449fac30b167d203212c806e73690abd4ff94fbad0a9a7b7ea109a2a638ae9 + languageName: node + linkType: hard + "smart-buffer@npm:^4.2.0": version: 4.2.0 resolution: "smart-buffer@npm:4.2.0" @@ -20435,6 +20724,13 @@ __metadata: languageName: node linkType: hard +"stream-buffers@npm:2.2.x": + version: 2.2.0 + resolution: "stream-buffers@npm:2.2.0" + checksum: 4587d9e8f050d689fb38b4295e73408401b16de8edecc12026c6f4ae92956705ecfd995ae3845d7fa3ebf19502d5754df9143d91447fd881d86e518f43882c1c + languageName: node + linkType: hard + "strict-uri-encode@npm:^2.0.0": version: 2.0.0 resolution: "strict-uri-encode@npm:2.0.0" @@ -21764,6 +22060,15 @@ __metadata: languageName: node linkType: hard +"uuid@npm:^7.0.3": + version: 7.0.3 + resolution: "uuid@npm:7.0.3" + bin: + uuid: dist/bin/uuid + checksum: f5b7b5cc28accac68d5c083fd51cca64896639ebd4cca88c6cfb363801aaa83aa439c86dfc8446ea250a7a98d17afd2ad9e88d9d4958c79a412eccb93bae29de + languageName: node + linkType: hard + "uuid@npm:^9.0.0": version: 9.0.0 resolution: "uuid@npm:9.0.0" @@ -22292,6 +22597,16 @@ __metadata: languageName: node linkType: hard +"xcode@npm:^3.0.1": + version: 3.0.1 + resolution: "xcode@npm:3.0.1" + dependencies: + simple-plist: ^1.1.0 + uuid: ^7.0.3 + checksum: 908ff85851f81aec6e36ca24427db092e1cc068f052716e14de5e762196858039efabbe053a1abe8920184622501049e74a93618e8692b982f7604a9847db108 + languageName: node + linkType: hard + "xdg-basedir@npm:^5.0.1, xdg-basedir@npm:^5.1.0": version: 5.1.0 resolution: "xdg-basedir@npm:5.1.0" @@ -22299,6 +22614,37 @@ __metadata: languageName: node linkType: hard +"xml2js@npm:0.6.0": + version: 0.6.0 + resolution: "xml2js@npm:0.6.0" + dependencies: + sax: ">=0.6.0" + xmlbuilder: ~11.0.0 + checksum: 437f353fd66d367bf158e9555a0625df9965d944e499728a5c6bc92a54a2763179b144f14b7e1c725040f56bbd22b0fa6cfcb09ec4faf39c45ce01efe631f40b + languageName: node + linkType: hard + +"xmlbuilder@npm:^14.0.0": + version: 14.0.0 + resolution: "xmlbuilder@npm:14.0.0" + checksum: 9e93d3c73957dbb21acde63afa5d241b19057bdbdca9d53534d8351e70f1d5c9db154e3ca19bd3e9ea84c082539ab6e7845591c8778a663e8b5d3470d5427a8b + languageName: node + linkType: hard + +"xmlbuilder@npm:^15.1.1": + version: 15.1.1 + resolution: "xmlbuilder@npm:15.1.1" + checksum: 14f7302402e28d1f32823583d121594a9dca36408d40320b33f598bd589ca5163a352d076489c9c64d2dc1da19a790926a07bf4191275330d4de2b0d85bb1843 + languageName: node + linkType: hard + +"xmlbuilder@npm:~11.0.0": + version: 11.0.1 + resolution: "xmlbuilder@npm:11.0.1" + checksum: 7152695e16f1a9976658215abab27e55d08b1b97bca901d58b048d2b6e106b5af31efccbdecf9b07af37c8377d8e7e821b494af10b3a68b0ff4ae60331b415b0 + languageName: node + linkType: hard + "xtend@npm:~4.0.1": version: 4.0.2 resolution: "xtend@npm:4.0.2"