Compare commits

..

4 commits

Author SHA1 Message Date
96420d340d Update .github/workflows/pr-validation.yml 2026-03-26 14:31:50 +00:00
d4293d975d Merge pull request 'Configure Renovate' (#28) from renovate/configure into main
Reviewed-on: #28
2026-03-26 14:28:53 +00:00
Renovate Bot
24e242b18a Add renovate.json
Some checks are pending
PR Validation / pr-validation (pull_request) Waiting to run
2026-03-26 05:01:24 +00:00
598d749dbc Fix Vulnerabilities 2025-12-01 23:08:31 -05:00
115 changed files with 9653 additions and 7501 deletions

View file

@ -11,7 +11,7 @@ jobs:
permissions: permissions:
contents: read contents: read
pull-requests: write pull-requests: write
runs-on: ['self-hosted', 'pi'] runs-on: ['nas', 'pi']
steps: steps:
- uses: TimonVS/pr-labeler-action@v5 - uses: TimonVS/pr-labeler-action@v5
with: with:

View file

@ -1,32 +0,0 @@
<?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>

View file

@ -1,30 +0,0 @@
{
"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"
}

View file

@ -14,19 +14,18 @@ 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
@ -58,9 +57,6 @@ 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()
} }
/** /**
@ -79,7 +75,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 = 'io.github.react-native-community:jsc-android:2026004.+' def jscFlavor = 'org.webkit:android-jsc:+'
android { android {
ndkVersion rootProject.ext.ndkVersion ndkVersion rootProject.ext.ndkVersion
@ -87,13 +83,13 @@ android {
buildToolsVersion rootProject.ext.buildToolsVersion buildToolsVersion rootProject.ext.buildToolsVersion
compileSdk rootProject.ext.compileSdkVersion compileSdk rootProject.ext.compileSdkVersion
namespace 'com.mattdimegs.tones' namespace 'com.anonymous.testapplication'
defaultConfig { defaultConfig {
applicationId 'com.mattdimegs.tones' applicationId 'com.anonymous.testapplication'
minSdkVersion rootProject.ext.minSdkVersion minSdkVersion rootProject.ext.minSdkVersion
targetSdkVersion rootProject.ext.targetSdkVersion targetSdkVersion rootProject.ext.targetSdkVersion
versionCode 1 versionCode 1
versionName "1.0.1" versionName "1.0.0"
} }
signingConfigs { signingConfigs {
debug { debug {
@ -114,7 +110,6 @@ 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 {
@ -122,9 +117,6 @@ 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`
@ -157,15 +149,15 @@ dependencies {
if (isGifEnabled) { if (isGifEnabled) {
// For animated gif support // For animated gif support
implementation("com.facebook.fresco:animated-gif:${expoLibs.versions.fresco.get()}") implementation("com.facebook.fresco:animated-gif:${reactAndroidLibs.versions.fresco.get()}")
} }
if (isWebpEnabled) { if (isWebpEnabled) {
// For webp support // For webp support
implementation("com.facebook.fresco:webpsupport:${expoLibs.versions.fresco.get()}") implementation("com.facebook.fresco:webpsupport:${reactAndroidLibs.versions.fresco.get()}")
if (isWebpAnimatedEnabled) { if (isWebpAnimatedEnabled) {
// Animated webp support // Animated webp support
implementation("com.facebook.fresco:animated-webp:${expoLibs.versions.fresco.get()}") implementation("com.facebook.fresco:animated-webp:${reactAndroidLibs.versions.fresco.get()}")
} }
} }
@ -176,4 +168,5 @@ dependencies {
} }
} }
apply plugin: 'com.google.gms.google-services' 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");
applyNativeModulesAppBuildGradle(project)

View file

@ -1,30 +0,0 @@
{
"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"
}

View file

@ -3,7 +3,5 @@
<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>

View file

@ -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" android:supportsRtl="true"> <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">
<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,7 +25,9 @@
<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>

View file

@ -1,5 +1,4 @@
package com.mattdimegs.tones package com.anonymous.testapplication
import expo.modules.splashscreen.SplashScreenManager
import android.os.Build import android.os.Build
import android.os.Bundle import android.os.Bundle
@ -16,10 +15,7 @@ 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)
} }

View file

@ -1,4 +1,4 @@
package com.mattdimegs.tones package com.anonymous.testapplication
import android.app.Application import android.app.Application
import android.content.res.Configuration import android.content.res.Configuration
@ -10,7 +10,6 @@ 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
@ -22,10 +21,9 @@ 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(MyReactNativePackage()) // packages.add(new MyReactNativePackage());
return packages return PackageList(this).packages
} }
override fun getJSMainModuleName(): String = ".expo/.virtual-metro-entry" override fun getJSMainModuleName(): String = ".expo/.virtual-metro-entry"
@ -42,7 +40,7 @@ class MainApplication : Application(), ReactApplication {
override fun onCreate() { override fun onCreate() {
super.onCreate() super.onCreate()
SoLoader.init(this, OpenSourceMergedSoMapping) SoLoader.init(this, false)
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()

View file

Before

Width:  |  Height:  |  Size: 58 KiB

After

Width:  |  Height:  |  Size: 58 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 5 KiB

View file

Before

Width:  |  Height:  |  Size: 58 KiB

After

Width:  |  Height:  |  Size: 58 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 3 KiB

View file

Before

Width:  |  Height:  |  Size: 58 KiB

After

Width:  |  Height:  |  Size: 58 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 7.2 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 58 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 12 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 58 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 19 KiB

View file

@ -1,6 +1,3 @@
<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>

Binary file not shown.

After

Width:  |  Height:  |  Size: 8.2 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 3.2 KiB

View file

Before

Width:  |  Height:  |  Size: 7.8 KiB

After

Width:  |  Height:  |  Size: 7.8 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 10 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 4 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 5.1 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 2 KiB

View file

Before

Width:  |  Height:  |  Size: 5 KiB

After

Width:  |  Height:  |  Size: 5 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 6.4 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 2.6 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 11 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 4.4 KiB

View file

Before

Width:  |  Height:  |  Size: 11 KiB

After

Width:  |  Height:  |  Size: 11 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 14 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 5.5 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 18 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 7.2 KiB

View file

Before

Width:  |  Height:  |  Size: 18 KiB

After

Width:  |  Height:  |  Size: 18 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 22 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 8.9 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 25 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 9.9 KiB

View file

Before

Width:  |  Height:  |  Size: 24 KiB

After

Width:  |  Height:  |  Size: 24 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 30 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 12 KiB

View file

@ -1,5 +1,5 @@
<resources> <resources>
<string name="app_name">Tones</string> <string name="app_name">test-application</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>

View file

@ -1,13 +1,17 @@
<resources xmlns:tools="http://schemas.android.com/tools"> <resources xmlns:tools="http://schemas.android.com/tools">
<style name="AppTheme" parent="Theme.AppCompat.DayNight.NoActionBar"> <style name="AppTheme" parent="Theme.AppCompat.Light.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="Theme.App.SplashScreen" parent="Theme.SplashScreen"> <style name="ResetEditText" parent="@android:style/Widget.EditText">
<item name="windowSplashScreenBackground">@color/splashscreen_background</item> <item name="android:padding">0dp</item>
<item name="windowSplashScreenAnimatedIcon">@drawable/splashscreen_logo</item> <item name="android:textColorHint">#c8c8c8</item>
<item name="postSplashScreenTheme">@style/AppTheme</item> <item name="android:textColor">@android:color/black</item>
</style>
<style name="Theme.App.SplashScreen" parent="AppTheme">
<item name="android:windowBackground">@drawable/splashscreen</item>
</style> </style>
</resources> </resources>

View file

@ -1,38 +1,41 @@
// 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 {
repositories { ext {
google() buildToolsVersion = findProperty('android.buildToolsVersion') ?: '34.0.0'
mavenCentral() minSdkVersion = Integer.parseInt(findProperty('android.minSdkVersion') ?: '23')
} compileSdkVersion = Integer.parseInt(findProperty('android.compileSdkVersion') ?: '34')
dependencies { targetSdkVersion = Integer.parseInt(findProperty('android.targetSdkVersion') ?: '34')
classpath 'com.google.gms:google-services:4.4.1' kotlinVersion = findProperty('android.kotlinVersion') ?: '1.9.23'
classpath('com.android.tools.build:gradle')
classpath('com.facebook.react:react-native-gradle-plugin') ndkVersion = "26.1.10909125"
classpath('org.jetbrains.kotlin:kotlin-gradle-plugin') }
} repositories {
google()
mavenCentral()
}
dependencies {
classpath('com.android.tools.build:gradle')
classpath('com.facebook.react:react-native-gradle-plugin')
classpath('org.jetbrains.kotlin:kotlin-gradle-plugin')
}
} }
def reactNativeAndroidDir = new File( apply plugin: "com.facebook.react.rootproject"
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(reactNativeAndroidDir) url(new File(['node', '--print', "require.resolve('react-native/package.json')"].execute(null, rootDir).text.trim(), '../android'))
}
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()
mavenCentral()
maven { url 'https://www.jitpack.io' }
} }
google()
mavenCentral()
maven { url 'https://www.jitpack.io' }
}
} }
apply plugin: "expo-root-project"
apply plugin: "com.facebook.react.rootproject"

View file

@ -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
# Enable AAPT2 PNG crunching # Automatically convert third-party libraries to use AndroidX
android.enablePngCrunchInReleaseBuilds=true android.enableJetifier=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=true newArchEnabled=false
# 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,6 +54,3 @@ 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

Binary file not shown.

View file

@ -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.13-bin.zip distributionUrl=https\://services.gradle.org/distributions/gradle-8.6-all.zip
networkTimeout=10000 networkTimeout=10000
validateDistributionUrl=true validateDistributionUrl=true
zipStoreBase=GRADLE_USER_HOME zipStoreBase=GRADLE_USER_HOME

6
android/gradlew vendored Normal file → Executable file
View file

@ -15,8 +15,6 @@
# 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
#
############################################################################## ##############################################################################
# #
@ -57,7 +55,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/platforms/jvm/plugins-application/src/main/resources/org/gradle/api/internal/plugins/unixStartScript.txt # https://github.com/gradle/gradle/blob/HEAD/subprojects/plugins/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/.
@ -86,7 +84,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 -P "${APP_HOME:-./}" > /dev/null && printf '%s\n' "$PWD" ) || exit APP_HOME=$( cd "${APP_HOME:-./}" > /dev/null && pwd -P ) || 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
View file

@ -13,8 +13,6 @@
@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 ##########################################################################

View file

@ -1,39 +1,18 @@
pluginManagement { rootProject.name = 'test-application'
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)
def expoPluginsPath = new File( dependencyResolutionManagement {
providers.exec { versionCatalogs {
workingDir(rootDir) reactAndroidLibs {
commandLine("node", "--print", "require.resolve('expo-modules-autolinking/package.json', { paths: [require.resolve('expo/package.json')] })") from(files(new File(["node", "--print", "require.resolve('react-native/package.json')"].execute(null, rootDir).text.trim(), "../gradle/libs.versions.toml")))
}.standardOutput.asText.get().trim(), }
"../android/expo-gradle-plugin"
).absolutePath
includeBuild(expoPluginsPath)
}
plugins {
id("com.facebook.react.settings")
id("expo-autolinking-settings")
}
extensions.configure(com.facebook.react.ReactSettingsExtension) { ex ->
if (System.getenv('EXPO_USE_COMMUNITY_AUTOLINKING') == '1') {
ex.autolinkLibrariesFromCommand()
} else {
ex.autolinkLibrariesFromCommand(expoAutolinking.rnConfigCommand)
} }
} }
expoAutolinking.useExpoModules()
rootProject.name = 'Tones' apply from: new File(["node", "--print", "require.resolve('expo/package.json')"].execute(null, rootDir).text.trim(), "../scripts/autolinking.gradle");
useExpoModules()
expoAutolinking.useExpoVersionCatalog() 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");
applyNativeModulesSettingsGradle(settings)
include ':app' include ':app'
includeBuild(expoAutolinking.reactNativeGradlePlugin) 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())

View file

@ -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,40 +13,22 @@
"backgroundColor": "#ffffff" "backgroundColor": "#ffffff"
}, },
"ios": { "ios": {
"entitlements": {
"aps-environment": "production"
},
"infoPlist": {
"UIBackgroundModes": ["remote-notification"]
},
"supportsTablet": true, "supportsTablet": true,
"bundleIdentifier": "com.mattdimegs.tones", "bundleIdentifier": "com.anonymous.testapplication"
"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.mattdimegs.tones", "package": "com.anonymous.testapplication"
"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"
} }
} }

View file

@ -1,72 +0,0 @@
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>
);
}

26
app/_layout.tsx Normal file
View file

@ -0,0 +1,26 @@
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>
);
}

File diff suppressed because it is too large Load diff

View file

@ -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>

View file

@ -1,421 +1,366 @@
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"; import { useCallFeed } from '../hooks/useCallFeed';
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 {
Platform, PageHeader,
Linking, PageFooter,
View, } from '../components/generalHelpers.jsx';
ScrollView, import { Ionicons } from '@expo/vector-icons';
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();
const { const {
departments, departments,
callIconMap, callIconMap,
callDetails, callDetails,
callColorSelector, callColorSelector,
formatCallTimePast, formatCallTimePast,
formatCallDateTime, formatCallDateTime
} = callFeed; } = callFeed;
const sortedAndFilteredCalls = const sortedAndFilteredCalls = callDetails
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,
accountDetails, accountDetails,
deptList, deptList,
setDeptList, setDeptList,
selectedDepartment, selectedDepartment,
setSelectedDepartment, setSelectedDepartment,
updateSelectedDepartment, updateSelectedDepartment,
selectedDepartmentColorPicker, selectedDepartmentColorPicker,
} = departments; } = departments;
return ( return (
<React.Fragment> <React.Fragment>
<PageHeader <PageHeader>
centerHeader={ <View
<View style={{ flex: 1, alignItems: "center" }}>
<TouchableOpacity
style={{
borderRadius: 6,
elevation: 3,
backgroundColor: "#fff",
shadowOffset: { width: 0, height: 0 },
shadowColor: "#333",
shadowOpacity: 0.8,
shadowRadius: 2,
paddingHorizontal: 10,
paddingVertical: 2,
}}
onPress={() => {
actionSheetRef.current?.show();
}}
>
<Text
style={{
color: selectedDepartmentColorPicker(
selectedDepartment?.type
),
fontWeight: 600,
fontSize: 14,
}}
>
{selectedDepartment?.deptAbv}
</Text>
</TouchableOpacity>
</View>
}
/>
<ScrollView>
<StatusBar style="dark" />
<SafeAreaView />
<View style={{ flexDirection: "column", padding: 20 }}>
{sortedAndFilteredCalls?.length ? (
sortedAndFilteredCalls?.map((callItem, index) => {
const { incident, address, response, timestamp } = callItem;
const {
serviceNumber,
incDate,
incNature,
incNatureCode,
incNatureCodeDesc,
status,
} = incident;
const {
streetAddress,
addressApartment,
town,
state,
locationName,
} = address;
const { serviceName } = response;
const SelectedIcon =
callIconMap[incNature] || AccidentAndEmergency;
return (
<TouchableOpacity
key={`callDetails - ${timestamp}`}
style={{ paddingBottom: 15 }}
onPress={() => {
router.push({
pathname: "/call",
params: {
callDetails: toBase64Unicode(JSON.stringify(callItem)),
},
});
}}
>
<View
style={{ style={{
borderRadius: 12, flexDirection: 'column',
elevation: 3, height: 80,
backgroundColor: "#fff", alignItems: 'center',
shadowOffset: { width: 0, height: 0 }, justifyContent: 'flex-end',
shadowColor: callColorSelector( paddingBottom: 7
incNatureCodeDesc,
incNature,
status
),
shadowOpacity: 1,
shadowRadius: 5,
padding: 10,
}} }}
>
<View style={{ flexDirection: "column" }}>
<View
key="callDateAndTime"
style={{
paddingBottom: 6,
flexDirection: "row",
justifyContent: "space-between",
}}
>
<Text style={{ fontSize: 12 }}>
{formatCallDateTime(incDate)}
</Text>
<View
style={{ flexDirection: "row", alignItems: "center" }}
>
<Text style={{ fontSize: 12 }}>
{formatCallTimePast(incDate)}
</Text>
{status === "CLOSED" ? (
<Ionicons
name="lock-closed-outline"
color="red"
style={{
shadowColor: "black",
shadowOffset: 0,
shadowOpacity: 1,
shadowRadius: 10,
}}
/>
) : null}
</View>
</View>
<View
style={{ flexDirection: "row", alignItems: "center" }}
>
<SelectedIcon
color={callColorSelector(
incNatureCodeDesc,
incNature,
status
)}
opacity={0.3}
width={56}
height={56}
/>
<View
style={{
flex: 1,
flexDirection: "column",
alignItems: "flex-start",
paddingHorizontal: 2,
maxWidth: "80%",
}}
>
{locationName ? (
<Text
style={{
color: "black",
fontWeight: 600,
fontSize: 16,
}}
>
{`${locationName}`}
</Text>
) : (
<View style={{ flexDirection: "row" }}>
<Text
style={[
{
color: "black",
fontSize: 12,
fontWeight: 600,
},
]}
>
{`${streetAddress?.split(",")[0]}`}
</Text>
{addressApartment ? (
<Text
style={[
{
color: "black",
fontSize: 12,
fontWeight: 600,
},
]}
>
{` - ${addressApartment}`}
</Text>
) : null}
<Text
style={[
{
color: "black",
fontSize: 12,
fontWeight: 600,
},
]}
>
{` ${town}, ${state}`}
</Text>
</View>
)}
<Text
style={{
color: "black",
fontWeight: 600,
fontSize: 16,
}}
>
{`${incNature}`}
</Text>
<View
style={{
flexDirection: "row",
justifyContent: "space-between",
}}
>
<Text
style={{
color: "black",
fontSize: 12,
textShadowColor: callColorSelector(
incNatureCode,
incNature,
status
),
textShadowRadius: 1,
}}
>
{`${incNatureCodeDesc}`}
</Text>
</View>
</View>
<View style={{ padding: 0 }}>
<View>
<Ionicons name="chevron-forward-outline" />
</View>
</View>
</View>
<View
style={{
paddingTop: 5,
flexDirection: "row",
justifyContent: "space-between",
}}
>
<Text
style={{
fontSize: 12,
}}
>
Service: {serviceName}
</Text>
<Text
style={{
fontSize: 12,
textAlign: "right",
}}
>
{`Incident #: ${serviceNumber}`}
</Text>
</View>
</View>
</View>
</TouchableOpacity>
);
})
) : (
<Text>There are no Calls</Text>
)}
</View>
</ScrollView>
<PageFooter>
<View
style={{
flexDirection: "column",
height: 100,
alignItems: "center",
justifyContent: "flex-start",
paddingTop: 7,
}}
/>
</PageFooter>
<DepartmentActionSheet
ref={actionSheetRef}
gestureEnabled
containerStyle={{
height: "50%",
width: "100%",
backgroundColor: "#ECEDEE",
}}
>
<View style={{ flexDirection: "column", padding: 20 }}>
{deptList?.map((item) => {
return (
<View style={{ padding: 2 }} key={item?.deptId}>
<TouchableOpacity
style={{
borderRadius: 6,
elevation: 3,
backgroundColor: item?.selected ? "grey" : "#fff",
shadowOffset: { width: 1, height: 1 },
shadowColor: "#333",
shadowOpacity: 0.3,
shadowRadius: 2,
marginHorizontal: 20,
marginVertical: 6,
padding: 10,
}}
onPress={() => {
actionSheetRef.current?.hide();
return updateSelectedDepartment(
selectedDepartment?.deptId,
item?.deptId
);
}}
> >
<View <TouchableOpacity
style={{ style={{
flexDirection: "row", borderRadius: 6,
justifyContent: "space-between", elevation: 3,
}} backgroundColor: '#fff',
> shadowOffset: { width: 0, height: 0 },
<Text shadowColor: '#333',
style={{ shadowOpacity: .8,
color: selectedDepartmentColorPicker(item?.type), shadowRadius: 2,
fontWeight: 600, paddingHorizontal: 10,
fontSize: 16, paddingVertical: 2,
}} }}
onPress={() => {
actionSheetRef.current?.show();
}}
> >
{item?.dept} <Text
</Text> style={{
{item?.primary ? ( color: selectedDepartmentColorPicker(selectedDepartment?.type),
<Ionicons fontWeight: 600,
name="star" fontSize: 14
size={16} }}
color="yellow" >
style={{ {selectedDepartment?.deptAbv}
paddingLeft: 20, </Text>
shadowColor: "#333", </TouchableOpacity>
shadowOffset: 1, </View>
shadowOpacity: 1, </PageHeader>
shadowRadius: 6, <ScrollView>
}} <StatusBar style="dark" />
/> <SafeAreaView />
) : null} <View style={{ flexDirection: 'column', padding: 20 }}>
</View> {sortedAndFilteredCalls?.length ? (
<Text>{`${item?.deptAbv} - ${ sortedAndFilteredCalls?.map((callItem, index) => {
departmentTypeMap[item?.type] const { data: call, timestamp } = callItem;
}`}</Text> const { Incident, Address, Response } = call;
</TouchableOpacity> const {
</View> ServiceNumber,
); IncDate,
})} IncNature,
</View> IncNatureCode,
</DepartmentActionSheet> IncNatureCodeDesc,
</React.Fragment> Status,
); } = Incident;
const {
StreetAddress,
AddressApartment,
Town,
State,
LocationName,
} = Address;
const {
ServiceName
} = Response;
const SelectedIcon = callIconMap[IncNature] || AccidentAndEmergency;
return (
<TouchableOpacity
key={`callDetails - ${timestamp}`}
style={{ padding: 2 }}
onPress={() => {
router.push({
pathname: '/call',
params: {
callDetails: btoa(JSON.stringify(call))
}
})
}}
>
<View
style={{
borderRadius: 12,
elevation: 3,
backgroundColor: '#fff',
shadowOffset: { width: 0, height: 0 },
shadowColor: callColorSelector(
IncNatureCode,
IncNature,
Status
),
shadowOpacity: 1,
shadowRadius: 5,
padding: 10,
}}
>
<View style={{ flexDirection: 'column' }}>
<View key="callDateAndTime"
style={{
paddingBottom: 6,
flexDirection: 'row',
justifyContent: 'space-between'
}}
>
<Text style={{ fontSize: 12 }}>{formatCallDateTime(IncDate)}</Text>
<View style={{ flexDirection: 'row', alignItems: 'center' }}>
<Text style={{ fontSize: 12 }}>{formatCallTimePast(IncDate)}</Text>
{Status === 'CLOSED' ? (
<Ionicons
name="lock-closed-outline"
color='red'
style={{
shadowColor: 'black',
shadowOffset: 0,
shadowOpacity: 1,
shadowRadius: 10
}}
/>
) : null}
</View>
</View>
<View style={{ flexDirection: 'row', alignItems: 'center', justifyContent: 'space-between' }}>
<SelectedIcon
color={callColorSelector(
IncNatureCode,
IncNature,
Status
)}
opacity={0.3}
width={56}
height={56}
/>
<View style={{ flexDirection: 'column' }}>
{LocationName ? (
<Text
style={{
color: 'black',
fontWeight: 600,
fontSize: 16
}}
>
{`${LocationName}`}
</Text>
) : (
<View style={{ flexDirection: 'row' }}>
<Text
style={[{
color: 'black',
fontSize: 12,
fontWeight: 600
}]}
>
{`${StreetAddress}`}
</Text>
{AddressApartment ? (
<Text
style={[{
color: 'black',
fontSize: 12,
fontWeight: 600
}]}
>
{` - ${AddressApartment}`}
</Text>
) : null }
<Text
style={[{
color: 'black',
fontSize: 12,
fontWeight: 600
}]}
>
{` ${Town}, ${State}`}
</Text>
</View>
)}
<Text
style={{
color: 'black',
fontWeight: 600,
fontSize: 16
}}
>
{`${IncNature}`}
</Text>
<View style={{ flexDirection: 'row', justifyContent: 'space-between' }}>
<Text
style={{
color: 'black',
fontSize: 12,
textShadowColor: callColorSelector(
IncNatureCode,
IncNature,
Status
),
textShadowRadius: 1
}}
>
{`${IncNatureCodeDesc}`}
</Text>
</View>
</View>
<View style={{ padding: 0 }}>
<View>
<Ionicons name="chevron-forward-outline" />
</View>
</View>
</View>
<View style={{ flexDirection: 'row', justifyContent: 'space-between' }}>
<Text
style={{
fontSize: 12,
}}
>
Service: {ServiceName}
</Text>
<Text
style={{
fontSize: 12,
textAlign: 'right'
}}
>
{`Incident #: ${ServiceNumber}`}
</Text>
</View>
</View>
</View>
</TouchableOpacity>
)
})) : (
<View style={{
marginTop: '50%',
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>
</ScrollView>
<PageFooter>
<View
style={{
flexDirection: 'column',
height: 100,
alignItems: 'center',
justifyContent: 'flex-start',
paddingTop: 7
}}
/>
</PageFooter>
<DepartmentActionSheet
ref={actionSheetRef}
gestureEnabled
containerStyle={{
height: "50%",
width: "100%",
backgroundColor: '#ECEDEE',
}}
>
<View style={{ flexDirection: 'column', padding: 20 }}>
{deptList?.map((item) => {
return (
<View style={{ padding: 2 }} key={item?.deptId}>
<TouchableOpacity
style={{
borderRadius: 6,
elevation: 3,
backgroundColor: item?.selected ? 'grey' : '#fff',
shadowOffset: { width: 1, height: 1 },
shadowColor: '#333',
shadowOpacity: 0.3,
shadowRadius: 2,
marginHorizontal: 20,
marginVertical: 6,
padding: 10
}}
onPress={() => {
actionSheetRef.current?.hide();
return updateSelectedDepartment(
selectedDepartment?.deptId,
item?.deptId
)
}}
>
<View style={{ flexDirection: 'row', justifyContent: 'space-between' }}>
<Text
style={{
color: selectedDepartmentColorPicker(
item?.type
),
fontWeight: 600,
fontSize: 16
}}
>
{item?.dept}
</Text>
{item?.primary ? <Ionicons name="star" size={16} color="yellow" style={{
paddingLeft: 20,
shadowColor: '#333',
shadowOffset: 1,
shadowOpacity: 1,
shadowRadius: 6
}} /> : null}
</View>
<Text>{`${item?.deptAbv} - ${departmentTypeMap[item?.type]}`}</Text>
</TouchableOpacity>
</View>
);
})}
</View>
</DepartmentActionSheet>
</React.Fragment>
)
} }

View file

@ -1,5 +1,5 @@
import React, { useState, useEffect } from 'react'; import React, { useState, useEffect } from 'react';
import { View, Text, ScrollView, KeyboardAvoidingView, Platform } from 'react-native'; import { View, Text } 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,123 +20,111 @@ 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 [error, setError] = useState(''); const [auth, setAuth] = useState(false);
const [loading, setLoading] = useState(false);
const { expoPushToken } = useNotifications();
const formik = useFormik({ const formik = useFormik({
initialValues: { initialValues: {
email: '', number: '',
password: '' password: ''
}, },
onSubmit: async (values) => { onSubmit: (values) => {
setError(''); values.number = values.number.replace(/[()\-\s]/g, '');
setLoading(true); console.log(values);
try { setAuth(true);
await signInWithEmailAndPassword(auth, values.email, values.password); },
});
const formValues = formik.values;
useEffect(() => {
if (formValues) {
if (formValues.number.length === 14 && formValues.password) {
setLoginButtonDisabled(false);
} else {
setLoginButtonDisabled(true);
}
}
}, [formValues])
useEffect(() => {
// Temp for Testing
// if (!auth) {
// setTimeout(() => {
// router.replace('./incidents');
// }, 1000);
// }
if (auth) {
router.replace('./incidents'); router.replace('./incidents');
} catch (err) {
setError(err.message);
} finally {
setLoading(false);
} }
}, }, [auth])
});
const formValues = formik.values; return (
<React.Fragment>
useEffect(() => { <PageHeader>
if (formValues) { <View style={{ flexDirection: 'row', height: 80, alignItems: 'center' }} />
if (formValues.email && formValues.password) { </PageHeader>
setLoginButtonDisabled(false); <StyledContainer>
} else { <StatusBar style="dark" />
setLoginButtonDisabled(true); <SafeAreaView />
} <InnerContainer>
} <PageImage resizeMode="cover" source={require('./../assets/images/tones-logo.png')} />
}, [formValues]); <Title>Tones</Title>
<SubTitle>Account Login</SubTitle>
return ( <StyledFormArea>
<View style={{ flex: 1 }}> <LoginTextInput
<StatusBar style="dark" /> label="Phone Number"
<PageHeader> icon="call-outline"
<View style={{ flexDirection: 'row', height: 80, alignItems: 'center' }} /> placeholder="123-456-7890"
</PageHeader> placeholderTextColor="gray"
<KeyboardAvoidingView onChangeText={formik.handleChange('number')}
style={{ flex: 1 }} onBlur={formik.handleBlur('number')}
behavior={Platform.OS === 'ios' ? 'padding' : 'height'} value={formik.values.number.replace(/^(\d{3})(\d{3})(\d+)$/, "($1) $2-$3")}
keyboardVerticalOffset={0} keyboardType="number-pad"
> maxLength={14}
<ScrollView keyboardShouldPersistTaps="handled" contentContainerStyle={{ flexGrow: 1 }}> />
<StyledContainer> <LoginTextInput
<SafeAreaView /> label="Password"
<InnerContainer> icon="lock-closed-outline"
<PageImage resizeMode="cover" source={require('./../assets/images/tones-logo.png')} /> placeholder="* * * * * *"
<Title>Tones</Title> placeholderTextColor="gray"
<SubTitle>Account Login</SubTitle> onChangeText={formik.handleChange('password')}
<StyledFormArea> onBlur={formik.handleBlur('password')}
{error ? <MessageBox style={{ color: 'red' }}>{error}</MessageBox> : null} value={formik.values.password}
<LoginTextInput secureTextEntry={hidePassword}
label="Email Address" isPassword
icon="mail-outline" hidePassword={hidePassword}
placeholder="test@organization.com" setHidePassword={setHidePassword}
placeholderTextColor="gray" />
onChangeText={formik.handleChange('email')} <MessageBox>...</MessageBox>
onBlur={formik.handleBlur('email')} <StyledButton onPress={formik.handleSubmit} disabled={loginButtonDisabled} style={loginButtonDisabled ? {backgroundColor: 'grey'} : {}}>
value={formik.values.email} <ButtonText>Login</ButtonText>
keyboardType="email-address" </StyledButton>
autoComplete='email'
autoCapitalize='none'
/>
<LoginTextInput
label="Password"
icon="lock-closed-outline"
placeholder="* * * * * *"
placeholderTextColor="gray"
onChangeText={formik.handleChange('password')}
onBlur={formik.handleBlur('password')}
value={formik.values.password}
secureTextEntry={hidePassword}
isPassword
hidePassword={hidePassword}
setHidePassword={setHidePassword}
/>
<MessageBox>...</MessageBox>
<StyledButton onPress={formik.handleSubmit} disabled={loginButtonDisabled} style={loginButtonDisabled ? { backgroundColor: 'grey' } : {}}>
<ButtonText>Login</ButtonText>
</StyledButton>
<Line />
<ExtraView>
<ExtraText>Don't have an account already? </ExtraText>
<Link href='./register'>
<TextLinkContent>Register</TextLinkContent>
</Link>
</ExtraView>
</StyledFormArea>
<Line /> <Line />
<Text>Temporary Area:</Text> <ExtraView>
<View> <ExtraText>Don't have an account already? </ExtraText>
<Link href='./incidents'> <Link href='./register'>
<TextLinkContent>Incidents</TextLinkContent> <TextLinkContent>Register</TextLinkContent>
</Link> </Link>
<Link href='./landing'> </ExtraView>
<TextLinkContent>Landing</TextLinkContent> </StyledFormArea>
</Link> <Line />
</View> <Text>Temporary Area:</Text>
<Text>View Token: {expoPushToken}</Text> <View>
<Line /> <Link href='./incidents'>
</InnerContainer> <TextLinkContent>Incidents</TextLinkContent>
</StyledContainer> </Link>
</ScrollView> <Link href='./landing'>
</KeyboardAvoidingView> <TextLinkContent>Landing</TextLinkContent>
</View> </Link>
); </View>
} <Line />
</InnerContainer>
</StyledContainer>
</React.Fragment>
);
}

View file

@ -1,10 +1,6 @@
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 { createUserWithEmailAndPassword, updateProfile } from 'firebase/auth'; import { View, ScrollView, Text, TouchableOpacity } from 'react-native';
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';
@ -23,16 +19,14 @@ import {
MessageBox, MessageBox,
LoginTextInput, LoginTextInput,
RegisterDropdownInput, RegisterDropdownInput,
formatPhoneNumber } from '../components/generalHelpers.jsx';
} 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: {
@ -44,60 +38,9 @@ export default function Register() {
password: '', password: '',
passwordConfirmation: '' passwordConfirmation: ''
}, },
onSubmit: async (values) => { onSubmit: (values) => {
setError(''); values.number = values.number.replace(/[()\-\s]/g, '');
setLoading(true); console.log(values);
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);
}
} }
}); });
@ -105,8 +48,7 @@ export default function Register() {
useEffect(() => { useEffect(() => {
if (formValues) { if (formValues) {
const regex = /^[^@]+@(?:[a-zA-Z0-9-]+\.)+[a-zA-Z0-9-]+$/; if ((formValues.number.length === 14 || (formValues.number.length === 10 && !formValues.number.includes('('))) && formValues.email && formValues.firstName && formValues.lastName) {
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 {
@ -120,121 +62,106 @@ export default function Register() {
} }
}, [formValues]) }, [formValues])
useEffect(() => {
if (user) {
router.replace('./incidents');
}
}, [user]);
return ( return (
<View style={{ flex: 1 }}> <View>
<StatusBar style="dark" /> <PageHeader>
<PageHeader <View style={{ flexDirection: 'row', height: 80, alignItems: 'flex-end' }}>
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>
<KeyboardAvoidingView </PageHeader>
style={{ flex: 1 }} <ScrollView>
behavior={Platform.OS === 'ios' ? 'padding' : 'height'} <StyledContainer>
keyboardVerticalOffset={0} <StatusBar style="dark" />
>
<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')} /> <Title>Tones</Title>
{error ? <MessageBox style={{ color: 'red' }}>{error}</MessageBox> : null} <SubTitle>Account Register</SubTitle>
<Title>Tones</Title> <StyledFormArea>
<SubTitle>Account Register</SubTitle> <LoginTextInput
<StyledFormArea> label="First Name"
<LoginTextInput icon="person-outline"
label="First Name" placeholder="Bud"
icon="person-outline" placeholderTextColor="gray"
placeholder="Bud" onChangeText={formik.handleChange('firstName')}
placeholderTextColor="gray" onBlur={formik.handleBlur('firstName')}
onChangeText={formik.handleChange('firstName')} value={formik.values.firstName}
onBlur={formik.handleBlur('firstName')} />
value={formik.values.firstName} <LoginTextInput
/> label="Last Name"
<LoginTextInput icon="people-outline"
label="Last Name" placeholder="Doble"
icon="people-outline" placeholderTextColor="gray"
placeholder="Doble" onChangeText={formik.handleChange('lastName')}
placeholderTextColor="gray" onBlur={formik.handleBlur('lastName')}
onChangeText={formik.handleChange('lastName')} value={formik.values.lastName}
onBlur={formik.handleBlur('lastName')} />
value={formik.values.lastName} <LoginTextInput
/> label="Phone Number"
<LoginTextInput icon="call-outline"
label="Phone Number" placeholder="123-456-7890"
icon="call-outline" placeholderTextColor="gray"
placeholder="123-456-7890" onChangeText={formik.handleChange('number')}
placeholderTextColor="gray" onBlur={formik.handleBlur('number')}
onChangeText={formik.handleChange('number')} value={formik.values.number.replace(/^(\d{3})(\d{3})(\d+)$/, "($1) $2-$3")}
onBlur={formik.handleBlur('number')} keyboardType="number-pad"
value={formatPhoneNumber(formik.values.number)} maxLength={14}
autoComplete='tel' />
keyboardType='phone-pad' <RegisterDropdownInput
maxLength={14} label="Cellular Provider"
/> isOpen={providerDropdownOpen}
<RegisterDropdownInput setOpen={setProviderDropdownOpen}
label="Cellular Provider" selectedValue={formik.values.provider}
isOpen={providerDropdownOpen} onValueChange={formik.handleChange('provider')}
setOpen={setProviderDropdownOpen} menu={providerMenu}
selectedValue={formik.values.provider} />
onValueChange={formik.handleChange('provider')} <LoginTextInput
menu={providerMenu} label="Email Address"
/> icon="mail-outline"
<LoginTextInput placeholder="test@organization.com"
label="Email Address" placeholderTextColor="gray"
icon="mail-outline" onChangeText={formik.handleChange('email')}
placeholder="test@organization.com" onBlur={formik.handleBlur('email')}
placeholderTextColor="gray" value={formik.values.email}
onChangeText={formik.handleChange('email')} keyboardType="email-address"
onBlur={formik.handleBlur('email')} />
value={formik.values.email} <LoginTextInput
keyboardType="email-address" label="Password"
autoComplete='email' icon="lock-closed-outline"
autoCapitalize='none' placeholder="* * * * * *"
/> placeholderTextColor="gray"
<LoginTextInput onChangeText={formik.handleChange('password')}
label="Password" onBlur={formik.handleBlur('password')}
icon="lock-closed-outline" value={formik.values.password}
placeholder="* * * * * *" secureTextEntry={hidePassword}
placeholderTextColor="gray" isPassword
onChangeText={formik.handleChange('password')} hidePassword={hidePassword}
onBlur={formik.handleBlur('password')} setHidePassword={setHidePassword}
value={formik.values.password} />
secureTextEntry={hidePassword} <LoginTextInput
isPassword label="Confirm Password"
hidePassword={hidePassword} icon="shield-checkmark-outline"
setHidePassword={setHidePassword} placeholder="* * * * * *"
/> placeholderTextColor="gray"
<LoginTextInput onChangeText={formik.handleChange('passwordConfirmation')}
label="Confirm Password" onBlur={formik.handleBlur('passwordConfirmation')}
icon="shield-checkmark-outline" value={formik.values.passwordConfirmation}
placeholder="* * * * * *" secureTextEntry={hidePassword}
placeholderTextColor="gray" isPassword
onChangeText={formik.handleChange('passwordConfirmation')} hidePassword={hidePassword}
onBlur={formik.handleBlur('passwordConfirmation')} setHidePassword={setHidePassword}
value={formik.values.passwordConfirmation} />
secureTextEntry={hidePassword} <MessageBox>...</MessageBox>
isPassword <StyledButton onPress={formik.handleSubmit} style={registerButtonDisabled ? {backgroundColor: 'grey'} : {}}>
hidePassword={hidePassword} <ButtonText>Register</ButtonText>
setHidePassword={setHidePassword} </StyledButton>
/> </StyledFormArea>
<MessageBox>...</MessageBox> </InnerContainer>
<StyledButton onPress={formik.handleSubmit} style={registerButtonDisabled ? { backgroundColor: 'grey' } : {}}> </StyledContainer>
<ButtonText>Register</ButtonText> </ScrollView>
</StyledButton>
</StyledFormArea>
</InnerContainer>
</StyledContainer>
</ScrollView>
</KeyboardAvoidingView>
</View> </View>
) )
} }

91
app/trash/index.tsx Normal file
View file

@ -0,0 +1,91 @@
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',
},
});

View file

@ -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 }) {

View file

@ -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);

View file

@ -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;

View file

@ -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;

View file

@ -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;

View file

@ -1,8 +1,7 @@
import React, { useState } from 'react';
import styled from 'styled-components'; import styled from 'styled-components';
import { View, Text, LayoutAnimation, Image, TextInput, TouchableOpacity, TouchableNativeFeedback, ScrollView, Platform, Modal, Pressable } from 'react-native'; import { View, Text, LayoutAnimation, Image, TextInput, TouchableOpacity, TouchableNativeFeedback, ScrollView } 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`
@ -45,7 +44,7 @@ export const StyledTextInput = styled.TextInput`
margin-bottom: 10px; margin-bottom: 10px;
`; `;
export const StyledInputLabel = styled.Text` export const StyledInputLabel = styled.Text`
font-size: 13px; font-size: 13px;
text-align: left; text-align: left;
`; `;
@ -205,33 +204,11 @@ const providerConversion = {
} }
export const PageHeader = ({ export const PageHeader = ({
leftHeader = <View style={{ flex: 1 }} />, children
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 }}>
<View {children}
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>
) )
} }
@ -251,7 +228,7 @@ export const LoginTextInput = ({
icon, icon,
isPassword = false, isPassword = false,
hidePassword = true, hidePassword = true,
setHidePassword = (boolean) => { }, setHidePassword = (boolean) => {},
...props ...props
}) => { }) => {
return ( return (
@ -262,7 +239,7 @@ export const LoginTextInput = ({
<StyledInputLabel>{label}</StyledInputLabel> <StyledInputLabel>{label}</StyledInputLabel>
<StyledTextInput {...props} /> <StyledTextInput {...props} />
{isPassword ? ( {isPassword ? (
<RightIcon onPress={() => { setHidePassword(!hidePassword) }}> <RightIcon onPress={() => {setHidePassword(!hidePassword)}}>
<Ionicons name={hidePassword ? 'eye-off-outline' : 'eye-outline'} size={30} color="gray" /> <Ionicons name={hidePassword ? 'eye-off-outline' : 'eye-outline'} size={30} color="gray" />
</RightIcon> </RightIcon>
) : null} ) : null}
@ -272,108 +249,91 @@ 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 <TouchableOpacity activeOpacity={0.8} key={`${menu.menuName}2`}
activeOpacity={0.8}
style={{ style={{
backgroundColor: '#E5E7EB', backgroundColor: '#E5E7EB',
marginTop: 3, marginTop: 3,
marginBottom: 10, marginBottom: 10,
borderRadius: 5, borderRadius: '5px',
flexDirection: 'row',
alignItems: 'center',
minHeight: 60,
paddingHorizontal: 15,
}} }}
onPress={() => setModalVisible(true)} onPress={() => {
> LayoutAnimation.configureNext(LayoutAnimation.Presets.easeInEaseOut);
<Ionicons LayoutAnimation.configureNext(LayoutAnimation.create(200, 'easeInEaseOut', 'opacity'));
name={menu.iconName} isOpen ? setOpen(false) : setOpen(true);
size={30}
color={menu.iconColor}
/>
<Text style={{ color: selectedValue ? 'black' : 'grey', fontSize: 16, paddingHorizontal: 16, flex: 1 }}>
{selectedValue ? providerConversion[selectedValue] : menu.placeholder}
</Text>
<DropdownArrow onPress={() => setModalVisible(!modalVisible)}>
<Ionicons name={modalVisible ? "chevron-up-outline" : "chevron-down-outline"} size={30} color="gray" />
</DropdownArrow>
</TouchableOpacity>
<Modal
visible={modalVisible}
animationType="slide"
transparent={true}
onRequestClose={() => setModalVisible(false)}
>
<Pressable
style={{ flex: 1 }}
onPress={() => setModalVisible(false)}
/>
<View style={{
position: 'absolute',
left: 0,
right: 0,
bottom: 0,
backgroundColor: '#fff',
borderTopLeftRadius: 16,
borderTopRightRadius: 16,
paddingBottom: 32,
paddingTop: 16,
}}> }}>
<Pressable <Row style={{
style={{ flex: 1, paddingHorizontal: 15, alignItems: 'flex-end' }} paddingHorizontal: 16,
onPress={() => setModalVisible(false)} paddingVertical: 16 / 1.2,
> }}>
<Text style={{ color: 'red', fontWeight: 600 }}> <Ionicons
Close name={menu.iconName}
</Text> size={30}
</Pressable> color={menu.iconColor}
<Picker />
selectedValue={selectedValue} <Text style={{
onValueChange={(value) => { fontSize: 16,
onValueChange(value); paddingHorizontal: 16
}}>
{selectedValue ? providerConversion[selectedValue] : menu.placeholder}
</Text>
<DropdownArrow
onPress={() => {
LayoutAnimation.configureNext(LayoutAnimation.Presets.easeInEaseOut);
LayoutAnimation.configureNext(LayoutAnimation.create(200, 'easeInEaseOut', 'opacity'));
isOpen ? setOpen(false) : setOpen(true);
}} }}
> >
{menu.dropdownList.map((item) => ( <Ionicons
<Picker.Item color="black" label={item.label} value={item.value} key={item.value} /> name={isOpen ? "chevron-up-outline" : "chevron-down-outline"}
))} size={30}
</Picker> color="gray"
</View> />
</Modal> </DropdownArrow>
</Row>
{isOpen && <ScrollView style={{ borderRadius: '5px', backgroundColor: '#E5E7EB' }}>
{menu.dropdownList.map((subMenu, index) => {
return (
<TouchableNativeFeedback
key={index}
onPress={() => {
onValueChange(subMenu.value);
LayoutAnimation.configureNext(LayoutAnimation.Presets.easeInEaseOut);
LayoutAnimation.configureNext(LayoutAnimation.create(200, 'easeInEaseOut', 'opacity'));
setOpen(false);
}}
>
<View style={{
paddingHorizontal: 16,
paddingVertical: 16 / 1.5,
borderTopColor: 'gray',
borderTopWidth: .5,
marginHorizontal: 10
}}>
<Text>{subMenu.label}</Text>
{selectedValue === subMenu.value &&
<SelectedCheckmark>
<Ionicons
name="checkmark-outline"
size={30}
color="red"
/>
</SelectedCheckmark>
}
</View>
</TouchableNativeFeedback>
)
})}
</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;
};

View file

@ -1,30 +0,0 @@
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);
};

View file

@ -1,35 +0,0 @@
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>
)
};

View file

@ -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}/callfeed?apiKey=${process.env.EXPO_PUBLIC_DATABASE_API_KEY}`); ws.current = new WebSocket(process.env.EXPO_PUBLIC_WS_URL);
ws.current.onopen = () => { ws.current.onopen = () => {
console.log('✅ WebSocket connected'); console.log('✅ WebSocket connected');

View file

@ -1,23 +0,0 @@
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 };

View file

@ -1,4 +0,0 @@
export { AuthProvider } from './AuthContext';
export { GlobalVariablesProvider, GlobalVariablesContext } from './GlobalVariablesContext';
export { postgresServices } from './postgres';
export { WebSocketProvider, WebSocketContext } from './WebSocketContext';

View file

@ -1,62 +0,0 @@
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';
}
}

View file

@ -1,21 +0,0 @@
{
"cli": {
"version": ">= 16.3.2",
"appVersionSource": "remote"
},
"build": {
"development": {
"developmentClient": true,
"distribution": "internal"
},
"preview": {
"distribution": "internal"
},
"production": {
"autoIncrement": true
}
},
"submit": {
"production": {}
}
}

View file

@ -1,5 +1,2 @@
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';

View file

@ -1,18 +1,13 @@
import React, { useState, useEffect } from "react"; import React, { useState, useEffect } from 'react';
import { useDepartments } from "../useDepartments"; import { useDepartments } from '../useDepartments';
import { import { C, Cardiology, Cpr, FourByFour } from "healthicons-react-native/dist/outline";
Cardiology, import { useWebSocketContext } from '../useWebSocketContext';
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
@ -42,116 +37,200 @@ 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();
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( const hours = Math.floor((timeDifference % (1000 * 60 * 60 * 24)) / (1000 * 60 * 60));
(timeDifference % (1000 * 60 * 60 * 24)) / (1000 * 60 * 60) const minutes = Math.floor((timeDifference % (1000 * 60 * 60)) / (1000 * 60));
); const seconds = Math.floor((timeDifference % (1000 * 60)) / 1000);
const minutes = Math.floor((timeDifference % (1000 * 60 * 60)) / (1000 * 60)); if (days && days !== 0) {
const seconds = Math.floor((timeDifference % (1000 * 60)) / 1000); return `${days} day${days === 1 ? '' : 's'} ago`;
if (days && days !== 0) { } else if (hours && hours !== 0) {
return `${days} day${days === 1 ? "" : "s"} ago`; return `${hours} hour${hours === 1 ? '' : 's'} ago`;
} else if (hours && hours !== 0) { } else if (minutes && minutes !== 0) {
return `${hours} hour${hours === 1 ? "" : "s"} ago`; return `${minutes} minute${minutes === 1 ? '' : 's'} ago`;
} else if (minutes && minutes !== 0) { } else if (seconds && seconds !== 0) {
return `${minutes} minute${minutes === 1 ? "" : "s"} ago`; return `${seconds} second${seconds === 1 ? '' : 's'} ago`;
} else if (seconds && seconds !== 0) { }
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";
};
const getIncidents = async (departments, incidentStatus) => {
return postgresServices.getCallsParams({
numCalls: 25,
departments,
status: incidentStatus
});
};
export const useCallFeed = (callPage = false) => {
const departments = useDepartments();
const { lastMessage } = useWebSocketContext();
const [allCalls, setAllCalls] = useState([]);
const [init, setInit] = useState(true);
const { CallThemes, InitList } = departments?.accountDetails;
const { CriticalCallList, HighCallList, MediumCallList, LowCallList } =
CallThemes;
const [selectedStatus, setSelectedStatus] = useState({id: 'all', value: 'All Incidents'});
useEffect(() => {
async function fetchData() {
const incidents = await getIncidents(InitList?.map((dept) => { return dept?.deptId }), selectedStatus?.id);
setAllCalls(incidents);
setInit(false);
} }
if (!callPage) fetchData(); return 'Date Unavailable';
}, []); }
useEffect(() => { export const useCallFeed = () => {
if (lastMessage && !init) { const departments = useDepartments();
const parsedMessage = JSON?.parse(lastMessage); const { lastMessage } = useWebSocketContext();
if (parsedMessage?.data) { const [allCalls, setAllCalls] = useState([]);
setAllCalls([...allCalls, parsedMessage]); const { CallThemes } = departments?.accountDetails;
} const {
} CriticalCallList,
}, [lastMessage]); HighCallList,
MediumCallList,
LowCallList,
} = CallThemes;
useEffect(() => { useEffect(() => {
async function fetchData() { if (lastMessage) {
const incidents = await getIncidents(InitList?.map((dept) => { return dept?.deptId }), selectedStatus?.id); const parsedMessage = JSON?.parse(lastMessage);
setAllCalls(incidents); if (parsedMessage?.data) {
} setAllCalls([...allCalls, parsedMessage]);
if (!init) { }
if (!callPage) fetchData(); }
} }, [lastMessage]);
}, [selectedStatus]);
const callColorSelector = (callAcuity, cardiacArrestCall, status) => { const callColorSelector = (callAcuity, cardiacArrestCall, status) => {
if (status?.toLowerCase() === "closed") { if (status === 'CLOSED') {
return "#0000CD"; return '#0000CD';
} else if (CriticalCallList.some(critical => cardiacArrestCall.includes(critical))) { } else if (CriticalCallList.includes(cardiacArrestCall)) {
return "#8B0000"; return '#8B0000';
} else if (HighCallList.some(high => callAcuity.includes(high))) { } else if (HighCallList.includes(callAcuity)) {
return "#FF0000"; return "#FF0000";
} else if (MediumCallList.some(medium => callAcuity.includes(medium))) { } else if (MediumCallList.includes(callAcuity)) {
return "#FF8C00"; return "#FF8C00";
} else if (LowCallList.some(low => callAcuity.includes(low))) { } else if (LowCallList.includes(callAcuity)) {
return "#228B22"; return "#228B22";
} }
return "grey"; return 'grey';
}; };
return { return {
departments, departments,
callIconMap, callIconMap,
callDetails: allCalls, callDetails: allCalls,
callColorSelector, callColorSelector,
formatCallTimePast, formatCallTimePast,
formatCallDateTime, formatCallDateTime
selectedStatus, }
setSelectedStatus }
};
};

View file

@ -1,4 +1,5 @@
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',
@ -9,47 +10,27 @@ const departmentTypeMap = {
const accountDetails = { const accountDetails = {
"CallThemes" : { "CallThemes" : {
"CriticalCallList": [ "CriticalCallList": [
"CARDIAC ARREST" "CARDIAC ARREST|DEATH",
], ],
"HighCallList": [ "HighCallList": [
"EMS ALS PRIORITY (ALS)", "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": [
"EMS Standard Basic Life Support Response (BLS)", "BLS-STANDARD"
"EMS BLS Non-Emergency Transport",
"EMS BLS Standby Event Coverage",
"EMS Public Assist Lift Only (BLS)",
"EMS BLS Scheduled Interfacility Transport"
] ]
}, },
"InitList": [ "InitList": [
{ {
deptId: 1, deptId: 0,
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,
@ -58,11 +39,9 @@ const accountDetails = {
hasVolunteer: true, hasVolunteer: true,
}, },
{ {
deptId: 2, deptId: 1,
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,
@ -71,11 +50,9 @@ const accountDetails = {
hasVolunteer: true, hasVolunteer: true,
}, },
{ {
deptId: 3, deptId: 2,
dept: 'Stamford Fire Rescue', dept: 'Stamford Fire Department',
deptAbv: 'SFD', deptAbv: 'SFD',
rank: 'Paramedic',
rankAbv: 'EMT-P',
type: 'Rescue', type: 'Rescue',
primary: false, primary: false,
selected: false, selected: false,

View file

@ -1 +0,0 @@
export { useGlobalVariablesContext } from './useGlobalVariablesContext';

View file

@ -1,4 +0,0 @@
import { useContext } from 'react';
import { GlobalVariablesContext } from '../../contexts';
export const useGlobalVariablesContext = () => useContext(GlobalVariablesContext);

View file

@ -1 +0,0 @@
export { useNotifications } from './useNotifications';

View file

@ -1,112 +0,0 @@
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,
});
}

View file

@ -1,4 +1,4 @@
import { useContext } from 'react'; import { useContext } from 'react';
import { WebSocketContext } from '../../contexts'; import { WebSocketContext } from '../../contexts/WebSocketContext';
export const useWebSocketContext = () => useContext(WebSocketContext); export const useWebSocketContext = () => useContext(WebSocketContext);

View file

@ -7,31 +7,15 @@ 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'] || '15.1' platform :ios, podfile_properties['ios.deploymentTarget'] || '13.4'
install! 'cocoapods', install! 'cocoapods',
:deterministic_uuids => false :deterministic_uuids => false
prepare_react_native_project! prepare_react_native_project!
target 'Tones' do target 'testapplication' 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']
@ -63,4 +47,12 @@ target 'Tones' 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

File diff suppressed because it is too large Load diff

View file

@ -1,5 +1,4 @@
{ {
"expo.jsEngine": "hermes", "expo.jsEngine": "hermes",
"EX_DEV_CLIENT_NETWORK_INSPECTOR": "true", "EX_DEV_CLIENT_NETWORK_INSPECTOR": "true"
"newArchEnabled": "false"
} }

View file

@ -1,32 +0,0 @@
<?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>

Binary file not shown.

Before

Width:  |  Height:  |  Size: 166 KiB

View file

@ -1,20 +0,0 @@
{
"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"
}
}

View file

@ -1,44 +0,0 @@
<?xml version="1.0" encoding="UTF-8"?>
<document type="com.apple.InterfaceBuilder3.CocoaTouch.Storyboard.XIB" version="3.0" toolsVersion="32700.99.1234" targetRuntime="iOS.CocoaTouch" propertyAccessControl="none" useAutolayout="YES" launchScreen="YES" useTraitCollections="YES" useSafeAreas="YES" colorMatched="YES" initialViewController="EXPO-VIEWCONTROLLER-1">
<device id="retina6_12" orientation="portrait" appearance="light"/>
<dependencies>
<deployment identifier="iOS"/>
<plugIn identifier="com.apple.InterfaceBuilder.IBCocoaTouchPlugin" version="22685"/>
<capability name="Named colors" minToolsVersion="9.0"/>
<capability name="Safe area layout guides" minToolsVersion="9.0"/>
<capability name="documents saved in the Xcode 8 format" minToolsVersion="8.0"/>
</dependencies>
<scenes>
<scene sceneID="EXPO-SCENE-1">
<objects>
<viewController storyboardIdentifier="SplashScreenViewController" id="EXPO-VIEWCONTROLLER-1" sceneMemberID="viewController">
<view key="view" userInteractionEnabled="NO" contentMode="scaleToFill" insetsLayoutMarginsFromSafeArea="NO" id="EXPO-ContainerView" userLabel="ContainerView">
<rect key="frame" x="0.0" y="0.0" width="393" height="852"/>
<autoresizingMask key="autoresizingMask" flexibleMaxX="YES" flexibleMaxY="YES"/>
<subviews>
<imageView id="EXPO-SplashScreen" userLabel="SplashScreenLogo" image="SplashScreenLogo" contentMode="scaleAspectFit" clipsSubviews="true" userInteractionEnabled="false" translatesAutoresizingMaskIntoConstraints="false">
<rect key="frame" x="0" y="0" width="414" height="736"/>
</imageView>
</subviews>
<viewLayoutGuide key="safeArea" id="Rmq-lb-GrQ"/>
<constraints>
<constraint firstItem="EXPO-SplashScreen" firstAttribute="top" secondItem="EXPO-ContainerView" secondAttribute="top" id="83fcb9b545b870ba44c24f0feeb116490c499c52"/>
<constraint firstItem="EXPO-SplashScreen" firstAttribute="leading" secondItem="EXPO-ContainerView" secondAttribute="leading" id="61d16215e44b98e39d0a2c74fdbfaaa22601b12c"/>
<constraint firstItem="EXPO-SplashScreen" firstAttribute="trailing" secondItem="EXPO-ContainerView" secondAttribute="trailing" id="f934da460e9ab5acae3ad9987d5b676a108796c1"/>
<constraint firstItem="EXPO-SplashScreen" firstAttribute="bottom" secondItem="EXPO-ContainerView" secondAttribute="bottom" id="d6a0be88096b36fb132659aa90203d39139deda9"/>
</constraints>
<color key="backgroundColor" name="SplashScreenBackground"/>
</view>
</viewController>
<placeholder placeholderIdentifier="IBFirstResponder" id="EXPO-PLACEHOLDER-1" userLabel="First Responder" sceneMemberID="firstResponder"/>
</objects>
<point key="canvasLocation" x="0.0" y="0.0"/>
</scene>
</scenes>
<resources>
<image name="SplashScreenLogo" width="414" height="736"/>
<namedColor name="SplashScreenBackground">
<color alpha="1.000" blue="1.00000000000000" green="1.00000000000000" red="1.00000000000000" customColorSpace="sRGB" colorSpace="custom"/>
</namedColor>
</resources>
</document>

View file

@ -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 */; };
93A35CBBC1C2DF84FE39E633 /* PrivacyInfo.xcprivacy in Resources */ = {isa = PBXBuildFile; fileRef = EA8B81AA605F084BFB23750B /* PrivacyInfo.xcprivacy */; }; 640C5CE36A784C1E86D867C7 /* noop-file.swift in Sources */ = {isa = PBXBuildFile; fileRef = 2358EABEB0CA4428951E7149 /* noop-file.swift */; };
96905EF65AED1B983A6B3ABC /* libPods-Tones.a in Frameworks */ = {isa = PBXBuildFile; fileRef = 58EEBF8E8E6FB1BC6CAF49B5 /* libPods-Tones.a */; }; 96905EF65AED1B983A6B3ABC /* libPods-testapplication.a in Frameworks */ = {isa = PBXBuildFile; fileRef = 58EEBF8E8E6FB1BC6CAF49B5 /* libPods-testapplication.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 */
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>"; }; 13B07F961A680F5B00A75B9A /* testapplication.app */ = {isa = PBXFileReference; explicitFileType = wrapper.application; includeInIndex = 0; path = testapplication.app; sourceTree = BUILT_PRODUCTS_DIR; };
13B07F961A680F5B00A75B9A /* Tones.app */ = {isa = PBXFileReference; explicitFileType = wrapper.application; includeInIndex = 0; path = Tones.app; sourceTree = BUILT_PRODUCTS_DIR; }; 13B07FAF1A68108700A75B9A /* AppDelegate.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = AppDelegate.h; path = testapplication/AppDelegate.h; sourceTree = "<group>"; };
13B07FAF1A68108700A75B9A /* AppDelegate.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = AppDelegate.h; path = Tones/AppDelegate.h; sourceTree = "<group>"; }; 13B07FB01A68108700A75B9A /* AppDelegate.mm */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.objcpp; name = AppDelegate.mm; path = testapplication/AppDelegate.mm; sourceTree = "<group>"; };
13B07FB01A68108700A75B9A /* AppDelegate.mm */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.objcpp; name = AppDelegate.mm; path = Tones/AppDelegate.mm; sourceTree = "<group>"; }; 13B07FB51A68108700A75B9A /* Images.xcassets */ = {isa = PBXFileReference; lastKnownFileType = folder.assetcatalog; name = Images.xcassets; path = testapplication/Images.xcassets; sourceTree = "<group>"; };
13B07FB51A68108700A75B9A /* Images.xcassets */ = {isa = PBXFileReference; lastKnownFileType = folder.assetcatalog; name = Images.xcassets; path = Tones/Images.xcassets; sourceTree = "<group>"; }; 13B07FB61A68108700A75B9A /* Info.plist */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.plist.xml; name = Info.plist; path = testapplication/Info.plist; sourceTree = "<group>"; };
13B07FB61A68108700A75B9A /* Info.plist */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.plist.xml; name = Info.plist; path = Tones/Info.plist; sourceTree = "<group>"; }; 13B07FB71A68108700A75B9A /* main.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = main.m; path = testapplication/main.m; sourceTree = "<group>"; };
13B07FB71A68108700A75B9A /* main.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = main.m; path = Tones/main.m; 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>"; };
58EEBF8E8E6FB1BC6CAF49B5 /* libPods-Tones.a */ = {isa = PBXFileReference; explicitFileType = archive.ar; includeInIndex = 0; path = "libPods-Tones.a"; sourceTree = BUILT_PRODUCTS_DIR; }; 58EEBF8E8E6FB1BC6CAF49B5 /* libPods-testapplication.a */ = {isa = PBXFileReference; explicitFileType = archive.ar; includeInIndex = 0; path = "libPods-testapplication.a"; sourceTree = BUILT_PRODUCTS_DIR; };
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>"; }; 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>"; };
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>"; }; 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>"; };
AA286B85B6C04FC6940260E9 /* SplashScreen.storyboard */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = file.storyboard; name = SplashScreen.storyboard; path = Tones/SplashScreen.storyboard; 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>"; };
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; };
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-testapplication/ExpoModulesProvider.swift"; 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-Tones.a in Frameworks */, 96905EF65AED1B983A6B3ABC /* libPods-testapplication.a in Frameworks */,
); );
runOnlyForDeploymentPostprocessing = 0; runOnlyForDeploymentPostprocessing = 0;
}; };
/* End PBXFrameworksBuildPhase section */ /* End PBXFrameworksBuildPhase section */
/* Begin PBXGroup section */ /* Begin PBXGroup section */
13B07FAE1A68108700A75B9A /* Tones */ = { 13B07FAE1A68108700A75B9A /* testapplication */ = {
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 */,
1350D069573E4AEBBF8BA6A3 /* noop-file.swift */, 2358EABEB0CA4428951E7149 /* noop-file.swift */,
F8CAF977DAD74AAA91FDDD99 /* Tones-Bridging-Header.h */, 96FAC8CF002144E68DCEBFD0 /* testapplication-Bridging-Header.h */,
EA8B81AA605F084BFB23750B /* PrivacyInfo.xcprivacy */, A9DA6C7B26A64A23DFDE186E /* PrivacyInfo.xcprivacy */,
); );
name = Tones; name = testapplication;
sourceTree = "<group>"; sourceTree = "<group>";
}; };
2D16E6871FA4F8E400B85C8A /* Frameworks */ = { 2D16E6871FA4F8E400B85C8A /* Frameworks */ = {
isa = PBXGroup; isa = PBXGroup;
children = ( children = (
ED297162215061F000B7C4FE /* JavaScriptCore.framework */, ED297162215061F000B7C4FE /* JavaScriptCore.framework */,
58EEBF8E8E6FB1BC6CAF49B5 /* libPods-Tones.a */, 58EEBF8E8E6FB1BC6CAF49B5 /* libPods-testapplication.a */,
); );
name = Frameworks; name = Frameworks;
sourceTree = "<group>"; sourceTree = "<group>";
@ -85,7 +85,7 @@
83CBB9F61A601CBA00E9B192 = { 83CBB9F61A601CBA00E9B192 = {
isa = PBXGroup; isa = PBXGroup;
children = ( children = (
13B07FAE1A68108700A75B9A /* Tones */, 13B07FAE1A68108700A75B9A /* testapplication */,
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 /* Tones.app */, 13B07F961A680F5B00A75B9A /* testapplication.app */,
); );
name = Products; name = Products;
sourceTree = "<group>"; sourceTree = "<group>";
}; };
92DBD88DE9BF7D494EA9DA96 /* Tones */ = { 92DBD88DE9BF7D494EA9DA96 /* testapplication */ = {
isa = PBXGroup; isa = PBXGroup;
children = ( children = (
FAC715A2D49A985799AEE119 /* ExpoModulesProvider.swift */, FAC715A2D49A985799AEE119 /* ExpoModulesProvider.swift */,
); );
name = Tones; name = testapplication;
sourceTree = "<group>"; sourceTree = "<group>";
}; };
BB2F792B24A3F905000567C9 /* Supporting */ = { BB2F792B24A3F905000567C9 /* Supporting */ = {
@ -119,14 +119,14 @@
BB2F792C24A3F905000567C9 /* Expo.plist */, BB2F792C24A3F905000567C9 /* Expo.plist */,
); );
name = Supporting; name = Supporting;
path = Tones/Supporting; path = testapplication/Supporting;
sourceTree = "<group>"; sourceTree = "<group>";
}; };
D65327D7A22EEC0BE12398D9 /* Pods */ = { D65327D7A22EEC0BE12398D9 /* Pods */ = {
isa = PBXGroup; isa = PBXGroup;
children = ( children = (
6C2E3173556A471DD304B334 /* Pods-Tones.debug.xcconfig */, 6C2E3173556A471DD304B334 /* Pods-testapplication.debug.xcconfig */,
7A4D352CD337FB3A3BF06240 /* Pods-Tones.release.xcconfig */, 7A4D352CD337FB3A3BF06240 /* Pods-testapplication.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 /* Tones */, 92DBD88DE9BF7D494EA9DA96 /* testapplication */,
); );
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 /* Tones */ = { 13B07F861A680F5B00A75B9A /* testapplication */ = {
isa = PBXNativeTarget; isa = PBXNativeTarget;
buildConfigurationList = 13B07F931A680F5B00A75B9A /* Build configuration list for PBXNativeTarget "Tones" */; buildConfigurationList = 13B07F931A680F5B00A75B9A /* Build configuration list for PBXNativeTarget "testapplication" */;
buildPhases = ( buildPhases = (
08A4A3CD28434E44B6B9DE2E /* [CP] Check Pods Manifest.lock */, 08A4A3CD28434E44B6B9DE2E /* [CP] Check Pods Manifest.lock */,
BBDF11722E0998CCEE7FC139 /* [Expo] Configure project */, 7E5AAFC44944C4D49F90AE74 /* [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 */,
5F318AA4CE51F8E175CC6D0A /* [CP] Embed Pods Frameworks */, 6CD366C487D1C4076EEFC1E9 /* [CP] Embed Pods Frameworks */,
); );
buildRules = ( buildRules = (
); );
dependencies = ( dependencies = (
); );
name = Tones; name = testapplication;
productName = Tones; productName = testapplication;
productReference = 13B07F961A680F5B00A75B9A /* Tones.app */; productReference = 13B07F961A680F5B00A75B9A /* testapplication.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 "Tones" */; buildConfigurationList = 83CBB9FA1A601CBA00E9B192 /* Build configuration list for PBXProject "testapplication" */;
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 /* Tones */, 13B07F861A680F5B00A75B9A /* testapplication */,
); );
}; };
/* 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 */,
93A35CBBC1C2DF84FE39E633 /* PrivacyInfo.xcprivacy in Resources */, FF358844A8FA907CDEC7216D /* PrivacyInfo.xcprivacy in Resources */,
); );
runOnlyForDeploymentPostprocessing = 0; runOnlyForDeploymentPostprocessing = 0;
}; };
@ -240,20 +240,20 @@
outputFileListPaths = ( outputFileListPaths = (
); );
outputPaths = ( outputPaths = (
"$(DERIVED_FILE_DIR)/Pods-Tones-checkManifestLockResult.txt", "$(DERIVED_FILE_DIR)/Pods-testapplication-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;
}; };
5F318AA4CE51F8E175CC6D0A /* [CP] Embed Pods Frameworks */ = { 6CD366C487D1C4076EEFC1E9 /* [CP] Embed Pods Frameworks */ = {
isa = PBXShellScriptBuildPhase; isa = PBXShellScriptBuildPhase;
buildActionMask = 2147483647; buildActionMask = 2147483647;
files = ( files = (
); );
inputPaths = ( inputPaths = (
"${PODS_ROOT}/Target Support Files/Pods-Tones/Pods-Tones-frameworks.sh", "${PODS_ROOT}/Target Support Files/Pods-testapplication/Pods-testapplication-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,50 +262,10 @@
); );
runOnlyForDeploymentPostprocessing = 0; runOnlyForDeploymentPostprocessing = 0;
shellPath = /bin/sh; shellPath = /bin/sh;
shellScript = "\"${PODS_ROOT}/Target Support Files/Pods-Tones/Pods-Tones-frameworks.sh\"\n"; shellScript = "\"${PODS_ROOT}/Target Support Files/Pods-testapplication/Pods-testapplication-frameworks.sh\"\n";
showEnvVarsInLog = 0; showEnvVarsInLog = 0;
}; };
800E24972A6A228C8D4807E9 /* [CP] Copy Pods Resources */ = { 7E5AAFC44944C4D49F90AE74 /* [Expo] Configure project */ = {
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;
@ -322,7 +282,33 @@
); );
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-Tones/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-testapplication/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 */
@ -334,7 +320,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 */,
3BB8D1083F3D4AAFA506B09F /* noop-file.swift in Sources */, 640C5CE36A784C1E86D867C7 /* noop-file.swift in Sources */,
); );
runOnlyForDeploymentPostprocessing = 0; runOnlyForDeploymentPostprocessing = 0;
}; };
@ -343,19 +329,19 @@
/* Begin XCBuildConfiguration section */ /* Begin XCBuildConfiguration section */
13B07F941A680F5B00A75B9A /* Debug */ = { 13B07F941A680F5B00A75B9A /* Debug */ = {
isa = XCBuildConfiguration; isa = XCBuildConfiguration;
baseConfigurationReference = 6C2E3173556A471DD304B334 /* Pods-Tones.debug.xcconfig */; baseConfigurationReference = 6C2E3173556A471DD304B334 /* Pods-testapplication.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 = Tones/Tones.entitlements; CODE_SIGN_ENTITLEMENTS = testapplication/testapplication.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 = Tones/Info.plist; INFOPLIST_FILE = testapplication/Info.plist;
IPHONEOS_DEPLOYMENT_TARGET = 15.1; IPHONEOS_DEPLOYMENT_TARGET = 13.4;
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 = (
@ -364,9 +350,9 @@
"-lc++", "-lc++",
); );
OTHER_SWIFT_FLAGS = "$(inherited) -D EXPO_CONFIGURATION_DEBUG"; OTHER_SWIFT_FLAGS = "$(inherited) -D EXPO_CONFIGURATION_DEBUG";
PRODUCT_BUNDLE_IDENTIFIER = com.mattdimegs.tones; PRODUCT_BUNDLE_IDENTIFIER = com.anonymous.testapplication;
PRODUCT_NAME = Tones; PRODUCT_NAME = testapplication;
SWIFT_OBJC_BRIDGING_HEADER = "Tones/Tones-Bridging-Header.h"; SWIFT_OBJC_BRIDGING_HEADER = "testapplication/testapplication-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";
@ -376,14 +362,14 @@
}; };
13B07F951A680F5B00A75B9A /* Release */ = { 13B07F951A680F5B00A75B9A /* Release */ = {
isa = XCBuildConfiguration; isa = XCBuildConfiguration;
baseConfigurationReference = 7A4D352CD337FB3A3BF06240 /* Pods-Tones.release.xcconfig */; baseConfigurationReference = 7A4D352CD337FB3A3BF06240 /* Pods-testapplication.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 = Tones/Tones.entitlements; CODE_SIGN_ENTITLEMENTS = testapplication/testapplication.entitlements;
CURRENT_PROJECT_VERSION = 1; CURRENT_PROJECT_VERSION = 1;
INFOPLIST_FILE = Tones/Info.plist; INFOPLIST_FILE = testapplication/Info.plist;
IPHONEOS_DEPLOYMENT_TARGET = 15.1; IPHONEOS_DEPLOYMENT_TARGET = 13.4;
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 = (
@ -392,9 +378,9 @@
"-lc++", "-lc++",
); );
OTHER_SWIFT_FLAGS = "$(inherited) -D EXPO_CONFIGURATION_RELEASE"; OTHER_SWIFT_FLAGS = "$(inherited) -D EXPO_CONFIGURATION_RELEASE";
PRODUCT_BUNDLE_IDENTIFIER = com.mattdimegs.tones; PRODUCT_BUNDLE_IDENTIFIER = com.anonymous.testapplication;
PRODUCT_NAME = Tones; PRODUCT_NAME = testapplication;
SWIFT_OBJC_BRIDGING_HEADER = "Tones/Tones-Bridging-Header.h"; SWIFT_OBJC_BRIDGING_HEADER = "testapplication/testapplication-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";
@ -405,6 +391,7 @@
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++";
@ -431,6 +418,7 @@
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;
@ -448,7 +436,9 @@
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 = 15.1; IPHONEOS_DEPLOYMENT_TARGET = 13.4;
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;
@ -459,7 +449,6 @@
); );
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;
@ -468,6 +457,7 @@
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++";
@ -494,6 +484,7 @@
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;
@ -504,7 +495,9 @@
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 = 15.1; IPHONEOS_DEPLOYMENT_TARGET = 13.4;
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;
@ -522,7 +515,7 @@
/* End XCBuildConfiguration section */ /* End XCBuildConfiguration section */
/* Begin XCConfigurationList section */ /* Begin XCConfigurationList section */
13B07F931A680F5B00A75B9A /* Build configuration list for PBXNativeTarget "Tones" */ = { 13B07F931A680F5B00A75B9A /* Build configuration list for PBXNativeTarget "testapplication" */ = {
isa = XCConfigurationList; isa = XCConfigurationList;
buildConfigurations = ( buildConfigurations = (
13B07F941A680F5B00A75B9A /* Debug */, 13B07F941A680F5B00A75B9A /* Debug */,
@ -531,7 +524,7 @@
defaultConfigurationIsVisible = 0; defaultConfigurationIsVisible = 0;
defaultConfigurationName = Release; defaultConfigurationName = Release;
}; };
83CBB9FA1A601CBA00E9B192 /* Build configuration list for PBXProject "Tones" */ = { 83CBB9FA1A601CBA00E9B192 /* Build configuration list for PBXProject "testapplication" */ = {
isa = XCConfigurationList; isa = XCConfigurationList;
buildConfigurations = ( buildConfigurations = (
83CBBA201A601CBA00E9B192 /* Debug */, 83CBBA201A601CBA00E9B192 /* Debug */,

View file

@ -15,9 +15,9 @@
<BuildableReference <BuildableReference
BuildableIdentifier = "primary" BuildableIdentifier = "primary"
BlueprintIdentifier = "13B07F861A680F5B00A75B9A" BlueprintIdentifier = "13B07F861A680F5B00A75B9A"
BuildableName = "Tones.app" BuildableName = "testapplication.app"
BlueprintName = "Tones" BlueprintName = "testapplication"
ReferencedContainer = "container:Tones.xcodeproj"> ReferencedContainer = "container:testapplication.xcodeproj">
</BuildableReference> </BuildableReference>
</BuildActionEntry> </BuildActionEntry>
</BuildActionEntries> </BuildActionEntries>
@ -33,9 +33,9 @@
<BuildableReference <BuildableReference
BuildableIdentifier = "primary" BuildableIdentifier = "primary"
BlueprintIdentifier = "00E356ED1AD99517003FC87E" BlueprintIdentifier = "00E356ED1AD99517003FC87E"
BuildableName = "TonesTests.xctest" BuildableName = "testapplicationTests.xctest"
BlueprintName = "TonesTests" BlueprintName = "testapplicationTests"
ReferencedContainer = "container:Tones.xcodeproj"> ReferencedContainer = "container:testapplication.xcodeproj">
</BuildableReference> </BuildableReference>
</TestableReference> </TestableReference>
</Testables> </Testables>
@ -55,9 +55,9 @@
<BuildableReference <BuildableReference
BuildableIdentifier = "primary" BuildableIdentifier = "primary"
BlueprintIdentifier = "13B07F861A680F5B00A75B9A" BlueprintIdentifier = "13B07F861A680F5B00A75B9A"
BuildableName = "Tones.app" BuildableName = "testapplication.app"
BlueprintName = "Tones" BlueprintName = "testapplication"
ReferencedContainer = "container:Tones.xcodeproj"> ReferencedContainer = "container:testapplication.xcodeproj">
</BuildableReference> </BuildableReference>
</BuildableProductRunnable> </BuildableProductRunnable>
</LaunchAction> </LaunchAction>
@ -72,9 +72,9 @@
<BuildableReference <BuildableReference
BuildableIdentifier = "primary" BuildableIdentifier = "primary"
BlueprintIdentifier = "13B07F861A680F5B00A75B9A" BlueprintIdentifier = "13B07F861A680F5B00A75B9A"
BuildableName = "Tones.app" BuildableName = "testapplication.app"
BlueprintName = "Tones" BlueprintName = "testapplication"
ReferencedContainer = "container:Tones.xcodeproj"> ReferencedContainer = "container:testapplication.xcodeproj">
</BuildableReference> </BuildableReference>
</BuildableProductRunnable> </BuildableProductRunnable>
</ProfileAction> </ProfileAction>

View file

@ -2,7 +2,7 @@
<Workspace <Workspace
version = "1.0"> version = "1.0">
<FileRef <FileRef
location = "group:Tones.xcodeproj"> location = "group:testapplication.xcodeproj">
</FileRef> </FileRef>
<FileRef <FileRef
location = "group:Pods/Pods.xcodeproj"> location = "group:Pods/Pods.xcodeproj">

Binary file not shown.

After

Width:  |  Height:  |  Size: 58 KiB

View file

@ -7,12 +7,10 @@
}, },
{ {
"idiom": "universal", "idiom": "universal",
"filename": "image@2x.png",
"scale": "2x" "scale": "2x"
}, },
{ {
"idiom": "universal", "idiom": "universal",
"filename": "image@3x.png",
"scale": "3x" "scale": "3x"
} }
], ],

Some files were not shown because too many files have changed in this diff Show more