Merge c1e2ddd811 into bc9878053d
32
GoogleServices/GoogleService-Info.plist
Normal file
|
|
@ -0,0 +1,32 @@
|
||||||
|
<?xml version="1.0" encoding="UTF-8"?>
|
||||||
|
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
|
||||||
|
<plist version="1.0">
|
||||||
|
<dict>
|
||||||
|
<key>API_KEY</key>
|
||||||
|
<string>AIzaSyClZkx4PFWhfIG3JDb6GD3g6Bl7-pWLNrU</string>
|
||||||
|
<key>GCM_SENDER_ID</key>
|
||||||
|
<string>917296693147</string>
|
||||||
|
<key>PLIST_VERSION</key>
|
||||||
|
<string>1</string>
|
||||||
|
<key>BUNDLE_ID</key>
|
||||||
|
<string>com.mattdimegs.tones</string>
|
||||||
|
<key>PROJECT_ID</key>
|
||||||
|
<string>tones-9f1d4</string>
|
||||||
|
<key>STORAGE_BUCKET</key>
|
||||||
|
<string>tones-9f1d4.firebasestorage.app</string>
|
||||||
|
<key>IS_ADS_ENABLED</key>
|
||||||
|
<false></false>
|
||||||
|
<key>IS_ANALYTICS_ENABLED</key>
|
||||||
|
<false></false>
|
||||||
|
<key>IS_APPINVITE_ENABLED</key>
|
||||||
|
<true></true>
|
||||||
|
<key>IS_GCM_ENABLED</key>
|
||||||
|
<true></true>
|
||||||
|
<key>IS_SIGNIN_ENABLED</key>
|
||||||
|
<true></true>
|
||||||
|
<key>GOOGLE_APP_ID</key>
|
||||||
|
<string>1:917296693147:ios:73d6d426aa60e52b35ab3e</string>
|
||||||
|
<key>DATABASE_URL</key>
|
||||||
|
<string>https://tones-9f1d4-default-rtdb.firebaseio.com</string>
|
||||||
|
</dict>
|
||||||
|
</plist>
|
||||||
30
GoogleServices/google-services.json
Normal file
|
|
@ -0,0 +1,30 @@
|
||||||
|
{
|
||||||
|
"project_info": {
|
||||||
|
"project_number": "917296693147",
|
||||||
|
"firebase_url": "https://tones-9f1d4-default-rtdb.firebaseio.com",
|
||||||
|
"project_id": "tones-9f1d4",
|
||||||
|
"storage_bucket": "tones-9f1d4.firebasestorage.app"
|
||||||
|
},
|
||||||
|
"client": [
|
||||||
|
{
|
||||||
|
"client_info": {
|
||||||
|
"mobilesdk_app_id": "1:917296693147:android:9387809020ba083035ab3e",
|
||||||
|
"android_client_info": {
|
||||||
|
"package_name": "com.mattdimegs.tones"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"oauth_client": [],
|
||||||
|
"api_key": [
|
||||||
|
{
|
||||||
|
"current_key": "AIzaSyAT0khB8fuAvWjz0WeWrdPAw1RD-v9ylNU"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"services": {
|
||||||
|
"appinvite_service": {
|
||||||
|
"other_platform_oauth_client": []
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"configuration_version": "1"
|
||||||
|
}
|
||||||
|
|
@ -14,18 +14,19 @@ react {
|
||||||
hermesCommand = new File(["node", "--print", "require.resolve('react-native/package.json')"].execute(null, rootDir).text.trim()).getParentFile().getAbsolutePath() + "/sdks/hermesc/%OS-BIN%/hermesc"
|
hermesCommand = new File(["node", "--print", "require.resolve('react-native/package.json')"].execute(null, rootDir).text.trim()).getParentFile().getAbsolutePath() + "/sdks/hermesc/%OS-BIN%/hermesc"
|
||||||
codegenDir = new File(["node", "--print", "require.resolve('@react-native/codegen/package.json', { paths: [require.resolve('react-native/package.json')] })"].execute(null, rootDir).text.trim()).getParentFile().getAbsoluteFile()
|
codegenDir = new File(["node", "--print", "require.resolve('@react-native/codegen/package.json', { paths: [require.resolve('react-native/package.json')] })"].execute(null, rootDir).text.trim()).getParentFile().getAbsoluteFile()
|
||||||
|
|
||||||
|
enableBundleCompression = (findProperty('android.enableBundleCompression') ?: false).toBoolean()
|
||||||
// Use Expo CLI to bundle the app, this ensures the Metro config
|
// Use Expo CLI to bundle the app, this ensures the Metro config
|
||||||
// works correctly with Expo projects.
|
// works correctly with Expo projects.
|
||||||
cliFile = new File(["node", "--print", "require.resolve('@expo/cli', { paths: [require.resolve('expo/package.json')] })"].execute(null, rootDir).text.trim())
|
cliFile = new File(["node", "--print", "require.resolve('@expo/cli', { paths: [require.resolve('expo/package.json')] })"].execute(null, rootDir).text.trim())
|
||||||
bundleCommand = "export:embed"
|
bundleCommand = "export:embed"
|
||||||
|
|
||||||
/* Folders */
|
/* Folders */
|
||||||
// The root of your project, i.e. where "package.json" lives. Default is '..'
|
// The root of your project, i.e. where "package.json" lives. Default is '../..'
|
||||||
// root = file("../")
|
// root = file("../../")
|
||||||
// The folder where the react-native NPM package is. Default is ../node_modules/react-native
|
// The folder where the react-native NPM package is. Default is ../../node_modules/react-native
|
||||||
// reactNativeDir = file("../node_modules/react-native")
|
// reactNativeDir = file("../../node_modules/react-native")
|
||||||
// The folder where the react-native Codegen package is. Default is ../node_modules/@react-native/codegen
|
// The folder where the react-native Codegen package is. Default is ../../node_modules/@react-native/codegen
|
||||||
// codegenDir = file("../node_modules/@react-native/codegen")
|
// codegenDir = file("../../node_modules/@react-native/codegen")
|
||||||
|
|
||||||
/* Variants */
|
/* Variants */
|
||||||
// The list of variants to that are debuggable. For those we're going to
|
// The list of variants to that are debuggable. For those we're going to
|
||||||
|
|
@ -57,6 +58,9 @@ react {
|
||||||
//
|
//
|
||||||
// The list of flags to pass to the Hermes compiler. By default is "-O", "-output-source-map"
|
// The list of flags to pass to the Hermes compiler. By default is "-O", "-output-source-map"
|
||||||
// hermesFlags = ["-O", "-output-source-map"]
|
// hermesFlags = ["-O", "-output-source-map"]
|
||||||
|
|
||||||
|
/* Autolinking */
|
||||||
|
autolinkLibrariesWithApp()
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|
@ -75,7 +79,7 @@ def enableProguardInReleaseBuilds = (findProperty('android.enableProguardInRelea
|
||||||
* give correct results when using with locales other than en-US. Note that
|
* give correct results when using with locales other than en-US. Note that
|
||||||
* this variant is about 6MiB larger per architecture than default.
|
* this variant is about 6MiB larger per architecture than default.
|
||||||
*/
|
*/
|
||||||
def jscFlavor = 'org.webkit:android-jsc:+'
|
def jscFlavor = 'io.github.react-native-community:jsc-android:2026004.+'
|
||||||
|
|
||||||
android {
|
android {
|
||||||
ndkVersion rootProject.ext.ndkVersion
|
ndkVersion rootProject.ext.ndkVersion
|
||||||
|
|
@ -83,13 +87,13 @@ android {
|
||||||
buildToolsVersion rootProject.ext.buildToolsVersion
|
buildToolsVersion rootProject.ext.buildToolsVersion
|
||||||
compileSdk rootProject.ext.compileSdkVersion
|
compileSdk rootProject.ext.compileSdkVersion
|
||||||
|
|
||||||
namespace 'com.anonymous.testapplication'
|
namespace 'com.mattdimegs.tones'
|
||||||
defaultConfig {
|
defaultConfig {
|
||||||
applicationId 'com.anonymous.testapplication'
|
applicationId 'com.mattdimegs.tones'
|
||||||
minSdkVersion rootProject.ext.minSdkVersion
|
minSdkVersion rootProject.ext.minSdkVersion
|
||||||
targetSdkVersion rootProject.ext.targetSdkVersion
|
targetSdkVersion rootProject.ext.targetSdkVersion
|
||||||
versionCode 1
|
versionCode 1
|
||||||
versionName "1.0.0"
|
versionName "1.0.1"
|
||||||
}
|
}
|
||||||
signingConfigs {
|
signingConfigs {
|
||||||
debug {
|
debug {
|
||||||
|
|
@ -110,6 +114,7 @@ android {
|
||||||
shrinkResources (findProperty('android.enableShrinkResourcesInReleaseBuilds')?.toBoolean() ?: false)
|
shrinkResources (findProperty('android.enableShrinkResourcesInReleaseBuilds')?.toBoolean() ?: false)
|
||||||
minifyEnabled enableProguardInReleaseBuilds
|
minifyEnabled enableProguardInReleaseBuilds
|
||||||
proguardFiles getDefaultProguardFile("proguard-android.txt"), "proguard-rules.pro"
|
proguardFiles getDefaultProguardFile("proguard-android.txt"), "proguard-rules.pro"
|
||||||
|
crunchPngs (findProperty('android.enablePngCrunchInReleaseBuilds')?.toBoolean() ?: true)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
packagingOptions {
|
packagingOptions {
|
||||||
|
|
@ -117,6 +122,9 @@ android {
|
||||||
useLegacyPackaging (findProperty('expo.useLegacyPackaging')?.toBoolean() ?: false)
|
useLegacyPackaging (findProperty('expo.useLegacyPackaging')?.toBoolean() ?: false)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
androidResources {
|
||||||
|
ignoreAssetsPattern '!.svn:!.git:!.ds_store:!*.scc:!CVS:!thumbs.db:!picasa.ini:!*~'
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Apply static values from `gradle.properties` to the `android.packagingOptions`
|
// Apply static values from `gradle.properties` to the `android.packagingOptions`
|
||||||
|
|
@ -149,15 +157,15 @@ dependencies {
|
||||||
|
|
||||||
if (isGifEnabled) {
|
if (isGifEnabled) {
|
||||||
// For animated gif support
|
// For animated gif support
|
||||||
implementation("com.facebook.fresco:animated-gif:${reactAndroidLibs.versions.fresco.get()}")
|
implementation("com.facebook.fresco:animated-gif:${expoLibs.versions.fresco.get()}")
|
||||||
}
|
}
|
||||||
|
|
||||||
if (isWebpEnabled) {
|
if (isWebpEnabled) {
|
||||||
// For webp support
|
// For webp support
|
||||||
implementation("com.facebook.fresco:webpsupport:${reactAndroidLibs.versions.fresco.get()}")
|
implementation("com.facebook.fresco:webpsupport:${expoLibs.versions.fresco.get()}")
|
||||||
if (isWebpAnimatedEnabled) {
|
if (isWebpAnimatedEnabled) {
|
||||||
// Animated webp support
|
// Animated webp support
|
||||||
implementation("com.facebook.fresco:animated-webp:${reactAndroidLibs.versions.fresco.get()}")
|
implementation("com.facebook.fresco:animated-webp:${expoLibs.versions.fresco.get()}")
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -168,5 +176,4 @@ dependencies {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
apply from: new File(["node", "--print", "require.resolve('@react-native-community/cli-platform-android/package.json', { paths: [require.resolve('react-native/package.json')] })"].execute(null, rootDir).text.trim(), "../native_modules.gradle");
|
apply plugin: 'com.google.gms.google-services'
|
||||||
applyNativeModulesAppBuildGradle(project)
|
|
||||||
30
android/app/google-services.json
Normal file
|
|
@ -0,0 +1,30 @@
|
||||||
|
{
|
||||||
|
"project_info": {
|
||||||
|
"project_number": "917296693147",
|
||||||
|
"firebase_url": "https://tones-9f1d4-default-rtdb.firebaseio.com",
|
||||||
|
"project_id": "tones-9f1d4",
|
||||||
|
"storage_bucket": "tones-9f1d4.firebasestorage.app"
|
||||||
|
},
|
||||||
|
"client": [
|
||||||
|
{
|
||||||
|
"client_info": {
|
||||||
|
"mobilesdk_app_id": "1:917296693147:android:9387809020ba083035ab3e",
|
||||||
|
"android_client_info": {
|
||||||
|
"package_name": "com.mattdimegs.tones"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"oauth_client": [],
|
||||||
|
"api_key": [
|
||||||
|
{
|
||||||
|
"current_key": "AIzaSyAT0khB8fuAvWjz0WeWrdPAw1RD-v9ylNU"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"services": {
|
||||||
|
"appinvite_service": {
|
||||||
|
"other_platform_oauth_client": []
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"configuration_version": "1"
|
||||||
|
}
|
||||||
|
|
@ -3,5 +3,7 @@
|
||||||
|
|
||||||
<uses-permission android:name="android.permission.SYSTEM_ALERT_WINDOW"/>
|
<uses-permission android:name="android.permission.SYSTEM_ALERT_WINDOW"/>
|
||||||
|
|
||||||
<application android:usesCleartextTraffic="true" tools:targetApi="28" tools:ignore="GoogleAppIndexingWarning" tools:replace="android:usesCleartextTraffic" />
|
<application android:usesCleartextTraffic="true" tools:targetApi="28" tools:ignore="GoogleAppIndexingWarning" tools:replace="android:usesCleartextTraffic">
|
||||||
|
<meta-data android:name="delivery_metrics_exported_to_big_query_enabled" android:value="false"/>
|
||||||
|
</application>
|
||||||
</manifest>
|
</manifest>
|
||||||
|
|
|
||||||
|
|
@ -11,7 +11,7 @@
|
||||||
<data android:scheme="https"/>
|
<data android:scheme="https"/>
|
||||||
</intent>
|
</intent>
|
||||||
</queries>
|
</queries>
|
||||||
<application android:name=".MainApplication" android:label="@string/app_name" android:icon="@mipmap/ic_launcher" android:roundIcon="@mipmap/ic_launcher_round" android:allowBackup="true" android:theme="@style/AppTheme">
|
<application android:name=".MainApplication" android:label="@string/app_name" android:icon="@mipmap/ic_launcher" android:roundIcon="@mipmap/ic_launcher_round" android:allowBackup="true" android:theme="@style/AppTheme" android:supportsRtl="true">
|
||||||
<meta-data android:name="expo.modules.updates.ENABLED" android:value="false"/>
|
<meta-data android:name="expo.modules.updates.ENABLED" android:value="false"/>
|
||||||
<meta-data android:name="expo.modules.updates.EXPO_UPDATES_CHECK_ON_LAUNCH" android:value="ALWAYS"/>
|
<meta-data android:name="expo.modules.updates.EXPO_UPDATES_CHECK_ON_LAUNCH" android:value="ALWAYS"/>
|
||||||
<meta-data android:name="expo.modules.updates.EXPO_UPDATES_LAUNCH_WAIT_MS" android:value="0"/>
|
<meta-data android:name="expo.modules.updates.EXPO_UPDATES_LAUNCH_WAIT_MS" android:value="0"/>
|
||||||
|
|
@ -25,9 +25,7 @@
|
||||||
<category android:name="android.intent.category.DEFAULT"/>
|
<category android:name="android.intent.category.DEFAULT"/>
|
||||||
<category android:name="android.intent.category.BROWSABLE"/>
|
<category android:name="android.intent.category.BROWSABLE"/>
|
||||||
<data android:scheme="myapp"/>
|
<data android:scheme="myapp"/>
|
||||||
<data android:scheme="com.anonymous.testapplication"/>
|
|
||||||
</intent-filter>
|
</intent-filter>
|
||||||
</activity>
|
</activity>
|
||||||
<activity android:name="com.facebook.react.devsupport.DevSettingsActivity" android:exported="false"/>
|
|
||||||
</application>
|
</application>
|
||||||
</manifest>
|
</manifest>
|
||||||
|
|
@ -1,4 +1,5 @@
|
||||||
package com.anonymous.testapplication
|
package com.mattdimegs.tones
|
||||||
|
import expo.modules.splashscreen.SplashScreenManager
|
||||||
|
|
||||||
import android.os.Build
|
import android.os.Build
|
||||||
import android.os.Bundle
|
import android.os.Bundle
|
||||||
|
|
@ -15,7 +16,10 @@ class MainActivity : ReactActivity() {
|
||||||
// Set the theme to AppTheme BEFORE onCreate to support
|
// Set the theme to AppTheme BEFORE onCreate to support
|
||||||
// coloring the background, status bar, and navigation bar.
|
// coloring the background, status bar, and navigation bar.
|
||||||
// This is required for expo-splash-screen.
|
// This is required for expo-splash-screen.
|
||||||
setTheme(R.style.AppTheme);
|
// setTheme(R.style.AppTheme);
|
||||||
|
// @generated begin expo-splashscreen - expo prebuild (DO NOT MODIFY) sync-f3ff59a738c56c9a6119210cb55f0b613eb8b6af
|
||||||
|
SplashScreenManager.registerOnActivity(this)
|
||||||
|
// @generated end expo-splashscreen
|
||||||
super.onCreate(null)
|
super.onCreate(null)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -1,4 +1,4 @@
|
||||||
package com.anonymous.testapplication
|
package com.mattdimegs.tones
|
||||||
|
|
||||||
import android.app.Application
|
import android.app.Application
|
||||||
import android.content.res.Configuration
|
import android.content.res.Configuration
|
||||||
|
|
@ -10,6 +10,7 @@ import com.facebook.react.ReactPackage
|
||||||
import com.facebook.react.ReactHost
|
import com.facebook.react.ReactHost
|
||||||
import com.facebook.react.defaults.DefaultNewArchitectureEntryPoint.load
|
import com.facebook.react.defaults.DefaultNewArchitectureEntryPoint.load
|
||||||
import com.facebook.react.defaults.DefaultReactNativeHost
|
import com.facebook.react.defaults.DefaultReactNativeHost
|
||||||
|
import com.facebook.react.soloader.OpenSourceMergedSoMapping
|
||||||
import com.facebook.soloader.SoLoader
|
import com.facebook.soloader.SoLoader
|
||||||
|
|
||||||
import expo.modules.ApplicationLifecycleDispatcher
|
import expo.modules.ApplicationLifecycleDispatcher
|
||||||
|
|
@ -21,9 +22,10 @@ class MainApplication : Application(), ReactApplication {
|
||||||
this,
|
this,
|
||||||
object : DefaultReactNativeHost(this) {
|
object : DefaultReactNativeHost(this) {
|
||||||
override fun getPackages(): List<ReactPackage> {
|
override fun getPackages(): List<ReactPackage> {
|
||||||
|
val packages = PackageList(this).packages
|
||||||
// Packages that cannot be autolinked yet can be added manually here, for example:
|
// Packages that cannot be autolinked yet can be added manually here, for example:
|
||||||
// packages.add(new MyReactNativePackage());
|
// packages.add(MyReactNativePackage())
|
||||||
return PackageList(this).packages
|
return packages
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun getJSMainModuleName(): String = ".expo/.virtual-metro-entry"
|
override fun getJSMainModuleName(): String = ".expo/.virtual-metro-entry"
|
||||||
|
|
@ -40,7 +42,7 @@ class MainApplication : Application(), ReactApplication {
|
||||||
|
|
||||||
override fun onCreate() {
|
override fun onCreate() {
|
||||||
super.onCreate()
|
super.onCreate()
|
||||||
SoLoader.init(this, false)
|
SoLoader.init(this, OpenSourceMergedSoMapping)
|
||||||
if (BuildConfig.IS_NEW_ARCHITECTURE_ENABLED) {
|
if (BuildConfig.IS_NEW_ARCHITECTURE_ENABLED) {
|
||||||
// If you opted-in for the New Architecture, we load the native entry point for this app.
|
// If you opted-in for the New Architecture, we load the native entry point for this app.
|
||||||
load()
|
load()
|
||||||
BIN
android/app/src/main/res/drawable-hdpi/splashscreen_logo.png
Normal file
|
After Width: | Height: | Size: 5 KiB |
BIN
android/app/src/main/res/drawable-mdpi/splashscreen_logo.png
Normal file
|
After Width: | Height: | Size: 3 KiB |
|
Before Width: | Height: | Size: 58 KiB |
BIN
android/app/src/main/res/drawable-xhdpi/splashscreen_logo.png
Normal file
|
After Width: | Height: | Size: 7.2 KiB |
|
Before Width: | Height: | Size: 58 KiB |
BIN
android/app/src/main/res/drawable-xxhdpi/splashscreen_logo.png
Normal file
|
After Width: | Height: | Size: 12 KiB |
|
Before Width: | Height: | Size: 58 KiB |
BIN
android/app/src/main/res/drawable-xxxhdpi/splashscreen_logo.png
Normal file
|
After Width: | Height: | Size: 19 KiB |
|
|
@ -1,3 +1,6 @@
|
||||||
<layer-list xmlns:android="http://schemas.android.com/apk/res/android">
|
<layer-list xmlns:android="http://schemas.android.com/apk/res/android">
|
||||||
<item android:drawable="@color/splashscreen_background"/>
|
<item android:drawable="@color/splashscreen_background"/>
|
||||||
|
<item>
|
||||||
|
<bitmap android:gravity="center" android:src="@drawable/splashscreen_logo"/>
|
||||||
|
</item>
|
||||||
</layer-list>
|
</layer-list>
|
||||||
|
Before Width: | Height: | Size: 8.2 KiB |
BIN
android/app/src/main/res/mipmap-hdpi/ic_launcher.webp
Normal file
|
After Width: | Height: | Size: 3.2 KiB |
|
Before Width: | Height: | Size: 7.8 KiB After Width: | Height: | Size: 7.8 KiB |
|
Before Width: | Height: | Size: 10 KiB |
BIN
android/app/src/main/res/mipmap-hdpi/ic_launcher_round.webp
Normal file
|
After Width: | Height: | Size: 4 KiB |
|
Before Width: | Height: | Size: 5.1 KiB |
BIN
android/app/src/main/res/mipmap-mdpi/ic_launcher.webp
Normal file
|
After Width: | Height: | Size: 2 KiB |
|
Before Width: | Height: | Size: 5 KiB After Width: | Height: | Size: 5 KiB |
|
Before Width: | Height: | Size: 6.4 KiB |
BIN
android/app/src/main/res/mipmap-mdpi/ic_launcher_round.webp
Normal file
|
After Width: | Height: | Size: 2.6 KiB |
|
Before Width: | Height: | Size: 11 KiB |
BIN
android/app/src/main/res/mipmap-xhdpi/ic_launcher.webp
Normal file
|
After Width: | Height: | Size: 4.4 KiB |
|
Before Width: | Height: | Size: 11 KiB After Width: | Height: | Size: 11 KiB |
|
Before Width: | Height: | Size: 14 KiB |
BIN
android/app/src/main/res/mipmap-xhdpi/ic_launcher_round.webp
Normal file
|
After Width: | Height: | Size: 5.5 KiB |
|
Before Width: | Height: | Size: 18 KiB |
BIN
android/app/src/main/res/mipmap-xxhdpi/ic_launcher.webp
Normal file
|
After Width: | Height: | Size: 7.2 KiB |
|
Before Width: | Height: | Size: 18 KiB After Width: | Height: | Size: 18 KiB |
|
Before Width: | Height: | Size: 22 KiB |
BIN
android/app/src/main/res/mipmap-xxhdpi/ic_launcher_round.webp
Normal file
|
After Width: | Height: | Size: 8.9 KiB |
|
Before Width: | Height: | Size: 25 KiB |
BIN
android/app/src/main/res/mipmap-xxxhdpi/ic_launcher.webp
Normal file
|
After Width: | Height: | Size: 9.9 KiB |
|
Before Width: | Height: | Size: 24 KiB After Width: | Height: | Size: 24 KiB |
|
Before Width: | Height: | Size: 30 KiB |
BIN
android/app/src/main/res/mipmap-xxxhdpi/ic_launcher_round.webp
Normal file
|
After Width: | Height: | Size: 12 KiB |
|
|
@ -1,5 +1,5 @@
|
||||||
<resources>
|
<resources>
|
||||||
<string name="app_name">test-application</string>
|
<string name="app_name">Tones</string>
|
||||||
<string name="expo_splash_screen_resize_mode" translatable="false">contain</string>
|
<string name="expo_splash_screen_resize_mode" translatable="false">contain</string>
|
||||||
<string name="expo_splash_screen_status_bar_translucent" translatable="false">false</string>
|
<string name="expo_splash_screen_status_bar_translucent" translatable="false">false</string>
|
||||||
<string name="expo_system_ui_user_interface_style" translatable="false">automatic</string>
|
<string name="expo_system_ui_user_interface_style" translatable="false">automatic</string>
|
||||||
|
|
|
||||||
|
|
@ -1,17 +1,13 @@
|
||||||
<resources xmlns:tools="http://schemas.android.com/tools">
|
<resources xmlns:tools="http://schemas.android.com/tools">
|
||||||
<style name="AppTheme" parent="Theme.AppCompat.Light.NoActionBar">
|
<style name="AppTheme" parent="Theme.AppCompat.DayNight.NoActionBar">
|
||||||
<item name="android:textColor">@android:color/black</item>
|
|
||||||
<item name="android:editTextStyle">@style/ResetEditText</item>
|
|
||||||
<item name="android:editTextBackground">@drawable/rn_edit_text_material</item>
|
<item name="android:editTextBackground">@drawable/rn_edit_text_material</item>
|
||||||
|
<item name="android:windowOptOutEdgeToEdgeEnforcement" tools:targetApi="35">true</item>
|
||||||
<item name="colorPrimary">@color/colorPrimary</item>
|
<item name="colorPrimary">@color/colorPrimary</item>
|
||||||
<item name="android:statusBarColor">#ffffff</item>
|
<item name="android:statusBarColor">#ffffff</item>
|
||||||
</style>
|
</style>
|
||||||
<style name="ResetEditText" parent="@android:style/Widget.EditText">
|
<style name="Theme.App.SplashScreen" parent="Theme.SplashScreen">
|
||||||
<item name="android:padding">0dp</item>
|
<item name="windowSplashScreenBackground">@color/splashscreen_background</item>
|
||||||
<item name="android:textColorHint">#c8c8c8</item>
|
<item name="windowSplashScreenAnimatedIcon">@drawable/splashscreen_logo</item>
|
||||||
<item name="android:textColor">@android:color/black</item>
|
<item name="postSplashScreenTheme">@style/AppTheme</item>
|
||||||
</style>
|
|
||||||
<style name="Theme.App.SplashScreen" parent="AppTheme">
|
|
||||||
<item name="android:windowBackground">@drawable/splashscreen</item>
|
|
||||||
</style>
|
</style>
|
||||||
</resources>
|
</resources>
|
||||||
|
|
@ -1,37 +1,31 @@
|
||||||
// Top-level build file where you can add configuration options common to all sub-projects/modules.
|
// Top-level build file where you can add configuration options common to all sub-projects/modules.
|
||||||
|
|
||||||
buildscript {
|
buildscript {
|
||||||
ext {
|
|
||||||
buildToolsVersion = findProperty('android.buildToolsVersion') ?: '34.0.0'
|
|
||||||
minSdkVersion = Integer.parseInt(findProperty('android.minSdkVersion') ?: '23')
|
|
||||||
compileSdkVersion = Integer.parseInt(findProperty('android.compileSdkVersion') ?: '34')
|
|
||||||
targetSdkVersion = Integer.parseInt(findProperty('android.targetSdkVersion') ?: '34')
|
|
||||||
kotlinVersion = findProperty('android.kotlinVersion') ?: '1.9.23'
|
|
||||||
|
|
||||||
ndkVersion = "26.1.10909125"
|
|
||||||
}
|
|
||||||
repositories {
|
repositories {
|
||||||
google()
|
google()
|
||||||
mavenCentral()
|
mavenCentral()
|
||||||
}
|
}
|
||||||
dependencies {
|
dependencies {
|
||||||
|
classpath 'com.google.gms:google-services:4.4.1'
|
||||||
classpath('com.android.tools.build:gradle')
|
classpath('com.android.tools.build:gradle')
|
||||||
classpath('com.facebook.react:react-native-gradle-plugin')
|
classpath('com.facebook.react:react-native-gradle-plugin')
|
||||||
classpath('org.jetbrains.kotlin:kotlin-gradle-plugin')
|
classpath('org.jetbrains.kotlin:kotlin-gradle-plugin')
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
apply plugin: "com.facebook.react.rootproject"
|
def reactNativeAndroidDir = new File(
|
||||||
|
providers.exec {
|
||||||
|
workingDir(rootDir)
|
||||||
|
commandLine("node", "--print", "require.resolve('react-native/package.json')")
|
||||||
|
}.standardOutput.asText.get().trim(),
|
||||||
|
"../android"
|
||||||
|
)
|
||||||
|
|
||||||
allprojects {
|
allprojects {
|
||||||
repositories {
|
repositories {
|
||||||
maven {
|
maven {
|
||||||
// All of React Native (JS, Obj-C sources, Android binaries) is installed from npm
|
// All of React Native (JS, Obj-C sources, Android binaries) is installed from npm
|
||||||
url(new File(['node', '--print', "require.resolve('react-native/package.json')"].execute(null, rootDir).text.trim(), '../android'))
|
url(reactNativeAndroidDir)
|
||||||
}
|
|
||||||
maven {
|
|
||||||
// Android JSC is installed from npm
|
|
||||||
url(new File(['node', '--print', "require.resolve('jsc-android/package.json', { paths: [require.resolve('react-native/package.json')] })"].execute(null, rootDir).text.trim(), '../dist'))
|
|
||||||
}
|
}
|
||||||
|
|
||||||
google()
|
google()
|
||||||
|
|
@ -39,3 +33,6 @@ allprojects {
|
||||||
maven { url 'https://www.jitpack.io' }
|
maven { url 'https://www.jitpack.io' }
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
apply plugin: "expo-root-project"
|
||||||
|
apply plugin: "com.facebook.react.rootproject"
|
||||||
|
|
|
||||||
|
|
@ -22,8 +22,8 @@ org.gradle.jvmargs=-Xmx2048m -XX:MaxMetaspaceSize=512m
|
||||||
# https://developer.android.com/topic/libraries/support-library/androidx-rn
|
# https://developer.android.com/topic/libraries/support-library/androidx-rn
|
||||||
android.useAndroidX=true
|
android.useAndroidX=true
|
||||||
|
|
||||||
# Automatically convert third-party libraries to use AndroidX
|
# Enable AAPT2 PNG crunching
|
||||||
android.enableJetifier=true
|
android.enablePngCrunchInReleaseBuilds=true
|
||||||
|
|
||||||
# Use this property to specify which architecture you want to build.
|
# Use this property to specify which architecture you want to build.
|
||||||
# You can also override it from the CLI using
|
# You can also override it from the CLI using
|
||||||
|
|
@ -35,7 +35,7 @@ reactNativeArchitectures=armeabi-v7a,arm64-v8a,x86,x86_64
|
||||||
# your application. You should enable this flag either if you want
|
# your application. You should enable this flag either if you want
|
||||||
# to write custom TurboModules/Fabric components OR use libraries that
|
# to write custom TurboModules/Fabric components OR use libraries that
|
||||||
# are providing them.
|
# are providing them.
|
||||||
newArchEnabled=false
|
newArchEnabled=true
|
||||||
|
|
||||||
# Use this property to enable or disable the Hermes JS engine.
|
# Use this property to enable or disable the Hermes JS engine.
|
||||||
# If set to false, you will be using JSC instead.
|
# If set to false, you will be using JSC instead.
|
||||||
|
|
@ -54,3 +54,6 @@ EX_DEV_CLIENT_NETWORK_INSPECTOR=true
|
||||||
|
|
||||||
# Use legacy packaging to compress native libraries in the resulting APK.
|
# Use legacy packaging to compress native libraries in the resulting APK.
|
||||||
expo.useLegacyPackaging=false
|
expo.useLegacyPackaging=false
|
||||||
|
|
||||||
|
# Whether the app is configured to use edge-to-edge via the app config or `react-native-edge-to-edge` plugin
|
||||||
|
expo.edgeToEdgeEnabled=false
|
||||||
BIN
android/gradle/wrapper/gradle-wrapper.jar
vendored
|
|
@ -1,6 +1,6 @@
|
||||||
distributionBase=GRADLE_USER_HOME
|
distributionBase=GRADLE_USER_HOME
|
||||||
distributionPath=wrapper/dists
|
distributionPath=wrapper/dists
|
||||||
distributionUrl=https\://services.gradle.org/distributions/gradle-8.6-all.zip
|
distributionUrl=https\://services.gradle.org/distributions/gradle-8.13-bin.zip
|
||||||
networkTimeout=10000
|
networkTimeout=10000
|
||||||
validateDistributionUrl=true
|
validateDistributionUrl=true
|
||||||
zipStoreBase=GRADLE_USER_HOME
|
zipStoreBase=GRADLE_USER_HOME
|
||||||
|
|
|
||||||
6
android/gradlew
vendored
Executable file → Normal file
|
|
@ -15,6 +15,8 @@
|
||||||
# See the License for the specific language governing permissions and
|
# See the License for the specific language governing permissions and
|
||||||
# limitations under the License.
|
# limitations under the License.
|
||||||
#
|
#
|
||||||
|
# SPDX-License-Identifier: Apache-2.0
|
||||||
|
#
|
||||||
|
|
||||||
##############################################################################
|
##############################################################################
|
||||||
#
|
#
|
||||||
|
|
@ -55,7 +57,7 @@
|
||||||
# Darwin, MinGW, and NonStop.
|
# Darwin, MinGW, and NonStop.
|
||||||
#
|
#
|
||||||
# (3) This script is generated from the Groovy template
|
# (3) This script is generated from the Groovy template
|
||||||
# https://github.com/gradle/gradle/blob/HEAD/subprojects/plugins/src/main/resources/org/gradle/api/internal/plugins/unixStartScript.txt
|
# https://github.com/gradle/gradle/blob/HEAD/platforms/jvm/plugins-application/src/main/resources/org/gradle/api/internal/plugins/unixStartScript.txt
|
||||||
# within the Gradle project.
|
# within the Gradle project.
|
||||||
#
|
#
|
||||||
# You can find Gradle at https://github.com/gradle/gradle/.
|
# You can find Gradle at https://github.com/gradle/gradle/.
|
||||||
|
|
@ -84,7 +86,7 @@ done
|
||||||
# shellcheck disable=SC2034
|
# shellcheck disable=SC2034
|
||||||
APP_BASE_NAME=${0##*/}
|
APP_BASE_NAME=${0##*/}
|
||||||
# Discard cd standard output in case $CDPATH is set (https://github.com/gradle/gradle/issues/25036)
|
# Discard cd standard output in case $CDPATH is set (https://github.com/gradle/gradle/issues/25036)
|
||||||
APP_HOME=$( cd "${APP_HOME:-./}" > /dev/null && pwd -P ) || exit
|
APP_HOME=$( cd -P "${APP_HOME:-./}" > /dev/null && printf '%s\n' "$PWD" ) || exit
|
||||||
|
|
||||||
# Use the maximum available, or set MAX_FD != -1 to use that value.
|
# Use the maximum available, or set MAX_FD != -1 to use that value.
|
||||||
MAX_FD=maximum
|
MAX_FD=maximum
|
||||||
|
|
|
||||||
2
android/gradlew.bat
vendored
|
|
@ -13,6 +13,8 @@
|
||||||
@rem See the License for the specific language governing permissions and
|
@rem See the License for the specific language governing permissions and
|
||||||
@rem limitations under the License.
|
@rem limitations under the License.
|
||||||
@rem
|
@rem
|
||||||
|
@rem SPDX-License-Identifier: Apache-2.0
|
||||||
|
@rem
|
||||||
|
|
||||||
@if "%DEBUG%"=="" @echo off
|
@if "%DEBUG%"=="" @echo off
|
||||||
@rem ##########################################################################
|
@rem ##########################################################################
|
||||||
|
|
|
||||||
|
|
@ -1,18 +1,39 @@
|
||||||
rootProject.name = 'test-application'
|
pluginManagement {
|
||||||
|
def reactNativeGradlePlugin = new File(
|
||||||
|
providers.exec {
|
||||||
|
workingDir(rootDir)
|
||||||
|
commandLine("node", "--print", "require.resolve('@react-native/gradle-plugin/package.json', { paths: [require.resolve('react-native/package.json')] })")
|
||||||
|
}.standardOutput.asText.get().trim()
|
||||||
|
).getParentFile().absolutePath
|
||||||
|
includeBuild(reactNativeGradlePlugin)
|
||||||
|
|
||||||
dependencyResolutionManagement {
|
def expoPluginsPath = new File(
|
||||||
versionCatalogs {
|
providers.exec {
|
||||||
reactAndroidLibs {
|
workingDir(rootDir)
|
||||||
from(files(new File(["node", "--print", "require.resolve('react-native/package.json')"].execute(null, rootDir).text.trim(), "../gradle/libs.versions.toml")))
|
commandLine("node", "--print", "require.resolve('expo-modules-autolinking/package.json', { paths: [require.resolve('expo/package.json')] })")
|
||||||
}
|
}.standardOutput.asText.get().trim(),
|
||||||
}
|
"../android/expo-gradle-plugin"
|
||||||
|
).absolutePath
|
||||||
|
includeBuild(expoPluginsPath)
|
||||||
}
|
}
|
||||||
|
|
||||||
apply from: new File(["node", "--print", "require.resolve('expo/package.json')"].execute(null, rootDir).text.trim(), "../scripts/autolinking.gradle");
|
plugins {
|
||||||
useExpoModules()
|
id("com.facebook.react.settings")
|
||||||
|
id("expo-autolinking-settings")
|
||||||
|
}
|
||||||
|
|
||||||
apply from: new File(["node", "--print", "require.resolve('@react-native-community/cli-platform-android/package.json', { paths: [require.resolve('react-native/package.json')] })"].execute(null, rootDir).text.trim(), "../native_modules.gradle");
|
extensions.configure(com.facebook.react.ReactSettingsExtension) { ex ->
|
||||||
applyNativeModulesSettingsGradle(settings)
|
if (System.getenv('EXPO_USE_COMMUNITY_AUTOLINKING') == '1') {
|
||||||
|
ex.autolinkLibrariesFromCommand()
|
||||||
|
} else {
|
||||||
|
ex.autolinkLibrariesFromCommand(expoAutolinking.rnConfigCommand)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
expoAutolinking.useExpoModules()
|
||||||
|
|
||||||
|
rootProject.name = 'Tones'
|
||||||
|
|
||||||
|
expoAutolinking.useExpoVersionCatalog()
|
||||||
|
|
||||||
include ':app'
|
include ':app'
|
||||||
includeBuild(new File(["node", "--print", "require.resolve('@react-native/gradle-plugin/package.json', { paths: [require.resolve('react-native/package.json')] })"].execute(null, rootDir).text.trim()).getParentFile())
|
includeBuild(expoAutolinking.reactNativeGradlePlugin)
|
||||||
|
|
|
||||||
28
app.json
|
|
@ -1,7 +1,7 @@
|
||||||
{
|
{
|
||||||
"expo": {
|
"expo": {
|
||||||
"name": "Tones",
|
"name": "Tones",
|
||||||
"slug": "Tones",
|
"slug": "tones",
|
||||||
"version": "1.0.1",
|
"version": "1.0.1",
|
||||||
"orientation": "portrait",
|
"orientation": "portrait",
|
||||||
"icon": "./assets/images/icon.png",
|
"icon": "./assets/images/icon.png",
|
||||||
|
|
@ -13,22 +13,40 @@
|
||||||
"backgroundColor": "#ffffff"
|
"backgroundColor": "#ffffff"
|
||||||
},
|
},
|
||||||
"ios": {
|
"ios": {
|
||||||
|
"entitlements": {
|
||||||
|
"aps-environment": "production"
|
||||||
|
},
|
||||||
|
"infoPlist": {
|
||||||
|
"UIBackgroundModes": ["remote-notification"]
|
||||||
|
},
|
||||||
"supportsTablet": true,
|
"supportsTablet": true,
|
||||||
"bundleIdentifier": "com.anonymous.testapplication"
|
"bundleIdentifier": "com.mattdimegs.tones",
|
||||||
|
"googleServicesFile": "./GoogleServices/GoogleService-Info.plist"
|
||||||
},
|
},
|
||||||
"android": {
|
"android": {
|
||||||
"adaptiveIcon": {
|
"adaptiveIcon": {
|
||||||
"foregroundImage": "./assets/images/adaptive-icon.png",
|
"foregroundImage": "./assets/images/adaptive-icon.png",
|
||||||
"backgroundColor": "#ffffff"
|
"backgroundColor": "#ffffff"
|
||||||
},
|
},
|
||||||
"package": "com.anonymous.testapplication"
|
"package": "com.mattdimegs.tones",
|
||||||
|
"googleServicesFile": "./GoogleServices/google-services.json"
|
||||||
},
|
},
|
||||||
"plugins": [
|
"plugins": [
|
||||||
"expo-router",
|
"expo-router",
|
||||||
"expo-font"
|
"expo-font",
|
||||||
|
"expo-web-browser"
|
||||||
],
|
],
|
||||||
"experiments": {
|
"experiments": {
|
||||||
"typedRoutes": true
|
"typedRoutes": true
|
||||||
}
|
},
|
||||||
|
"extra": {
|
||||||
|
"router": {
|
||||||
|
"origin": false
|
||||||
|
},
|
||||||
|
"eas": {
|
||||||
|
"projectId": "6903a306-dafd-42ab-b010-f0c8205269ad"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"owner": "tones-bd"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
72
app/_layout.jsx
Normal file
|
|
@ -0,0 +1,72 @@
|
||||||
|
import React, { useState, useEffect } from 'react';
|
||||||
|
import { router, Stack } from 'expo-router';
|
||||||
|
import { AuthProvider, GlobalVariablesProvider, WebSocketProvider } from '@/contexts';
|
||||||
|
import { useNotifications, useWebSocketContext } from '@/hooks';
|
||||||
|
import { useAuth } from '@/contexts/AuthContext';
|
||||||
|
|
||||||
|
function AppTest() {
|
||||||
|
const [ oldMessage, setOldMessage ] = useState(1);
|
||||||
|
const { user } = useAuth();
|
||||||
|
const { lastMessage } = useWebSocketContext();
|
||||||
|
const { schedulePushNotification } = useNotifications();
|
||||||
|
const [isReady, setIsReady] = useState(false);
|
||||||
|
|
||||||
|
useEffect(() => {
|
||||||
|
setIsReady(true);
|
||||||
|
}, []);
|
||||||
|
|
||||||
|
useEffect(() => {
|
||||||
|
if (isReady) {
|
||||||
|
if (user) {
|
||||||
|
// Ok to Leave Console Log... Displays the name so you know what you are signed in as.
|
||||||
|
console.log('user: ', user?.displayName || 'Not Found');
|
||||||
|
router.replace('./incidents');
|
||||||
|
} else {
|
||||||
|
router.replace('/login');
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}, [isReady, user]);
|
||||||
|
|
||||||
|
const parseAddress = (data) => {
|
||||||
|
const { Address } = data;
|
||||||
|
const { StreetAddress, AddressApartment, Town, State } = Address;
|
||||||
|
const response = `${StreetAddress}${AddressApartment ? ` - ${AddressApartment}` : ''} ${Town}, ${State}`
|
||||||
|
return response;
|
||||||
|
}
|
||||||
|
|
||||||
|
useEffect(() => {
|
||||||
|
if (lastMessage) {
|
||||||
|
const parsedMessage = JSON?.parse(lastMessage);
|
||||||
|
if (parsedMessage?.data && new Date(oldMessage)?.getTime() < new Date(parsedMessage?.timestamp)?.getTime()) {
|
||||||
|
setOldMessage(new Date(parsedMessage?.timestamp)?.getTime());
|
||||||
|
schedulePushNotification(
|
||||||
|
`${parsedMessage?.data?.Response?.ServiceName} - ${parsedMessage?.data?.Incident?.IncNatureCode}`,
|
||||||
|
`${parsedMessage?.data?.Incident?.IncNature}\n${parseAddress(parsedMessage?.data)}`,
|
||||||
|
parsedMessage?.data
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}, [lastMessage]);
|
||||||
|
|
||||||
|
return (
|
||||||
|
<Stack
|
||||||
|
screenOptions={{
|
||||||
|
gestureEnabled: false,
|
||||||
|
headerBackVisible: false,
|
||||||
|
headerShown: false
|
||||||
|
}}
|
||||||
|
/>
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
export default function App() {
|
||||||
|
return (
|
||||||
|
<GlobalVariablesProvider>
|
||||||
|
<WebSocketProvider>
|
||||||
|
<AuthProvider>
|
||||||
|
<AppTest />
|
||||||
|
</AuthProvider>
|
||||||
|
</WebSocketProvider>
|
||||||
|
</GlobalVariablesProvider>
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
@ -1,26 +0,0 @@
|
||||||
import React, { useEffect } from 'react';
|
|
||||||
import { router, Stack } from 'expo-router';
|
|
||||||
import { WebSocketProvider } from '../contexts/WebSocketContext';
|
|
||||||
|
|
||||||
export const unstable_settings = {
|
|
||||||
initialRouteName: 'login',
|
|
||||||
};
|
|
||||||
|
|
||||||
export default function App() {
|
|
||||||
|
|
||||||
useEffect(() => {
|
|
||||||
router.replace('/login');
|
|
||||||
}, []);
|
|
||||||
|
|
||||||
return (
|
|
||||||
<WebSocketProvider>
|
|
||||||
<Stack
|
|
||||||
screenOptions={{
|
|
||||||
headerShown: false
|
|
||||||
}}
|
|
||||||
>
|
|
||||||
<Stack.Screen name="login" />
|
|
||||||
</Stack>
|
|
||||||
</WebSocketProvider>
|
|
||||||
);
|
|
||||||
}
|
|
||||||
252
app/call.jsx
|
|
@ -1,8 +1,9 @@
|
||||||
import React, { useState, useRef, useEffect } from 'react';
|
import React, { useRef } from 'react';
|
||||||
import styled from 'styled-components';
|
import styled from 'styled-components';
|
||||||
|
import { router } from 'expo-router';
|
||||||
import { useCallFeed } from '../hooks/useCallFeed';
|
import { useCallFeed } from '../hooks/useCallFeed';
|
||||||
import { Platform, Linking, View, ScrollView, Text, TouchableOpacity } from 'react-native';
|
import { Platform, Linking, View, ScrollView, Text, TouchableOpacity } from 'react-native';
|
||||||
import { useLocalSearchParams, router } from 'expo-router';
|
import { useLocalSearchParams } from 'expo-router';
|
||||||
import { StatusBar } from 'expo-status-bar';
|
import { StatusBar } from 'expo-status-bar';
|
||||||
import { SafeAreaView } from 'react-native-safe-area-context';
|
import { SafeAreaView } from 'react-native-safe-area-context';
|
||||||
import { Ionicons } from '@expo/vector-icons';
|
import { Ionicons } from '@expo/vector-icons';
|
||||||
|
|
@ -11,15 +12,19 @@ import { Phone } from "healthicons-react-native/dist/filled";
|
||||||
import {
|
import {
|
||||||
PageHeader,
|
PageHeader,
|
||||||
PageFooter,
|
PageFooter,
|
||||||
} from '../components/generalHelpers.jsx';
|
} from '@/components/generalHelpers.jsx';
|
||||||
import ActionSheet from 'react-native-actions-sheet';
|
import ActionSheet from 'react-native-actions-sheet';
|
||||||
|
|
||||||
const DepartmentActionSheet = styled(ActionSheet)``;
|
const DepartmentActionSheet = styled(ActionSheet)``;
|
||||||
|
|
||||||
|
function fromBase64Unicode(str) {
|
||||||
|
return new TextDecoder().decode(Uint8Array.from(atob(str), c => c.charCodeAt(0)));
|
||||||
|
}
|
||||||
|
|
||||||
export default function Call() {
|
export default function Call() {
|
||||||
const { callDetails } = useLocalSearchParams();
|
const { callDetails } = useLocalSearchParams();
|
||||||
const actionSheetRef = useRef(null);
|
const actionSheetRef = useRef(null);
|
||||||
const callFeed = useCallFeed();
|
const callFeed = useCallFeed(true);
|
||||||
|
|
||||||
const {
|
const {
|
||||||
departments,
|
departments,
|
||||||
|
|
@ -39,56 +44,56 @@ export default function Call() {
|
||||||
deptList,
|
deptList,
|
||||||
} = departments;
|
} = departments;
|
||||||
|
|
||||||
const decoded = atob(callDetails);
|
const decoded = fromBase64Unicode(callDetails);
|
||||||
|
|
||||||
const { Incident, Address, Person, Response } = JSON.parse(decoded);
|
const { incident, address, person, response } = JSON.parse(decoded);
|
||||||
const { CallThemes } = accountDetails;
|
const { CallThemes } = accountDetails;
|
||||||
const {
|
const {
|
||||||
IncID,
|
incID,
|
||||||
IncNumber,
|
incNumber,
|
||||||
JurisdictionNumber,
|
jurisdictionNumber,
|
||||||
ServiceNumber,
|
serviceNumber,
|
||||||
ServiceID,
|
serviceID,
|
||||||
IncDate,
|
incDate,
|
||||||
IncNature,
|
incNature,
|
||||||
IncNatureCode,
|
incNatureCode,
|
||||||
IncNatureCodeDesc,
|
incNatureCodeDesc,
|
||||||
Notes,
|
notes,
|
||||||
Status,
|
status,
|
||||||
Origin,
|
origin,
|
||||||
} = Incident;
|
} = incident;
|
||||||
const {
|
const {
|
||||||
StreetAddress,
|
streetAddress,
|
||||||
AddressApartment,
|
addressApartment,
|
||||||
Town,
|
town,
|
||||||
State,
|
state,
|
||||||
ZipCode,
|
zipCode,
|
||||||
Latitude,
|
latitude,
|
||||||
Longitude,
|
longitude,
|
||||||
County,
|
county,
|
||||||
Intersection1,
|
intersection1,
|
||||||
Intersection2,
|
intersection2,
|
||||||
LocationName,
|
locationName,
|
||||||
WeatherCondition,
|
weatherCondition,
|
||||||
} = Address;
|
} = address;
|
||||||
const {
|
const {
|
||||||
Name,
|
name,
|
||||||
Age,
|
age,
|
||||||
Gender,
|
gender,
|
||||||
Statement,
|
statement,
|
||||||
Conscious,
|
conscious,
|
||||||
Breathing,
|
breathing,
|
||||||
CallBackNumber,
|
callBackNumber,
|
||||||
} = Person;
|
} = person;
|
||||||
const {
|
const {
|
||||||
Units
|
units
|
||||||
} = Response;
|
} = response;
|
||||||
|
|
||||||
const SelectedIcon = callIconMap[IncNature] || AccidentAndEmergency;
|
const SelectedIcon = callIconMap[incNature] || AccidentAndEmergency;
|
||||||
|
|
||||||
const ownDepartmentResponse = Units?.map((unit) => {
|
const ownDepartmentResponse = units?.map((unit) => {
|
||||||
if (unit?.Department === selectedDepartment?.dept ||
|
if (unit?.department === selectedDepartment?.dept ||
|
||||||
selectedDepartment?.addDepts?.includes(unit?.Department)) {
|
selectedDepartment?.addDepts?.includes(unit?.department)) {
|
||||||
return unit;
|
return unit;
|
||||||
}
|
}
|
||||||
return null;
|
return null;
|
||||||
|
|
@ -96,9 +101,9 @@ export default function Call() {
|
||||||
return filterItem;
|
return filterItem;
|
||||||
});
|
});
|
||||||
|
|
||||||
const mutualAidDepartmentResponse = Units?.map((unit) => {
|
const mutualAidDepartmentResponse = units?.map((unit) => {
|
||||||
if (unit?.Department !== selectedDepartment?.dept &&
|
if (unit?.department !== selectedDepartment?.dept &&
|
||||||
!selectedDepartment?.addDepts?.includes(unit?.Department)) {
|
!selectedDepartment?.addDepts?.includes(unit?.department)) {
|
||||||
return unit;
|
return unit;
|
||||||
}
|
}
|
||||||
return null;
|
return null;
|
||||||
|
|
@ -107,7 +112,7 @@ export default function Call() {
|
||||||
});;
|
});;
|
||||||
|
|
||||||
const formatResponseTimes = (time) => {
|
const formatResponseTimes = (time) => {
|
||||||
if (time === null) {
|
if (time === null || time === undefined || time === '') {
|
||||||
return '';
|
return '';
|
||||||
}
|
}
|
||||||
const initTime = new Date(time);
|
const initTime = new Date(time);
|
||||||
|
|
@ -129,16 +134,17 @@ export default function Call() {
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<React.Fragment>
|
<React.Fragment>
|
||||||
<PageHeader>
|
<PageHeader
|
||||||
<View
|
leftHeader={ <View style={{ flex: 1, alignItems: 'flex-start' }}>
|
||||||
style={{
|
<TouchableOpacity
|
||||||
flexDirection: 'column',
|
onPress={router.back}
|
||||||
height: 80,
|
style={{ flexDirection: 'row', alignItems: 'center' }}
|
||||||
alignItems: 'center',
|
|
||||||
justifyContent: 'flex-end',
|
|
||||||
paddingBottom: 7
|
|
||||||
}}
|
|
||||||
>
|
>
|
||||||
|
<Ionicons name="chevron-back-outline" size={22} color="red" style={{ paddingLeft: 10 }} />
|
||||||
|
<Text style={{ color: 'red', fontWeight: 600 }}>Back to Incidents</Text>
|
||||||
|
</TouchableOpacity>
|
||||||
|
</View>}
|
||||||
|
centerHeader={<View style={{ flex: 1, alignItems: 'center' }}>
|
||||||
<TouchableOpacity
|
<TouchableOpacity
|
||||||
style={{
|
style={{
|
||||||
borderRadius: 6,
|
borderRadius: 6,
|
||||||
|
|
@ -159,15 +165,15 @@ export default function Call() {
|
||||||
style={{
|
style={{
|
||||||
color: selectedDepartmentColorPicker(selectedDepartment?.type),
|
color: selectedDepartmentColorPicker(selectedDepartment?.type),
|
||||||
fontWeight: 600,
|
fontWeight: 600,
|
||||||
fontSize: '14'
|
fontSize: 14
|
||||||
}}
|
}}
|
||||||
>
|
>
|
||||||
{selectedDepartment?.deptAbv}
|
{selectedDepartment?.deptAbv}
|
||||||
</Text>
|
</Text>
|
||||||
</TouchableOpacity>
|
</TouchableOpacity>
|
||||||
</View>
|
</View>}
|
||||||
</PageHeader>
|
/>
|
||||||
<ScrollView>
|
<ScrollView showsVerticalScrollIndicator={false}>
|
||||||
<StatusBar style="dark" />
|
<StatusBar style="dark" />
|
||||||
<SafeAreaView />
|
<SafeAreaView />
|
||||||
<View style={{ flexDirection: 'column', padding: 20 }}>
|
<View style={{ flexDirection: 'column', padding: 20 }}>
|
||||||
|
|
@ -180,8 +186,8 @@ export default function Call() {
|
||||||
justifyContent: 'space-between'
|
justifyContent: 'space-between'
|
||||||
}}
|
}}
|
||||||
>
|
>
|
||||||
<Text style={{ fontSize: 12 }}>{formatCallDateTime(IncDate)}</Text>
|
<Text style={{ fontSize: 12 }}>{formatCallDateTime(incDate)}</Text>
|
||||||
<Text style={{ fontSize: 12 }}>{formatCallTimePast(IncDate)}</Text>
|
<Text style={{ fontSize: 12 }}>{formatCallTimePast(incDate)}</Text>
|
||||||
</View>
|
</View>
|
||||||
<View key="callDetails" style={{ padding: 2 }}>
|
<View key="callDetails" style={{ padding: 2 }}>
|
||||||
<View
|
<View
|
||||||
|
|
@ -191,9 +197,9 @@ export default function Call() {
|
||||||
backgroundColor: '#fff',
|
backgroundColor: '#fff',
|
||||||
shadowOffset: { width: 0, height: 0 },
|
shadowOffset: { width: 0, height: 0 },
|
||||||
shadowColor: callColorSelector(
|
shadowColor: callColorSelector(
|
||||||
IncNatureCode,
|
incNatureCodeDesc,
|
||||||
IncNature,
|
incNature,
|
||||||
Status
|
status
|
||||||
),
|
),
|
||||||
shadowOpacity: 1,
|
shadowOpacity: 1,
|
||||||
shadowRadius: 5,
|
shadowRadius: 5,
|
||||||
|
|
@ -201,18 +207,18 @@ export default function Call() {
|
||||||
}}
|
}}
|
||||||
>
|
>
|
||||||
<View style={{ flexDirection: 'column' }}>
|
<View style={{ flexDirection: 'column' }}>
|
||||||
<View style={{ flexDirection: 'row', alignItems: 'center' }}>
|
<View style={{ flexDirection: 'row', alignItems: 'center', width: '100%' }}>
|
||||||
<SelectedIcon
|
<SelectedIcon
|
||||||
color={callColorSelector(
|
color={callColorSelector(
|
||||||
IncNatureCode,
|
incNatureCodeDesc,
|
||||||
IncNature,
|
incNature,
|
||||||
Status
|
status
|
||||||
)}
|
)}
|
||||||
opacity={0.3}
|
opacity={0.3}
|
||||||
width={56}
|
width={56}
|
||||||
height={56}
|
height={56}
|
||||||
/>
|
/>
|
||||||
<View style={{ flexDirection: 'column' }}>
|
<View style={{ flex: 1, flexDirection: 'column' }}>
|
||||||
<Text
|
<Text
|
||||||
style={{
|
style={{
|
||||||
color: 'black',
|
color: 'black',
|
||||||
|
|
@ -220,7 +226,7 @@ export default function Call() {
|
||||||
fontSize: 16
|
fontSize: 16
|
||||||
}}
|
}}
|
||||||
>
|
>
|
||||||
{`${IncNature}`}
|
{`${incNature}`}
|
||||||
</Text>
|
</Text>
|
||||||
<View style={{ flexDirection: 'row', justifyContent: 'space-between' }}>
|
<View style={{ flexDirection: 'row', justifyContent: 'space-between' }}>
|
||||||
<Text
|
<Text
|
||||||
|
|
@ -228,20 +234,20 @@ export default function Call() {
|
||||||
color: 'black',
|
color: 'black',
|
||||||
fontSize: 12,
|
fontSize: 12,
|
||||||
textShadowColor: callColorSelector(
|
textShadowColor: callColorSelector(
|
||||||
IncNatureCode,
|
incNatureCodeDesc,
|
||||||
IncNature,
|
incNature,
|
||||||
Status
|
status
|
||||||
),
|
),
|
||||||
textShadowRadius: 1
|
textShadowRadius: 1
|
||||||
}}
|
}}
|
||||||
>
|
>
|
||||||
{`${IncNatureCodeDesc}`}
|
{`${incNatureCodeDesc}`}
|
||||||
</Text>
|
</Text>
|
||||||
</View>
|
</View>
|
||||||
</View>
|
</View>
|
||||||
</View>
|
</View>
|
||||||
<View style={{ flexDirection: 'row', justifyContent: 'space-between' }}>
|
<View style={{ flexDirection: 'row', justifyContent: 'space-between' }}>
|
||||||
{Status === 'CLOSED' ? (
|
{status.toLowerCase() === 'closed' ? (
|
||||||
<Text
|
<Text
|
||||||
style={{
|
style={{
|
||||||
fontSize: 12,
|
fontSize: 12,
|
||||||
|
|
@ -258,7 +264,7 @@ export default function Call() {
|
||||||
textAlign: 'right'
|
textAlign: 'right'
|
||||||
}}
|
}}
|
||||||
>
|
>
|
||||||
{`Incident #: ${ServiceNumber}`}
|
{`Incident #: ${serviceNumber}`}
|
||||||
</Text>
|
</Text>
|
||||||
</View>
|
</View>
|
||||||
</View>
|
</View>
|
||||||
|
|
@ -285,8 +291,8 @@ export default function Call() {
|
||||||
justifyContent: 'space-between'
|
justifyContent: 'space-between'
|
||||||
}}
|
}}
|
||||||
>
|
>
|
||||||
<View style={{ flexDirection: 'column' }}>
|
<View style={{ flexDirection: 'column', maxWidth: '70%' }}>
|
||||||
{LocationName ? (
|
{locationName ? (
|
||||||
<Text
|
<Text
|
||||||
style={{
|
style={{
|
||||||
color: 'black',
|
color: 'black',
|
||||||
|
|
@ -294,38 +300,38 @@ export default function Call() {
|
||||||
fontSize: 16
|
fontSize: 16
|
||||||
}}
|
}}
|
||||||
>
|
>
|
||||||
{`${LocationName}`}
|
{`${locationName}`}
|
||||||
</Text>
|
</Text>
|
||||||
) : null}
|
) : null}
|
||||||
<TouchableOpacity
|
<TouchableOpacity
|
||||||
onLongPress={() => {
|
onLongPress={() => {
|
||||||
return openMaps(Latitude, Longitude);
|
return openMaps(latitude, longitude);
|
||||||
}}
|
}}
|
||||||
>
|
>
|
||||||
<Text
|
<Text
|
||||||
style={[{
|
style={[{
|
||||||
color: 'black',
|
color: 'black',
|
||||||
}, LocationName ? {} : {fontSize: 12, fontWeight: 600}]}
|
}, locationName ? {} : { fontSize: 12, fontWeight: 600 }]}
|
||||||
>
|
>
|
||||||
{`${StreetAddress}`}
|
{`${streetAddress}`}
|
||||||
</Text>
|
</Text>
|
||||||
<Text
|
<Text
|
||||||
style={[{
|
style={[{
|
||||||
color: 'black',
|
color: 'black',
|
||||||
}, LocationName ? {} : {fontSize: 12, fontWeight: 600}]}
|
}, locationName ? {} : { fontSize: 12, fontWeight: 600 }]}
|
||||||
>
|
>
|
||||||
{`${Town}, ${State}`}
|
{`${town}, ${state}`}
|
||||||
</Text>
|
</Text>
|
||||||
</TouchableOpacity>
|
</TouchableOpacity>
|
||||||
{AddressApartment ? (
|
{addressApartment ? (
|
||||||
<View>
|
<View>
|
||||||
<View style={{ margin: 10 }} />
|
<View style={{ margin: 10 }} />
|
||||||
<Text
|
<Text
|
||||||
style={[{
|
style={[{
|
||||||
color: 'black',
|
color: 'black',
|
||||||
}, LocationName ? {} : {fontSize: 12, fontWeight: 600}]}
|
}, locationName ? {} : { fontSize: 12, fontWeight: 600 }]}
|
||||||
>
|
>
|
||||||
{`${AddressApartment}`}
|
{`${addressApartment}`}
|
||||||
</Text>
|
</Text>
|
||||||
</View>
|
</View>
|
||||||
) : null}
|
) : null}
|
||||||
|
|
@ -361,7 +367,7 @@ export default function Call() {
|
||||||
justifyContent: 'center'
|
justifyContent: 'center'
|
||||||
}}
|
}}
|
||||||
onPress={() => {
|
onPress={() => {
|
||||||
return openMaps(Latitude, Longitude);
|
return openMaps(latitude, longitude);
|
||||||
}}
|
}}
|
||||||
>
|
>
|
||||||
<Text style={{ fontSize: 10 }}>Nav</Text>
|
<Text style={{ fontSize: 10 }}>Nav</Text>
|
||||||
|
|
@ -400,10 +406,10 @@ export default function Call() {
|
||||||
textAlign: 'center'
|
textAlign: 'center'
|
||||||
}}
|
}}
|
||||||
>
|
>
|
||||||
{Intersection1}
|
{intersection1}
|
||||||
</Text>
|
</Text>
|
||||||
</View>
|
</View>
|
||||||
<View style={{ paddingHorizontal: "3%" }}/>
|
<View style={{ paddingHorizontal: "2%" }} />
|
||||||
<View
|
<View
|
||||||
style={{
|
style={{
|
||||||
borderRadius: 12,
|
borderRadius: 12,
|
||||||
|
|
@ -424,7 +430,7 @@ export default function Call() {
|
||||||
textAlign: 'center'
|
textAlign: 'center'
|
||||||
}}
|
}}
|
||||||
>
|
>
|
||||||
{Intersection2}
|
{intersection2}
|
||||||
</Text>
|
</Text>
|
||||||
</View>
|
</View>
|
||||||
</View>
|
</View>
|
||||||
|
|
@ -461,23 +467,23 @@ export default function Call() {
|
||||||
fontSize: 16
|
fontSize: 16
|
||||||
}}
|
}}
|
||||||
>
|
>
|
||||||
{`${Name}`}
|
{`${name}`}
|
||||||
</Text>
|
</Text>
|
||||||
<TouchableOpacity
|
<TouchableOpacity
|
||||||
onLongPress={() => {
|
onLongPress={() => {
|
||||||
return callNumber(CallBackNumber);
|
return callNumber(callBackNumber);
|
||||||
}}
|
}}
|
||||||
>
|
>
|
||||||
<Text
|
<Text
|
||||||
style={{ color: 'black', fontSize: 12 }}
|
style={{ color: 'black', fontSize: 12 }}
|
||||||
>
|
>
|
||||||
{`${CallBackNumber}`}
|
{`${callBackNumber}`}
|
||||||
</Text>
|
</Text>
|
||||||
</TouchableOpacity>
|
</TouchableOpacity>
|
||||||
</View>
|
</View>
|
||||||
<TouchableOpacity
|
<TouchableOpacity
|
||||||
onLongPress={() => {
|
onLongPress={() => {
|
||||||
return callNumber(CallBackNumber);
|
return callNumber(callBackNumber);
|
||||||
}}
|
}}
|
||||||
>
|
>
|
||||||
<Phone
|
<Phone
|
||||||
|
|
@ -502,20 +508,20 @@ export default function Call() {
|
||||||
<View style={{ alignItems: 'center' }}>
|
<View style={{ alignItems: 'center' }}>
|
||||||
<View style={{ flexDirection: 'row' }}>
|
<View style={{ flexDirection: 'row' }}>
|
||||||
<Text style={{ fontSize: 14 }}>
|
<Text style={{ fontSize: 14 }}>
|
||||||
{`${Age} `}
|
{`${age} `}
|
||||||
</Text>
|
</Text>
|
||||||
<Text style={{ fontSize: 14 }}>
|
<Text style={{ fontSize: 14 }}>
|
||||||
{`${Gender} - `}
|
{`${gender} - `}
|
||||||
</Text>
|
</Text>
|
||||||
<Text style={{ fontSize: 14 }}>
|
<Text style={{ fontSize: 14 }}>
|
||||||
{`Concious: ${Conscious} | `}
|
{`Conscious: ${conscious} | `}
|
||||||
</Text>
|
</Text>
|
||||||
<Text style={{ fontSize: 14 }}>
|
<Text style={{ fontSize: 14 }}>
|
||||||
{`Breathing: ${Breathing}`}
|
{`Breathing: ${breathing}`}
|
||||||
</Text>
|
</Text>
|
||||||
</View>
|
</View>
|
||||||
<Text style={{ fontSize: 12 }}>
|
<Text style={{ fontSize: 12 }}>
|
||||||
{`${Statement}`}
|
{`${statement}`}
|
||||||
</Text>
|
</Text>
|
||||||
</View>
|
</View>
|
||||||
</View>
|
</View>
|
||||||
|
|
@ -544,7 +550,7 @@ export default function Call() {
|
||||||
}}
|
}}
|
||||||
>
|
>
|
||||||
<View style={{ flexDirection: 'column' }}>
|
<View style={{ flexDirection: 'column' }}>
|
||||||
{Units?.length > 0 ? (
|
{units?.length > 0 ? (
|
||||||
<View>
|
<View>
|
||||||
{ownDepartmentResponse?.length > 0 ? (
|
{ownDepartmentResponse?.length > 0 ? (
|
||||||
<View>
|
<View>
|
||||||
|
|
@ -577,7 +583,7 @@ export default function Call() {
|
||||||
>
|
>
|
||||||
{ownDepartmentResponse?.map((unit) => {
|
{ownDepartmentResponse?.map((unit) => {
|
||||||
return (
|
return (
|
||||||
<View key={unit?.Unit}
|
<View key={unit?.unit}
|
||||||
style={{
|
style={{
|
||||||
flex: 1,
|
flex: 1,
|
||||||
alignSelf: 'stretch',
|
alignSelf: 'stretch',
|
||||||
|
|
@ -588,30 +594,31 @@ export default function Call() {
|
||||||
>
|
>
|
||||||
<Text
|
<Text
|
||||||
style={{
|
style={{
|
||||||
|
fontSize: 12,
|
||||||
fontWeight: 600,
|
fontWeight: 600,
|
||||||
textAlign: 'center',
|
textAlign: 'center',
|
||||||
flex: 1
|
flex: 1
|
||||||
}}
|
}}
|
||||||
>
|
>
|
||||||
{unit?.Unit}
|
{unit?.unit}
|
||||||
</Text>
|
</Text>
|
||||||
<Text style={{ textAlign: 'center', flex: 1 }}>
|
<Text style={{ textAlign: 'center', flex: 1 }}>
|
||||||
{formatResponseTimes(unit?.Dispatched)}
|
{formatResponseTimes(unit?.dispatched)}
|
||||||
</Text>
|
</Text>
|
||||||
<Text style={{ textAlign: 'center', flex: 1 }}>
|
<Text style={{ textAlign: 'center', flex: 1 }}>
|
||||||
{formatResponseTimes(unit?.Responding)}
|
{formatResponseTimes(unit?.responding)}
|
||||||
</Text>
|
</Text>
|
||||||
<Text style={{ textAlign: 'center', flex: 1 }}>
|
<Text style={{ textAlign: 'center', flex: 1 }}>
|
||||||
{formatResponseTimes(unit?.OnScene)}
|
{formatResponseTimes(unit?.onScene)}
|
||||||
</Text>
|
</Text>
|
||||||
{selectedDepartment?.type === 'EMS' ||
|
{selectedDepartment?.type === 'EMS' ||
|
||||||
selectedDepartment?.type === 'Rescue' ? (
|
selectedDepartment?.type === 'Rescue' ? (
|
||||||
<Text style={{ textAlign: 'center', flex: 1 }}>
|
<Text style={{ textAlign: 'center', flex: 1 }}>
|
||||||
{formatResponseTimes(unit?.Transporting)}
|
{formatResponseTimes(unit?.transporting)}
|
||||||
</Text>
|
</Text>
|
||||||
) : null}
|
) : null}
|
||||||
<Text style={{ textAlign: 'center', flex: 1 }}>
|
<Text style={{ textAlign: 'center', flex: 1 }}>
|
||||||
{formatResponseTimes(unit?.InService)}
|
{formatResponseTimes(unit?.inService)}
|
||||||
</Text>
|
</Text>
|
||||||
</View>
|
</View>
|
||||||
)
|
)
|
||||||
|
|
@ -661,7 +668,7 @@ export default function Call() {
|
||||||
/>
|
/>
|
||||||
{mutualAidDepartmentResponse?.map((unit) => {
|
{mutualAidDepartmentResponse?.map((unit) => {
|
||||||
return (
|
return (
|
||||||
<View key={unit?.Unit}
|
<View key={unit?.unit}
|
||||||
style={{
|
style={{
|
||||||
flex: 1,
|
flex: 1,
|
||||||
alignSelf: 'stretch',
|
alignSelf: 'stretch',
|
||||||
|
|
@ -672,30 +679,31 @@ export default function Call() {
|
||||||
>
|
>
|
||||||
<Text
|
<Text
|
||||||
style={{
|
style={{
|
||||||
|
fontSize: 12,
|
||||||
fontWeight: 600,
|
fontWeight: 600,
|
||||||
textAlign: 'center',
|
textAlign: 'center',
|
||||||
flex: 1
|
flex: 1
|
||||||
}}
|
}}
|
||||||
>
|
>
|
||||||
{unit?.Unit}
|
{unit?.unit}
|
||||||
</Text>
|
</Text>
|
||||||
<Text style={{ textAlign: 'center', flex: 1 }}>
|
<Text style={{ textAlign: 'center', flex: 1 }}>
|
||||||
{formatResponseTimes(unit?.Dispatched)}
|
{formatResponseTimes(unit?.dispatched)}
|
||||||
</Text>
|
</Text>
|
||||||
<Text style={{ textAlign: 'center', flex: 1 }}>
|
<Text style={{ textAlign: 'center', flex: 1 }}>
|
||||||
{formatResponseTimes(unit?.Responding)}
|
{formatResponseTimes(unit?.responding)}
|
||||||
</Text>
|
</Text>
|
||||||
<Text style={{ textAlign: 'center', flex: 1 }}>
|
<Text style={{ textAlign: 'center', flex: 1 }}>
|
||||||
{formatResponseTimes(unit?.OnScene)}
|
{formatResponseTimes(unit?.onScene)}
|
||||||
</Text>
|
</Text>
|
||||||
{selectedDepartment?.type === 'EMS' ||
|
{selectedDepartment?.type === 'EMS' ||
|
||||||
selectedDepartment?.type === 'Rescue' ? (
|
selectedDepartment?.type === 'Rescue' ? (
|
||||||
<Text style={{ textAlign: 'center', flex: 1 }}>
|
<Text style={{ textAlign: 'center', flex: 1 }}>
|
||||||
{formatResponseTimes(unit?.Transporting)}
|
{formatResponseTimes(unit?.transporting)}
|
||||||
</Text>
|
</Text>
|
||||||
) : null}
|
) : null}
|
||||||
<Text style={{ textAlign: 'center', flex: 1 }}>
|
<Text style={{ textAlign: 'center', flex: 1 }}>
|
||||||
{formatResponseTimes(unit?.InService)}
|
{formatResponseTimes(unit?.inService)}
|
||||||
</Text>
|
</Text>
|
||||||
</View>
|
</View>
|
||||||
)
|
)
|
||||||
|
|
@ -736,10 +744,10 @@ export default function Call() {
|
||||||
minHeight: 200
|
minHeight: 200
|
||||||
}}
|
}}
|
||||||
>
|
>
|
||||||
{Notes?.split('\n').map((note, index) => (
|
{notes?.split('\n').map((note, index) => (
|
||||||
<View key={index}>
|
<View key={`notes-${index}`}>
|
||||||
<Text>{note}</Text>
|
<Text>{note}</Text>
|
||||||
{index < Notes.split('\n').length - 1 && (
|
{index < notes.split('\n').length - 1 && (
|
||||||
<View
|
<View
|
||||||
style={{
|
style={{
|
||||||
height: 1,
|
height: 1,
|
||||||
|
|
|
||||||
|
|
@ -42,7 +42,7 @@ export default function TabTwoScreen() {
|
||||||
<ThemedText type="defaultSemiBold">@3x</ThemedText> suffixes to provide files for
|
<ThemedText type="defaultSemiBold">@3x</ThemedText> suffixes to provide files for
|
||||||
different screen densities
|
different screen densities
|
||||||
</ThemedText>
|
</ThemedText>
|
||||||
<Image source={require('@/assets/images/tones-logo.png')} style={{ alignSelf: 'center' }} />
|
<Image source={require('../assets/images/tones-logo.png')} style={{ alignSelf: 'center' }} />
|
||||||
<ExternalLink href="https://reactnative.dev/docs/images">
|
<ExternalLink href="https://reactnative.dev/docs/images">
|
||||||
<ThemedText type="link">Learn more</ThemedText>
|
<ThemedText type="link">Learn more</ThemedText>
|
||||||
</ExternalLink>
|
</ExternalLink>
|
||||||
|
|
|
||||||
|
|
@ -1,20 +1,32 @@
|
||||||
import React, { useState, useRef, useEffect } from 'react';
|
import React, { useState, useRef, useEffect } from "react";
|
||||||
import styled from 'styled-components';
|
import styled from "styled-components";
|
||||||
import { useCallFeed } from '../hooks/useCallFeed';
|
import { useCallFeed } from "@/hooks";
|
||||||
import { router } from 'expo-router';
|
import { router } from "expo-router";
|
||||||
import { Platform, Linking, View, ScrollView, Text, TouchableOpacity } from 'react-native';
|
|
||||||
import { StatusBar } from 'expo-status-bar';
|
|
||||||
import { SafeAreaView } from 'react-native-safe-area-context';
|
|
||||||
import {
|
import {
|
||||||
PageHeader,
|
Platform,
|
||||||
PageFooter,
|
Linking,
|
||||||
} from '../components/generalHelpers.jsx';
|
View,
|
||||||
import { Ionicons } from '@expo/vector-icons';
|
ScrollView,
|
||||||
|
Text,
|
||||||
|
TouchableOpacity,
|
||||||
|
} from "react-native";
|
||||||
|
import { StatusBar } from "expo-status-bar";
|
||||||
|
import { SafeAreaView } from "react-native-safe-area-context";
|
||||||
|
import { PageHeader, PageFooter } from "@/components/generalHelpers.jsx";
|
||||||
|
import { Ionicons } from "@expo/vector-icons";
|
||||||
import { AccidentAndEmergency } from "healthicons-react-native/dist/outline";
|
import { AccidentAndEmergency } from "healthicons-react-native/dist/outline";
|
||||||
import ActionSheet from 'react-native-actions-sheet';
|
import ActionSheet from "react-native-actions-sheet";
|
||||||
|
|
||||||
const DepartmentActionSheet = styled(ActionSheet)``;
|
const DepartmentActionSheet = styled(ActionSheet)``;
|
||||||
|
|
||||||
|
function toBase64Unicode(str) {
|
||||||
|
return btoa(
|
||||||
|
new TextEncoder()
|
||||||
|
.encode(str)
|
||||||
|
.reduce((data, byte) => data + String.fromCharCode(byte), "")
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
export default function Incidents() {
|
export default function Incidents() {
|
||||||
const actionSheetRef = useRef(null);
|
const actionSheetRef = useRef(null);
|
||||||
const callFeed = useCallFeed();
|
const callFeed = useCallFeed();
|
||||||
|
|
@ -25,16 +37,26 @@ export default function Incidents() {
|
||||||
callDetails,
|
callDetails,
|
||||||
callColorSelector,
|
callColorSelector,
|
||||||
formatCallTimePast,
|
formatCallTimePast,
|
||||||
formatCallDateTime
|
formatCallDateTime,
|
||||||
} = callFeed;
|
} = callFeed;
|
||||||
|
|
||||||
const sortedAndFilteredCalls = callDetails
|
const sortedAndFilteredCalls =
|
||||||
|
callDetails
|
||||||
.sort((a, b) => new Date(b.timestamp) - new Date(a.timestamp))
|
.sort((a, b) => new Date(b.timestamp) - new Date(a.timestamp))
|
||||||
.filter((item, index, self) => {
|
.filter((item, index, self) => {
|
||||||
return index === self.findIndex(i => {
|
return (
|
||||||
return `${i?.data?.Incident?.IncID}${i?.data?.Response?.ServiceName}` === `${item?.data?.Incident?.IncID}${item?.data?.Response?.ServiceName}`
|
index ===
|
||||||
});
|
self.findIndex((i) => {
|
||||||
});
|
return (
|
||||||
|
`${i?.incident?.incID}${i?.response?.serviceName}` ===
|
||||||
|
`${item?.incident?.incID}${item?.response?.serviceName}`
|
||||||
|
);
|
||||||
|
})
|
||||||
|
);
|
||||||
|
})
|
||||||
|
?.map((item) => {
|
||||||
|
return { ...item, timestamp: item?.incident?.incDate };
|
||||||
|
}) || [];
|
||||||
|
|
||||||
const {
|
const {
|
||||||
departmentTypeMap,
|
departmentTypeMap,
|
||||||
|
|
@ -49,24 +71,17 @@ export default function Incidents() {
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<React.Fragment>
|
<React.Fragment>
|
||||||
<PageHeader>
|
<PageHeader
|
||||||
<View
|
centerHeader={
|
||||||
style={{
|
<View style={{ flex: 1, alignItems: "center" }}>
|
||||||
flexDirection: 'column',
|
|
||||||
height: 80,
|
|
||||||
alignItems: 'center',
|
|
||||||
justifyContent: 'flex-end',
|
|
||||||
paddingBottom: 7
|
|
||||||
}}
|
|
||||||
>
|
|
||||||
<TouchableOpacity
|
<TouchableOpacity
|
||||||
style={{
|
style={{
|
||||||
borderRadius: 6,
|
borderRadius: 6,
|
||||||
elevation: 3,
|
elevation: 3,
|
||||||
backgroundColor: '#fff',
|
backgroundColor: "#fff",
|
||||||
shadowOffset: { width: 0, height: 0 },
|
shadowOffset: { width: 0, height: 0 },
|
||||||
shadowColor: '#333',
|
shadowColor: "#333",
|
||||||
shadowOpacity: .8,
|
shadowOpacity: 0.8,
|
||||||
shadowRadius: 2,
|
shadowRadius: 2,
|
||||||
paddingHorizontal: 10,
|
paddingHorizontal: 10,
|
||||||
paddingVertical: 2,
|
paddingVertical: 2,
|
||||||
|
|
@ -77,175 +92,204 @@ export default function Incidents() {
|
||||||
>
|
>
|
||||||
<Text
|
<Text
|
||||||
style={{
|
style={{
|
||||||
color: selectedDepartmentColorPicker(selectedDepartment?.type),
|
color: selectedDepartmentColorPicker(
|
||||||
|
selectedDepartment?.type
|
||||||
|
),
|
||||||
fontWeight: 600,
|
fontWeight: 600,
|
||||||
fontSize: 14
|
fontSize: 14,
|
||||||
}}
|
}}
|
||||||
>
|
>
|
||||||
{selectedDepartment?.deptAbv}
|
{selectedDepartment?.deptAbv}
|
||||||
</Text>
|
</Text>
|
||||||
</TouchableOpacity>
|
</TouchableOpacity>
|
||||||
</View>
|
</View>
|
||||||
</PageHeader>
|
}
|
||||||
|
/>
|
||||||
<ScrollView>
|
<ScrollView>
|
||||||
<StatusBar style="dark" />
|
<StatusBar style="dark" />
|
||||||
<SafeAreaView />
|
<SafeAreaView />
|
||||||
<View style={{ flexDirection: 'column', padding: 20 }}>
|
<View style={{ flexDirection: "column", padding: 20 }}>
|
||||||
{sortedAndFilteredCalls?.length ? (
|
{sortedAndFilteredCalls?.length ? (
|
||||||
sortedAndFilteredCalls?.map((callItem, index) => {
|
sortedAndFilteredCalls?.map((callItem, index) => {
|
||||||
const { data: call, timestamp } = callItem;
|
const { incident, address, response, timestamp } = callItem;
|
||||||
const { Incident, Address, Response } = call;
|
|
||||||
const {
|
const {
|
||||||
ServiceNumber,
|
serviceNumber,
|
||||||
IncDate,
|
incDate,
|
||||||
IncNature,
|
incNature,
|
||||||
IncNatureCode,
|
incNatureCode,
|
||||||
IncNatureCodeDesc,
|
incNatureCodeDesc,
|
||||||
Status,
|
status,
|
||||||
} = Incident;
|
} = incident;
|
||||||
const {
|
const {
|
||||||
StreetAddress,
|
streetAddress,
|
||||||
AddressApartment,
|
addressApartment,
|
||||||
Town,
|
town,
|
||||||
State,
|
state,
|
||||||
LocationName,
|
locationName,
|
||||||
} = Address;
|
} = address;
|
||||||
const {
|
const { serviceName } = response;
|
||||||
ServiceName
|
const SelectedIcon =
|
||||||
} = Response;
|
callIconMap[incNature] || AccidentAndEmergency;
|
||||||
const SelectedIcon = callIconMap[IncNature] || AccidentAndEmergency;
|
|
||||||
return (
|
return (
|
||||||
<TouchableOpacity
|
<TouchableOpacity
|
||||||
key={`callDetails - ${timestamp}`}
|
key={`callDetails - ${timestamp}`}
|
||||||
style={{ padding: 2 }}
|
style={{ paddingBottom: 15 }}
|
||||||
onPress={() => {
|
onPress={() => {
|
||||||
router.push({
|
router.push({
|
||||||
pathname: '/call',
|
pathname: "/call",
|
||||||
params: {
|
params: {
|
||||||
callDetails: btoa(JSON.stringify(call))
|
callDetails: toBase64Unicode(JSON.stringify(callItem)),
|
||||||
}
|
},
|
||||||
})
|
});
|
||||||
}}
|
}}
|
||||||
>
|
>
|
||||||
<View
|
<View
|
||||||
style={{
|
style={{
|
||||||
borderRadius: 12,
|
borderRadius: 12,
|
||||||
elevation: 3,
|
elevation: 3,
|
||||||
backgroundColor: '#fff',
|
backgroundColor: "#fff",
|
||||||
shadowOffset: { width: 0, height: 0 },
|
shadowOffset: { width: 0, height: 0 },
|
||||||
shadowColor: callColorSelector(
|
shadowColor: callColorSelector(
|
||||||
IncNatureCode,
|
incNatureCodeDesc,
|
||||||
IncNature,
|
incNature,
|
||||||
Status
|
status
|
||||||
),
|
),
|
||||||
shadowOpacity: 1,
|
shadowOpacity: 1,
|
||||||
shadowRadius: 5,
|
shadowRadius: 5,
|
||||||
padding: 10,
|
padding: 10,
|
||||||
}}
|
}}
|
||||||
>
|
>
|
||||||
<View style={{ flexDirection: 'column' }}>
|
<View style={{ flexDirection: "column" }}>
|
||||||
<View key="callDateAndTime"
|
<View
|
||||||
|
key="callDateAndTime"
|
||||||
style={{
|
style={{
|
||||||
paddingBottom: 6,
|
paddingBottom: 6,
|
||||||
flexDirection: 'row',
|
flexDirection: "row",
|
||||||
justifyContent: 'space-between'
|
justifyContent: "space-between",
|
||||||
}}
|
}}
|
||||||
>
|
>
|
||||||
<Text style={{ fontSize: 12 }}>{formatCallDateTime(IncDate)}</Text>
|
<Text style={{ fontSize: 12 }}>
|
||||||
<View style={{ flexDirection: 'row', alignItems: 'center' }}>
|
{formatCallDateTime(incDate)}
|
||||||
<Text style={{ fontSize: 12 }}>{formatCallTimePast(IncDate)}</Text>
|
</Text>
|
||||||
{Status === 'CLOSED' ? (
|
<View
|
||||||
|
style={{ flexDirection: "row", alignItems: "center" }}
|
||||||
|
>
|
||||||
|
<Text style={{ fontSize: 12 }}>
|
||||||
|
{formatCallTimePast(incDate)}
|
||||||
|
</Text>
|
||||||
|
{status === "CLOSED" ? (
|
||||||
<Ionicons
|
<Ionicons
|
||||||
name="lock-closed-outline"
|
name="lock-closed-outline"
|
||||||
color='red'
|
color="red"
|
||||||
style={{
|
style={{
|
||||||
shadowColor: 'black',
|
shadowColor: "black",
|
||||||
shadowOffset: 0,
|
shadowOffset: 0,
|
||||||
shadowOpacity: 1,
|
shadowOpacity: 1,
|
||||||
shadowRadius: 10
|
shadowRadius: 10,
|
||||||
}}
|
}}
|
||||||
/>
|
/>
|
||||||
) : null}
|
) : null}
|
||||||
</View>
|
</View>
|
||||||
</View>
|
</View>
|
||||||
<View style={{ flexDirection: 'row', alignItems: 'center', justifyContent: 'space-between' }}>
|
<View
|
||||||
|
style={{ flexDirection: "row", alignItems: "center" }}
|
||||||
|
>
|
||||||
<SelectedIcon
|
<SelectedIcon
|
||||||
color={callColorSelector(
|
color={callColorSelector(
|
||||||
IncNatureCode,
|
incNatureCodeDesc,
|
||||||
IncNature,
|
incNature,
|
||||||
Status
|
status
|
||||||
)}
|
)}
|
||||||
opacity={0.3}
|
opacity={0.3}
|
||||||
width={56}
|
width={56}
|
||||||
height={56}
|
height={56}
|
||||||
/>
|
/>
|
||||||
<View style={{ flexDirection: 'column' }}>
|
<View
|
||||||
{LocationName ? (
|
|
||||||
<Text
|
|
||||||
style={{
|
style={{
|
||||||
color: 'black',
|
flex: 1,
|
||||||
fontWeight: 600,
|
flexDirection: "column",
|
||||||
fontSize: 16
|
alignItems: "flex-start",
|
||||||
|
paddingHorizontal: 2,
|
||||||
|
maxWidth: "80%",
|
||||||
}}
|
}}
|
||||||
>
|
>
|
||||||
{`${LocationName}`}
|
{locationName ? (
|
||||||
|
<Text
|
||||||
|
style={{
|
||||||
|
color: "black",
|
||||||
|
fontWeight: 600,
|
||||||
|
fontSize: 16,
|
||||||
|
}}
|
||||||
|
>
|
||||||
|
{`${locationName}`}
|
||||||
</Text>
|
</Text>
|
||||||
) : (
|
) : (
|
||||||
<View style={{ flexDirection: 'row' }}>
|
<View style={{ flexDirection: "row" }}>
|
||||||
<Text
|
<Text
|
||||||
style={[{
|
style={[
|
||||||
color: 'black',
|
{
|
||||||
|
color: "black",
|
||||||
fontSize: 12,
|
fontSize: 12,
|
||||||
fontWeight: 600
|
fontWeight: 600,
|
||||||
}]}
|
},
|
||||||
|
]}
|
||||||
>
|
>
|
||||||
{`${StreetAddress}`}
|
{`${streetAddress?.split(",")[0]}`}
|
||||||
</Text>
|
</Text>
|
||||||
{AddressApartment ? (
|
{addressApartment ? (
|
||||||
<Text
|
<Text
|
||||||
style={[{
|
style={[
|
||||||
color: 'black',
|
{
|
||||||
|
color: "black",
|
||||||
fontSize: 12,
|
fontSize: 12,
|
||||||
fontWeight: 600
|
fontWeight: 600,
|
||||||
}]}
|
},
|
||||||
|
]}
|
||||||
>
|
>
|
||||||
{` - ${AddressApartment}`}
|
{` - ${addressApartment}`}
|
||||||
</Text>
|
</Text>
|
||||||
) : null}
|
) : null}
|
||||||
<Text
|
<Text
|
||||||
style={[{
|
style={[
|
||||||
color: 'black',
|
{
|
||||||
|
color: "black",
|
||||||
fontSize: 12,
|
fontSize: 12,
|
||||||
fontWeight: 600
|
fontWeight: 600,
|
||||||
}]}
|
},
|
||||||
|
]}
|
||||||
>
|
>
|
||||||
{` ${Town}, ${State}`}
|
{` ${town}, ${state}`}
|
||||||
</Text>
|
</Text>
|
||||||
</View>
|
</View>
|
||||||
)}
|
)}
|
||||||
<Text
|
<Text
|
||||||
style={{
|
style={{
|
||||||
color: 'black',
|
color: "black",
|
||||||
fontWeight: 600,
|
fontWeight: 600,
|
||||||
fontSize: 16
|
fontSize: 16,
|
||||||
}}
|
}}
|
||||||
>
|
>
|
||||||
{`${IncNature}`}
|
{`${incNature}`}
|
||||||
</Text>
|
</Text>
|
||||||
<View style={{ flexDirection: 'row', justifyContent: 'space-between' }}>
|
<View
|
||||||
|
style={{
|
||||||
|
flexDirection: "row",
|
||||||
|
justifyContent: "space-between",
|
||||||
|
}}
|
||||||
|
>
|
||||||
<Text
|
<Text
|
||||||
style={{
|
style={{
|
||||||
color: 'black',
|
color: "black",
|
||||||
fontSize: 12,
|
fontSize: 12,
|
||||||
textShadowColor: callColorSelector(
|
textShadowColor: callColorSelector(
|
||||||
IncNatureCode,
|
incNatureCode,
|
||||||
IncNature,
|
incNature,
|
||||||
Status
|
status
|
||||||
),
|
),
|
||||||
textShadowRadius: 1
|
textShadowRadius: 1,
|
||||||
}}
|
}}
|
||||||
>
|
>
|
||||||
{`${IncNatureCodeDesc}`}
|
{`${incNatureCodeDesc}`}
|
||||||
</Text>
|
</Text>
|
||||||
</View>
|
</View>
|
||||||
</View>
|
</View>
|
||||||
|
|
@ -255,48 +299,47 @@ export default function Incidents() {
|
||||||
</View>
|
</View>
|
||||||
</View>
|
</View>
|
||||||
</View>
|
</View>
|
||||||
<View style={{ flexDirection: 'row', justifyContent: 'space-between' }}>
|
<View
|
||||||
|
style={{
|
||||||
|
paddingTop: 5,
|
||||||
|
flexDirection: "row",
|
||||||
|
justifyContent: "space-between",
|
||||||
|
}}
|
||||||
|
>
|
||||||
<Text
|
<Text
|
||||||
style={{
|
style={{
|
||||||
fontSize: 12,
|
fontSize: 12,
|
||||||
}}
|
}}
|
||||||
>
|
>
|
||||||
Service: {ServiceName}
|
Service: {serviceName}
|
||||||
</Text>
|
</Text>
|
||||||
<Text
|
<Text
|
||||||
style={{
|
style={{
|
||||||
fontSize: 12,
|
fontSize: 12,
|
||||||
textAlign: 'right'
|
textAlign: "right",
|
||||||
}}
|
}}
|
||||||
>
|
>
|
||||||
{`Incident #: ${ServiceNumber}`}
|
{`Incident #: ${serviceNumber}`}
|
||||||
</Text>
|
</Text>
|
||||||
</View>
|
</View>
|
||||||
</View>
|
</View>
|
||||||
</View>
|
</View>
|
||||||
</TouchableOpacity>
|
</TouchableOpacity>
|
||||||
)
|
);
|
||||||
})) : (
|
})
|
||||||
<View style={{
|
) : (
|
||||||
marginTop: '50%',
|
<Text>There are no Calls</Text>
|
||||||
flexDirection: 'column',
|
|
||||||
alignItems: 'center',
|
|
||||||
justifyContent: 'flex-end',
|
|
||||||
}}>
|
|
||||||
<Ionicons name="warning-outline" size={100} color='orange' />
|
|
||||||
<Text style={{ fontSize: 25 }}>There are no Incidents</Text>
|
|
||||||
</View>
|
|
||||||
)}
|
)}
|
||||||
</View>
|
</View>
|
||||||
</ScrollView>
|
</ScrollView>
|
||||||
<PageFooter>
|
<PageFooter>
|
||||||
<View
|
<View
|
||||||
style={{
|
style={{
|
||||||
flexDirection: 'column',
|
flexDirection: "column",
|
||||||
height: 100,
|
height: 100,
|
||||||
alignItems: 'center',
|
alignItems: "center",
|
||||||
justifyContent: 'flex-start',
|
justifyContent: "flex-start",
|
||||||
paddingTop: 7
|
paddingTop: 7,
|
||||||
}}
|
}}
|
||||||
/>
|
/>
|
||||||
</PageFooter>
|
</PageFooter>
|
||||||
|
|
@ -306,10 +349,10 @@ export default function Incidents() {
|
||||||
containerStyle={{
|
containerStyle={{
|
||||||
height: "50%",
|
height: "50%",
|
||||||
width: "100%",
|
width: "100%",
|
||||||
backgroundColor: '#ECEDEE',
|
backgroundColor: "#ECEDEE",
|
||||||
}}
|
}}
|
||||||
>
|
>
|
||||||
<View style={{ flexDirection: 'column', padding: 20 }}>
|
<View style={{ flexDirection: "column", padding: 20 }}>
|
||||||
{deptList?.map((item) => {
|
{deptList?.map((item) => {
|
||||||
return (
|
return (
|
||||||
<View style={{ padding: 2 }} key={item?.deptId}>
|
<View style={{ padding: 2 }} key={item?.deptId}>
|
||||||
|
|
@ -317,44 +360,56 @@ export default function Incidents() {
|
||||||
style={{
|
style={{
|
||||||
borderRadius: 6,
|
borderRadius: 6,
|
||||||
elevation: 3,
|
elevation: 3,
|
||||||
backgroundColor: item?.selected ? 'grey' : '#fff',
|
backgroundColor: item?.selected ? "grey" : "#fff",
|
||||||
shadowOffset: { width: 1, height: 1 },
|
shadowOffset: { width: 1, height: 1 },
|
||||||
shadowColor: '#333',
|
shadowColor: "#333",
|
||||||
shadowOpacity: 0.3,
|
shadowOpacity: 0.3,
|
||||||
shadowRadius: 2,
|
shadowRadius: 2,
|
||||||
marginHorizontal: 20,
|
marginHorizontal: 20,
|
||||||
marginVertical: 6,
|
marginVertical: 6,
|
||||||
padding: 10
|
padding: 10,
|
||||||
}}
|
}}
|
||||||
onPress={() => {
|
onPress={() => {
|
||||||
actionSheetRef.current?.hide();
|
actionSheetRef.current?.hide();
|
||||||
return updateSelectedDepartment(
|
return updateSelectedDepartment(
|
||||||
selectedDepartment?.deptId,
|
selectedDepartment?.deptId,
|
||||||
item?.deptId
|
item?.deptId
|
||||||
)
|
);
|
||||||
|
}}
|
||||||
|
>
|
||||||
|
<View
|
||||||
|
style={{
|
||||||
|
flexDirection: "row",
|
||||||
|
justifyContent: "space-between",
|
||||||
}}
|
}}
|
||||||
>
|
>
|
||||||
<View style={{ flexDirection: 'row', justifyContent: 'space-between' }}>
|
|
||||||
<Text
|
<Text
|
||||||
style={{
|
style={{
|
||||||
color: selectedDepartmentColorPicker(
|
color: selectedDepartmentColorPicker(item?.type),
|
||||||
item?.type
|
|
||||||
),
|
|
||||||
fontWeight: 600,
|
fontWeight: 600,
|
||||||
fontSize: 16
|
fontSize: 16,
|
||||||
}}
|
}}
|
||||||
>
|
>
|
||||||
{item?.dept}
|
{item?.dept}
|
||||||
</Text>
|
</Text>
|
||||||
{item?.primary ? <Ionicons name="star" size={16} color="yellow" style={{
|
{item?.primary ? (
|
||||||
|
<Ionicons
|
||||||
|
name="star"
|
||||||
|
size={16}
|
||||||
|
color="yellow"
|
||||||
|
style={{
|
||||||
paddingLeft: 20,
|
paddingLeft: 20,
|
||||||
shadowColor: '#333',
|
shadowColor: "#333",
|
||||||
shadowOffset: 1,
|
shadowOffset: 1,
|
||||||
shadowOpacity: 1,
|
shadowOpacity: 1,
|
||||||
shadowRadius: 6
|
shadowRadius: 6,
|
||||||
}} /> : null}
|
}}
|
||||||
|
/>
|
||||||
|
) : null}
|
||||||
</View>
|
</View>
|
||||||
<Text>{`${item?.deptAbv} - ${departmentTypeMap[item?.type]}`}</Text>
|
<Text>{`${item?.deptAbv} - ${
|
||||||
|
departmentTypeMap[item?.type]
|
||||||
|
}`}</Text>
|
||||||
</TouchableOpacity>
|
</TouchableOpacity>
|
||||||
</View>
|
</View>
|
||||||
);
|
);
|
||||||
|
|
@ -362,5 +417,5 @@ export default function Incidents() {
|
||||||
</View>
|
</View>
|
||||||
</DepartmentActionSheet>
|
</DepartmentActionSheet>
|
||||||
</React.Fragment>
|
</React.Fragment>
|
||||||
)
|
);
|
||||||
}
|
}
|
||||||
|
|
@ -1,5 +1,5 @@
|
||||||
import React, { useState, useEffect } from 'react';
|
import React, { useState, useEffect } from 'react';
|
||||||
import { View, Text } from 'react-native';
|
import { View, Text, ScrollView, KeyboardAvoidingView, Platform } from 'react-native';
|
||||||
import { StatusBar } from 'expo-status-bar';
|
import { StatusBar } from 'expo-status-bar';
|
||||||
import { useFormik } from 'formik';
|
import { useFormik } from 'formik';
|
||||||
import { SafeAreaView } from 'react-native-safe-area-context';
|
import { SafeAreaView } from 'react-native-safe-area-context';
|
||||||
|
|
@ -20,22 +20,35 @@ import {
|
||||||
ExtraText,
|
ExtraText,
|
||||||
TextLinkContent,
|
TextLinkContent,
|
||||||
LoginTextInput
|
LoginTextInput
|
||||||
} from '../components/generalHelpers.jsx';
|
} from '@/components/generalHelpers.jsx';
|
||||||
|
|
||||||
|
import { signInWithEmailAndPassword } from 'firebase/auth';
|
||||||
|
import { auth } from '@/contexts/firebase';
|
||||||
|
import { useNotifications } from '@/hooks';
|
||||||
|
|
||||||
export default function Login() {
|
export default function Login() {
|
||||||
const [hidePassword, setHidePassword] = useState(true);
|
const [hidePassword, setHidePassword] = useState(true);
|
||||||
const [loginButtonDisabled, setLoginButtonDisabled] = useState(true);
|
const [loginButtonDisabled, setLoginButtonDisabled] = useState(true);
|
||||||
const [auth, setAuth] = useState(false);
|
const [error, setError] = useState('');
|
||||||
|
const [loading, setLoading] = useState(false);
|
||||||
|
const { expoPushToken } = useNotifications();
|
||||||
|
|
||||||
const formik = useFormik({
|
const formik = useFormik({
|
||||||
initialValues: {
|
initialValues: {
|
||||||
number: '',
|
email: '',
|
||||||
password: ''
|
password: ''
|
||||||
},
|
},
|
||||||
onSubmit: (values) => {
|
onSubmit: async (values) => {
|
||||||
values.number = values.number.replace(/[()\-\s]/g, '');
|
setError('');
|
||||||
console.log(values);
|
setLoading(true);
|
||||||
setAuth(true);
|
try {
|
||||||
|
await signInWithEmailAndPassword(auth, values.email, values.password);
|
||||||
|
router.replace('./incidents');
|
||||||
|
} catch (err) {
|
||||||
|
setError(err.message);
|
||||||
|
} finally {
|
||||||
|
setLoading(false);
|
||||||
|
}
|
||||||
},
|
},
|
||||||
});
|
});
|
||||||
|
|
||||||
|
|
@ -43,49 +56,45 @@ export default function Login() {
|
||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
if (formValues) {
|
if (formValues) {
|
||||||
if (formValues.number.length === 14 && formValues.password) {
|
if (formValues.email && formValues.password) {
|
||||||
setLoginButtonDisabled(false);
|
setLoginButtonDisabled(false);
|
||||||
} else {
|
} else {
|
||||||
setLoginButtonDisabled(true);
|
setLoginButtonDisabled(true);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}, [formValues])
|
}, [formValues]);
|
||||||
|
|
||||||
useEffect(() => {
|
|
||||||
// Temp for Testing
|
|
||||||
// if (!auth) {
|
|
||||||
// setTimeout(() => {
|
|
||||||
// router.replace('./incidents');
|
|
||||||
// }, 1000);
|
|
||||||
// }
|
|
||||||
if (auth) {
|
|
||||||
router.replace('./incidents');
|
|
||||||
}
|
|
||||||
}, [auth])
|
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<React.Fragment>
|
<View style={{ flex: 1 }}>
|
||||||
|
<StatusBar style="dark" />
|
||||||
<PageHeader>
|
<PageHeader>
|
||||||
<View style={{ flexDirection: 'row', height: 80, alignItems: 'center' }} />
|
<View style={{ flexDirection: 'row', height: 80, alignItems: 'center' }} />
|
||||||
</PageHeader>
|
</PageHeader>
|
||||||
|
<KeyboardAvoidingView
|
||||||
|
style={{ flex: 1 }}
|
||||||
|
behavior={Platform.OS === 'ios' ? 'padding' : 'height'}
|
||||||
|
keyboardVerticalOffset={0}
|
||||||
|
>
|
||||||
|
<ScrollView keyboardShouldPersistTaps="handled" contentContainerStyle={{ flexGrow: 1 }}>
|
||||||
<StyledContainer>
|
<StyledContainer>
|
||||||
<StatusBar style="dark" />
|
|
||||||
<SafeAreaView />
|
<SafeAreaView />
|
||||||
<InnerContainer>
|
<InnerContainer>
|
||||||
<PageImage resizeMode="cover" source={require('./../assets/images/tones-logo.png')} />
|
<PageImage resizeMode="cover" source={require('./../assets/images/tones-logo.png')} />
|
||||||
<Title>Tones</Title>
|
<Title>Tones</Title>
|
||||||
<SubTitle>Account Login</SubTitle>
|
<SubTitle>Account Login</SubTitle>
|
||||||
<StyledFormArea>
|
<StyledFormArea>
|
||||||
|
{error ? <MessageBox style={{ color: 'red' }}>{error}</MessageBox> : null}
|
||||||
<LoginTextInput
|
<LoginTextInput
|
||||||
label="Phone Number"
|
label="Email Address"
|
||||||
icon="call-outline"
|
icon="mail-outline"
|
||||||
placeholder="123-456-7890"
|
placeholder="test@organization.com"
|
||||||
placeholderTextColor="gray"
|
placeholderTextColor="gray"
|
||||||
onChangeText={formik.handleChange('number')}
|
onChangeText={formik.handleChange('email')}
|
||||||
onBlur={formik.handleBlur('number')}
|
onBlur={formik.handleBlur('email')}
|
||||||
value={formik.values.number.replace(/^(\d{3})(\d{3})(\d+)$/, "($1) $2-$3")}
|
value={formik.values.email}
|
||||||
keyboardType="number-pad"
|
keyboardType="email-address"
|
||||||
maxLength={14}
|
autoComplete='email'
|
||||||
|
autoCapitalize='none'
|
||||||
/>
|
/>
|
||||||
<LoginTextInput
|
<LoginTextInput
|
||||||
label="Password"
|
label="Password"
|
||||||
|
|
@ -122,9 +131,12 @@ export default function Login() {
|
||||||
<TextLinkContent>Landing</TextLinkContent>
|
<TextLinkContent>Landing</TextLinkContent>
|
||||||
</Link>
|
</Link>
|
||||||
</View>
|
</View>
|
||||||
|
<Text>View Token: {expoPushToken}</Text>
|
||||||
<Line />
|
<Line />
|
||||||
</InnerContainer>
|
</InnerContainer>
|
||||||
</StyledContainer>
|
</StyledContainer>
|
||||||
</React.Fragment>
|
</ScrollView>
|
||||||
|
</KeyboardAvoidingView>
|
||||||
|
</View>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
111
app/register.jsx
|
|
@ -1,6 +1,10 @@
|
||||||
import React, { useState, useEffect } from 'react';
|
import React, { useState, useEffect } from 'react';
|
||||||
|
import * as Notifications from 'expo-notifications';
|
||||||
import { router } from 'expo-router';
|
import { router } from 'expo-router';
|
||||||
import { View, ScrollView, Text, TouchableOpacity } from 'react-native';
|
import { createUserWithEmailAndPassword, updateProfile } from 'firebase/auth';
|
||||||
|
import { auth } from '@/contexts/firebase';
|
||||||
|
import { useAuth } from '@/contexts/AuthContext';
|
||||||
|
import { View, ScrollView, Text, TouchableOpacity, KeyboardAvoidingView, Platform } from 'react-native';
|
||||||
import { StatusBar } from 'expo-status-bar';
|
import { StatusBar } from 'expo-status-bar';
|
||||||
import { useFormik } from 'formik';
|
import { useFormik } from 'formik';
|
||||||
import { SafeAreaView } from 'react-native-safe-area-context';
|
import { SafeAreaView } from 'react-native-safe-area-context';
|
||||||
|
|
@ -19,14 +23,16 @@ import {
|
||||||
MessageBox,
|
MessageBox,
|
||||||
LoginTextInput,
|
LoginTextInput,
|
||||||
RegisterDropdownInput,
|
RegisterDropdownInput,
|
||||||
} from '../components/generalHelpers.jsx';
|
formatPhoneNumber
|
||||||
|
} from '@/components/generalHelpers.jsx';
|
||||||
|
|
||||||
export default function Register() {
|
export default function Register() {
|
||||||
|
|
||||||
const [providerDropdownOpen, setProviderDropdownOpen] = useState(false);
|
const [providerDropdownOpen, setProviderDropdownOpen] = useState(false);
|
||||||
const [hidePassword, setHidePassword] = useState(true);
|
const [hidePassword, setHidePassword] = useState(true);
|
||||||
const [registerButtonDisabled, setRegisterButtonDisabled] = useState(true);
|
const [registerButtonDisabled, setRegisterButtonDisabled] = useState(true);
|
||||||
|
const [error, setError] = useState('');
|
||||||
|
const [loading, setLoading] = useState(false);
|
||||||
|
const { user } = useAuth();
|
||||||
|
|
||||||
const formik = useFormik({
|
const formik = useFormik({
|
||||||
initialValues: {
|
initialValues: {
|
||||||
|
|
@ -38,9 +44,60 @@ export default function Register() {
|
||||||
password: '',
|
password: '',
|
||||||
passwordConfirmation: ''
|
passwordConfirmation: ''
|
||||||
},
|
},
|
||||||
onSubmit: (values) => {
|
onSubmit: async (values) => {
|
||||||
values.number = values.number.replace(/[()\-\s]/g, '');
|
setError('');
|
||||||
console.log(values);
|
setLoading(true);
|
||||||
|
try {
|
||||||
|
const userCredential = await createUserWithEmailAndPassword(auth, values.email, values.password);
|
||||||
|
await updateProfile(userCredential.user, {
|
||||||
|
displayName: `${values.firstName} ${values.lastName}`
|
||||||
|
});
|
||||||
|
// Request permissions and get push token (native FCM if possible, else Expo token)
|
||||||
|
let token = null;
|
||||||
|
let tokenType = null;
|
||||||
|
const { status: existingStatus } = await Notifications.getPermissionsAsync();
|
||||||
|
let finalStatus = existingStatus;
|
||||||
|
if (existingStatus !== 'granted') {
|
||||||
|
const { status } = await Notifications.requestPermissionsAsync();
|
||||||
|
finalStatus = status;
|
||||||
|
}
|
||||||
|
if (finalStatus === 'granted') {
|
||||||
|
try {
|
||||||
|
// Try to get native FCM token (works in dev/prod builds, not Expo Go)
|
||||||
|
const deviceToken = await Notifications.getDevicePushTokenAsync({ provider: 'fcm' });
|
||||||
|
if (deviceToken?.data) {
|
||||||
|
token = deviceToken.data;
|
||||||
|
tokenType = 'fcm';
|
||||||
|
} else {
|
||||||
|
// Fallback to Expo push token
|
||||||
|
const expoToken = await Notifications.getExpoPushTokenAsync();
|
||||||
|
token = expoToken.data;
|
||||||
|
tokenType = 'expo';
|
||||||
|
}
|
||||||
|
} catch (e) {
|
||||||
|
// Fallback to Expo push token if native fails
|
||||||
|
const expoToken = await Notifications.getExpoPushTokenAsync();
|
||||||
|
token = expoToken.data;
|
||||||
|
tokenType = 'expo';
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
await postgresServices.createUser({
|
||||||
|
firstName: values.firstName,
|
||||||
|
lastName: values.lastName,
|
||||||
|
number: values.number,
|
||||||
|
email: values.email,
|
||||||
|
provider: values.provider,
|
||||||
|
departments: [],
|
||||||
|
token,
|
||||||
|
uid: userCredential.user.uid
|
||||||
|
})
|
||||||
|
router.replace('./incidents');
|
||||||
|
} catch (err) {
|
||||||
|
setError(err.message);
|
||||||
|
} finally {
|
||||||
|
setLoading(false);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
|
|
@ -48,7 +105,8 @@ export default function Register() {
|
||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
if (formValues) {
|
if (formValues) {
|
||||||
if ((formValues.number.length === 14 || (formValues.number.length === 10 && !formValues.number.includes('('))) && formValues.email && formValues.firstName && formValues.lastName) {
|
const regex = /^[^@]+@(?:[a-zA-Z0-9-]+\.)+[a-zA-Z0-9-]+$/;
|
||||||
|
if ((formValues.number.length === 14 || (formValues.number.length === 10 && !formValues.number.includes('('))) && regex.test(formValues.email) && formValues.firstName && formValues.lastName) {
|
||||||
if (formValues.password.length !== 0 && (formValues.password === formValues.passwordConfirmation)) {
|
if (formValues.password.length !== 0 && (formValues.password === formValues.passwordConfirmation)) {
|
||||||
setRegisterButtonDisabled(false);
|
setRegisterButtonDisabled(false);
|
||||||
} else {
|
} else {
|
||||||
|
|
@ -62,22 +120,33 @@ export default function Register() {
|
||||||
}
|
}
|
||||||
}, [formValues])
|
}, [formValues])
|
||||||
|
|
||||||
|
useEffect(() => {
|
||||||
|
if (user) {
|
||||||
|
router.replace('./incidents');
|
||||||
|
}
|
||||||
|
}, [user]);
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<View>
|
<View style={{ flex: 1 }}>
|
||||||
<PageHeader>
|
<StatusBar style="dark" />
|
||||||
<View style={{ flexDirection: 'row', height: 80, alignItems: 'flex-end' }}>
|
<PageHeader
|
||||||
|
leftHeader={
|
||||||
<TouchableOpacity onPress={router.back} style={{ flexDirection: 'row', alignItems: 'center', paddingBottom: 5 }}>
|
<TouchableOpacity onPress={router.back} style={{ flexDirection: 'row', alignItems: 'center', paddingBottom: 5 }}>
|
||||||
<Ionicons name="chevron-back-outline" size={22} color="red" style={{ paddingLeft: 20 }} />
|
<Ionicons name="chevron-back-outline" size={22} color="red" style={{ paddingLeft: 20 }} />
|
||||||
<Text style={{ color: 'red', fontWeight: 600 }}>Back to Login</Text>
|
<Text style={{ color: 'red', fontWeight: 600 }}>Back to Login</Text>
|
||||||
</TouchableOpacity>
|
</TouchableOpacity>}
|
||||||
</View>
|
/>
|
||||||
</PageHeader>
|
<KeyboardAvoidingView
|
||||||
<ScrollView>
|
style={{ flex: 1 }}
|
||||||
<StyledContainer>
|
behavior={Platform.OS === 'ios' ? 'padding' : 'height'}
|
||||||
<StatusBar style="dark" />
|
keyboardVerticalOffset={0}
|
||||||
|
>
|
||||||
|
<ScrollView keyboardShouldPersistTaps="handled" contentContainerStyle={{ flexGrow: 1 }}>
|
||||||
<SafeAreaView />
|
<SafeAreaView />
|
||||||
|
<StyledContainer>
|
||||||
<InnerContainer>
|
<InnerContainer>
|
||||||
<PageImage resizeMode="cover" source={require('./../assets/images/tones-logo.png')} />
|
<PageImage resizeMode="cover" source={require('./../assets/images/tones-logo.png')} />
|
||||||
|
{error ? <MessageBox style={{ color: 'red' }}>{error}</MessageBox> : null}
|
||||||
<Title>Tones</Title>
|
<Title>Tones</Title>
|
||||||
<SubTitle>Account Register</SubTitle>
|
<SubTitle>Account Register</SubTitle>
|
||||||
<StyledFormArea>
|
<StyledFormArea>
|
||||||
|
|
@ -106,8 +175,9 @@ export default function Register() {
|
||||||
placeholderTextColor="gray"
|
placeholderTextColor="gray"
|
||||||
onChangeText={formik.handleChange('number')}
|
onChangeText={formik.handleChange('number')}
|
||||||
onBlur={formik.handleBlur('number')}
|
onBlur={formik.handleBlur('number')}
|
||||||
value={formik.values.number.replace(/^(\d{3})(\d{3})(\d+)$/, "($1) $2-$3")}
|
value={formatPhoneNumber(formik.values.number)}
|
||||||
keyboardType="number-pad"
|
autoComplete='tel'
|
||||||
|
keyboardType='phone-pad'
|
||||||
maxLength={14}
|
maxLength={14}
|
||||||
/>
|
/>
|
||||||
<RegisterDropdownInput
|
<RegisterDropdownInput
|
||||||
|
|
@ -127,6 +197,8 @@ export default function Register() {
|
||||||
onBlur={formik.handleBlur('email')}
|
onBlur={formik.handleBlur('email')}
|
||||||
value={formik.values.email}
|
value={formik.values.email}
|
||||||
keyboardType="email-address"
|
keyboardType="email-address"
|
||||||
|
autoComplete='email'
|
||||||
|
autoCapitalize='none'
|
||||||
/>
|
/>
|
||||||
<LoginTextInput
|
<LoginTextInput
|
||||||
label="Password"
|
label="Password"
|
||||||
|
|
@ -162,6 +234,7 @@ export default function Register() {
|
||||||
</InnerContainer>
|
</InnerContainer>
|
||||||
</StyledContainer>
|
</StyledContainer>
|
||||||
</ScrollView>
|
</ScrollView>
|
||||||
|
</KeyboardAvoidingView>
|
||||||
</View>
|
</View>
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
@ -1,91 +0,0 @@
|
||||||
import { Image, StyleSheet, Platform } from 'react-native';
|
|
||||||
|
|
||||||
import { HelloWave } from '@/components/HelloWave';
|
|
||||||
import ParallaxScrollView from '@/components/ParallaxScrollView';
|
|
||||||
import { ThemedText } from '@/components/ThemedText';
|
|
||||||
import { ThemedView } from '@/components/ThemedView';
|
|
||||||
|
|
||||||
export default function HomeScreen() {
|
|
||||||
return (
|
|
||||||
<ParallaxScrollView
|
|
||||||
headerBackgroundColor={{ light: '#A1CEDC', dark: '#1D3D47' }}
|
|
||||||
headerImage={
|
|
||||||
<Image
|
|
||||||
source={require('@/assets/images/tones-logo.png')}
|
|
||||||
style={styles.reactLogo}
|
|
||||||
/>
|
|
||||||
}
|
|
||||||
>
|
|
||||||
<ThemedView style={styles.titleContainer}>
|
|
||||||
<ThemedText type="title">Welcome!</ThemedText>
|
|
||||||
<HelloWave />
|
|
||||||
</ThemedView>
|
|
||||||
<ThemedView style={styles.stepContainer}>
|
|
||||||
<ThemedText type="subtitle">Step 1: Try it</ThemedText>
|
|
||||||
<ThemedText>
|
|
||||||
Edit <ThemedText type="defaultSemiBold">app/(tabs)/index.tsx</ThemedText> to see changes.
|
|
||||||
Press{' '}
|
|
||||||
<ThemedText type="defaultSemiBold">
|
|
||||||
{Platform.select({ ios: 'cmd + d', android: 'cmd + m' })}
|
|
||||||
</ThemedText>{' '}
|
|
||||||
to open developer tools.
|
|
||||||
</ThemedText>
|
|
||||||
</ThemedView>
|
|
||||||
<ThemedView style={styles.stepContainer}>
|
|
||||||
<ThemedText type="subtitle">Step 2: Explore</ThemedText>
|
|
||||||
<ThemedText>
|
|
||||||
Tap the Explore tab to learn more about what's included in this starter app.
|
|
||||||
</ThemedText>
|
|
||||||
</ThemedView>
|
|
||||||
<ThemedView style={styles.stepContainer}>
|
|
||||||
<ThemedText type="subtitle">Step 3: Get a fresh start</ThemedText>
|
|
||||||
<ThemedText>
|
|
||||||
When you're ready, run{' '}
|
|
||||||
<ThemedText type="defaultSemiBold">npm run reset-project</ThemedText> to get a fresh{' '}
|
|
||||||
<ThemedText type="defaultSemiBold">app</ThemedText> directory. This will move the current{' '}
|
|
||||||
<ThemedText type="defaultSemiBold">app</ThemedText> to{' '}
|
|
||||||
<ThemedText type="defaultSemiBold">app-example</ThemedText>.
|
|
||||||
</ThemedText>
|
|
||||||
</ThemedView>
|
|
||||||
<ThemedView style={styles.stepContainer}>
|
|
||||||
<ThemedText type="subtitle">Step 3: Get a fresh start</ThemedText>
|
|
||||||
<ThemedText>
|
|
||||||
When you're ready, run{' '}
|
|
||||||
<ThemedText type="defaultSemiBold">npm run reset-project</ThemedText> to get a fresh{' '}
|
|
||||||
<ThemedText type="defaultSemiBold">app</ThemedText> directory. This will move the current{' '}
|
|
||||||
<ThemedText type="defaultSemiBold">app</ThemedText> to{' '}
|
|
||||||
<ThemedText type="defaultSemiBold">app-example</ThemedText>.
|
|
||||||
</ThemedText>
|
|
||||||
</ThemedView>
|
|
||||||
<ThemedView style={styles.stepContainer}>
|
|
||||||
<ThemedText type="subtitle">Step 3: Get a fresh start</ThemedText>
|
|
||||||
<ThemedText>
|
|
||||||
When you're ready, run{' '}
|
|
||||||
<ThemedText type="defaultSemiBold">npm run reset-project</ThemedText> to get a fresh{' '}
|
|
||||||
<ThemedText type="defaultSemiBold">app</ThemedText> directory. This will move the current{' '}
|
|
||||||
<ThemedText type="defaultSemiBold">app</ThemedText> to{' '}
|
|
||||||
<ThemedText type="defaultSemiBold">app-example</ThemedText>.
|
|
||||||
</ThemedText>
|
|
||||||
</ThemedView>
|
|
||||||
</ParallaxScrollView>
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
const styles = StyleSheet.create({
|
|
||||||
titleContainer: {
|
|
||||||
flexDirection: 'row',
|
|
||||||
alignItems: 'center',
|
|
||||||
gap: 8,
|
|
||||||
},
|
|
||||||
stepContainer: {
|
|
||||||
gap: 8,
|
|
||||||
marginBottom: 8,
|
|
||||||
},
|
|
||||||
reactLogo: {
|
|
||||||
height: 178,
|
|
||||||
width: 290,
|
|
||||||
bottom: 0,
|
|
||||||
left: 0,
|
|
||||||
position: 'absolute',
|
|
||||||
},
|
|
||||||
});
|
|
||||||
|
|
@ -2,8 +2,8 @@ import Ionicons from '@expo/vector-icons/Ionicons';
|
||||||
import { PropsWithChildren, useState } from 'react';
|
import { PropsWithChildren, useState } from 'react';
|
||||||
import { StyleSheet, TouchableOpacity, useColorScheme } from 'react-native';
|
import { StyleSheet, TouchableOpacity, useColorScheme } from 'react-native';
|
||||||
|
|
||||||
import { ThemedText } from '@/components/ThemedText';
|
import { ThemedText } from '../components/ThemedText';
|
||||||
import { ThemedView } from '@/components/ThemedView';
|
import { ThemedView } from '../components/ThemedView';
|
||||||
import { Colors } from '@/constants/Colors';
|
import { Colors } from '@/constants/Colors';
|
||||||
|
|
||||||
export function Collapsible({ children, title }: PropsWithChildren & { title: string }) {
|
export function Collapsible({ children, title }: PropsWithChildren & { title: string }) {
|
||||||
|
|
|
||||||
|
|
@ -7,7 +7,7 @@ import Animated, {
|
||||||
withSequence,
|
withSequence,
|
||||||
} from 'react-native-reanimated';
|
} from 'react-native-reanimated';
|
||||||
|
|
||||||
import { ThemedText } from '@/components/ThemedText';
|
import { ThemedText } from '../components/ThemedText';
|
||||||
|
|
||||||
export function HelloWave() {
|
export function HelloWave() {
|
||||||
const rotationAnimation = useSharedValue(0);
|
const rotationAnimation = useSharedValue(0);
|
||||||
|
|
|
||||||
|
|
@ -7,7 +7,7 @@ import Animated, {
|
||||||
useScrollViewOffset,
|
useScrollViewOffset,
|
||||||
} from 'react-native-reanimated';
|
} from 'react-native-reanimated';
|
||||||
|
|
||||||
import { ThemedView } from '@/components/ThemedView';
|
import { ThemedView } from '../components/ThemedView';
|
||||||
|
|
||||||
const HEADER_HEIGHT = 250;
|
const HEADER_HEIGHT = 250;
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -1,6 +1,6 @@
|
||||||
import { Text, type TextProps, StyleSheet } from 'react-native';
|
import { Text, type TextProps, StyleSheet } from 'react-native';
|
||||||
|
|
||||||
import { useThemeColor } from '@/hooks/useThemeColor';
|
import { useThemeColor } from '../hooks/useThemeColor';
|
||||||
|
|
||||||
export type ThemedTextProps = TextProps & {
|
export type ThemedTextProps = TextProps & {
|
||||||
lightColor?: string;
|
lightColor?: string;
|
||||||
|
|
|
||||||
|
|
@ -1,6 +1,6 @@
|
||||||
import { View, type ViewProps } from 'react-native';
|
import { View, type ViewProps } from 'react-native';
|
||||||
|
|
||||||
import { useThemeColor } from '@/hooks/useThemeColor';
|
import { useThemeColor } from '../hooks/useThemeColor';
|
||||||
|
|
||||||
export type ThemedViewProps = ViewProps & {
|
export type ThemedViewProps = ViewProps & {
|
||||||
lightColor?: string;
|
lightColor?: string;
|
||||||
|
|
|
||||||
|
|
@ -1,7 +1,8 @@
|
||||||
|
import React, { useState } from 'react';
|
||||||
import styled from 'styled-components';
|
import styled from 'styled-components';
|
||||||
import { View, Text, LayoutAnimation, Image, TextInput, TouchableOpacity, TouchableNativeFeedback, ScrollView } from 'react-native';
|
import { View, Text, LayoutAnimation, Image, TextInput, TouchableOpacity, TouchableNativeFeedback, ScrollView, Platform, Modal, Pressable } from 'react-native';
|
||||||
|
import { Picker } from '@react-native-picker/picker';
|
||||||
import { Ionicons } from '@expo/vector-icons';
|
import { Ionicons } from '@expo/vector-icons';
|
||||||
import { Row } from './Row';
|
|
||||||
import { Container } from './Container';
|
import { Container } from './Container';
|
||||||
|
|
||||||
export const StyledContainer = styled.View`
|
export const StyledContainer = styled.View`
|
||||||
|
|
@ -204,11 +205,33 @@ const providerConversion = {
|
||||||
}
|
}
|
||||||
|
|
||||||
export const PageHeader = ({
|
export const PageHeader = ({
|
||||||
children
|
leftHeader = <View style={{ flex: 1 }} />,
|
||||||
|
centerHeader = <View style={{ flex: 1 }} />,
|
||||||
|
rightHeader = <View style={{ flex: 1 }} />
|
||||||
}) => {
|
}) => {
|
||||||
return (
|
return (
|
||||||
<View style={{ position: 'sticky', top: 0, backgroundColor: '#ECEDEE', zIndex: 1, marginBottom: -100 }}>
|
<View style={{ position: 'sticky', top: 0, backgroundColor: '#ECEDEE', zIndex: 1, marginBottom: -100 }}>
|
||||||
{children}
|
<View
|
||||||
|
style={{
|
||||||
|
flexDirection: 'column',
|
||||||
|
height: 80,
|
||||||
|
alignItems: 'center',
|
||||||
|
justifyContent: 'flex-end',
|
||||||
|
paddingBottom: 7
|
||||||
|
}}
|
||||||
|
>
|
||||||
|
<View style={{
|
||||||
|
flexDirection: 'row',
|
||||||
|
alignItems: 'center',
|
||||||
|
justifyContent: 'space-between',
|
||||||
|
width: '100%',
|
||||||
|
paddingHorizontal: 0
|
||||||
|
}}>
|
||||||
|
{leftHeader}
|
||||||
|
{centerHeader}
|
||||||
|
{rightHeader}
|
||||||
|
</View>
|
||||||
|
</View>
|
||||||
</View>
|
</View>
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
@ -249,91 +272,108 @@ export const LoginTextInput = ({
|
||||||
|
|
||||||
export const RegisterDropdownInput = ({
|
export const RegisterDropdownInput = ({
|
||||||
label,
|
label,
|
||||||
isOpen,
|
isOpen: _isOpen,
|
||||||
setOpen,
|
setOpen: _setOpen,
|
||||||
selectedValue,
|
selectedValue,
|
||||||
onValueChange,
|
onValueChange,
|
||||||
menu
|
menu
|
||||||
}) => {
|
}) => {
|
||||||
|
const [modalVisible, setModalVisible] = useState(false);
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<Container>
|
<Container>
|
||||||
<StyledInputLabel>{label}</StyledInputLabel>
|
<StyledInputLabel>{label}</StyledInputLabel>
|
||||||
<TouchableOpacity activeOpacity={0.8} key={`${menu.menuName}2`}
|
<TouchableOpacity
|
||||||
|
activeOpacity={0.8}
|
||||||
style={{
|
style={{
|
||||||
backgroundColor: '#E5E7EB',
|
backgroundColor: '#E5E7EB',
|
||||||
marginTop: 3,
|
marginTop: 3,
|
||||||
marginBottom: 10,
|
marginBottom: 10,
|
||||||
borderRadius: '5px',
|
borderRadius: 5,
|
||||||
|
flexDirection: 'row',
|
||||||
|
alignItems: 'center',
|
||||||
|
minHeight: 60,
|
||||||
|
paddingHorizontal: 15,
|
||||||
}}
|
}}
|
||||||
onPress={() => {
|
onPress={() => setModalVisible(true)}
|
||||||
LayoutAnimation.configureNext(LayoutAnimation.Presets.easeInEaseOut);
|
>
|
||||||
LayoutAnimation.configureNext(LayoutAnimation.create(200, 'easeInEaseOut', 'opacity'));
|
|
||||||
isOpen ? setOpen(false) : setOpen(true);
|
|
||||||
}}>
|
|
||||||
<Row style={{
|
|
||||||
paddingHorizontal: 16,
|
|
||||||
paddingVertical: 16 / 1.2,
|
|
||||||
}}>
|
|
||||||
<Ionicons
|
<Ionicons
|
||||||
name={menu.iconName}
|
name={menu.iconName}
|
||||||
size={30}
|
size={30}
|
||||||
color={menu.iconColor}
|
color={menu.iconColor}
|
||||||
/>
|
/>
|
||||||
<Text style={{
|
<Text style={{ color: selectedValue ? 'black' : 'grey', fontSize: 16, paddingHorizontal: 16, flex: 1 }}>
|
||||||
fontSize: 16,
|
|
||||||
paddingHorizontal: 16
|
|
||||||
}}>
|
|
||||||
{selectedValue ? providerConversion[selectedValue] : menu.placeholder}
|
{selectedValue ? providerConversion[selectedValue] : menu.placeholder}
|
||||||
</Text>
|
</Text>
|
||||||
<DropdownArrow
|
<DropdownArrow onPress={() => setModalVisible(!modalVisible)}>
|
||||||
onPress={() => {
|
<Ionicons name={modalVisible ? "chevron-up-outline" : "chevron-down-outline"} size={30} color="gray" />
|
||||||
LayoutAnimation.configureNext(LayoutAnimation.Presets.easeInEaseOut);
|
|
||||||
LayoutAnimation.configureNext(LayoutAnimation.create(200, 'easeInEaseOut', 'opacity'));
|
|
||||||
isOpen ? setOpen(false) : setOpen(true);
|
|
||||||
}}
|
|
||||||
>
|
|
||||||
<Ionicons
|
|
||||||
name={isOpen ? "chevron-up-outline" : "chevron-down-outline"}
|
|
||||||
size={30}
|
|
||||||
color="gray"
|
|
||||||
/>
|
|
||||||
</DropdownArrow>
|
</DropdownArrow>
|
||||||
</Row>
|
</TouchableOpacity>
|
||||||
{isOpen && <ScrollView style={{ borderRadius: '5px', backgroundColor: '#E5E7EB' }}>
|
<Modal
|
||||||
{menu.dropdownList.map((subMenu, index) => {
|
visible={modalVisible}
|
||||||
return (
|
animationType="slide"
|
||||||
<TouchableNativeFeedback
|
transparent={true}
|
||||||
key={index}
|
onRequestClose={() => setModalVisible(false)}
|
||||||
onPress={() => {
|
>
|
||||||
onValueChange(subMenu.value);
|
<Pressable
|
||||||
LayoutAnimation.configureNext(LayoutAnimation.Presets.easeInEaseOut);
|
style={{ flex: 1 }}
|
||||||
LayoutAnimation.configureNext(LayoutAnimation.create(200, 'easeInEaseOut', 'opacity'));
|
onPress={() => setModalVisible(false)}
|
||||||
setOpen(false);
|
/>
|
||||||
|
<View style={{
|
||||||
|
position: 'absolute',
|
||||||
|
left: 0,
|
||||||
|
right: 0,
|
||||||
|
bottom: 0,
|
||||||
|
backgroundColor: '#fff',
|
||||||
|
borderTopLeftRadius: 16,
|
||||||
|
borderTopRightRadius: 16,
|
||||||
|
paddingBottom: 32,
|
||||||
|
paddingTop: 16,
|
||||||
|
}}>
|
||||||
|
<Pressable
|
||||||
|
style={{ flex: 1, paddingHorizontal: 15, alignItems: 'flex-end' }}
|
||||||
|
onPress={() => setModalVisible(false)}
|
||||||
|
>
|
||||||
|
<Text style={{ color: 'red', fontWeight: 600 }}>
|
||||||
|
Close
|
||||||
|
</Text>
|
||||||
|
</Pressable>
|
||||||
|
<Picker
|
||||||
|
selectedValue={selectedValue}
|
||||||
|
onValueChange={(value) => {
|
||||||
|
onValueChange(value);
|
||||||
}}
|
}}
|
||||||
>
|
>
|
||||||
<View style={{
|
{menu.dropdownList.map((item) => (
|
||||||
paddingHorizontal: 16,
|
<Picker.Item color="black" label={item.label} value={item.value} key={item.value} />
|
||||||
paddingVertical: 16 / 1.5,
|
))}
|
||||||
borderTopColor: 'gray',
|
</Picker>
|
||||||
borderTopWidth: .5,
|
|
||||||
marginHorizontal: 10
|
|
||||||
}}>
|
|
||||||
<Text>{subMenu.label}</Text>
|
|
||||||
{selectedValue === subMenu.value &&
|
|
||||||
<SelectedCheckmark>
|
|
||||||
<Ionicons
|
|
||||||
name="checkmark-outline"
|
|
||||||
size={30}
|
|
||||||
color="red"
|
|
||||||
/>
|
|
||||||
</SelectedCheckmark>
|
|
||||||
}
|
|
||||||
</View>
|
</View>
|
||||||
</TouchableNativeFeedback>
|
</Modal>
|
||||||
)
|
|
||||||
})}
|
|
||||||
</ScrollView>}
|
|
||||||
</TouchableOpacity>
|
|
||||||
</Container>
|
</Container>
|
||||||
)
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
export const formatPhoneNumber = (e) => {
|
||||||
|
let formattedNumber;
|
||||||
|
const length = e?.length;
|
||||||
|
|
||||||
|
const regex = () => e.replace(/[^0-9\.]+/g, "");
|
||||||
|
const areaCode = () => `(${regex().slice(0, 3)})`;
|
||||||
|
const firstSix = () => `${areaCode()} ${regex().slice(3, 6)}`;
|
||||||
|
const trailer = (start) => `${regex().slice(start, regex().length)}`;
|
||||||
|
|
||||||
|
if (length <= 3) {
|
||||||
|
formattedNumber = regex();
|
||||||
|
} else if (length === 4) {
|
||||||
|
formattedNumber = `${areaCode()} ${trailer(3)}`;
|
||||||
|
} else if (length === 5) {
|
||||||
|
formattedNumber = `${areaCode().replace(")", "")}`;
|
||||||
|
} else if (length >= 5 && length <= 9) {
|
||||||
|
formattedNumber = `${areaCode()} ${trailer(3)}`;
|
||||||
|
} else if (length >= 10) {
|
||||||
|
formattedNumber = `${firstSix()}-${trailer(6)}`;
|
||||||
|
}
|
||||||
|
|
||||||
|
return formattedNumber;
|
||||||
|
};
|
||||||
30
contexts/AuthContext.js
Normal file
|
|
@ -0,0 +1,30 @@
|
||||||
|
import React, { createContext, useContext, useEffect, useState } from 'react';
|
||||||
|
import { onAuthStateChanged, signOut } from 'firebase/auth';
|
||||||
|
import { auth } from './firebase';
|
||||||
|
|
||||||
|
const AuthContext = createContext();
|
||||||
|
|
||||||
|
export const AuthProvider = ({ children }) => {
|
||||||
|
const [user, setUser] = useState(null);
|
||||||
|
const [loading, setLoading] = useState(true);
|
||||||
|
|
||||||
|
useEffect(() => {
|
||||||
|
const unsubscribe = onAuthStateChanged(auth, (firebaseUser) => {
|
||||||
|
setUser(firebaseUser);
|
||||||
|
setLoading(false);
|
||||||
|
});
|
||||||
|
return unsubscribe;
|
||||||
|
}, []);
|
||||||
|
|
||||||
|
const logout = () => signOut(auth);
|
||||||
|
|
||||||
|
return (
|
||||||
|
<AuthContext.Provider value={{ user, loading, logout }}>
|
||||||
|
{children}
|
||||||
|
</AuthContext.Provider>
|
||||||
|
);
|
||||||
|
};
|
||||||
|
|
||||||
|
export const useAuth = () => {
|
||||||
|
return useContext(AuthContext);
|
||||||
|
};
|
||||||
35
contexts/GlobalVariablesContext.js
Normal file
|
|
@ -0,0 +1,35 @@
|
||||||
|
import React, { createContext, useEffect, useState } from 'react';
|
||||||
|
import { AppState } from 'react-native';
|
||||||
|
|
||||||
|
export const GlobalVariablesContext = createContext(null);
|
||||||
|
|
||||||
|
export const GlobalVariablesProvider = ({ children }) => {
|
||||||
|
const [appState, setAppState] = useState(AppState.currentState);
|
||||||
|
|
||||||
|
useEffect(() => {
|
||||||
|
const handleAppStateChange = (nextAppState) => {
|
||||||
|
if (appState.match(/active/) && nextAppState.match(/inactive|background/)) {
|
||||||
|
console.log('App is in background or inactive');
|
||||||
|
} else if (appState.match(/inactive|background/) && nextAppState === 'active') {
|
||||||
|
console.log('App is in the foreground');
|
||||||
|
}
|
||||||
|
setAppState(nextAppState);
|
||||||
|
};
|
||||||
|
const subscription = AppState.addEventListener('change', handleAppStateChange);
|
||||||
|
|
||||||
|
return () => {
|
||||||
|
subscription.remove();
|
||||||
|
};
|
||||||
|
}, [appState]);
|
||||||
|
|
||||||
|
const exportedVariables = {
|
||||||
|
appState,
|
||||||
|
setAppState
|
||||||
|
}
|
||||||
|
|
||||||
|
return (
|
||||||
|
<GlobalVariablesContext.Provider value={exportedVariables}>
|
||||||
|
{children}
|
||||||
|
</GlobalVariablesContext.Provider>
|
||||||
|
)
|
||||||
|
};
|
||||||
|
|
@ -20,7 +20,7 @@ export const WebSocketProvider = ({ children }) => {
|
||||||
}
|
}
|
||||||
|
|
||||||
console.log(`🔁 Connecting (Attempt ${reconnectAttempts.current + 1}/${maxReconnectAttempts})`);
|
console.log(`🔁 Connecting (Attempt ${reconnectAttempts.current + 1}/${maxReconnectAttempts})`);
|
||||||
ws.current = new WebSocket(process.env.EXPO_PUBLIC_WS_URL);
|
ws.current = new WebSocket(`${process.env.EXPO_PUBLIC_WS_URL}/callfeed?apiKey=${process.env.EXPO_PUBLIC_DATABASE_API_KEY}`);
|
||||||
|
|
||||||
ws.current.onopen = () => {
|
ws.current.onopen = () => {
|
||||||
console.log('✅ WebSocket connected');
|
console.log('✅ WebSocket connected');
|
||||||
|
|
|
||||||
23
contexts/firebase.js
Normal file
|
|
@ -0,0 +1,23 @@
|
||||||
|
|
||||||
|
|
||||||
|
import { initializeApp } from 'firebase/app';
|
||||||
|
import { initializeAuth, getReactNativePersistence } from 'firebase/auth';
|
||||||
|
import AsyncStorage from '@react-native-async-storage/async-storage';
|
||||||
|
|
||||||
|
const firebaseConfig = {
|
||||||
|
apiKey: process.env.EXPO_PUBLIC_FIREBASE_API_KEY,
|
||||||
|
authDomain: process.env.EXPO_PUBLIC_FIREBASE_AUTH_DOMAIN,
|
||||||
|
databaseURL: process.env.EXPO_PUBLIC_FIREBASE_DATABASE_URL,
|
||||||
|
projectId: process.env.EXPO_PUBLIC_FIREBASE_PROJECT_ID,
|
||||||
|
storageBucket: process.env.EXPO_PUBLIC_FIREBASE_STORAGE_BUCKET,
|
||||||
|
messagingSenderId: process.env.EXPO_PUBLIC_FIREBASE_MESSAGING_SENDER_ID,
|
||||||
|
appId: process.env.EXPO_PUBLIC_FIREBASE_APP_ID,
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
const app = initializeApp(firebaseConfig);
|
||||||
|
const auth = initializeAuth(app, {
|
||||||
|
persistence: getReactNativePersistence(AsyncStorage)
|
||||||
|
});
|
||||||
|
|
||||||
|
export { auth };
|
||||||
4
contexts/index.js
Normal file
|
|
@ -0,0 +1,4 @@
|
||||||
|
export { AuthProvider } from './AuthContext';
|
||||||
|
export { GlobalVariablesProvider, GlobalVariablesContext } from './GlobalVariablesContext';
|
||||||
|
export { postgresServices } from './postgres';
|
||||||
|
export { WebSocketProvider, WebSocketContext } from './WebSocketContext';
|
||||||
62
contexts/postgres.js
Normal file
|
|
@ -0,0 +1,62 @@
|
||||||
|
export const postgresServices = {
|
||||||
|
getCallsParams: async (args) => {
|
||||||
|
let response;
|
||||||
|
try {
|
||||||
|
const { numCalls, departments, status } = args;
|
||||||
|
response = await fetch(`${process.env.EXPO_PUBLIC_DATABASE_URL}/getCallsParams`, {
|
||||||
|
method: "POST",
|
||||||
|
headers: {
|
||||||
|
apiKey: process.env.EXPO_PUBLIC_DATABASE_API_KEY,
|
||||||
|
"Content-Type": 'application/json'
|
||||||
|
},
|
||||||
|
body: JSON.stringify({
|
||||||
|
numCalls,
|
||||||
|
departments,
|
||||||
|
status
|
||||||
|
}),
|
||||||
|
});
|
||||||
|
if (!response.ok) {
|
||||||
|
throw new Error(`HTTP error! status: ${response.status}`);
|
||||||
|
}
|
||||||
|
} catch (e) {
|
||||||
|
console.error("Failed to fetch initial calls: ", e);
|
||||||
|
}
|
||||||
|
return response?.json() || [];
|
||||||
|
},
|
||||||
|
createUser: async (args) => {
|
||||||
|
try {
|
||||||
|
const {
|
||||||
|
firstName,
|
||||||
|
lastName,
|
||||||
|
number,
|
||||||
|
email,
|
||||||
|
provider,
|
||||||
|
departments,
|
||||||
|
token,
|
||||||
|
uid
|
||||||
|
} = args;
|
||||||
|
await fetch(`${process.env.EXPO_PUBLIC_DATABASE_URL}/createUser`, {
|
||||||
|
method: "POST",
|
||||||
|
headers: {
|
||||||
|
apiKey: process.env.EXPO_PUBLIC_DATABASE_API_KEY,
|
||||||
|
"Content-Type": 'application/json'
|
||||||
|
},
|
||||||
|
body: JSON.stringify({
|
||||||
|
firstName,
|
||||||
|
lastName,
|
||||||
|
number,
|
||||||
|
email,
|
||||||
|
provider,
|
||||||
|
departments,
|
||||||
|
globalRole: 'user',
|
||||||
|
primaryDept,
|
||||||
|
token,
|
||||||
|
firebaseUid: uid
|
||||||
|
}),
|
||||||
|
});
|
||||||
|
} catch (e) {
|
||||||
|
console.error("Failed to Add User to Database: ", e);
|
||||||
|
}
|
||||||
|
return 'User Added to Database';
|
||||||
|
}
|
||||||
|
}
|
||||||
21
eas.json
Normal file
|
|
@ -0,0 +1,21 @@
|
||||||
|
{
|
||||||
|
"cli": {
|
||||||
|
"version": ">= 16.3.2",
|
||||||
|
"appVersionSource": "remote"
|
||||||
|
},
|
||||||
|
"build": {
|
||||||
|
"development": {
|
||||||
|
"developmentClient": true,
|
||||||
|
"distribution": "internal"
|
||||||
|
},
|
||||||
|
"preview": {
|
||||||
|
"distribution": "internal"
|
||||||
|
},
|
||||||
|
"production": {
|
||||||
|
"autoIncrement": true
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"submit": {
|
||||||
|
"production": {}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -1,2 +1,5 @@
|
||||||
export { useCallFeed } from './useCallFeed';
|
export { useCallFeed } from './useCallFeed';
|
||||||
export { useDepartments } from './useDepartments';
|
export { useDepartments } from './useDepartments';
|
||||||
|
export { useGlobalVariablesContext } from './useGlobalVariablesContext';
|
||||||
|
export { useNotifications } from './useNotifications';
|
||||||
|
export { useWebSocketContext } from './useWebSocketContext';
|
||||||
|
|
@ -1,13 +1,18 @@
|
||||||
import React, { useState, useEffect } from 'react';
|
import React, { useState, useEffect } from "react";
|
||||||
import { useDepartments } from '../useDepartments';
|
import { useDepartments } from "../useDepartments";
|
||||||
import { C, Cardiology, Cpr, FourByFour } from "healthicons-react-native/dist/outline";
|
import {
|
||||||
import { useWebSocketContext } from '../useWebSocketContext';
|
Cardiology,
|
||||||
|
Cpr,
|
||||||
|
FourByFour,
|
||||||
|
} from "healthicons-react-native/dist/outline";
|
||||||
|
import { postgresServices } from "@/contexts";
|
||||||
|
import { useWebSocketContext } from "../useWebSocketContext";
|
||||||
|
|
||||||
const callIconMap = {
|
const callIconMap = {
|
||||||
"CHEST PAIN|HEART PROBLEMS": Cardiology,
|
"CHEST PAIN|HEART PROBLEMS": Cardiology,
|
||||||
"CARDIAC ARREST|DEATH": Cpr,
|
"CARDIAC ARREST|DEATH": Cpr,
|
||||||
"MOTOR VEHICLE COLLISION (MVC)": FourByFour,
|
"MOTOR VEHICLE COLLISION (MVC)": FourByFour,
|
||||||
}
|
};
|
||||||
|
|
||||||
// Squares
|
// Squares
|
||||||
|
|
||||||
|
|
@ -37,119 +42,6 @@ const callIconMap = {
|
||||||
// Bacteria - Sick
|
// Bacteria - Sick
|
||||||
// RuralClinic - Medical Facility Response
|
// RuralClinic - Medical Facility Response
|
||||||
|
|
||||||
const callDetails = {
|
|
||||||
"Incident": {
|
|
||||||
"IncID": 75,
|
|
||||||
"IncNumber": 6873,
|
|
||||||
"JurisdictionNumber": 3,
|
|
||||||
"ServiceNumber": 42,
|
|
||||||
"ServiceID": 45,
|
|
||||||
"IncDate": "2024-09-25T01:01:01.55",
|
|
||||||
// "IncNature": "CHEST PAIN|HEART PROBLEMS",
|
|
||||||
"IncNature": "MOTOR VEHICLE COLLISION (MVC)",
|
|
||||||
// "IncNature": "CARDIAC ARREST|DEATH",
|
|
||||||
"IncNatureCode": "ALS",
|
|
||||||
"IncNatureCodeDesc": "ALS PRIORITY (ALS)",
|
|
||||||
"Notes": "570, 16:30> 311 Responding\n580, 16:25> Call Dispatched",
|
|
||||||
"Status": "OPEN",
|
|
||||||
"Origin": "911"
|
|
||||||
},
|
|
||||||
"Address": {
|
|
||||||
"StreetAddress": "275 E Main St",
|
|
||||||
"AddressApartment": "IFO",
|
|
||||||
"Town": "Bridgeport",
|
|
||||||
"State": "CT",
|
|
||||||
"ZipCode": "06608",
|
|
||||||
"Latitude": 41.178435683035445,
|
|
||||||
"Longitude": -73.18194442701176,
|
|
||||||
"County": "Fairfield",
|
|
||||||
"Intersection1": "E MAIN ST",
|
|
||||||
"Intersection2": "STRATFORD AVE",
|
|
||||||
"LocationName": "Chipotle Mexican Grill",
|
|
||||||
"WeatherCondition": "Foggy"
|
|
||||||
},
|
|
||||||
"Person": {
|
|
||||||
"Name": "John Doe",
|
|
||||||
"Age": 19,
|
|
||||||
"Gender": "Female",
|
|
||||||
"Statement": "BLOOD PRESSURE 56/41 - IN AND OUT OF CON",
|
|
||||||
"Conscious": "No",
|
|
||||||
"Breathing": "Yes",
|
|
||||||
"CallBackNumber": "(223) 456-7890"
|
|
||||||
},
|
|
||||||
"Response": {
|
|
||||||
"IncID": 75,
|
|
||||||
"ResponseID": 75,
|
|
||||||
"ServiceID": 45,
|
|
||||||
"ServiceName": "DARIEN EMS",
|
|
||||||
"Units": [
|
|
||||||
{
|
|
||||||
"Unit": 311,
|
|
||||||
"Department": 'Darien EMS',
|
|
||||||
"Dispatched": "2024-09-25T01:01:01.55",
|
|
||||||
"Responding": "2024-09-25T01:02:02.55",
|
|
||||||
"OnScene": "2024-09-25T01:10:10.55",
|
|
||||||
"Transporting": "2024-09-25T01:25:01.55",
|
|
||||||
"InService": "2024-09-25T02:00:01.55",
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"Unit": 315,
|
|
||||||
"Department": 'Darien EMS Supv',
|
|
||||||
"Dispatched": "2024-09-25T01:01:01.55",
|
|
||||||
"Responding": "2024-09-25T01:03:03.15",
|
|
||||||
"OnScene": "2024-09-25T01:11:11.55",
|
|
||||||
"Transporting": null,
|
|
||||||
"InService": "2024-09-25T02:10:01.55",
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"Unit": 310,
|
|
||||||
"Department": 'Darien EMS',
|
|
||||||
"Dispatched": "2024-09-25T01:01:01.55",
|
|
||||||
"Responding": "2024-09-25T01:01:01.55",
|
|
||||||
"OnScene": "2024-09-25T01:06:06.55",
|
|
||||||
"Transporting": "2024-09-25T01:25:01.55",
|
|
||||||
"InService": "2024-09-25T02:15:01.55",
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"Unit": 'NHT20',
|
|
||||||
"Department": 'Noroton Heights Fire Department',
|
|
||||||
"Dispatched": "2024-09-25T01:01:01.55",
|
|
||||||
"Responding": "2024-09-25T01:08:08.55",
|
|
||||||
"OnScene": "2024-09-25T01:12:12.55",
|
|
||||||
"Transporting": null,
|
|
||||||
"InService": "2024-09-25T01:01:01.55",
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"Unit": 'NFDE31',
|
|
||||||
"Department": 'Noroton Fire Department',
|
|
||||||
"Dispatched": "2024-09-25T01:01:01.55",
|
|
||||||
"Responding": "2024-09-25T01:07:07.55",
|
|
||||||
"OnScene": "2024-09-25T01:14:14.55",
|
|
||||||
"Transporting": null,
|
|
||||||
"InService": "2024-09-25T01:01:01.55",
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"Unit": 'DFDT43',
|
|
||||||
"Department": 'Darien Fire Department',
|
|
||||||
"Dispatched": "2024-09-25T01:01:01.55",
|
|
||||||
"Responding": "2024-09-25T01:10:10.55",
|
|
||||||
"OnScene": "2024-09-25T01:18:18.55",
|
|
||||||
"Transporting": null,
|
|
||||||
"InService": "2024-09-25T01:01:01.55",
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"Unit": 1514,
|
|
||||||
"Department": 'Greenwich EMS',
|
|
||||||
"Dispatched": "2024-09-25T01:15:15.55",
|
|
||||||
"Responding": "2024-09-25T01:30:30.55",
|
|
||||||
"OnScene": "2024-09-25T01:45:45.55",
|
|
||||||
"Transporting": "2024-09-25T02:05:15.55",
|
|
||||||
"InService": "2024-09-25T02:25:01.55",
|
|
||||||
},
|
|
||||||
]
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
const formatCallTimePast = (callValue) => {
|
const formatCallTimePast = (callValue) => {
|
||||||
const initDate = new Date(callValue);
|
const initDate = new Date(callValue);
|
||||||
const currentTime = new Date();
|
const currentTime = new Date();
|
||||||
|
|
@ -157,52 +49,69 @@ const formatCallTimePast = (callValue) => {
|
||||||
const timeDifference = currentTime - initDate;
|
const timeDifference = currentTime - initDate;
|
||||||
|
|
||||||
const days = Math.floor(timeDifference / (1000 * 60 * 60 * 24));
|
const days = Math.floor(timeDifference / (1000 * 60 * 60 * 24));
|
||||||
const hours = Math.floor((timeDifference % (1000 * 60 * 60 * 24)) / (1000 * 60 * 60));
|
const hours = Math.floor(
|
||||||
|
(timeDifference % (1000 * 60 * 60 * 24)) / (1000 * 60 * 60)
|
||||||
|
);
|
||||||
const minutes = Math.floor((timeDifference % (1000 * 60 * 60)) / (1000 * 60));
|
const minutes = Math.floor((timeDifference % (1000 * 60 * 60)) / (1000 * 60));
|
||||||
const seconds = Math.floor((timeDifference % (1000 * 60)) / 1000);
|
const seconds = Math.floor((timeDifference % (1000 * 60)) / 1000);
|
||||||
if (days && days !== 0) {
|
if (days && days !== 0) {
|
||||||
return `${days} day${days === 1 ? '' : 's'} ago`;
|
return `${days} day${days === 1 ? "" : "s"} ago`;
|
||||||
} else if (hours && hours !== 0) {
|
} else if (hours && hours !== 0) {
|
||||||
return `${hours} hour${hours === 1 ? '' : 's'} ago`;
|
return `${hours} hour${hours === 1 ? "" : "s"} ago`;
|
||||||
} else if (minutes && minutes !== 0) {
|
} else if (minutes && minutes !== 0) {
|
||||||
return `${minutes} minute${minutes === 1 ? '' : 's'} ago`;
|
return `${minutes} minute${minutes === 1 ? "" : "s"} ago`;
|
||||||
} else if (seconds && seconds !== 0) {
|
} else if (seconds && seconds !== 0) {
|
||||||
return `${seconds} second${seconds === 1 ? '' : 's'} ago`;
|
return `${seconds} second${seconds === 1 ? "" : "s"} ago`;
|
||||||
}
|
}
|
||||||
return `Unknown Time Past`;
|
return `Unknown Time Past`;
|
||||||
}
|
};
|
||||||
|
|
||||||
const formatCallDateTime = (callValue) => {
|
const formatCallDateTime = (callValue) => {
|
||||||
const initDate = new Date(callValue);
|
const initDate = new Date(callValue);
|
||||||
if (initDate) {
|
if (initDate) {
|
||||||
const formattedDate = `${initDate.toLocaleDateString('en-US', {
|
const formattedDate = `${initDate.toLocaleDateString("en-US", {
|
||||||
month: 'short',
|
month: "short",
|
||||||
day: 'numeric',
|
day: "numeric",
|
||||||
year: 'numeric',
|
year: "numeric",
|
||||||
})}`;
|
})}`;
|
||||||
const hours = initDate.getHours().toString().padStart(2, '0');
|
const hours = initDate.getHours().toString().padStart(2, "0");
|
||||||
const minutes = initDate.getMinutes().toString().padStart(2, '0');
|
const minutes = initDate.getMinutes().toString().padStart(2, "0");
|
||||||
const formattedTime = `${hours}:${minutes}`;
|
const formattedTime = `${hours}:${minutes}`;
|
||||||
|
|
||||||
return `${formattedDate} - ${formattedTime}`;
|
return `${formattedDate} - ${formattedTime}`;
|
||||||
}
|
}
|
||||||
return 'Date Unavailable';
|
return "Date Unavailable";
|
||||||
}
|
};
|
||||||
|
|
||||||
export const useCallFeed = () => {
|
const getIncidents = async (departments, incidentStatus) => {
|
||||||
|
return postgresServices.getCallsParams({
|
||||||
|
numCalls: 25,
|
||||||
|
departments,
|
||||||
|
status: incidentStatus
|
||||||
|
});
|
||||||
|
};
|
||||||
|
|
||||||
|
export const useCallFeed = (callPage = false) => {
|
||||||
const departments = useDepartments();
|
const departments = useDepartments();
|
||||||
const { lastMessage } = useWebSocketContext();
|
const { lastMessage } = useWebSocketContext();
|
||||||
const [allCalls, setAllCalls] = useState([]);
|
const [allCalls, setAllCalls] = useState([]);
|
||||||
const { CallThemes } = departments?.accountDetails;
|
const [init, setInit] = useState(true);
|
||||||
const {
|
const { CallThemes, InitList } = departments?.accountDetails;
|
||||||
CriticalCallList,
|
const { CriticalCallList, HighCallList, MediumCallList, LowCallList } =
|
||||||
HighCallList,
|
CallThemes;
|
||||||
MediumCallList,
|
const [selectedStatus, setSelectedStatus] = useState({id: 'all', value: 'All Incidents'});
|
||||||
LowCallList,
|
|
||||||
} = CallThemes;
|
|
||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
if (lastMessage) {
|
async function fetchData() {
|
||||||
|
const incidents = await getIncidents(InitList?.map((dept) => { return dept?.deptId }), selectedStatus?.id);
|
||||||
|
setAllCalls(incidents);
|
||||||
|
setInit(false);
|
||||||
|
}
|
||||||
|
if (!callPage) fetchData();
|
||||||
|
}, []);
|
||||||
|
|
||||||
|
useEffect(() => {
|
||||||
|
if (lastMessage && !init) {
|
||||||
const parsedMessage = JSON?.parse(lastMessage);
|
const parsedMessage = JSON?.parse(lastMessage);
|
||||||
if (parsedMessage?.data) {
|
if (parsedMessage?.data) {
|
||||||
setAllCalls([...allCalls, parsedMessage]);
|
setAllCalls([...allCalls, parsedMessage]);
|
||||||
|
|
@ -210,19 +119,29 @@ export const useCallFeed = () => {
|
||||||
}
|
}
|
||||||
}, [lastMessage]);
|
}, [lastMessage]);
|
||||||
|
|
||||||
|
useEffect(() => {
|
||||||
|
async function fetchData() {
|
||||||
|
const incidents = await getIncidents(InitList?.map((dept) => { return dept?.deptId }), selectedStatus?.id);
|
||||||
|
setAllCalls(incidents);
|
||||||
|
}
|
||||||
|
if (!init) {
|
||||||
|
if (!callPage) fetchData();
|
||||||
|
}
|
||||||
|
}, [selectedStatus]);
|
||||||
|
|
||||||
const callColorSelector = (callAcuity, cardiacArrestCall, status) => {
|
const callColorSelector = (callAcuity, cardiacArrestCall, status) => {
|
||||||
if (status === 'CLOSED') {
|
if (status?.toLowerCase() === "closed") {
|
||||||
return '#0000CD';
|
return "#0000CD";
|
||||||
} else if (CriticalCallList.includes(cardiacArrestCall)) {
|
} else if (CriticalCallList.some(critical => cardiacArrestCall.includes(critical))) {
|
||||||
return '#8B0000';
|
return "#8B0000";
|
||||||
} else if (HighCallList.includes(callAcuity)) {
|
} else if (HighCallList.some(high => callAcuity.includes(high))) {
|
||||||
return "#FF0000";
|
return "#FF0000";
|
||||||
} else if (MediumCallList.includes(callAcuity)) {
|
} else if (MediumCallList.some(medium => callAcuity.includes(medium))) {
|
||||||
return "#FF8C00";
|
return "#FF8C00";
|
||||||
} else if (LowCallList.includes(callAcuity)) {
|
} else if (LowCallList.some(low => callAcuity.includes(low))) {
|
||||||
return "#228B22";
|
return "#228B22";
|
||||||
}
|
}
|
||||||
return 'grey';
|
return "grey";
|
||||||
};
|
};
|
||||||
|
|
||||||
return {
|
return {
|
||||||
|
|
@ -231,6 +150,8 @@ export const useCallFeed = () => {
|
||||||
callDetails: allCalls,
|
callDetails: allCalls,
|
||||||
callColorSelector,
|
callColorSelector,
|
||||||
formatCallTimePast,
|
formatCallTimePast,
|
||||||
formatCallDateTime
|
formatCallDateTime,
|
||||||
}
|
selectedStatus,
|
||||||
}
|
setSelectedStatus
|
||||||
|
};
|
||||||
|
};
|
||||||
|
|
|
||||||
|
|
@ -1,5 +1,4 @@
|
||||||
import React, { useState, useEffect } from 'react';
|
import React, { useState, useEffect } from 'react';
|
||||||
import { View, Text, TouchableOpacity } from 'react-native';
|
|
||||||
|
|
||||||
const departmentTypeMap = {
|
const departmentTypeMap = {
|
||||||
EMS: 'Medical Services',
|
EMS: 'Medical Services',
|
||||||
|
|
@ -10,27 +9,47 @@ const departmentTypeMap = {
|
||||||
const accountDetails = {
|
const accountDetails = {
|
||||||
"CallThemes" : {
|
"CallThemes" : {
|
||||||
"CriticalCallList": [
|
"CriticalCallList": [
|
||||||
"CARDIAC ARREST|DEATH",
|
"CARDIAC ARREST"
|
||||||
],
|
],
|
||||||
"HighCallList": [
|
"HighCallList": [
|
||||||
"ALS"
|
"EMS ALS PRIORITY (ALS)",
|
||||||
|
"EMS Advanced Life Support life threatening response (ALS)",
|
||||||
|
"EMS ALS Intercept Required",
|
||||||
|
"EMS ALS Response – Cardiac Related",
|
||||||
|
"EMS ALS Response – Respiratory Distress",
|
||||||
|
"EMS ALS Response – Stroke Alert",
|
||||||
|
"EMS Basic Life Support with Paramedic Assist (BLS)",
|
||||||
|
"EMS ALS Tiered Response with Fire",
|
||||||
|
"EMS Response – Behavioral Emergency (ALS)",
|
||||||
|
"EMS Response – Obstetric Emergency (ALS)",
|
||||||
|
"EMS ALS Response – Overdose / Poisoning",
|
||||||
|
"EMS ALS Priority Interfacility Transfer",
|
||||||
|
"EMS Response – Unresponsive / Unconscious Patient (ALS)"
|
||||||
],
|
],
|
||||||
"MediumCallList": [
|
"MediumCallList": [
|
||||||
"ALS-STANDARD",
|
"ALS-STANDARD",
|
||||||
"BLS-PRIORITY"
|
"BLS-PRIORITY",
|
||||||
|
"EMS BLS Priority Response",
|
||||||
|
"EMS BLS Response – Fall Injury"
|
||||||
],
|
],
|
||||||
"LowCallList": [
|
"LowCallList": [
|
||||||
"BLS-STANDARD"
|
"EMS Standard Basic Life Support Response (BLS)",
|
||||||
|
"EMS BLS Non-Emergency Transport",
|
||||||
|
"EMS BLS Standby – Event Coverage",
|
||||||
|
"EMS Public Assist – Lift Only (BLS)",
|
||||||
|
"EMS BLS Scheduled Interfacility Transport"
|
||||||
]
|
]
|
||||||
},
|
},
|
||||||
"InitList": [
|
"InitList": [
|
||||||
{
|
{
|
||||||
deptId: 0,
|
deptId: 1,
|
||||||
dept: 'Darien EMS',
|
dept: 'Darien EMS',
|
||||||
addDepts: [
|
addDepts: [
|
||||||
'Darien EMS Supv'
|
'Darien EMS Supv'
|
||||||
],
|
],
|
||||||
deptAbv: 'DEMS',
|
deptAbv: 'DEMS',
|
||||||
|
rank: 'Assistant Director',
|
||||||
|
rankAbv: 'Asst. Director',
|
||||||
type: 'EMS',
|
type: 'EMS',
|
||||||
primary: true,
|
primary: true,
|
||||||
selected: true,
|
selected: true,
|
||||||
|
|
@ -39,9 +58,11 @@ const accountDetails = {
|
||||||
hasVolunteer: true,
|
hasVolunteer: true,
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
deptId: 1,
|
deptId: 2,
|
||||||
dept: 'Noroton Fire Department',
|
dept: 'Noroton Fire Department',
|
||||||
deptAbv: 'NFD',
|
deptAbv: 'NFD',
|
||||||
|
rank: 'Lieutenant',
|
||||||
|
rankAbv: 'Lt.',
|
||||||
type: 'Fire',
|
type: 'Fire',
|
||||||
primary: false,
|
primary: false,
|
||||||
selected: false,
|
selected: false,
|
||||||
|
|
@ -50,9 +71,11 @@ const accountDetails = {
|
||||||
hasVolunteer: true,
|
hasVolunteer: true,
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
deptId: 2,
|
deptId: 3,
|
||||||
dept: 'Stamford Fire Department',
|
dept: 'Stamford Fire Rescue',
|
||||||
deptAbv: 'SFD',
|
deptAbv: 'SFD',
|
||||||
|
rank: 'Paramedic',
|
||||||
|
rankAbv: 'EMT-P',
|
||||||
type: 'Rescue',
|
type: 'Rescue',
|
||||||
primary: false,
|
primary: false,
|
||||||
selected: false,
|
selected: false,
|
||||||
|
|
|
||||||
1
hooks/useGlobalVariablesContext/index.js
Normal file
|
|
@ -0,0 +1 @@
|
||||||
|
export { useGlobalVariablesContext } from './useGlobalVariablesContext';
|
||||||
|
|
@ -0,0 +1,4 @@
|
||||||
|
import { useContext } from 'react';
|
||||||
|
import { GlobalVariablesContext } from '../../contexts';
|
||||||
|
|
||||||
|
export const useGlobalVariablesContext = () => useContext(GlobalVariablesContext);
|
||||||
1
hooks/useNotifications/index.js
Normal file
|
|
@ -0,0 +1 @@
|
||||||
|
export { useNotifications } from './useNotifications';
|
||||||
112
hooks/useNotifications/useNotifications.jsx
Normal file
|
|
@ -0,0 +1,112 @@
|
||||||
|
|
||||||
|
import { useState, useEffect, useRef } from 'react';
|
||||||
|
import { Platform } from 'react-native';
|
||||||
|
import * as Device from 'expo-device';
|
||||||
|
import * as Notifications from 'expo-notifications';
|
||||||
|
import Constants from 'expo-constants';
|
||||||
|
|
||||||
|
Notifications.setNotificationHandler({
|
||||||
|
handleNotification: async () => ({
|
||||||
|
shouldShowAlert: true,
|
||||||
|
shouldPlaySound: false,
|
||||||
|
shouldSetBadge: false,
|
||||||
|
}),
|
||||||
|
});
|
||||||
|
|
||||||
|
const schedulePushNotification = async (title, body, dataObj) => {
|
||||||
|
await Notifications.scheduleNotificationAsync({
|
||||||
|
content: {
|
||||||
|
title,
|
||||||
|
body,
|
||||||
|
data: { data: dataObj },
|
||||||
|
},
|
||||||
|
trigger: {
|
||||||
|
type: Notifications.SchedulableTriggerInputTypes.TIME_INTERVAL,
|
||||||
|
seconds: 2,
|
||||||
|
},
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
const registerForPushNotificationsAsync = async () => {
|
||||||
|
let token;
|
||||||
|
|
||||||
|
if (Platform.OS === 'android') {
|
||||||
|
await Notifications.setNotificationChannelAsync('myNotificationChannel', {
|
||||||
|
name: 'A channel is needed for the permissions prompt to appear',
|
||||||
|
importance: Notifications.AndroidImportance.MAX,
|
||||||
|
vibrationPattern: [0, 250, 250, 250],
|
||||||
|
lightColor: '#FF231F7C',
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
// if (Device.isDevice) {
|
||||||
|
const { status: existingStatus } = await Notifications.getPermissionsAsync();
|
||||||
|
let finalStatus = existingStatus;
|
||||||
|
if (existingStatus !== 'granted') {
|
||||||
|
const { status } = await Notifications.requestPermissionsAsync();
|
||||||
|
finalStatus = status;
|
||||||
|
}
|
||||||
|
if (finalStatus !== 'granted') {
|
||||||
|
alert('Failed to get push token for push notification!');
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
// Learn more about projectId:
|
||||||
|
// https://docs.expo.dev/push-notifications/push-notifications-setup/#configure-projectid
|
||||||
|
// EAS projectId is used here.
|
||||||
|
try {
|
||||||
|
const projectId =
|
||||||
|
Constants?.expoConfig?.extra?.eas?.projectId ?? Constants?.easConfig?.projectId;
|
||||||
|
if (!projectId) {
|
||||||
|
throw new Error('Project ID not found');
|
||||||
|
}
|
||||||
|
token = (
|
||||||
|
await Notifications.getExpoPushTokenAsync({
|
||||||
|
projectId,
|
||||||
|
})
|
||||||
|
).data;
|
||||||
|
} catch (e) {
|
||||||
|
token = `${e}`;
|
||||||
|
}
|
||||||
|
// } else {
|
||||||
|
// alert('Must use physical device for Push Notifications');
|
||||||
|
// }
|
||||||
|
|
||||||
|
return token;
|
||||||
|
}
|
||||||
|
|
||||||
|
export const useNotifications = () => {
|
||||||
|
const [expoPushToken, setExpoPushToken] = useState('');
|
||||||
|
const [channels, setChannels] = useState([]);
|
||||||
|
const [notification, setNotification] = useState(undefined);
|
||||||
|
const notificationListener = useRef();
|
||||||
|
const responseListener = useRef();
|
||||||
|
|
||||||
|
useEffect(() => {
|
||||||
|
registerForPushNotificationsAsync().then(token => token && setExpoPushToken(token));
|
||||||
|
|
||||||
|
if (Platform.OS === 'android') {
|
||||||
|
Notifications.getNotificationChannelsAsync().then(value => setChannels(value ?? []));
|
||||||
|
}
|
||||||
|
notificationListener.current = Notifications.addNotificationReceivedListener(notification => {
|
||||||
|
setNotification(notification);
|
||||||
|
});
|
||||||
|
|
||||||
|
responseListener.current = Notifications.addNotificationResponseReceivedListener(response => {
|
||||||
|
console.log(response);
|
||||||
|
});
|
||||||
|
|
||||||
|
return () => {
|
||||||
|
notificationListener.current?.remove();
|
||||||
|
responseListener.current?.remove();
|
||||||
|
};
|
||||||
|
}, []);
|
||||||
|
|
||||||
|
return ({
|
||||||
|
schedulePushNotification: async (title, body, dataObj) => {
|
||||||
|
await schedulePushNotification(title, body, dataObj);
|
||||||
|
},
|
||||||
|
expoPushToken,
|
||||||
|
expoNotificationChannels: channels,
|
||||||
|
expoNotification: notification,
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
@ -1,4 +1,4 @@
|
||||||
import { useContext } from 'react';
|
import { useContext } from 'react';
|
||||||
import { WebSocketContext } from '../../contexts/WebSocketContext';
|
import { WebSocketContext } from '../../contexts';
|
||||||
|
|
||||||
export const useWebSocketContext = () => useContext(WebSocketContext);
|
export const useWebSocketContext = () => useContext(WebSocketContext);
|
||||||
|
|
|
||||||
30
ios/Podfile
|
|
@ -7,15 +7,31 @@ podfile_properties = JSON.parse(File.read(File.join(__dir__, 'Podfile.properties
|
||||||
ENV['RCT_NEW_ARCH_ENABLED'] = podfile_properties['newArchEnabled'] == 'true' ? '1' : '0'
|
ENV['RCT_NEW_ARCH_ENABLED'] = podfile_properties['newArchEnabled'] == 'true' ? '1' : '0'
|
||||||
ENV['EX_DEV_CLIENT_NETWORK_INSPECTOR'] = podfile_properties['EX_DEV_CLIENT_NETWORK_INSPECTOR']
|
ENV['EX_DEV_CLIENT_NETWORK_INSPECTOR'] = podfile_properties['EX_DEV_CLIENT_NETWORK_INSPECTOR']
|
||||||
|
|
||||||
platform :ios, podfile_properties['ios.deploymentTarget'] || '13.4'
|
platform :ios, podfile_properties['ios.deploymentTarget'] || '15.1'
|
||||||
install! 'cocoapods',
|
install! 'cocoapods',
|
||||||
:deterministic_uuids => false
|
:deterministic_uuids => false
|
||||||
|
|
||||||
prepare_react_native_project!
|
prepare_react_native_project!
|
||||||
|
|
||||||
target 'testapplication' do
|
target 'Tones' do
|
||||||
use_expo_modules!
|
use_expo_modules!
|
||||||
config = use_native_modules!
|
|
||||||
|
if ENV['EXPO_USE_COMMUNITY_AUTOLINKING'] == '1'
|
||||||
|
config_command = ['node', '-e', "process.argv=['', '', 'config'];require('@react-native-community/cli').run()"];
|
||||||
|
else
|
||||||
|
config_command = [
|
||||||
|
'node',
|
||||||
|
'--no-warnings',
|
||||||
|
'--eval',
|
||||||
|
'require(require.resolve(\'expo-modules-autolinking\', { paths: [require.resolve(\'expo/package.json\')] }))(process.argv.slice(1))',
|
||||||
|
'react-native-config',
|
||||||
|
'--json',
|
||||||
|
'--platform',
|
||||||
|
'ios'
|
||||||
|
]
|
||||||
|
end
|
||||||
|
|
||||||
|
config = use_native_modules!(config_command)
|
||||||
|
|
||||||
use_frameworks! :linkage => podfile_properties['ios.useFrameworks'].to_sym if podfile_properties['ios.useFrameworks']
|
use_frameworks! :linkage => podfile_properties['ios.useFrameworks'].to_sym if podfile_properties['ios.useFrameworks']
|
||||||
use_frameworks! :linkage => ENV['USE_FRAMEWORKS'].to_sym if ENV['USE_FRAMEWORKS']
|
use_frameworks! :linkage => ENV['USE_FRAMEWORKS'].to_sym if ENV['USE_FRAMEWORKS']
|
||||||
|
|
@ -47,12 +63,4 @@ target 'testapplication' do
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
post_integrate do |installer|
|
|
||||||
begin
|
|
||||||
expo_patch_react_imports!(installer)
|
|
||||||
rescue => e
|
|
||||||
Pod::UI.warn e
|
|
||||||
end
|
|
||||||
end
|
|
||||||
end
|
end
|
||||||
|
|
|
||||||
2976
ios/Podfile.lock
|
|
@ -1,4 +1,5 @@
|
||||||
{
|
{
|
||||||
"expo.jsEngine": "hermes",
|
"expo.jsEngine": "hermes",
|
||||||
"EX_DEV_CLIENT_NETWORK_INSPECTOR": "true"
|
"EX_DEV_CLIENT_NETWORK_INSPECTOR": "true",
|
||||||
|
"newArchEnabled": "false"
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -10,31 +10,31 @@
|
||||||
13B07FBC1A68108700A75B9A /* AppDelegate.mm in Sources */ = {isa = PBXBuildFile; fileRef = 13B07FB01A68108700A75B9A /* AppDelegate.mm */; };
|
13B07FBC1A68108700A75B9A /* AppDelegate.mm in Sources */ = {isa = PBXBuildFile; fileRef = 13B07FB01A68108700A75B9A /* AppDelegate.mm */; };
|
||||||
13B07FBF1A68108700A75B9A /* Images.xcassets in Resources */ = {isa = PBXBuildFile; fileRef = 13B07FB51A68108700A75B9A /* Images.xcassets */; };
|
13B07FBF1A68108700A75B9A /* Images.xcassets in Resources */ = {isa = PBXBuildFile; fileRef = 13B07FB51A68108700A75B9A /* Images.xcassets */; };
|
||||||
13B07FC11A68108700A75B9A /* main.m in Sources */ = {isa = PBXBuildFile; fileRef = 13B07FB71A68108700A75B9A /* main.m */; };
|
13B07FC11A68108700A75B9A /* main.m in Sources */ = {isa = PBXBuildFile; fileRef = 13B07FB71A68108700A75B9A /* main.m */; };
|
||||||
|
3BB8D1083F3D4AAFA506B09F /* noop-file.swift in Sources */ = {isa = PBXBuildFile; fileRef = 1350D069573E4AEBBF8BA6A3 /* noop-file.swift */; };
|
||||||
3E461D99554A48A4959DE609 /* SplashScreen.storyboard in Resources */ = {isa = PBXBuildFile; fileRef = AA286B85B6C04FC6940260E9 /* SplashScreen.storyboard */; };
|
3E461D99554A48A4959DE609 /* SplashScreen.storyboard in Resources */ = {isa = PBXBuildFile; fileRef = AA286B85B6C04FC6940260E9 /* SplashScreen.storyboard */; };
|
||||||
640C5CE36A784C1E86D867C7 /* noop-file.swift in Sources */ = {isa = PBXBuildFile; fileRef = 2358EABEB0CA4428951E7149 /* noop-file.swift */; };
|
93A35CBBC1C2DF84FE39E633 /* PrivacyInfo.xcprivacy in Resources */ = {isa = PBXBuildFile; fileRef = EA8B81AA605F084BFB23750B /* PrivacyInfo.xcprivacy */; };
|
||||||
96905EF65AED1B983A6B3ABC /* libPods-testapplication.a in Frameworks */ = {isa = PBXBuildFile; fileRef = 58EEBF8E8E6FB1BC6CAF49B5 /* libPods-testapplication.a */; };
|
96905EF65AED1B983A6B3ABC /* libPods-Tones.a in Frameworks */ = {isa = PBXBuildFile; fileRef = 58EEBF8E8E6FB1BC6CAF49B5 /* libPods-Tones.a */; };
|
||||||
B18059E884C0ABDD17F3DC3D /* ExpoModulesProvider.swift in Sources */ = {isa = PBXBuildFile; fileRef = FAC715A2D49A985799AEE119 /* ExpoModulesProvider.swift */; };
|
B18059E884C0ABDD17F3DC3D /* ExpoModulesProvider.swift in Sources */ = {isa = PBXBuildFile; fileRef = FAC715A2D49A985799AEE119 /* ExpoModulesProvider.swift */; };
|
||||||
BB2F792D24A3F905000567C9 /* Expo.plist in Resources */ = {isa = PBXBuildFile; fileRef = BB2F792C24A3F905000567C9 /* Expo.plist */; };
|
BB2F792D24A3F905000567C9 /* Expo.plist in Resources */ = {isa = PBXBuildFile; fileRef = BB2F792C24A3F905000567C9 /* Expo.plist */; };
|
||||||
FF358844A8FA907CDEC7216D /* PrivacyInfo.xcprivacy in Resources */ = {isa = PBXBuildFile; fileRef = A9DA6C7B26A64A23DFDE186E /* PrivacyInfo.xcprivacy */; };
|
|
||||||
/* End PBXBuildFile section */
|
/* End PBXBuildFile section */
|
||||||
|
|
||||||
/* Begin PBXFileReference section */
|
/* Begin PBXFileReference section */
|
||||||
13B07F961A680F5B00A75B9A /* testapplication.app */ = {isa = PBXFileReference; explicitFileType = wrapper.application; includeInIndex = 0; path = testapplication.app; sourceTree = BUILT_PRODUCTS_DIR; };
|
1350D069573E4AEBBF8BA6A3 /* noop-file.swift */ = {isa = PBXFileReference; explicitFileType = undefined; fileEncoding = 4; includeInIndex = 0; lastKnownFileType = sourcecode.swift; name = "noop-file.swift"; path = "Tones/noop-file.swift"; sourceTree = "<group>"; };
|
||||||
13B07FAF1A68108700A75B9A /* AppDelegate.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = AppDelegate.h; path = testapplication/AppDelegate.h; sourceTree = "<group>"; };
|
13B07F961A680F5B00A75B9A /* Tones.app */ = {isa = PBXFileReference; explicitFileType = wrapper.application; includeInIndex = 0; path = Tones.app; sourceTree = BUILT_PRODUCTS_DIR; };
|
||||||
13B07FB01A68108700A75B9A /* AppDelegate.mm */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.objcpp; name = AppDelegate.mm; path = testapplication/AppDelegate.mm; sourceTree = "<group>"; };
|
13B07FAF1A68108700A75B9A /* AppDelegate.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = AppDelegate.h; path = Tones/AppDelegate.h; sourceTree = "<group>"; };
|
||||||
13B07FB51A68108700A75B9A /* Images.xcassets */ = {isa = PBXFileReference; lastKnownFileType = folder.assetcatalog; name = Images.xcassets; path = testapplication/Images.xcassets; sourceTree = "<group>"; };
|
13B07FB01A68108700A75B9A /* AppDelegate.mm */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.objcpp; name = AppDelegate.mm; path = Tones/AppDelegate.mm; sourceTree = "<group>"; };
|
||||||
13B07FB61A68108700A75B9A /* Info.plist */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.plist.xml; name = Info.plist; path = testapplication/Info.plist; sourceTree = "<group>"; };
|
13B07FB51A68108700A75B9A /* Images.xcassets */ = {isa = PBXFileReference; lastKnownFileType = folder.assetcatalog; name = Images.xcassets; path = Tones/Images.xcassets; sourceTree = "<group>"; };
|
||||||
13B07FB71A68108700A75B9A /* main.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = main.m; path = testapplication/main.m; sourceTree = "<group>"; };
|
13B07FB61A68108700A75B9A /* Info.plist */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.plist.xml; name = Info.plist; path = Tones/Info.plist; sourceTree = "<group>"; };
|
||||||
2358EABEB0CA4428951E7149 /* noop-file.swift */ = {isa = PBXFileReference; explicitFileType = undefined; fileEncoding = 4; includeInIndex = 0; lastKnownFileType = sourcecode.swift; name = "noop-file.swift"; path = "testapplication/noop-file.swift"; sourceTree = "<group>"; };
|
13B07FB71A68108700A75B9A /* main.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = main.m; path = Tones/main.m; sourceTree = "<group>"; };
|
||||||
58EEBF8E8E6FB1BC6CAF49B5 /* libPods-testapplication.a */ = {isa = PBXFileReference; explicitFileType = archive.ar; includeInIndex = 0; path = "libPods-testapplication.a"; sourceTree = BUILT_PRODUCTS_DIR; };
|
58EEBF8E8E6FB1BC6CAF49B5 /* libPods-Tones.a */ = {isa = PBXFileReference; explicitFileType = archive.ar; includeInIndex = 0; path = "libPods-Tones.a"; sourceTree = BUILT_PRODUCTS_DIR; };
|
||||||
6C2E3173556A471DD304B334 /* Pods-testapplication.debug.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-testapplication.debug.xcconfig"; path = "Target Support Files/Pods-testapplication/Pods-testapplication.debug.xcconfig"; sourceTree = "<group>"; };
|
6C2E3173556A471DD304B334 /* Pods-Tones.debug.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-Tones.debug.xcconfig"; path = "Target Support Files/Pods-Tones/Pods-Tones.debug.xcconfig"; sourceTree = "<group>"; };
|
||||||
7A4D352CD337FB3A3BF06240 /* Pods-testapplication.release.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-testapplication.release.xcconfig"; path = "Target Support Files/Pods-testapplication/Pods-testapplication.release.xcconfig"; sourceTree = "<group>"; };
|
7A4D352CD337FB3A3BF06240 /* Pods-Tones.release.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-Tones.release.xcconfig"; path = "Target Support Files/Pods-Tones/Pods-Tones.release.xcconfig"; sourceTree = "<group>"; };
|
||||||
96FAC8CF002144E68DCEBFD0 /* testapplication-Bridging-Header.h */ = {isa = PBXFileReference; explicitFileType = undefined; fileEncoding = 4; includeInIndex = 0; lastKnownFileType = sourcecode.c.h; name = "testapplication-Bridging-Header.h"; path = "testapplication/testapplication-Bridging-Header.h"; sourceTree = "<group>"; };
|
AA286B85B6C04FC6940260E9 /* SplashScreen.storyboard */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = file.storyboard; name = SplashScreen.storyboard; path = Tones/SplashScreen.storyboard; sourceTree = "<group>"; };
|
||||||
A9DA6C7B26A64A23DFDE186E /* PrivacyInfo.xcprivacy */ = {isa = PBXFileReference; includeInIndex = 1; name = PrivacyInfo.xcprivacy; path = testapplication/PrivacyInfo.xcprivacy; sourceTree = "<group>"; };
|
|
||||||
AA286B85B6C04FC6940260E9 /* SplashScreen.storyboard */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = file.storyboard; name = SplashScreen.storyboard; path = testapplication/SplashScreen.storyboard; sourceTree = "<group>"; };
|
|
||||||
BB2F792C24A3F905000567C9 /* Expo.plist */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.plist.xml; path = Expo.plist; sourceTree = "<group>"; };
|
BB2F792C24A3F905000567C9 /* Expo.plist */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.plist.xml; path = Expo.plist; sourceTree = "<group>"; };
|
||||||
|
EA8B81AA605F084BFB23750B /* PrivacyInfo.xcprivacy */ = {isa = PBXFileReference; includeInIndex = 1; name = PrivacyInfo.xcprivacy; path = Tones/PrivacyInfo.xcprivacy; sourceTree = "<group>"; };
|
||||||
ED297162215061F000B7C4FE /* JavaScriptCore.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = JavaScriptCore.framework; path = System/Library/Frameworks/JavaScriptCore.framework; sourceTree = SDKROOT; };
|
ED297162215061F000B7C4FE /* JavaScriptCore.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = JavaScriptCore.framework; path = System/Library/Frameworks/JavaScriptCore.framework; sourceTree = SDKROOT; };
|
||||||
FAC715A2D49A985799AEE119 /* ExpoModulesProvider.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; name = ExpoModulesProvider.swift; path = "Pods/Target Support Files/Pods-testapplication/ExpoModulesProvider.swift"; sourceTree = "<group>"; };
|
F8CAF977DAD74AAA91FDDD99 /* Tones-Bridging-Header.h */ = {isa = PBXFileReference; explicitFileType = undefined; fileEncoding = 4; includeInIndex = 0; lastKnownFileType = sourcecode.c.h; name = "Tones-Bridging-Header.h"; path = "Tones/Tones-Bridging-Header.h"; sourceTree = "<group>"; };
|
||||||
|
FAC715A2D49A985799AEE119 /* ExpoModulesProvider.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; name = ExpoModulesProvider.swift; path = "Pods/Target Support Files/Pods-Tones/ExpoModulesProvider.swift"; sourceTree = "<group>"; };
|
||||||
/* End PBXFileReference section */
|
/* End PBXFileReference section */
|
||||||
|
|
||||||
/* Begin PBXFrameworksBuildPhase section */
|
/* Begin PBXFrameworksBuildPhase section */
|
||||||
|
|
@ -42,14 +42,14 @@
|
||||||
isa = PBXFrameworksBuildPhase;
|
isa = PBXFrameworksBuildPhase;
|
||||||
buildActionMask = 2147483647;
|
buildActionMask = 2147483647;
|
||||||
files = (
|
files = (
|
||||||
96905EF65AED1B983A6B3ABC /* libPods-testapplication.a in Frameworks */,
|
96905EF65AED1B983A6B3ABC /* libPods-Tones.a in Frameworks */,
|
||||||
);
|
);
|
||||||
runOnlyForDeploymentPostprocessing = 0;
|
runOnlyForDeploymentPostprocessing = 0;
|
||||||
};
|
};
|
||||||
/* End PBXFrameworksBuildPhase section */
|
/* End PBXFrameworksBuildPhase section */
|
||||||
|
|
||||||
/* Begin PBXGroup section */
|
/* Begin PBXGroup section */
|
||||||
13B07FAE1A68108700A75B9A /* testapplication */ = {
|
13B07FAE1A68108700A75B9A /* Tones */ = {
|
||||||
isa = PBXGroup;
|
isa = PBXGroup;
|
||||||
children = (
|
children = (
|
||||||
BB2F792B24A3F905000567C9 /* Supporting */,
|
BB2F792B24A3F905000567C9 /* Supporting */,
|
||||||
|
|
@ -59,18 +59,18 @@
|
||||||
13B07FB61A68108700A75B9A /* Info.plist */,
|
13B07FB61A68108700A75B9A /* Info.plist */,
|
||||||
13B07FB71A68108700A75B9A /* main.m */,
|
13B07FB71A68108700A75B9A /* main.m */,
|
||||||
AA286B85B6C04FC6940260E9 /* SplashScreen.storyboard */,
|
AA286B85B6C04FC6940260E9 /* SplashScreen.storyboard */,
|
||||||
2358EABEB0CA4428951E7149 /* noop-file.swift */,
|
1350D069573E4AEBBF8BA6A3 /* noop-file.swift */,
|
||||||
96FAC8CF002144E68DCEBFD0 /* testapplication-Bridging-Header.h */,
|
F8CAF977DAD74AAA91FDDD99 /* Tones-Bridging-Header.h */,
|
||||||
A9DA6C7B26A64A23DFDE186E /* PrivacyInfo.xcprivacy */,
|
EA8B81AA605F084BFB23750B /* PrivacyInfo.xcprivacy */,
|
||||||
);
|
);
|
||||||
name = testapplication;
|
name = Tones;
|
||||||
sourceTree = "<group>";
|
sourceTree = "<group>";
|
||||||
};
|
};
|
||||||
2D16E6871FA4F8E400B85C8A /* Frameworks */ = {
|
2D16E6871FA4F8E400B85C8A /* Frameworks */ = {
|
||||||
isa = PBXGroup;
|
isa = PBXGroup;
|
||||||
children = (
|
children = (
|
||||||
ED297162215061F000B7C4FE /* JavaScriptCore.framework */,
|
ED297162215061F000B7C4FE /* JavaScriptCore.framework */,
|
||||||
58EEBF8E8E6FB1BC6CAF49B5 /* libPods-testapplication.a */,
|
58EEBF8E8E6FB1BC6CAF49B5 /* libPods-Tones.a */,
|
||||||
);
|
);
|
||||||
name = Frameworks;
|
name = Frameworks;
|
||||||
sourceTree = "<group>";
|
sourceTree = "<group>";
|
||||||
|
|
@ -85,7 +85,7 @@
|
||||||
83CBB9F61A601CBA00E9B192 = {
|
83CBB9F61A601CBA00E9B192 = {
|
||||||
isa = PBXGroup;
|
isa = PBXGroup;
|
||||||
children = (
|
children = (
|
||||||
13B07FAE1A68108700A75B9A /* testapplication */,
|
13B07FAE1A68108700A75B9A /* Tones */,
|
||||||
832341AE1AAA6A7D00B99B32 /* Libraries */,
|
832341AE1AAA6A7D00B99B32 /* Libraries */,
|
||||||
83CBBA001A601CBA00E9B192 /* Products */,
|
83CBBA001A601CBA00E9B192 /* Products */,
|
||||||
2D16E6871FA4F8E400B85C8A /* Frameworks */,
|
2D16E6871FA4F8E400B85C8A /* Frameworks */,
|
||||||
|
|
@ -100,17 +100,17 @@
|
||||||
83CBBA001A601CBA00E9B192 /* Products */ = {
|
83CBBA001A601CBA00E9B192 /* Products */ = {
|
||||||
isa = PBXGroup;
|
isa = PBXGroup;
|
||||||
children = (
|
children = (
|
||||||
13B07F961A680F5B00A75B9A /* testapplication.app */,
|
13B07F961A680F5B00A75B9A /* Tones.app */,
|
||||||
);
|
);
|
||||||
name = Products;
|
name = Products;
|
||||||
sourceTree = "<group>";
|
sourceTree = "<group>";
|
||||||
};
|
};
|
||||||
92DBD88DE9BF7D494EA9DA96 /* testapplication */ = {
|
92DBD88DE9BF7D494EA9DA96 /* Tones */ = {
|
||||||
isa = PBXGroup;
|
isa = PBXGroup;
|
||||||
children = (
|
children = (
|
||||||
FAC715A2D49A985799AEE119 /* ExpoModulesProvider.swift */,
|
FAC715A2D49A985799AEE119 /* ExpoModulesProvider.swift */,
|
||||||
);
|
);
|
||||||
name = testapplication;
|
name = Tones;
|
||||||
sourceTree = "<group>";
|
sourceTree = "<group>";
|
||||||
};
|
};
|
||||||
BB2F792B24A3F905000567C9 /* Supporting */ = {
|
BB2F792B24A3F905000567C9 /* Supporting */ = {
|
||||||
|
|
@ -119,14 +119,14 @@
|
||||||
BB2F792C24A3F905000567C9 /* Expo.plist */,
|
BB2F792C24A3F905000567C9 /* Expo.plist */,
|
||||||
);
|
);
|
||||||
name = Supporting;
|
name = Supporting;
|
||||||
path = testapplication/Supporting;
|
path = Tones/Supporting;
|
||||||
sourceTree = "<group>";
|
sourceTree = "<group>";
|
||||||
};
|
};
|
||||||
D65327D7A22EEC0BE12398D9 /* Pods */ = {
|
D65327D7A22EEC0BE12398D9 /* Pods */ = {
|
||||||
isa = PBXGroup;
|
isa = PBXGroup;
|
||||||
children = (
|
children = (
|
||||||
6C2E3173556A471DD304B334 /* Pods-testapplication.debug.xcconfig */,
|
6C2E3173556A471DD304B334 /* Pods-Tones.debug.xcconfig */,
|
||||||
7A4D352CD337FB3A3BF06240 /* Pods-testapplication.release.xcconfig */,
|
7A4D352CD337FB3A3BF06240 /* Pods-Tones.release.xcconfig */,
|
||||||
);
|
);
|
||||||
path = Pods;
|
path = Pods;
|
||||||
sourceTree = "<group>";
|
sourceTree = "<group>";
|
||||||
|
|
@ -134,7 +134,7 @@
|
||||||
D7E4C46ADA2E9064B798F356 /* ExpoModulesProviders */ = {
|
D7E4C46ADA2E9064B798F356 /* ExpoModulesProviders */ = {
|
||||||
isa = PBXGroup;
|
isa = PBXGroup;
|
||||||
children = (
|
children = (
|
||||||
92DBD88DE9BF7D494EA9DA96 /* testapplication */,
|
92DBD88DE9BF7D494EA9DA96 /* Tones */,
|
||||||
);
|
);
|
||||||
name = ExpoModulesProviders;
|
name = ExpoModulesProviders;
|
||||||
sourceTree = "<group>";
|
sourceTree = "<group>";
|
||||||
|
|
@ -142,26 +142,26 @@
|
||||||
/* End PBXGroup section */
|
/* End PBXGroup section */
|
||||||
|
|
||||||
/* Begin PBXNativeTarget section */
|
/* Begin PBXNativeTarget section */
|
||||||
13B07F861A680F5B00A75B9A /* testapplication */ = {
|
13B07F861A680F5B00A75B9A /* Tones */ = {
|
||||||
isa = PBXNativeTarget;
|
isa = PBXNativeTarget;
|
||||||
buildConfigurationList = 13B07F931A680F5B00A75B9A /* Build configuration list for PBXNativeTarget "testapplication" */;
|
buildConfigurationList = 13B07F931A680F5B00A75B9A /* Build configuration list for PBXNativeTarget "Tones" */;
|
||||||
buildPhases = (
|
buildPhases = (
|
||||||
08A4A3CD28434E44B6B9DE2E /* [CP] Check Pods Manifest.lock */,
|
08A4A3CD28434E44B6B9DE2E /* [CP] Check Pods Manifest.lock */,
|
||||||
7E5AAFC44944C4D49F90AE74 /* [Expo] Configure project */,
|
BBDF11722E0998CCEE7FC139 /* [Expo] Configure project */,
|
||||||
13B07F871A680F5B00A75B9A /* Sources */,
|
13B07F871A680F5B00A75B9A /* Sources */,
|
||||||
13B07F8C1A680F5B00A75B9A /* Frameworks */,
|
13B07F8C1A680F5B00A75B9A /* Frameworks */,
|
||||||
13B07F8E1A680F5B00A75B9A /* Resources */,
|
13B07F8E1A680F5B00A75B9A /* Resources */,
|
||||||
00DD1BFF1BD5951E006B06BC /* Bundle React Native code and images */,
|
00DD1BFF1BD5951E006B06BC /* Bundle React Native code and images */,
|
||||||
800E24972A6A228C8D4807E9 /* [CP] Copy Pods Resources */,
|
800E24972A6A228C8D4807E9 /* [CP] Copy Pods Resources */,
|
||||||
6CD366C487D1C4076EEFC1E9 /* [CP] Embed Pods Frameworks */,
|
5F318AA4CE51F8E175CC6D0A /* [CP] Embed Pods Frameworks */,
|
||||||
);
|
);
|
||||||
buildRules = (
|
buildRules = (
|
||||||
);
|
);
|
||||||
dependencies = (
|
dependencies = (
|
||||||
);
|
);
|
||||||
name = testapplication;
|
name = Tones;
|
||||||
productName = testapplication;
|
productName = Tones;
|
||||||
productReference = 13B07F961A680F5B00A75B9A /* testapplication.app */;
|
productReference = 13B07F961A680F5B00A75B9A /* Tones.app */;
|
||||||
productType = "com.apple.product-type.application";
|
productType = "com.apple.product-type.application";
|
||||||
};
|
};
|
||||||
/* End PBXNativeTarget section */
|
/* End PBXNativeTarget section */
|
||||||
|
|
@ -177,7 +177,7 @@
|
||||||
};
|
};
|
||||||
};
|
};
|
||||||
};
|
};
|
||||||
buildConfigurationList = 83CBB9FA1A601CBA00E9B192 /* Build configuration list for PBXProject "testapplication" */;
|
buildConfigurationList = 83CBB9FA1A601CBA00E9B192 /* Build configuration list for PBXProject "Tones" */;
|
||||||
compatibilityVersion = "Xcode 3.2";
|
compatibilityVersion = "Xcode 3.2";
|
||||||
developmentRegion = en;
|
developmentRegion = en;
|
||||||
hasScannedForEncodings = 0;
|
hasScannedForEncodings = 0;
|
||||||
|
|
@ -190,7 +190,7 @@
|
||||||
projectDirPath = "";
|
projectDirPath = "";
|
||||||
projectRoot = "";
|
projectRoot = "";
|
||||||
targets = (
|
targets = (
|
||||||
13B07F861A680F5B00A75B9A /* testapplication */,
|
13B07F861A680F5B00A75B9A /* Tones */,
|
||||||
);
|
);
|
||||||
};
|
};
|
||||||
/* End PBXProject section */
|
/* End PBXProject section */
|
||||||
|
|
@ -203,7 +203,7 @@
|
||||||
BB2F792D24A3F905000567C9 /* Expo.plist in Resources */,
|
BB2F792D24A3F905000567C9 /* Expo.plist in Resources */,
|
||||||
13B07FBF1A68108700A75B9A /* Images.xcassets in Resources */,
|
13B07FBF1A68108700A75B9A /* Images.xcassets in Resources */,
|
||||||
3E461D99554A48A4959DE609 /* SplashScreen.storyboard in Resources */,
|
3E461D99554A48A4959DE609 /* SplashScreen.storyboard in Resources */,
|
||||||
FF358844A8FA907CDEC7216D /* PrivacyInfo.xcprivacy in Resources */,
|
93A35CBBC1C2DF84FE39E633 /* PrivacyInfo.xcprivacy in Resources */,
|
||||||
);
|
);
|
||||||
runOnlyForDeploymentPostprocessing = 0;
|
runOnlyForDeploymentPostprocessing = 0;
|
||||||
};
|
};
|
||||||
|
|
@ -240,20 +240,20 @@
|
||||||
outputFileListPaths = (
|
outputFileListPaths = (
|
||||||
);
|
);
|
||||||
outputPaths = (
|
outputPaths = (
|
||||||
"$(DERIVED_FILE_DIR)/Pods-testapplication-checkManifestLockResult.txt",
|
"$(DERIVED_FILE_DIR)/Pods-Tones-checkManifestLockResult.txt",
|
||||||
);
|
);
|
||||||
runOnlyForDeploymentPostprocessing = 0;
|
runOnlyForDeploymentPostprocessing = 0;
|
||||||
shellPath = /bin/sh;
|
shellPath = /bin/sh;
|
||||||
shellScript = "diff \"${PODS_PODFILE_DIR_PATH}/Podfile.lock\" \"${PODS_ROOT}/Manifest.lock\" > /dev/null\nif [ $? != 0 ] ; then\n # print error to STDERR\n echo \"error: The sandbox is not in sync with the Podfile.lock. Run 'pod install' or update your CocoaPods installation.\" >&2\n exit 1\nfi\n# This output is used by Xcode 'outputs' to avoid re-running this script phase.\necho \"SUCCESS\" > \"${SCRIPT_OUTPUT_FILE_0}\"\n";
|
shellScript = "diff \"${PODS_PODFILE_DIR_PATH}/Podfile.lock\" \"${PODS_ROOT}/Manifest.lock\" > /dev/null\nif [ $? != 0 ] ; then\n # print error to STDERR\n echo \"error: The sandbox is not in sync with the Podfile.lock. Run 'pod install' or update your CocoaPods installation.\" >&2\n exit 1\nfi\n# This output is used by Xcode 'outputs' to avoid re-running this script phase.\necho \"SUCCESS\" > \"${SCRIPT_OUTPUT_FILE_0}\"\n";
|
||||||
showEnvVarsInLog = 0;
|
showEnvVarsInLog = 0;
|
||||||
};
|
};
|
||||||
6CD366C487D1C4076EEFC1E9 /* [CP] Embed Pods Frameworks */ = {
|
5F318AA4CE51F8E175CC6D0A /* [CP] Embed Pods Frameworks */ = {
|
||||||
isa = PBXShellScriptBuildPhase;
|
isa = PBXShellScriptBuildPhase;
|
||||||
buildActionMask = 2147483647;
|
buildActionMask = 2147483647;
|
||||||
files = (
|
files = (
|
||||||
);
|
);
|
||||||
inputPaths = (
|
inputPaths = (
|
||||||
"${PODS_ROOT}/Target Support Files/Pods-testapplication/Pods-testapplication-frameworks.sh",
|
"${PODS_ROOT}/Target Support Files/Pods-Tones/Pods-Tones-frameworks.sh",
|
||||||
"${PODS_XCFRAMEWORKS_BUILD_DIR}/hermes-engine/Pre-built/hermes.framework/hermes",
|
"${PODS_XCFRAMEWORKS_BUILD_DIR}/hermes-engine/Pre-built/hermes.framework/hermes",
|
||||||
);
|
);
|
||||||
name = "[CP] Embed Pods Frameworks";
|
name = "[CP] Embed Pods Frameworks";
|
||||||
|
|
@ -262,10 +262,50 @@
|
||||||
);
|
);
|
||||||
runOnlyForDeploymentPostprocessing = 0;
|
runOnlyForDeploymentPostprocessing = 0;
|
||||||
shellPath = /bin/sh;
|
shellPath = /bin/sh;
|
||||||
shellScript = "\"${PODS_ROOT}/Target Support Files/Pods-testapplication/Pods-testapplication-frameworks.sh\"\n";
|
shellScript = "\"${PODS_ROOT}/Target Support Files/Pods-Tones/Pods-Tones-frameworks.sh\"\n";
|
||||||
showEnvVarsInLog = 0;
|
showEnvVarsInLog = 0;
|
||||||
};
|
};
|
||||||
7E5AAFC44944C4D49F90AE74 /* [Expo] Configure project */ = {
|
800E24972A6A228C8D4807E9 /* [CP] Copy Pods Resources */ = {
|
||||||
|
isa = PBXShellScriptBuildPhase;
|
||||||
|
buildActionMask = 2147483647;
|
||||||
|
files = (
|
||||||
|
);
|
||||||
|
inputPaths = (
|
||||||
|
"${PODS_ROOT}/Target Support Files/Pods-Tones/Pods-Tones-resources.sh",
|
||||||
|
"${PODS_CONFIGURATION_BUILD_DIR}/EXApplication/ExpoApplication_privacy.bundle",
|
||||||
|
"${PODS_CONFIGURATION_BUILD_DIR}/EXConstants/EXConstants.bundle",
|
||||||
|
"${PODS_CONFIGURATION_BUILD_DIR}/EXConstants/ExpoConstants_privacy.bundle",
|
||||||
|
"${PODS_CONFIGURATION_BUILD_DIR}/EXNotifications/ExpoNotifications_privacy.bundle",
|
||||||
|
"${PODS_CONFIGURATION_BUILD_DIR}/ExpoDevice/ExpoDevice_privacy.bundle",
|
||||||
|
"${PODS_CONFIGURATION_BUILD_DIR}/ExpoFileSystem/ExpoFileSystem_privacy.bundle",
|
||||||
|
"${PODS_CONFIGURATION_BUILD_DIR}/ExpoSystemUI/ExpoSystemUI_privacy.bundle",
|
||||||
|
"${PODS_CONFIGURATION_BUILD_DIR}/RCT-Folly/RCT-Folly_privacy.bundle",
|
||||||
|
"${PODS_CONFIGURATION_BUILD_DIR}/React-Core/React-Core_privacy.bundle",
|
||||||
|
"${PODS_CONFIGURATION_BUILD_DIR}/React-cxxreact/React-cxxreact_privacy.bundle",
|
||||||
|
"${PODS_CONFIGURATION_BUILD_DIR}/boost/boost_privacy.bundle",
|
||||||
|
"${PODS_CONFIGURATION_BUILD_DIR}/glog/glog_privacy.bundle",
|
||||||
|
);
|
||||||
|
name = "[CP] Copy Pods Resources";
|
||||||
|
outputPaths = (
|
||||||
|
"${TARGET_BUILD_DIR}/${UNLOCALIZED_RESOURCES_FOLDER_PATH}/ExpoApplication_privacy.bundle",
|
||||||
|
"${TARGET_BUILD_DIR}/${UNLOCALIZED_RESOURCES_FOLDER_PATH}/EXConstants.bundle",
|
||||||
|
"${TARGET_BUILD_DIR}/${UNLOCALIZED_RESOURCES_FOLDER_PATH}/ExpoConstants_privacy.bundle",
|
||||||
|
"${TARGET_BUILD_DIR}/${UNLOCALIZED_RESOURCES_FOLDER_PATH}/ExpoNotifications_privacy.bundle",
|
||||||
|
"${TARGET_BUILD_DIR}/${UNLOCALIZED_RESOURCES_FOLDER_PATH}/ExpoDevice_privacy.bundle",
|
||||||
|
"${TARGET_BUILD_DIR}/${UNLOCALIZED_RESOURCES_FOLDER_PATH}/ExpoFileSystem_privacy.bundle",
|
||||||
|
"${TARGET_BUILD_DIR}/${UNLOCALIZED_RESOURCES_FOLDER_PATH}/ExpoSystemUI_privacy.bundle",
|
||||||
|
"${TARGET_BUILD_DIR}/${UNLOCALIZED_RESOURCES_FOLDER_PATH}/RCT-Folly_privacy.bundle",
|
||||||
|
"${TARGET_BUILD_DIR}/${UNLOCALIZED_RESOURCES_FOLDER_PATH}/React-Core_privacy.bundle",
|
||||||
|
"${TARGET_BUILD_DIR}/${UNLOCALIZED_RESOURCES_FOLDER_PATH}/React-cxxreact_privacy.bundle",
|
||||||
|
"${TARGET_BUILD_DIR}/${UNLOCALIZED_RESOURCES_FOLDER_PATH}/boost_privacy.bundle",
|
||||||
|
"${TARGET_BUILD_DIR}/${UNLOCALIZED_RESOURCES_FOLDER_PATH}/glog_privacy.bundle",
|
||||||
|
);
|
||||||
|
runOnlyForDeploymentPostprocessing = 0;
|
||||||
|
shellPath = /bin/sh;
|
||||||
|
shellScript = "\"${PODS_ROOT}/Target Support Files/Pods-Tones/Pods-Tones-resources.sh\"\n";
|
||||||
|
showEnvVarsInLog = 0;
|
||||||
|
};
|
||||||
|
BBDF11722E0998CCEE7FC139 /* [Expo] Configure project */ = {
|
||||||
isa = PBXShellScriptBuildPhase;
|
isa = PBXShellScriptBuildPhase;
|
||||||
alwaysOutOfDate = 1;
|
alwaysOutOfDate = 1;
|
||||||
buildActionMask = 2147483647;
|
buildActionMask = 2147483647;
|
||||||
|
|
@ -282,33 +322,7 @@
|
||||||
);
|
);
|
||||||
runOnlyForDeploymentPostprocessing = 0;
|
runOnlyForDeploymentPostprocessing = 0;
|
||||||
shellPath = /bin/sh;
|
shellPath = /bin/sh;
|
||||||
shellScript = "# This script configures Expo modules and generates the modules provider file.\nbash -l -c \"./Pods/Target\\ Support\\ Files/Pods-testapplication/expo-configure-project.sh\"\n";
|
shellScript = "# This script configures Expo modules and generates the modules provider file.\nbash -l -c \"./Pods/Target\\ Support\\ Files/Pods-Tones/expo-configure-project.sh\"\n";
|
||||||
};
|
|
||||||
800E24972A6A228C8D4807E9 /* [CP] Copy Pods Resources */ = {
|
|
||||||
isa = PBXShellScriptBuildPhase;
|
|
||||||
buildActionMask = 2147483647;
|
|
||||||
files = (
|
|
||||||
);
|
|
||||||
inputPaths = (
|
|
||||||
"${PODS_ROOT}/Target Support Files/Pods-testapplication/Pods-testapplication-resources.sh",
|
|
||||||
"${PODS_CONFIGURATION_BUILD_DIR}/EXConstants/EXConstants.bundle",
|
|
||||||
"${PODS_CONFIGURATION_BUILD_DIR}/EXConstants/ExpoConstants_privacy.bundle",
|
|
||||||
"${PODS_CONFIGURATION_BUILD_DIR}/ExpoFileSystem/ExpoFileSystem_privacy.bundle",
|
|
||||||
"${PODS_CONFIGURATION_BUILD_DIR}/ExpoSystemUI/ExpoSystemUI_privacy.bundle",
|
|
||||||
"${PODS_CONFIGURATION_BUILD_DIR}/React-Core/RCTI18nStrings.bundle",
|
|
||||||
);
|
|
||||||
name = "[CP] Copy Pods Resources";
|
|
||||||
outputPaths = (
|
|
||||||
"${TARGET_BUILD_DIR}/${UNLOCALIZED_RESOURCES_FOLDER_PATH}/EXConstants.bundle",
|
|
||||||
"${TARGET_BUILD_DIR}/${UNLOCALIZED_RESOURCES_FOLDER_PATH}/ExpoConstants_privacy.bundle",
|
|
||||||
"${TARGET_BUILD_DIR}/${UNLOCALIZED_RESOURCES_FOLDER_PATH}/ExpoFileSystem_privacy.bundle",
|
|
||||||
"${TARGET_BUILD_DIR}/${UNLOCALIZED_RESOURCES_FOLDER_PATH}/ExpoSystemUI_privacy.bundle",
|
|
||||||
"${TARGET_BUILD_DIR}/${UNLOCALIZED_RESOURCES_FOLDER_PATH}/RCTI18nStrings.bundle",
|
|
||||||
);
|
|
||||||
runOnlyForDeploymentPostprocessing = 0;
|
|
||||||
shellPath = /bin/sh;
|
|
||||||
shellScript = "\"${PODS_ROOT}/Target Support Files/Pods-testapplication/Pods-testapplication-resources.sh\"\n";
|
|
||||||
showEnvVarsInLog = 0;
|
|
||||||
};
|
};
|
||||||
/* End PBXShellScriptBuildPhase section */
|
/* End PBXShellScriptBuildPhase section */
|
||||||
|
|
||||||
|
|
@ -320,7 +334,7 @@
|
||||||
13B07FBC1A68108700A75B9A /* AppDelegate.mm in Sources */,
|
13B07FBC1A68108700A75B9A /* AppDelegate.mm in Sources */,
|
||||||
13B07FC11A68108700A75B9A /* main.m in Sources */,
|
13B07FC11A68108700A75B9A /* main.m in Sources */,
|
||||||
B18059E884C0ABDD17F3DC3D /* ExpoModulesProvider.swift in Sources */,
|
B18059E884C0ABDD17F3DC3D /* ExpoModulesProvider.swift in Sources */,
|
||||||
640C5CE36A784C1E86D867C7 /* noop-file.swift in Sources */,
|
3BB8D1083F3D4AAFA506B09F /* noop-file.swift in Sources */,
|
||||||
);
|
);
|
||||||
runOnlyForDeploymentPostprocessing = 0;
|
runOnlyForDeploymentPostprocessing = 0;
|
||||||
};
|
};
|
||||||
|
|
@ -329,19 +343,19 @@
|
||||||
/* Begin XCBuildConfiguration section */
|
/* Begin XCBuildConfiguration section */
|
||||||
13B07F941A680F5B00A75B9A /* Debug */ = {
|
13B07F941A680F5B00A75B9A /* Debug */ = {
|
||||||
isa = XCBuildConfiguration;
|
isa = XCBuildConfiguration;
|
||||||
baseConfigurationReference = 6C2E3173556A471DD304B334 /* Pods-testapplication.debug.xcconfig */;
|
baseConfigurationReference = 6C2E3173556A471DD304B334 /* Pods-Tones.debug.xcconfig */;
|
||||||
buildSettings = {
|
buildSettings = {
|
||||||
ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon;
|
ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon;
|
||||||
CLANG_ENABLE_MODULES = YES;
|
CLANG_ENABLE_MODULES = YES;
|
||||||
CODE_SIGN_ENTITLEMENTS = testapplication/testapplication.entitlements;
|
CODE_SIGN_ENTITLEMENTS = Tones/Tones.entitlements;
|
||||||
CURRENT_PROJECT_VERSION = 1;
|
CURRENT_PROJECT_VERSION = 1;
|
||||||
ENABLE_BITCODE = NO;
|
ENABLE_BITCODE = NO;
|
||||||
GCC_PREPROCESSOR_DEFINITIONS = (
|
GCC_PREPROCESSOR_DEFINITIONS = (
|
||||||
"$(inherited)",
|
"$(inherited)",
|
||||||
"FB_SONARKIT_ENABLED=1",
|
"FB_SONARKIT_ENABLED=1",
|
||||||
);
|
);
|
||||||
INFOPLIST_FILE = testapplication/Info.plist;
|
INFOPLIST_FILE = Tones/Info.plist;
|
||||||
IPHONEOS_DEPLOYMENT_TARGET = 13.4;
|
IPHONEOS_DEPLOYMENT_TARGET = 15.1;
|
||||||
LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks";
|
LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks";
|
||||||
MARKETING_VERSION = 1.0;
|
MARKETING_VERSION = 1.0;
|
||||||
OTHER_LDFLAGS = (
|
OTHER_LDFLAGS = (
|
||||||
|
|
@ -350,9 +364,9 @@
|
||||||
"-lc++",
|
"-lc++",
|
||||||
);
|
);
|
||||||
OTHER_SWIFT_FLAGS = "$(inherited) -D EXPO_CONFIGURATION_DEBUG";
|
OTHER_SWIFT_FLAGS = "$(inherited) -D EXPO_CONFIGURATION_DEBUG";
|
||||||
PRODUCT_BUNDLE_IDENTIFIER = com.anonymous.testapplication;
|
PRODUCT_BUNDLE_IDENTIFIER = com.mattdimegs.tones;
|
||||||
PRODUCT_NAME = testapplication;
|
PRODUCT_NAME = Tones;
|
||||||
SWIFT_OBJC_BRIDGING_HEADER = "testapplication/testapplication-Bridging-Header.h";
|
SWIFT_OBJC_BRIDGING_HEADER = "Tones/Tones-Bridging-Header.h";
|
||||||
SWIFT_OPTIMIZATION_LEVEL = "-Onone";
|
SWIFT_OPTIMIZATION_LEVEL = "-Onone";
|
||||||
SWIFT_VERSION = 5.0;
|
SWIFT_VERSION = 5.0;
|
||||||
TARGETED_DEVICE_FAMILY = "1,2";
|
TARGETED_DEVICE_FAMILY = "1,2";
|
||||||
|
|
@ -362,14 +376,14 @@
|
||||||
};
|
};
|
||||||
13B07F951A680F5B00A75B9A /* Release */ = {
|
13B07F951A680F5B00A75B9A /* Release */ = {
|
||||||
isa = XCBuildConfiguration;
|
isa = XCBuildConfiguration;
|
||||||
baseConfigurationReference = 7A4D352CD337FB3A3BF06240 /* Pods-testapplication.release.xcconfig */;
|
baseConfigurationReference = 7A4D352CD337FB3A3BF06240 /* Pods-Tones.release.xcconfig */;
|
||||||
buildSettings = {
|
buildSettings = {
|
||||||
ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon;
|
ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon;
|
||||||
CLANG_ENABLE_MODULES = YES;
|
CLANG_ENABLE_MODULES = YES;
|
||||||
CODE_SIGN_ENTITLEMENTS = testapplication/testapplication.entitlements;
|
CODE_SIGN_ENTITLEMENTS = Tones/Tones.entitlements;
|
||||||
CURRENT_PROJECT_VERSION = 1;
|
CURRENT_PROJECT_VERSION = 1;
|
||||||
INFOPLIST_FILE = testapplication/Info.plist;
|
INFOPLIST_FILE = Tones/Info.plist;
|
||||||
IPHONEOS_DEPLOYMENT_TARGET = 13.4;
|
IPHONEOS_DEPLOYMENT_TARGET = 15.1;
|
||||||
LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks";
|
LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks";
|
||||||
MARKETING_VERSION = 1.0;
|
MARKETING_VERSION = 1.0;
|
||||||
OTHER_LDFLAGS = (
|
OTHER_LDFLAGS = (
|
||||||
|
|
@ -378,9 +392,9 @@
|
||||||
"-lc++",
|
"-lc++",
|
||||||
);
|
);
|
||||||
OTHER_SWIFT_FLAGS = "$(inherited) -D EXPO_CONFIGURATION_RELEASE";
|
OTHER_SWIFT_FLAGS = "$(inherited) -D EXPO_CONFIGURATION_RELEASE";
|
||||||
PRODUCT_BUNDLE_IDENTIFIER = com.anonymous.testapplication;
|
PRODUCT_BUNDLE_IDENTIFIER = com.mattdimegs.tones;
|
||||||
PRODUCT_NAME = testapplication;
|
PRODUCT_NAME = Tones;
|
||||||
SWIFT_OBJC_BRIDGING_HEADER = "testapplication/testapplication-Bridging-Header.h";
|
SWIFT_OBJC_BRIDGING_HEADER = "Tones/Tones-Bridging-Header.h";
|
||||||
SWIFT_VERSION = 5.0;
|
SWIFT_VERSION = 5.0;
|
||||||
TARGETED_DEVICE_FAMILY = "1,2";
|
TARGETED_DEVICE_FAMILY = "1,2";
|
||||||
VERSIONING_SYSTEM = "apple-generic";
|
VERSIONING_SYSTEM = "apple-generic";
|
||||||
|
|
@ -391,7 +405,6 @@
|
||||||
isa = XCBuildConfiguration;
|
isa = XCBuildConfiguration;
|
||||||
buildSettings = {
|
buildSettings = {
|
||||||
ALWAYS_SEARCH_USER_PATHS = NO;
|
ALWAYS_SEARCH_USER_PATHS = NO;
|
||||||
CC = "";
|
|
||||||
CLANG_ANALYZER_LOCALIZABILITY_NONLOCALIZED = YES;
|
CLANG_ANALYZER_LOCALIZABILITY_NONLOCALIZED = YES;
|
||||||
CLANG_CXX_LANGUAGE_STANDARD = "c++20";
|
CLANG_CXX_LANGUAGE_STANDARD = "c++20";
|
||||||
CLANG_CXX_LIBRARY = "libc++";
|
CLANG_CXX_LIBRARY = "libc++";
|
||||||
|
|
@ -418,7 +431,6 @@
|
||||||
CLANG_WARN__DUPLICATE_METHOD_MATCH = YES;
|
CLANG_WARN__DUPLICATE_METHOD_MATCH = YES;
|
||||||
"CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Developer";
|
"CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Developer";
|
||||||
COPY_PHASE_STRIP = NO;
|
COPY_PHASE_STRIP = NO;
|
||||||
CXX = "";
|
|
||||||
ENABLE_STRICT_OBJC_MSGSEND = YES;
|
ENABLE_STRICT_OBJC_MSGSEND = YES;
|
||||||
ENABLE_TESTABILITY = YES;
|
ENABLE_TESTABILITY = YES;
|
||||||
GCC_C_LANGUAGE_STANDARD = gnu99;
|
GCC_C_LANGUAGE_STANDARD = gnu99;
|
||||||
|
|
@ -436,9 +448,7 @@
|
||||||
GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE;
|
GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE;
|
||||||
GCC_WARN_UNUSED_FUNCTION = YES;
|
GCC_WARN_UNUSED_FUNCTION = YES;
|
||||||
GCC_WARN_UNUSED_VARIABLE = YES;
|
GCC_WARN_UNUSED_VARIABLE = YES;
|
||||||
IPHONEOS_DEPLOYMENT_TARGET = 13.4;
|
IPHONEOS_DEPLOYMENT_TARGET = 15.1;
|
||||||
LD = "";
|
|
||||||
LDPLUSPLUS = "";
|
|
||||||
LD_RUNPATH_SEARCH_PATHS = "/usr/lib/swift $(inherited)";
|
LD_RUNPATH_SEARCH_PATHS = "/usr/lib/swift $(inherited)";
|
||||||
LIBRARY_SEARCH_PATHS = "$(SDKROOT)/usr/lib/swift\"$(inherited)\"";
|
LIBRARY_SEARCH_PATHS = "$(SDKROOT)/usr/lib/swift\"$(inherited)\"";
|
||||||
MTL_ENABLE_DEBUG_INFO = YES;
|
MTL_ENABLE_DEBUG_INFO = YES;
|
||||||
|
|
@ -449,6 +459,7 @@
|
||||||
);
|
);
|
||||||
REACT_NATIVE_PATH = "${PODS_ROOT}/../../node_modules/react-native";
|
REACT_NATIVE_PATH = "${PODS_ROOT}/../../node_modules/react-native";
|
||||||
SDKROOT = iphoneos;
|
SDKROOT = iphoneos;
|
||||||
|
SWIFT_ACTIVE_COMPILATION_CONDITIONS = "$(inherited) DEBUG";
|
||||||
USE_HERMES = true;
|
USE_HERMES = true;
|
||||||
};
|
};
|
||||||
name = Debug;
|
name = Debug;
|
||||||
|
|
@ -457,7 +468,6 @@
|
||||||
isa = XCBuildConfiguration;
|
isa = XCBuildConfiguration;
|
||||||
buildSettings = {
|
buildSettings = {
|
||||||
ALWAYS_SEARCH_USER_PATHS = NO;
|
ALWAYS_SEARCH_USER_PATHS = NO;
|
||||||
CC = "";
|
|
||||||
CLANG_ANALYZER_LOCALIZABILITY_NONLOCALIZED = YES;
|
CLANG_ANALYZER_LOCALIZABILITY_NONLOCALIZED = YES;
|
||||||
CLANG_CXX_LANGUAGE_STANDARD = "c++20";
|
CLANG_CXX_LANGUAGE_STANDARD = "c++20";
|
||||||
CLANG_CXX_LIBRARY = "libc++";
|
CLANG_CXX_LIBRARY = "libc++";
|
||||||
|
|
@ -484,7 +494,6 @@
|
||||||
CLANG_WARN__DUPLICATE_METHOD_MATCH = YES;
|
CLANG_WARN__DUPLICATE_METHOD_MATCH = YES;
|
||||||
"CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Developer";
|
"CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Developer";
|
||||||
COPY_PHASE_STRIP = YES;
|
COPY_PHASE_STRIP = YES;
|
||||||
CXX = "";
|
|
||||||
ENABLE_NS_ASSERTIONS = NO;
|
ENABLE_NS_ASSERTIONS = NO;
|
||||||
ENABLE_STRICT_OBJC_MSGSEND = YES;
|
ENABLE_STRICT_OBJC_MSGSEND = YES;
|
||||||
GCC_C_LANGUAGE_STANDARD = gnu99;
|
GCC_C_LANGUAGE_STANDARD = gnu99;
|
||||||
|
|
@ -495,9 +504,7 @@
|
||||||
GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE;
|
GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE;
|
||||||
GCC_WARN_UNUSED_FUNCTION = YES;
|
GCC_WARN_UNUSED_FUNCTION = YES;
|
||||||
GCC_WARN_UNUSED_VARIABLE = YES;
|
GCC_WARN_UNUSED_VARIABLE = YES;
|
||||||
IPHONEOS_DEPLOYMENT_TARGET = 13.4;
|
IPHONEOS_DEPLOYMENT_TARGET = 15.1;
|
||||||
LD = "";
|
|
||||||
LDPLUSPLUS = "";
|
|
||||||
LD_RUNPATH_SEARCH_PATHS = "/usr/lib/swift $(inherited)";
|
LD_RUNPATH_SEARCH_PATHS = "/usr/lib/swift $(inherited)";
|
||||||
LIBRARY_SEARCH_PATHS = "$(SDKROOT)/usr/lib/swift\"$(inherited)\"";
|
LIBRARY_SEARCH_PATHS = "$(SDKROOT)/usr/lib/swift\"$(inherited)\"";
|
||||||
MTL_ENABLE_DEBUG_INFO = NO;
|
MTL_ENABLE_DEBUG_INFO = NO;
|
||||||
|
|
@ -515,7 +522,7 @@
|
||||||
/* End XCBuildConfiguration section */
|
/* End XCBuildConfiguration section */
|
||||||
|
|
||||||
/* Begin XCConfigurationList section */
|
/* Begin XCConfigurationList section */
|
||||||
13B07F931A680F5B00A75B9A /* Build configuration list for PBXNativeTarget "testapplication" */ = {
|
13B07F931A680F5B00A75B9A /* Build configuration list for PBXNativeTarget "Tones" */ = {
|
||||||
isa = XCConfigurationList;
|
isa = XCConfigurationList;
|
||||||
buildConfigurations = (
|
buildConfigurations = (
|
||||||
13B07F941A680F5B00A75B9A /* Debug */,
|
13B07F941A680F5B00A75B9A /* Debug */,
|
||||||
|
|
@ -524,7 +531,7 @@
|
||||||
defaultConfigurationIsVisible = 0;
|
defaultConfigurationIsVisible = 0;
|
||||||
defaultConfigurationName = Release;
|
defaultConfigurationName = Release;
|
||||||
};
|
};
|
||||||
83CBB9FA1A601CBA00E9B192 /* Build configuration list for PBXProject "testapplication" */ = {
|
83CBB9FA1A601CBA00E9B192 /* Build configuration list for PBXProject "Tones" */ = {
|
||||||
isa = XCConfigurationList;
|
isa = XCConfigurationList;
|
||||||
buildConfigurations = (
|
buildConfigurations = (
|
||||||
83CBBA201A601CBA00E9B192 /* Debug */,
|
83CBBA201A601CBA00E9B192 /* Debug */,
|
||||||
|
|
@ -15,9 +15,9 @@
|
||||||
<BuildableReference
|
<BuildableReference
|
||||||
BuildableIdentifier = "primary"
|
BuildableIdentifier = "primary"
|
||||||
BlueprintIdentifier = "13B07F861A680F5B00A75B9A"
|
BlueprintIdentifier = "13B07F861A680F5B00A75B9A"
|
||||||
BuildableName = "testapplication.app"
|
BuildableName = "Tones.app"
|
||||||
BlueprintName = "testapplication"
|
BlueprintName = "Tones"
|
||||||
ReferencedContainer = "container:testapplication.xcodeproj">
|
ReferencedContainer = "container:Tones.xcodeproj">
|
||||||
</BuildableReference>
|
</BuildableReference>
|
||||||
</BuildActionEntry>
|
</BuildActionEntry>
|
||||||
</BuildActionEntries>
|
</BuildActionEntries>
|
||||||
|
|
@ -33,9 +33,9 @@
|
||||||
<BuildableReference
|
<BuildableReference
|
||||||
BuildableIdentifier = "primary"
|
BuildableIdentifier = "primary"
|
||||||
BlueprintIdentifier = "00E356ED1AD99517003FC87E"
|
BlueprintIdentifier = "00E356ED1AD99517003FC87E"
|
||||||
BuildableName = "testapplicationTests.xctest"
|
BuildableName = "TonesTests.xctest"
|
||||||
BlueprintName = "testapplicationTests"
|
BlueprintName = "TonesTests"
|
||||||
ReferencedContainer = "container:testapplication.xcodeproj">
|
ReferencedContainer = "container:Tones.xcodeproj">
|
||||||
</BuildableReference>
|
</BuildableReference>
|
||||||
</TestableReference>
|
</TestableReference>
|
||||||
</Testables>
|
</Testables>
|
||||||
|
|
@ -55,9 +55,9 @@
|
||||||
<BuildableReference
|
<BuildableReference
|
||||||
BuildableIdentifier = "primary"
|
BuildableIdentifier = "primary"
|
||||||
BlueprintIdentifier = "13B07F861A680F5B00A75B9A"
|
BlueprintIdentifier = "13B07F861A680F5B00A75B9A"
|
||||||
BuildableName = "testapplication.app"
|
BuildableName = "Tones.app"
|
||||||
BlueprintName = "testapplication"
|
BlueprintName = "Tones"
|
||||||
ReferencedContainer = "container:testapplication.xcodeproj">
|
ReferencedContainer = "container:Tones.xcodeproj">
|
||||||
</BuildableReference>
|
</BuildableReference>
|
||||||
</BuildableProductRunnable>
|
</BuildableProductRunnable>
|
||||||
</LaunchAction>
|
</LaunchAction>
|
||||||
|
|
@ -72,9 +72,9 @@
|
||||||
<BuildableReference
|
<BuildableReference
|
||||||
BuildableIdentifier = "primary"
|
BuildableIdentifier = "primary"
|
||||||
BlueprintIdentifier = "13B07F861A680F5B00A75B9A"
|
BlueprintIdentifier = "13B07F861A680F5B00A75B9A"
|
||||||
BuildableName = "testapplication.app"
|
BuildableName = "Tones.app"
|
||||||
BlueprintName = "testapplication"
|
BlueprintName = "Tones"
|
||||||
ReferencedContainer = "container:testapplication.xcodeproj">
|
ReferencedContainer = "container:Tones.xcodeproj">
|
||||||
</BuildableReference>
|
</BuildableReference>
|
||||||
</BuildableProductRunnable>
|
</BuildableProductRunnable>
|
||||||
</ProfileAction>
|
</ProfileAction>
|
||||||
|
|
@ -2,7 +2,7 @@
|
||||||
<Workspace
|
<Workspace
|
||||||
version = "1.0">
|
version = "1.0">
|
||||||
<FileRef
|
<FileRef
|
||||||
location = "group:testapplication.xcodeproj">
|
location = "group:Tones.xcodeproj">
|
||||||
</FileRef>
|
</FileRef>
|
||||||
<FileRef
|
<FileRef
|
||||||
location = "group:Pods/Pods.xcodeproj">
|
location = "group:Pods/Pods.xcodeproj">
|
||||||
32
ios/Tones/GoogleService-Info.plist
Normal file
|
|
@ -0,0 +1,32 @@
|
||||||
|
<?xml version="1.0" encoding="UTF-8"?>
|
||||||
|
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
|
||||||
|
<plist version="1.0">
|
||||||
|
<dict>
|
||||||
|
<key>API_KEY</key>
|
||||||
|
<string>AIzaSyClZkx4PFWhfIG3JDb6GD3g6Bl7-pWLNrU</string>
|
||||||
|
<key>GCM_SENDER_ID</key>
|
||||||
|
<string>917296693147</string>
|
||||||
|
<key>PLIST_VERSION</key>
|
||||||
|
<string>1</string>
|
||||||
|
<key>BUNDLE_ID</key>
|
||||||
|
<string>com.mattdimegs.tones</string>
|
||||||
|
<key>PROJECT_ID</key>
|
||||||
|
<string>tones-9f1d4</string>
|
||||||
|
<key>STORAGE_BUCKET</key>
|
||||||
|
<string>tones-9f1d4.firebasestorage.app</string>
|
||||||
|
<key>IS_ADS_ENABLED</key>
|
||||||
|
<false></false>
|
||||||
|
<key>IS_ANALYTICS_ENABLED</key>
|
||||||
|
<false></false>
|
||||||
|
<key>IS_APPINVITE_ENABLED</key>
|
||||||
|
<true></true>
|
||||||
|
<key>IS_GCM_ENABLED</key>
|
||||||
|
<true></true>
|
||||||
|
<key>IS_SIGNIN_ENABLED</key>
|
||||||
|
<true></true>
|
||||||
|
<key>GOOGLE_APP_ID</key>
|
||||||
|
<string>1:917296693147:ios:73d6d426aa60e52b35ab3e</string>
|
||||||
|
<key>DATABASE_URL</key>
|
||||||
|
<string>https://tones-9f1d4-default-rtdb.firebaseio.com</string>
|
||||||
|
</dict>
|
||||||
|
</plist>
|
||||||
|
After Width: | Height: | Size: 166 KiB |
|
|
@ -0,0 +1,20 @@
|
||||||
|
{
|
||||||
|
"colors": [
|
||||||
|
{
|
||||||
|
"color": {
|
||||||
|
"components": {
|
||||||
|
"alpha": "1.000",
|
||||||
|
"blue": "1.00000000000000",
|
||||||
|
"green": "1.00000000000000",
|
||||||
|
"red": "1.00000000000000"
|
||||||
|
},
|
||||||
|
"color-space": "srgb"
|
||||||
|
},
|
||||||
|
"idiom": "universal"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"info": {
|
||||||
|
"version": 1,
|
||||||
|
"author": "expo"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -7,10 +7,12 @@
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"idiom": "universal",
|
"idiom": "universal",
|
||||||
|
"filename": "image@2x.png",
|
||||||
"scale": "2x"
|
"scale": "2x"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"idiom": "universal",
|
"idiom": "universal",
|
||||||
|
"filename": "image@3x.png",
|
||||||
"scale": "3x"
|
"scale": "3x"
|
||||||
}
|
}
|
||||||
],
|
],
|
||||||
|
Before Width: | Height: | Size: 58 KiB After Width: | Height: | Size: 58 KiB |
|
Before Width: | Height: | Size: 58 KiB After Width: | Height: | Size: 58 KiB |
|
Before Width: | Height: | Size: 58 KiB After Width: | Height: | Size: 58 KiB |
|
|
@ -7,7 +7,7 @@
|
||||||
<key>CFBundleDevelopmentRegion</key>
|
<key>CFBundleDevelopmentRegion</key>
|
||||||
<string>$(DEVELOPMENT_LANGUAGE)</string>
|
<string>$(DEVELOPMENT_LANGUAGE)</string>
|
||||||
<key>CFBundleDisplayName</key>
|
<key>CFBundleDisplayName</key>
|
||||||
<string>test-application</string>
|
<string>Tones</string>
|
||||||
<key>CFBundleExecutable</key>
|
<key>CFBundleExecutable</key>
|
||||||
<string>$(EXECUTABLE_NAME)</string>
|
<string>$(EXECUTABLE_NAME)</string>
|
||||||
<key>CFBundleIdentifier</key>
|
<key>CFBundleIdentifier</key>
|
||||||
|
|
@ -19,7 +19,7 @@
|
||||||
<key>CFBundlePackageType</key>
|
<key>CFBundlePackageType</key>
|
||||||
<string>$(PRODUCT_BUNDLE_PACKAGE_TYPE)</string>
|
<string>$(PRODUCT_BUNDLE_PACKAGE_TYPE)</string>
|
||||||
<key>CFBundleShortVersionString</key>
|
<key>CFBundleShortVersionString</key>
|
||||||
<string>1.0.0</string>
|
<string>1.0.1</string>
|
||||||
<key>CFBundleSignature</key>
|
<key>CFBundleSignature</key>
|
||||||
<string>????</string>
|
<string>????</string>
|
||||||
<key>CFBundleURLTypes</key>
|
<key>CFBundleURLTypes</key>
|
||||||
|
|
@ -28,12 +28,14 @@
|
||||||
<key>CFBundleURLSchemes</key>
|
<key>CFBundleURLSchemes</key>
|
||||||
<array>
|
<array>
|
||||||
<string>myapp</string>
|
<string>myapp</string>
|
||||||
<string>com.anonymous.testapplication</string>
|
<string>com.mattdimegs.tones</string>
|
||||||
</array>
|
</array>
|
||||||
</dict>
|
</dict>
|
||||||
</array>
|
</array>
|
||||||
<key>CFBundleVersion</key>
|
<key>CFBundleVersion</key>
|
||||||
<string>1</string>
|
<string>1</string>
|
||||||
|
<key>LSMinimumSystemVersion</key>
|
||||||
|
<string>12.0</string>
|
||||||
<key>LSRequiresIPhoneOS</key>
|
<key>LSRequiresIPhoneOS</key>
|
||||||
<true/>
|
<true/>
|
||||||
<key>NSAppTransportSecurity</key>
|
<key>NSAppTransportSecurity</key>
|
||||||
|
|
@ -4,6 +4,16 @@
|
||||||
<dict>
|
<dict>
|
||||||
<key>NSPrivacyAccessedAPITypes</key>
|
<key>NSPrivacyAccessedAPITypes</key>
|
||||||
<array>
|
<array>
|
||||||
|
<dict>
|
||||||
|
<key>NSPrivacyAccessedAPIType</key>
|
||||||
|
<string>NSPrivacyAccessedAPICategoryFileTimestamp</string>
|
||||||
|
<key>NSPrivacyAccessedAPITypeReasons</key>
|
||||||
|
<array>
|
||||||
|
<string>C617.1</string>
|
||||||
|
<string>0A2A.1</string>
|
||||||
|
<string>3B52.1</string>
|
||||||
|
</array>
|
||||||
|
</dict>
|
||||||
<dict>
|
<dict>
|
||||||
<key>NSPrivacyAccessedAPIType</key>
|
<key>NSPrivacyAccessedAPIType</key>
|
||||||
<string>NSPrivacyAccessedAPICategoryUserDefaults</string>
|
<string>NSPrivacyAccessedAPICategoryUserDefaults</string>
|
||||||
|
|
@ -14,12 +24,10 @@
|
||||||
</dict>
|
</dict>
|
||||||
<dict>
|
<dict>
|
||||||
<key>NSPrivacyAccessedAPIType</key>
|
<key>NSPrivacyAccessedAPIType</key>
|
||||||
<string>NSPrivacyAccessedAPICategoryFileTimestamp</string>
|
<string>NSPrivacyAccessedAPICategorySystemBootTime</string>
|
||||||
<key>NSPrivacyAccessedAPITypeReasons</key>
|
<key>NSPrivacyAccessedAPITypeReasons</key>
|
||||||
<array>
|
<array>
|
||||||
<string>0A2A.1</string>
|
<string>35F9.1</string>
|
||||||
<string>3B52.1</string>
|
|
||||||
<string>C617.1</string>
|
|
||||||
</array>
|
</array>
|
||||||
</dict>
|
</dict>
|
||||||
<dict>
|
<dict>
|
||||||
|
|
@ -31,14 +39,6 @@
|
||||||
<string>85F4.1</string>
|
<string>85F4.1</string>
|
||||||
</array>
|
</array>
|
||||||
</dict>
|
</dict>
|
||||||
<dict>
|
|
||||||
<key>NSPrivacyAccessedAPIType</key>
|
|
||||||
<string>NSPrivacyAccessedAPICategorySystemBootTime</string>
|
|
||||||
<key>NSPrivacyAccessedAPITypeReasons</key>
|
|
||||||
<array>
|
|
||||||
<string>35F9.1</string>
|
|
||||||
</array>
|
|
||||||
</dict>
|
|
||||||
</array>
|
</array>
|
||||||
<key>NSPrivacyCollectedDataTypes</key>
|
<key>NSPrivacyCollectedDataTypes</key>
|
||||||
<array/>
|
<array/>
|
||||||