Feature/notification system #26
32
GoogleServices/GoogleService-Info.plist
Normal file
|
|
@ -0,0 +1,32 @@
|
|||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
|
||||
<plist version="1.0">
|
||||
<dict>
|
||||
<key>API_KEY</key>
|
||||
<string>AIzaSyClZkx4PFWhfIG3JDb6GD3g6Bl7-pWLNrU</string>
|
||||
<key>GCM_SENDER_ID</key>
|
||||
<string>917296693147</string>
|
||||
<key>PLIST_VERSION</key>
|
||||
<string>1</string>
|
||||
<key>BUNDLE_ID</key>
|
||||
<string>com.mattdimegs.tones</string>
|
||||
<key>PROJECT_ID</key>
|
||||
<string>tones-9f1d4</string>
|
||||
<key>STORAGE_BUCKET</key>
|
||||
<string>tones-9f1d4.firebasestorage.app</string>
|
||||
<key>IS_ADS_ENABLED</key>
|
||||
<false></false>
|
||||
<key>IS_ANALYTICS_ENABLED</key>
|
||||
<false></false>
|
||||
<key>IS_APPINVITE_ENABLED</key>
|
||||
<true></true>
|
||||
<key>IS_GCM_ENABLED</key>
|
||||
<true></true>
|
||||
<key>IS_SIGNIN_ENABLED</key>
|
||||
<true></true>
|
||||
<key>GOOGLE_APP_ID</key>
|
||||
<string>1:917296693147:ios:73d6d426aa60e52b35ab3e</string>
|
||||
<key>DATABASE_URL</key>
|
||||
<string>https://tones-9f1d4-default-rtdb.firebaseio.com</string>
|
||||
</dict>
|
||||
</plist>
|
||||
30
GoogleServices/google-services.json
Normal file
|
|
@ -0,0 +1,30 @@
|
|||
{
|
||||
"project_info": {
|
||||
"project_number": "917296693147",
|
||||
"firebase_url": "https://tones-9f1d4-default-rtdb.firebaseio.com",
|
||||
"project_id": "tones-9f1d4",
|
||||
"storage_bucket": "tones-9f1d4.firebasestorage.app"
|
||||
},
|
||||
"client": [
|
||||
{
|
||||
"client_info": {
|
||||
"mobilesdk_app_id": "1:917296693147:android:9387809020ba083035ab3e",
|
||||
"android_client_info": {
|
||||
"package_name": "com.mattdimegs.tones"
|
||||
}
|
||||
},
|
||||
"oauth_client": [],
|
||||
"api_key": [
|
||||
{
|
||||
"current_key": "AIzaSyAT0khB8fuAvWjz0WeWrdPAw1RD-v9ylNU"
|
||||
}
|
||||
],
|
||||
"services": {
|
||||
"appinvite_service": {
|
||||
"other_platform_oauth_client": []
|
||||
}
|
||||
}
|
||||
}
|
||||
],
|
||||
"configuration_version": "1"
|
||||
}
|
||||
|
|
@ -14,18 +14,19 @@ react {
|
|||
hermesCommand = new File(["node", "--print", "require.resolve('react-native/package.json')"].execute(null, rootDir).text.trim()).getParentFile().getAbsolutePath() + "/sdks/hermesc/%OS-BIN%/hermesc"
|
||||
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
|
||||
// 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())
|
||||
bundleCommand = "export:embed"
|
||||
|
||||
/* Folders */
|
||||
// The root of your project, i.e. where "package.json" lives. Default is '..'
|
||||
// root = file("../")
|
||||
// The folder where the react-native NPM package is. Default is ../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
|
||||
// codegenDir = file("../node_modules/@react-native/codegen")
|
||||
// The root of your project, i.e. where "package.json" lives. Default is '../..'
|
||||
// root = file("../../")
|
||||
// The folder where the react-native NPM package is. Default is ../../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
|
||||
// codegenDir = file("../../node_modules/@react-native/codegen")
|
||||
|
||||
/* Variants */
|
||||
// The list of variants to that are debuggable. For those we're going to
|
||||
|
|
@ -57,6 +58,9 @@ react {
|
|||
//
|
||||
// The list of flags to pass to the Hermes compiler. By default is "-O", "-output-source-map"
|
||||
// hermesFlags = ["-O", "-output-source-map"]
|
||||
|
||||
/* Autolinking */
|
||||
autolinkLibrariesWithApp()
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
@ -75,7 +79,7 @@ def enableProguardInReleaseBuilds = (findProperty('android.enableProguardInRelea
|
|||
* give correct results when using with locales other than en-US. Note that
|
||||
* this variant is about 6MiB larger per architecture than default.
|
||||
*/
|
||||
def jscFlavor = 'org.webkit:android-jsc:+'
|
||||
def jscFlavor = 'io.github.react-native-community:jsc-android:2026004.+'
|
||||
|
||||
android {
|
||||
ndkVersion rootProject.ext.ndkVersion
|
||||
|
|
@ -83,13 +87,13 @@ android {
|
|||
buildToolsVersion rootProject.ext.buildToolsVersion
|
||||
compileSdk rootProject.ext.compileSdkVersion
|
||||
|
||||
namespace 'com.anonymous.testapplication'
|
||||
namespace 'com.mattdimegs.tones'
|
||||
defaultConfig {
|
||||
applicationId 'com.anonymous.testapplication'
|
||||
applicationId 'com.mattdimegs.tones'
|
||||
minSdkVersion rootProject.ext.minSdkVersion
|
||||
targetSdkVersion rootProject.ext.targetSdkVersion
|
||||
versionCode 1
|
||||
versionName "1.0.0"
|
||||
versionName "1.0.1"
|
||||
}
|
||||
signingConfigs {
|
||||
debug {
|
||||
|
|
@ -110,6 +114,7 @@ android {
|
|||
shrinkResources (findProperty('android.enableShrinkResourcesInReleaseBuilds')?.toBoolean() ?: false)
|
||||
minifyEnabled enableProguardInReleaseBuilds
|
||||
proguardFiles getDefaultProguardFile("proguard-android.txt"), "proguard-rules.pro"
|
||||
crunchPngs (findProperty('android.enablePngCrunchInReleaseBuilds')?.toBoolean() ?: true)
|
||||
}
|
||||
}
|
||||
packagingOptions {
|
||||
|
|
@ -117,6 +122,9 @@ android {
|
|||
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`
|
||||
|
|
@ -149,15 +157,15 @@ dependencies {
|
|||
|
||||
if (isGifEnabled) {
|
||||
// For animated gif support
|
||||
implementation("com.facebook.fresco:animated-gif:${reactAndroidLibs.versions.fresco.get()}")
|
||||
implementation("com.facebook.fresco:animated-gif:${expoLibs.versions.fresco.get()}")
|
||||
}
|
||||
|
||||
if (isWebpEnabled) {
|
||||
// For webp support
|
||||
implementation("com.facebook.fresco:webpsupport:${reactAndroidLibs.versions.fresco.get()}")
|
||||
implementation("com.facebook.fresco:webpsupport:${expoLibs.versions.fresco.get()}")
|
||||
if (isWebpAnimatedEnabled) {
|
||||
// Animated webp support
|
||||
implementation("com.facebook.fresco:animated-webp:${reactAndroidLibs.versions.fresco.get()}")
|
||||
implementation("com.facebook.fresco:animated-webp:${expoLibs.versions.fresco.get()}")
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -168,5 +176,4 @@ dependencies {
|
|||
}
|
||||
}
|
||||
|
||||
apply from: new File(["node", "--print", "require.resolve('@react-native-community/cli-platform-android/package.json', { paths: [require.resolve('react-native/package.json')] })"].execute(null, rootDir).text.trim(), "../native_modules.gradle");
|
||||
applyNativeModulesAppBuildGradle(project)
|
||||
apply plugin: 'com.google.gms.google-services'
|
||||
30
android/app/google-services.json
Normal file
|
|
@ -0,0 +1,30 @@
|
|||
{
|
||||
"project_info": {
|
||||
"project_number": "917296693147",
|
||||
"firebase_url": "https://tones-9f1d4-default-rtdb.firebaseio.com",
|
||||
"project_id": "tones-9f1d4",
|
||||
"storage_bucket": "tones-9f1d4.firebasestorage.app"
|
||||
},
|
||||
"client": [
|
||||
{
|
||||
"client_info": {
|
||||
"mobilesdk_app_id": "1:917296693147:android:9387809020ba083035ab3e",
|
||||
"android_client_info": {
|
||||
"package_name": "com.mattdimegs.tones"
|
||||
}
|
||||
},
|
||||
"oauth_client": [],
|
||||
"api_key": [
|
||||
{
|
||||
"current_key": "AIzaSyAT0khB8fuAvWjz0WeWrdPAw1RD-v9ylNU"
|
||||
}
|
||||
],
|
||||
"services": {
|
||||
"appinvite_service": {
|
||||
"other_platform_oauth_client": []
|
||||
}
|
||||
}
|
||||
}
|
||||
],
|
||||
"configuration_version": "1"
|
||||
}
|
||||
|
|
@ -3,5 +3,7 @@
|
|||
|
||||
<uses-permission android:name="android.permission.SYSTEM_ALERT_WINDOW"/>
|
||||
|
||||
<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>
|
||||
|
|
|
|||
|
|
@ -11,7 +11,7 @@
|
|||
<data android:scheme="https"/>
|
||||
</intent>
|
||||
</queries>
|
||||
<application android:name=".MainApplication" android:label="@string/app_name" android:icon="@mipmap/ic_launcher" android:roundIcon="@mipmap/ic_launcher_round" android:allowBackup="true" android:theme="@style/AppTheme">
|
||||
<application android:name=".MainApplication" android:label="@string/app_name" android:icon="@mipmap/ic_launcher" android:roundIcon="@mipmap/ic_launcher_round" android:allowBackup="true" android:theme="@style/AppTheme" android:supportsRtl="true">
|
||||
<meta-data android:name="expo.modules.updates.ENABLED" android:value="false"/>
|
||||
<meta-data android:name="expo.modules.updates.EXPO_UPDATES_CHECK_ON_LAUNCH" android:value="ALWAYS"/>
|
||||
<meta-data android:name="expo.modules.updates.EXPO_UPDATES_LAUNCH_WAIT_MS" android:value="0"/>
|
||||
|
|
@ -25,9 +25,7 @@
|
|||
<category android:name="android.intent.category.DEFAULT"/>
|
||||
<category android:name="android.intent.category.BROWSABLE"/>
|
||||
<data android:scheme="myapp"/>
|
||||
<data android:scheme="com.anonymous.testapplication"/>
|
||||
</intent-filter>
|
||||
</activity>
|
||||
<activity android:name="com.facebook.react.devsupport.DevSettingsActivity" android:exported="false"/>
|
||||
</application>
|
||||
</manifest>
|
||||
|
|
@ -1,4 +1,5 @@
|
|||
package com.anonymous.testapplication
|
||||
package com.mattdimegs.tones
|
||||
import expo.modules.splashscreen.SplashScreenManager
|
||||
|
||||
import android.os.Build
|
||||
import android.os.Bundle
|
||||
|
|
@ -15,7 +16,10 @@ class MainActivity : ReactActivity() {
|
|||
// Set the theme to AppTheme BEFORE onCreate to support
|
||||
// coloring the background, status bar, and navigation bar.
|
||||
// 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)
|
||||
}
|
||||
|
||||
|
|
@ -1,4 +1,4 @@
|
|||
package com.anonymous.testapplication
|
||||
package com.mattdimegs.tones
|
||||
|
||||
import android.app.Application
|
||||
import android.content.res.Configuration
|
||||
|
|
@ -10,6 +10,7 @@ import com.facebook.react.ReactPackage
|
|||
import com.facebook.react.ReactHost
|
||||
import com.facebook.react.defaults.DefaultNewArchitectureEntryPoint.load
|
||||
import com.facebook.react.defaults.DefaultReactNativeHost
|
||||
import com.facebook.react.soloader.OpenSourceMergedSoMapping
|
||||
import com.facebook.soloader.SoLoader
|
||||
|
||||
import expo.modules.ApplicationLifecycleDispatcher
|
||||
|
|
@ -21,9 +22,10 @@ class MainApplication : Application(), ReactApplication {
|
|||
this,
|
||||
object : DefaultReactNativeHost(this) {
|
||||
override fun getPackages(): List<ReactPackage> {
|
||||
val packages = PackageList(this).packages
|
||||
// Packages that cannot be autolinked yet can be added manually here, for example:
|
||||
// packages.add(new MyReactNativePackage());
|
||||
return PackageList(this).packages
|
||||
// packages.add(MyReactNativePackage())
|
||||
return packages
|
||||
}
|
||||
|
||||
override fun getJSMainModuleName(): String = ".expo/.virtual-metro-entry"
|
||||
|
|
@ -40,7 +42,7 @@ class MainApplication : Application(), ReactApplication {
|
|||
|
||||
override fun onCreate() {
|
||||
super.onCreate()
|
||||
SoLoader.init(this, false)
|
||||
SoLoader.init(this, OpenSourceMergedSoMapping)
|
||||
if (BuildConfig.IS_NEW_ARCHITECTURE_ENABLED) {
|
||||
// If you opted-in for the New Architecture, we load the native entry point for this app.
|
||||
load()
|
||||
BIN
android/app/src/main/res/drawable-hdpi/splashscreen_logo.png
Normal file
|
After Width: | Height: | Size: 5 KiB |
BIN
android/app/src/main/res/drawable-mdpi/splashscreen_logo.png
Normal file
|
After Width: | Height: | Size: 3 KiB |
|
Before Width: | Height: | Size: 58 KiB |
BIN
android/app/src/main/res/drawable-xhdpi/splashscreen_logo.png
Normal file
|
After Width: | Height: | Size: 7.2 KiB |
|
Before Width: | Height: | Size: 58 KiB |
BIN
android/app/src/main/res/drawable-xxhdpi/splashscreen_logo.png
Normal file
|
After Width: | Height: | Size: 12 KiB |
|
Before Width: | Height: | Size: 58 KiB |
BIN
android/app/src/main/res/drawable-xxxhdpi/splashscreen_logo.png
Normal file
|
After Width: | Height: | Size: 19 KiB |
|
|
@ -1,3 +1,6 @@
|
|||
<layer-list xmlns:android="http://schemas.android.com/apk/res/android">
|
||||
<item android:drawable="@color/splashscreen_background"/>
|
||||
<item>
|
||||
<bitmap android:gravity="center" android:src="@drawable/splashscreen_logo"/>
|
||||
</item>
|
||||
</layer-list>
|
||||
|
Before Width: | Height: | Size: 8.2 KiB |
BIN
android/app/src/main/res/mipmap-hdpi/ic_launcher.webp
Normal file
|
After Width: | Height: | Size: 3.2 KiB |
|
Before Width: | Height: | Size: 7.8 KiB After Width: | Height: | Size: 7.8 KiB |
|
Before Width: | Height: | Size: 10 KiB |
BIN
android/app/src/main/res/mipmap-hdpi/ic_launcher_round.webp
Normal file
|
After Width: | Height: | Size: 4 KiB |
|
Before Width: | Height: | Size: 5.1 KiB |
BIN
android/app/src/main/res/mipmap-mdpi/ic_launcher.webp
Normal file
|
After Width: | Height: | Size: 2 KiB |
|
Before Width: | Height: | Size: 5 KiB After Width: | Height: | Size: 5 KiB |
|
Before Width: | Height: | Size: 6.4 KiB |
BIN
android/app/src/main/res/mipmap-mdpi/ic_launcher_round.webp
Normal file
|
After Width: | Height: | Size: 2.6 KiB |
|
Before Width: | Height: | Size: 11 KiB |
BIN
android/app/src/main/res/mipmap-xhdpi/ic_launcher.webp
Normal file
|
After Width: | Height: | Size: 4.4 KiB |
|
Before Width: | Height: | Size: 11 KiB After Width: | Height: | Size: 11 KiB |
|
Before Width: | Height: | Size: 14 KiB |
BIN
android/app/src/main/res/mipmap-xhdpi/ic_launcher_round.webp
Normal file
|
After Width: | Height: | Size: 5.5 KiB |
|
Before Width: | Height: | Size: 18 KiB |
BIN
android/app/src/main/res/mipmap-xxhdpi/ic_launcher.webp
Normal file
|
After Width: | Height: | Size: 7.2 KiB |
|
Before Width: | Height: | Size: 18 KiB After Width: | Height: | Size: 18 KiB |
|
Before Width: | Height: | Size: 22 KiB |
BIN
android/app/src/main/res/mipmap-xxhdpi/ic_launcher_round.webp
Normal file
|
After Width: | Height: | Size: 8.9 KiB |
|
Before Width: | Height: | Size: 25 KiB |
BIN
android/app/src/main/res/mipmap-xxxhdpi/ic_launcher.webp
Normal file
|
After Width: | Height: | Size: 9.9 KiB |
|
Before Width: | Height: | Size: 24 KiB After Width: | Height: | Size: 24 KiB |
|
Before Width: | Height: | Size: 30 KiB |
BIN
android/app/src/main/res/mipmap-xxxhdpi/ic_launcher_round.webp
Normal file
|
After Width: | Height: | Size: 12 KiB |
|
|
@ -1,5 +1,5 @@
|
|||
<resources>
|
||||
<string name="app_name">test-application</string>
|
||||
<string name="app_name">Tones</string>
|
||||
<string name="expo_splash_screen_resize_mode" translatable="false">contain</string>
|
||||
<string name="expo_splash_screen_status_bar_translucent" translatable="false">false</string>
|
||||
<string name="expo_system_ui_user_interface_style" translatable="false">automatic</string>
|
||||
|
|
|
|||
|
|
@ -1,17 +1,13 @@
|
|||
<resources xmlns:tools="http://schemas.android.com/tools">
|
||||
<style name="AppTheme" parent="Theme.AppCompat.Light.NoActionBar">
|
||||
<item name="android:textColor">@android:color/black</item>
|
||||
<item name="android:editTextStyle">@style/ResetEditText</item>
|
||||
<style name="AppTheme" parent="Theme.AppCompat.DayNight.NoActionBar">
|
||||
<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="android:statusBarColor">#ffffff</item>
|
||||
</style>
|
||||
<style name="ResetEditText" parent="@android:style/Widget.EditText">
|
||||
<item name="android:padding">0dp</item>
|
||||
<item name="android:textColorHint">#c8c8c8</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 name="Theme.App.SplashScreen" parent="Theme.SplashScreen">
|
||||
<item name="windowSplashScreenBackground">@color/splashscreen_background</item>
|
||||
<item name="windowSplashScreenAnimatedIcon">@drawable/splashscreen_logo</item>
|
||||
<item name="postSplashScreenTheme">@style/AppTheme</item>
|
||||
</style>
|
||||
</resources>
|
||||
|
|
@ -1,41 +1,38 @@
|
|||
// Top-level build file where you can add configuration options common to all sub-projects/modules.
|
||||
|
||||
buildscript {
|
||||
ext {
|
||||
buildToolsVersion = findProperty('android.buildToolsVersion') ?: '34.0.0'
|
||||
minSdkVersion = Integer.parseInt(findProperty('android.minSdkVersion') ?: '23')
|
||||
compileSdkVersion = Integer.parseInt(findProperty('android.compileSdkVersion') ?: '34')
|
||||
targetSdkVersion = Integer.parseInt(findProperty('android.targetSdkVersion') ?: '34')
|
||||
kotlinVersion = findProperty('android.kotlinVersion') ?: '1.9.23'
|
||||
|
||||
ndkVersion = "26.1.10909125"
|
||||
}
|
||||
repositories {
|
||||
google()
|
||||
mavenCentral()
|
||||
}
|
||||
dependencies {
|
||||
classpath('com.android.tools.build:gradle')
|
||||
classpath('com.facebook.react:react-native-gradle-plugin')
|
||||
classpath('org.jetbrains.kotlin:kotlin-gradle-plugin')
|
||||
}
|
||||
repositories {
|
||||
google()
|
||||
mavenCentral()
|
||||
}
|
||||
dependencies {
|
||||
classpath 'com.google.gms:google-services:4.4.1'
|
||||
classpath('com.android.tools.build:gradle')
|
||||
classpath('com.facebook.react:react-native-gradle-plugin')
|
||||
classpath('org.jetbrains.kotlin:kotlin-gradle-plugin')
|
||||
}
|
||||
}
|
||||
|
||||
apply plugin: "com.facebook.react.rootproject"
|
||||
def reactNativeAndroidDir = new File(
|
||||
providers.exec {
|
||||
workingDir(rootDir)
|
||||
commandLine("node", "--print", "require.resolve('react-native/package.json')")
|
||||
}.standardOutput.asText.get().trim(),
|
||||
"../android"
|
||||
)
|
||||
|
||||
allprojects {
|
||||
repositories {
|
||||
maven {
|
||||
// All of React Native (JS, Obj-C sources, Android binaries) is installed from npm
|
||||
url(new File(['node', '--print', "require.resolve('react-native/package.json')"].execute(null, rootDir).text.trim(), '../android'))
|
||||
}
|
||||
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' }
|
||||
repositories {
|
||||
maven {
|
||||
// All of React Native (JS, Obj-C sources, Android binaries) is installed from npm
|
||||
url(reactNativeAndroidDir)
|
||||
}
|
||||
|
||||
google()
|
||||
mavenCentral()
|
||||
maven { url 'https://www.jitpack.io' }
|
||||
}
|
||||
}
|
||||
|
||||
apply plugin: "expo-root-project"
|
||||
apply plugin: "com.facebook.react.rootproject"
|
||||
|
|
|
|||
|
|
@ -22,8 +22,8 @@ org.gradle.jvmargs=-Xmx2048m -XX:MaxMetaspaceSize=512m
|
|||
# https://developer.android.com/topic/libraries/support-library/androidx-rn
|
||||
android.useAndroidX=true
|
||||
|
||||
# Automatically convert third-party libraries to use AndroidX
|
||||
android.enableJetifier=true
|
||||
# Enable AAPT2 PNG crunching
|
||||
android.enablePngCrunchInReleaseBuilds=true
|
||||
|
||||
# Use this property to specify which architecture you want to build.
|
||||
# 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
|
||||
# to write custom TurboModules/Fabric components OR use libraries that
|
||||
# are providing them.
|
||||
newArchEnabled=false
|
||||
newArchEnabled=true
|
||||
|
||||
# Use this property to enable or disable the Hermes JS engine.
|
||||
# If set to false, you will be using JSC instead.
|
||||
|
|
@ -54,3 +54,6 @@ EX_DEV_CLIENT_NETWORK_INSPECTOR=true
|
|||
|
||||
# Use legacy packaging to compress native libraries in the resulting APK.
|
||||
expo.useLegacyPackaging=false
|
||||
|
||||
# Whether the app is configured to use edge-to-edge via the app config or `react-native-edge-to-edge` plugin
|
||||
expo.edgeToEdgeEnabled=false
|
||||
BIN
android/gradle/wrapper/gradle-wrapper.jar
vendored
|
|
@ -1,6 +1,6 @@
|
|||
distributionBase=GRADLE_USER_HOME
|
||||
distributionPath=wrapper/dists
|
||||
distributionUrl=https\://services.gradle.org/distributions/gradle-8.6-all.zip
|
||||
distributionUrl=https\://services.gradle.org/distributions/gradle-8.13-bin.zip
|
||||
networkTimeout=10000
|
||||
validateDistributionUrl=true
|
||||
zipStoreBase=GRADLE_USER_HOME
|
||||
|
|
|
|||
6
android/gradlew
vendored
Executable file → Normal file
|
|
@ -15,6 +15,8 @@
|
|||
# See the License for the specific language governing permissions and
|
||||
# limitations under the License.
|
||||
#
|
||||
# SPDX-License-Identifier: Apache-2.0
|
||||
#
|
||||
|
||||
##############################################################################
|
||||
#
|
||||
|
|
@ -55,7 +57,7 @@
|
|||
# Darwin, MinGW, and NonStop.
|
||||
#
|
||||
# (3) This script is generated from the Groovy template
|
||||
# https://github.com/gradle/gradle/blob/HEAD/subprojects/plugins/src/main/resources/org/gradle/api/internal/plugins/unixStartScript.txt
|
||||
# https://github.com/gradle/gradle/blob/HEAD/platforms/jvm/plugins-application/src/main/resources/org/gradle/api/internal/plugins/unixStartScript.txt
|
||||
# within the Gradle project.
|
||||
#
|
||||
# You can find Gradle at https://github.com/gradle/gradle/.
|
||||
|
|
@ -84,7 +86,7 @@ done
|
|||
# shellcheck disable=SC2034
|
||||
APP_BASE_NAME=${0##*/}
|
||||
# Discard cd standard output in case $CDPATH is set (https://github.com/gradle/gradle/issues/25036)
|
||||
APP_HOME=$( cd "${APP_HOME:-./}" > /dev/null && pwd -P ) || exit
|
||||
APP_HOME=$( cd -P "${APP_HOME:-./}" > /dev/null && printf '%s\n' "$PWD" ) || exit
|
||||
|
||||
# Use the maximum available, or set MAX_FD != -1 to use that value.
|
||||
MAX_FD=maximum
|
||||
|
|
|
|||
186
android/gradlew.bat
vendored
|
|
@ -1,92 +1,94 @@
|
|||
@rem
|
||||
@rem Copyright 2015 the original author or authors.
|
||||
@rem
|
||||
@rem Licensed under the Apache License, Version 2.0 (the "License");
|
||||
@rem you may not use this file except in compliance with the License.
|
||||
@rem You may obtain a copy of the License at
|
||||
@rem
|
||||
@rem https://www.apache.org/licenses/LICENSE-2.0
|
||||
@rem
|
||||
@rem Unless required by applicable law or agreed to in writing, software
|
||||
@rem distributed under the License is distributed on an "AS IS" BASIS,
|
||||
@rem WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
@rem See the License for the specific language governing permissions and
|
||||
@rem limitations under the License.
|
||||
@rem
|
||||
|
||||
@if "%DEBUG%"=="" @echo off
|
||||
@rem ##########################################################################
|
||||
@rem
|
||||
@rem Gradle startup script for Windows
|
||||
@rem
|
||||
@rem ##########################################################################
|
||||
|
||||
@rem Set local scope for the variables with windows NT shell
|
||||
if "%OS%"=="Windows_NT" setlocal
|
||||
|
||||
set DIRNAME=%~dp0
|
||||
if "%DIRNAME%"=="" set DIRNAME=.
|
||||
@rem This is normally unused
|
||||
set APP_BASE_NAME=%~n0
|
||||
set APP_HOME=%DIRNAME%
|
||||
|
||||
@rem Resolve any "." and ".." in APP_HOME to make it shorter.
|
||||
for %%i in ("%APP_HOME%") do set APP_HOME=%%~fi
|
||||
|
||||
@rem Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script.
|
||||
set DEFAULT_JVM_OPTS="-Xmx64m" "-Xms64m"
|
||||
|
||||
@rem Find java.exe
|
||||
if defined JAVA_HOME goto findJavaFromJavaHome
|
||||
|
||||
set JAVA_EXE=java.exe
|
||||
%JAVA_EXE% -version >NUL 2>&1
|
||||
if %ERRORLEVEL% equ 0 goto execute
|
||||
|
||||
echo. 1>&2
|
||||
echo ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH. 1>&2
|
||||
echo. 1>&2
|
||||
echo Please set the JAVA_HOME variable in your environment to match the 1>&2
|
||||
echo location of your Java installation. 1>&2
|
||||
|
||||
goto fail
|
||||
|
||||
:findJavaFromJavaHome
|
||||
set JAVA_HOME=%JAVA_HOME:"=%
|
||||
set JAVA_EXE=%JAVA_HOME%/bin/java.exe
|
||||
|
||||
if exist "%JAVA_EXE%" goto execute
|
||||
|
||||
echo. 1>&2
|
||||
echo ERROR: JAVA_HOME is set to an invalid directory: %JAVA_HOME% 1>&2
|
||||
echo. 1>&2
|
||||
echo Please set the JAVA_HOME variable in your environment to match the 1>&2
|
||||
echo location of your Java installation. 1>&2
|
||||
|
||||
goto fail
|
||||
|
||||
:execute
|
||||
@rem Setup the command line
|
||||
|
||||
set CLASSPATH=%APP_HOME%\gradle\wrapper\gradle-wrapper.jar
|
||||
|
||||
|
||||
@rem Execute Gradle
|
||||
"%JAVA_EXE%" %DEFAULT_JVM_OPTS% %JAVA_OPTS% %GRADLE_OPTS% "-Dorg.gradle.appname=%APP_BASE_NAME%" -classpath "%CLASSPATH%" org.gradle.wrapper.GradleWrapperMain %*
|
||||
|
||||
:end
|
||||
@rem End local scope for the variables with windows NT shell
|
||||
if %ERRORLEVEL% equ 0 goto mainEnd
|
||||
|
||||
:fail
|
||||
rem Set variable GRADLE_EXIT_CONSOLE if you need the _script_ return code instead of
|
||||
rem the _cmd.exe /c_ return code!
|
||||
set EXIT_CODE=%ERRORLEVEL%
|
||||
if %EXIT_CODE% equ 0 set EXIT_CODE=1
|
||||
if not ""=="%GRADLE_EXIT_CONSOLE%" exit %EXIT_CODE%
|
||||
exit /b %EXIT_CODE%
|
||||
|
||||
:mainEnd
|
||||
if "%OS%"=="Windows_NT" endlocal
|
||||
|
||||
:omega
|
||||
@rem
|
||||
@rem Copyright 2015 the original author or authors.
|
||||
@rem
|
||||
@rem Licensed under the Apache License, Version 2.0 (the "License");
|
||||
@rem you may not use this file except in compliance with the License.
|
||||
@rem You may obtain a copy of the License at
|
||||
@rem
|
||||
@rem https://www.apache.org/licenses/LICENSE-2.0
|
||||
@rem
|
||||
@rem Unless required by applicable law or agreed to in writing, software
|
||||
@rem distributed under the License is distributed on an "AS IS" BASIS,
|
||||
@rem WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
@rem See the License for the specific language governing permissions and
|
||||
@rem limitations under the License.
|
||||
@rem
|
||||
@rem SPDX-License-Identifier: Apache-2.0
|
||||
@rem
|
||||
|
||||
@if "%DEBUG%"=="" @echo off
|
||||
@rem ##########################################################################
|
||||
@rem
|
||||
@rem Gradle startup script for Windows
|
||||
@rem
|
||||
@rem ##########################################################################
|
||||
|
||||
@rem Set local scope for the variables with windows NT shell
|
||||
if "%OS%"=="Windows_NT" setlocal
|
||||
|
||||
set DIRNAME=%~dp0
|
||||
if "%DIRNAME%"=="" set DIRNAME=.
|
||||
@rem This is normally unused
|
||||
set APP_BASE_NAME=%~n0
|
||||
set APP_HOME=%DIRNAME%
|
||||
|
||||
@rem Resolve any "." and ".." in APP_HOME to make it shorter.
|
||||
for %%i in ("%APP_HOME%") do set APP_HOME=%%~fi
|
||||
|
||||
@rem Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script.
|
||||
set DEFAULT_JVM_OPTS="-Xmx64m" "-Xms64m"
|
||||
|
||||
@rem Find java.exe
|
||||
if defined JAVA_HOME goto findJavaFromJavaHome
|
||||
|
||||
set JAVA_EXE=java.exe
|
||||
%JAVA_EXE% -version >NUL 2>&1
|
||||
if %ERRORLEVEL% equ 0 goto execute
|
||||
|
||||
echo. 1>&2
|
||||
echo ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH. 1>&2
|
||||
echo. 1>&2
|
||||
echo Please set the JAVA_HOME variable in your environment to match the 1>&2
|
||||
echo location of your Java installation. 1>&2
|
||||
|
||||
goto fail
|
||||
|
||||
:findJavaFromJavaHome
|
||||
set JAVA_HOME=%JAVA_HOME:"=%
|
||||
set JAVA_EXE=%JAVA_HOME%/bin/java.exe
|
||||
|
||||
if exist "%JAVA_EXE%" goto execute
|
||||
|
||||
echo. 1>&2
|
||||
echo ERROR: JAVA_HOME is set to an invalid directory: %JAVA_HOME% 1>&2
|
||||
echo. 1>&2
|
||||
echo Please set the JAVA_HOME variable in your environment to match the 1>&2
|
||||
echo location of your Java installation. 1>&2
|
||||
|
||||
goto fail
|
||||
|
||||
:execute
|
||||
@rem Setup the command line
|
||||
|
||||
set CLASSPATH=%APP_HOME%\gradle\wrapper\gradle-wrapper.jar
|
||||
|
||||
|
||||
@rem Execute Gradle
|
||||
"%JAVA_EXE%" %DEFAULT_JVM_OPTS% %JAVA_OPTS% %GRADLE_OPTS% "-Dorg.gradle.appname=%APP_BASE_NAME%" -classpath "%CLASSPATH%" org.gradle.wrapper.GradleWrapperMain %*
|
||||
|
||||
:end
|
||||
@rem End local scope for the variables with windows NT shell
|
||||
if %ERRORLEVEL% equ 0 goto mainEnd
|
||||
|
||||
:fail
|
||||
rem Set variable GRADLE_EXIT_CONSOLE if you need the _script_ return code instead of
|
||||
rem the _cmd.exe /c_ return code!
|
||||
set EXIT_CODE=%ERRORLEVEL%
|
||||
if %EXIT_CODE% equ 0 set EXIT_CODE=1
|
||||
if not ""=="%GRADLE_EXIT_CONSOLE%" exit %EXIT_CODE%
|
||||
exit /b %EXIT_CODE%
|
||||
|
||||
:mainEnd
|
||||
if "%OS%"=="Windows_NT" endlocal
|
||||
|
||||
:omega
|
||||
|
|
|
|||
|
|
@ -1,18 +1,39 @@
|
|||
rootProject.name = 'test-application'
|
||||
|
||||
dependencyResolutionManagement {
|
||||
versionCatalogs {
|
||||
reactAndroidLibs {
|
||||
from(files(new File(["node", "--print", "require.resolve('react-native/package.json')"].execute(null, rootDir).text.trim(), "../gradle/libs.versions.toml")))
|
||||
}
|
||||
}
|
||||
pluginManagement {
|
||||
def reactNativeGradlePlugin = new File(
|
||||
providers.exec {
|
||||
workingDir(rootDir)
|
||||
commandLine("node", "--print", "require.resolve('@react-native/gradle-plugin/package.json', { paths: [require.resolve('react-native/package.json')] })")
|
||||
}.standardOutput.asText.get().trim()
|
||||
).getParentFile().absolutePath
|
||||
includeBuild(reactNativeGradlePlugin)
|
||||
|
||||
def expoPluginsPath = new File(
|
||||
providers.exec {
|
||||
workingDir(rootDir)
|
||||
commandLine("node", "--print", "require.resolve('expo-modules-autolinking/package.json', { paths: [require.resolve('expo/package.json')] })")
|
||||
}.standardOutput.asText.get().trim(),
|
||||
"../android/expo-gradle-plugin"
|
||||
).absolutePath
|
||||
includeBuild(expoPluginsPath)
|
||||
}
|
||||
|
||||
apply from: new File(["node", "--print", "require.resolve('expo/package.json')"].execute(null, rootDir).text.trim(), "../scripts/autolinking.gradle");
|
||||
useExpoModules()
|
||||
plugins {
|
||||
id("com.facebook.react.settings")
|
||||
id("expo-autolinking-settings")
|
||||
}
|
||||
|
||||
apply from: new File(["node", "--print", "require.resolve('@react-native-community/cli-platform-android/package.json', { paths: [require.resolve('react-native/package.json')] })"].execute(null, rootDir).text.trim(), "../native_modules.gradle");
|
||||
applyNativeModulesSettingsGradle(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'
|
||||
|
||||
expoAutolinking.useExpoVersionCatalog()
|
||||
|
||||
include ':app'
|
||||
includeBuild(new File(["node", "--print", "require.resolve('@react-native/gradle-plugin/package.json', { paths: [require.resolve('react-native/package.json')] })"].execute(null, rootDir).text.trim()).getParentFile())
|
||||
includeBuild(expoAutolinking.reactNativeGradlePlugin)
|
||||
|
|
|
|||
28
app.json
|
|
@ -1,7 +1,7 @@
|
|||
{
|
||||
"expo": {
|
||||
"name": "Tones",
|
||||
"slug": "Tones",
|
||||
"slug": "tones",
|
||||
"version": "1.0.1",
|
||||
"orientation": "portrait",
|
||||
"icon": "./assets/images/icon.png",
|
||||
|
|
@ -13,22 +13,40 @@
|
|||
"backgroundColor": "#ffffff"
|
||||
},
|
||||
"ios": {
|
||||
"entitlements": {
|
||||
"aps-environment": "production"
|
||||
},
|
||||
"infoPlist": {
|
||||
"UIBackgroundModes": ["remote-notification"]
|
||||
},
|
||||
"supportsTablet": true,
|
||||
"bundleIdentifier": "com.anonymous.testapplication"
|
||||
"bundleIdentifier": "com.mattdimegs.tones",
|
||||
"googleServicesFile": "./GoogleServices/GoogleService-Info.plist"
|
||||
},
|
||||
"android": {
|
||||
"adaptiveIcon": {
|
||||
"foregroundImage": "./assets/images/adaptive-icon.png",
|
||||
"backgroundColor": "#ffffff"
|
||||
},
|
||||
"package": "com.anonymous.testapplication"
|
||||
"package": "com.mattdimegs.tones",
|
||||
"googleServicesFile": "./GoogleServices/google-services.json"
|
||||
},
|
||||
"plugins": [
|
||||
"expo-router",
|
||||
"expo-font"
|
||||
"expo-font",
|
||||
"expo-web-browser"
|
||||
],
|
||||
"experiments": {
|
||||
"typedRoutes": true
|
||||
}
|
||||
},
|
||||
"extra": {
|
||||
"router": {
|
||||
"origin": false
|
||||
},
|
||||
"eas": {
|
||||
"projectId": "6903a306-dafd-42ab-b010-f0c8205269ad"
|
||||
}
|
||||
},
|
||||
"owner": "tones-bd"
|
||||
}
|
||||
}
|
||||
|
|
|
|||
72
app/_layout.jsx
Normal file
|
|
@ -0,0 +1,72 @@
|
|||
import React, { useState, useEffect } from 'react';
|
||||
import { router, Stack } from 'expo-router';
|
||||
import { AuthProvider, GlobalVariablesProvider, WebSocketProvider } from '@/contexts';
|
||||
import { useNotifications, useWebSocketContext } from '@/hooks';
|
||||
import { useAuth } from '@/contexts/AuthContext';
|
||||
|
||||
function AppTest() {
|
||||
const [ oldMessage, setOldMessage ] = useState(1);
|
||||
const { user } = useAuth();
|
||||
const { lastMessage } = useWebSocketContext();
|
||||
const { schedulePushNotification } = useNotifications();
|
||||
const [isReady, setIsReady] = useState(false);
|
||||
|
||||
useEffect(() => {
|
||||
setIsReady(true);
|
||||
}, []);
|
||||
|
||||
useEffect(() => {
|
||||
if (isReady) {
|
||||
if (user) {
|
||||
// Ok to Leave Console Log... Displays the name so you know what you are signed in as.
|
||||
console.log('user: ', user?.displayName || 'Not Found');
|
||||
router.replace('./incidents');
|
||||
} else {
|
||||
router.replace('/login');
|
||||
}
|
||||
}
|
||||
}, [isReady, user]);
|
||||
|
||||
const parseAddress = (data) => {
|
||||
const { Address } = data;
|
||||
const { StreetAddress, AddressApartment, Town, State } = Address;
|
||||
const response = `${StreetAddress}${AddressApartment ? ` - ${AddressApartment}` : ''} ${Town}, ${State}`
|
||||
return response;
|
||||
}
|
||||
|
||||
useEffect(() => {
|
||||
if (lastMessage) {
|
||||
const parsedMessage = JSON?.parse(lastMessage);
|
||||
if (parsedMessage?.data && new Date(oldMessage)?.getTime() < new Date(parsedMessage?.timestamp)?.getTime()) {
|
||||
setOldMessage(new Date(parsedMessage?.timestamp)?.getTime());
|
||||
schedulePushNotification(
|
||||
`${parsedMessage?.data?.Response?.ServiceName} - ${parsedMessage?.data?.Incident?.IncNatureCode}`,
|
||||
`${parsedMessage?.data?.Incident?.IncNature}\n${parseAddress(parsedMessage?.data)}`,
|
||||
parsedMessage?.data
|
||||
);
|
||||
}
|
||||
}
|
||||
}, [lastMessage]);
|
||||
|
||||
return (
|
||||
<Stack
|
||||
screenOptions={{
|
||||
gestureEnabled: false,
|
||||
headerBackVisible: false,
|
||||
headerShown: false
|
||||
}}
|
||||
/>
|
||||
)
|
||||
}
|
||||
|
||||
export default function App() {
|
||||
return (
|
||||
<GlobalVariablesProvider>
|
||||
<WebSocketProvider>
|
||||
<AuthProvider>
|
||||
<AppTest />
|
||||
</AuthProvider>
|
||||
</WebSocketProvider>
|
||||
</GlobalVariablesProvider>
|
||||
);
|
||||
}
|
||||
|
|
@ -1,26 +0,0 @@
|
|||
import React, { useEffect } from 'react';
|
||||
import { router, Stack } from 'expo-router';
|
||||
import { WebSocketProvider } from '../contexts/WebSocketContext';
|
||||
|
||||
export const unstable_settings = {
|
||||
initialRouteName: 'login',
|
||||
};
|
||||
|
||||
export default function App() {
|
||||
|
||||
useEffect(() => {
|
||||
router.replace('/login');
|
||||
}, []);
|
||||
|
||||
return (
|
||||
<WebSocketProvider>
|
||||
<Stack
|
||||
screenOptions={{
|
||||
headerShown: false
|
||||
}}
|
||||
>
|
||||
<Stack.Screen name="login" />
|
||||
</Stack>
|
||||
</WebSocketProvider>
|
||||
);
|
||||
}
|
||||
1600
app/call.jsx
|
|
@ -42,7 +42,7 @@ export default function TabTwoScreen() {
|
|||
<ThemedText type="defaultSemiBold">@3x</ThemedText> suffixes to provide files for
|
||||
different screen densities
|
||||
</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">
|
||||
<ThemedText type="link">Learn more</ThemedText>
|
||||
</ExternalLink>
|
||||
|
|
|
|||
|
|
@ -1,366 +1,421 @@
|
|||
import React, { useState, useRef, useEffect } from 'react';
|
||||
import styled from 'styled-components';
|
||||
import { useCallFeed } from '../hooks/useCallFeed';
|
||||
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 React, { useState, useRef, useEffect } from "react";
|
||||
import styled from "styled-components";
|
||||
import { useCallFeed } from "@/hooks";
|
||||
import { router } from "expo-router";
|
||||
import {
|
||||
PageHeader,
|
||||
PageFooter,
|
||||
} from '../components/generalHelpers.jsx';
|
||||
import { Ionicons } from '@expo/vector-icons';
|
||||
Platform,
|
||||
Linking,
|
||||
View,
|
||||
ScrollView,
|
||||
Text,
|
||||
TouchableOpacity,
|
||||
} from "react-native";
|
||||
import { StatusBar } from "expo-status-bar";
|
||||
import { SafeAreaView } from "react-native-safe-area-context";
|
||||
import { PageHeader, PageFooter } from "@/components/generalHelpers.jsx";
|
||||
import { Ionicons } from "@expo/vector-icons";
|
||||
import { AccidentAndEmergency } from "healthicons-react-native/dist/outline";
|
||||
import ActionSheet from 'react-native-actions-sheet';
|
||||
import ActionSheet from "react-native-actions-sheet";
|
||||
|
||||
const DepartmentActionSheet = styled(ActionSheet)``;
|
||||
|
||||
function toBase64Unicode(str) {
|
||||
return btoa(
|
||||
new TextEncoder()
|
||||
.encode(str)
|
||||
.reduce((data, byte) => data + String.fromCharCode(byte), "")
|
||||
);
|
||||
}
|
||||
|
||||
export default function Incidents() {
|
||||
const actionSheetRef = useRef(null);
|
||||
const callFeed = useCallFeed();
|
||||
const actionSheetRef = useRef(null);
|
||||
const callFeed = useCallFeed();
|
||||
|
||||
const {
|
||||
departments,
|
||||
callIconMap,
|
||||
callDetails,
|
||||
callColorSelector,
|
||||
formatCallTimePast,
|
||||
formatCallDateTime
|
||||
} = callFeed;
|
||||
const {
|
||||
departments,
|
||||
callIconMap,
|
||||
callDetails,
|
||||
callColorSelector,
|
||||
formatCallTimePast,
|
||||
formatCallDateTime,
|
||||
} = callFeed;
|
||||
|
||||
const sortedAndFilteredCalls = callDetails
|
||||
.sort((a, b) => new Date(b.timestamp) - new Date(a.timestamp))
|
||||
.filter((item, index, self) => {
|
||||
return index === self.findIndex(i => {
|
||||
return `${i?.data?.Incident?.IncID}${i?.data?.Response?.ServiceName}` === `${item?.data?.Incident?.IncID}${item?.data?.Response?.ServiceName}`
|
||||
});
|
||||
});
|
||||
const sortedAndFilteredCalls =
|
||||
callDetails
|
||||
.sort((a, b) => new Date(b.timestamp) - new Date(a.timestamp))
|
||||
.filter((item, index, self) => {
|
||||
return (
|
||||
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 {
|
||||
departmentTypeMap,
|
||||
accountDetails,
|
||||
deptList,
|
||||
setDeptList,
|
||||
selectedDepartment,
|
||||
setSelectedDepartment,
|
||||
updateSelectedDepartment,
|
||||
selectedDepartmentColorPicker,
|
||||
} = departments;
|
||||
const {
|
||||
departmentTypeMap,
|
||||
accountDetails,
|
||||
deptList,
|
||||
setDeptList,
|
||||
selectedDepartment,
|
||||
setSelectedDepartment,
|
||||
updateSelectedDepartment,
|
||||
selectedDepartmentColorPicker,
|
||||
} = departments;
|
||||
|
||||
return (
|
||||
<React.Fragment>
|
||||
<PageHeader>
|
||||
<View
|
||||
style={{
|
||||
flexDirection: 'column',
|
||||
height: 80,
|
||||
alignItems: 'center',
|
||||
justifyContent: 'flex-end',
|
||||
paddingBottom: 7
|
||||
}}
|
||||
>
|
||||
<TouchableOpacity
|
||||
style={{
|
||||
borderRadius: 6,
|
||||
elevation: 3,
|
||||
backgroundColor: '#fff',
|
||||
shadowOffset: { width: 0, height: 0 },
|
||||
shadowColor: '#333',
|
||||
shadowOpacity: .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>
|
||||
</PageHeader>
|
||||
<ScrollView>
|
||||
<StatusBar style="dark" />
|
||||
<SafeAreaView />
|
||||
<View style={{ flexDirection: 'column', padding: 20 }}>
|
||||
{sortedAndFilteredCalls?.length ? (
|
||||
sortedAndFilteredCalls?.map((callItem, index) => {
|
||||
const { data: call, timestamp } = callItem;
|
||||
const { Incident, Address, Response } = call;
|
||||
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={{ 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',
|
||||
}}
|
||||
return (
|
||||
<React.Fragment>
|
||||
<PageHeader
|
||||
centerHeader={
|
||||
<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();
|
||||
}}
|
||||
>
|
||||
<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
|
||||
)
|
||||
}}
|
||||
<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={{
|
||||
borderRadius: 12,
|
||||
elevation: 3,
|
||||
backgroundColor: "#fff",
|
||||
shadowOffset: { width: 0, height: 0 },
|
||||
shadowColor: callColorSelector(
|
||||
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,
|
||||
},
|
||||
]}
|
||||
>
|
||||
<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>
|
||||
{` - ${addressApartment}`}
|
||||
</Text>
|
||||
) : null}
|
||||
<Text
|
||||
style={[
|
||||
{
|
||||
color: "black",
|
||||
fontSize: 12,
|
||||
fontWeight: 600,
|
||||
},
|
||||
]}
|
||||
>
|
||||
{` ${town}, ${state}`}
|
||||
</Text>
|
||||
</View>
|
||||
);
|
||||
})}
|
||||
</View>
|
||||
</DepartmentActionSheet>
|
||||
</React.Fragment>
|
||||
)
|
||||
}
|
||||
)}
|
||||
<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
|
||||
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>
|
||||
);
|
||||
}
|
||||
|
|
|
|||
216
app/login.jsx
|
|
@ -1,5 +1,5 @@
|
|||
import React, { useState, useEffect } from 'react';
|
||||
import { View, Text } from 'react-native';
|
||||
import { View, Text, ScrollView, KeyboardAvoidingView, Platform } from 'react-native';
|
||||
import { StatusBar } from 'expo-status-bar';
|
||||
import { useFormik } from 'formik';
|
||||
import { SafeAreaView } from 'react-native-safe-area-context';
|
||||
|
|
@ -20,111 +20,123 @@ import {
|
|||
ExtraText,
|
||||
TextLinkContent,
|
||||
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() {
|
||||
const [hidePassword, setHidePassword] = useState(true);
|
||||
const [loginButtonDisabled, setLoginButtonDisabled] = useState(true);
|
||||
const [auth, setAuth] = useState(false);
|
||||
const [hidePassword, setHidePassword] = useState(true);
|
||||
const [loginButtonDisabled, setLoginButtonDisabled] = useState(true);
|
||||
const [error, setError] = useState('');
|
||||
const [loading, setLoading] = useState(false);
|
||||
const { expoPushToken } = useNotifications();
|
||||
|
||||
const formik = useFormik({
|
||||
initialValues: {
|
||||
number: '',
|
||||
password: ''
|
||||
},
|
||||
onSubmit: (values) => {
|
||||
values.number = values.number.replace(/[()\-\s]/g, '');
|
||||
console.log(values);
|
||||
setAuth(true);
|
||||
},
|
||||
});
|
||||
|
||||
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) {
|
||||
const formik = useFormik({
|
||||
initialValues: {
|
||||
email: '',
|
||||
password: ''
|
||||
},
|
||||
onSubmit: async (values) => {
|
||||
setError('');
|
||||
setLoading(true);
|
||||
try {
|
||||
await signInWithEmailAndPassword(auth, values.email, values.password);
|
||||
router.replace('./incidents');
|
||||
} catch (err) {
|
||||
setError(err.message);
|
||||
} finally {
|
||||
setLoading(false);
|
||||
}
|
||||
}, [auth])
|
||||
|
||||
return (
|
||||
<React.Fragment>
|
||||
<PageHeader>
|
||||
<View style={{ flexDirection: 'row', height: 80, alignItems: 'center' }} />
|
||||
</PageHeader>
|
||||
<StyledContainer>
|
||||
<StatusBar style="dark" />
|
||||
<SafeAreaView />
|
||||
<InnerContainer>
|
||||
<PageImage resizeMode="cover" source={require('./../assets/images/tones-logo.png')} />
|
||||
<Title>Tones</Title>
|
||||
<SubTitle>Account Login</SubTitle>
|
||||
<StyledFormArea>
|
||||
<LoginTextInput
|
||||
label="Phone Number"
|
||||
icon="call-outline"
|
||||
placeholder="123-456-7890"
|
||||
placeholderTextColor="gray"
|
||||
onChangeText={formik.handleChange('number')}
|
||||
onBlur={formik.handleBlur('number')}
|
||||
value={formik.values.number.replace(/^(\d{3})(\d{3})(\d+)$/, "($1) $2-$3")}
|
||||
keyboardType="number-pad"
|
||||
maxLength={14}
|
||||
/>
|
||||
<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>
|
||||
},
|
||||
});
|
||||
|
||||
const formValues = formik.values;
|
||||
|
||||
useEffect(() => {
|
||||
if (formValues) {
|
||||
if (formValues.email && formValues.password) {
|
||||
setLoginButtonDisabled(false);
|
||||
} else {
|
||||
setLoginButtonDisabled(true);
|
||||
}
|
||||
}
|
||||
}, [formValues]);
|
||||
|
||||
return (
|
||||
<View style={{ flex: 1 }}>
|
||||
<StatusBar style="dark" />
|
||||
<PageHeader>
|
||||
<View style={{ flexDirection: 'row', height: 80, alignItems: 'center' }} />
|
||||
</PageHeader>
|
||||
<KeyboardAvoidingView
|
||||
style={{ flex: 1 }}
|
||||
behavior={Platform.OS === 'ios' ? 'padding' : 'height'}
|
||||
keyboardVerticalOffset={0}
|
||||
>
|
||||
<ScrollView keyboardShouldPersistTaps="handled" contentContainerStyle={{ flexGrow: 1 }}>
|
||||
<StyledContainer>
|
||||
<SafeAreaView />
|
||||
<InnerContainer>
|
||||
<PageImage resizeMode="cover" source={require('./../assets/images/tones-logo.png')} />
|
||||
<Title>Tones</Title>
|
||||
<SubTitle>Account Login</SubTitle>
|
||||
<StyledFormArea>
|
||||
{error ? <MessageBox style={{ color: 'red' }}>{error}</MessageBox> : null}
|
||||
<LoginTextInput
|
||||
label="Email Address"
|
||||
icon="mail-outline"
|
||||
placeholder="test@organization.com"
|
||||
placeholderTextColor="gray"
|
||||
onChangeText={formik.handleChange('email')}
|
||||
onBlur={formik.handleBlur('email')}
|
||||
value={formik.values.email}
|
||||
keyboardType="email-address"
|
||||
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 />
|
||||
<ExtraView>
|
||||
<ExtraText>Don't have an account already? </ExtraText>
|
||||
<Link href='./register'>
|
||||
<TextLinkContent>Register</TextLinkContent>
|
||||
<Text>Temporary Area:</Text>
|
||||
<View>
|
||||
<Link href='./incidents'>
|
||||
<TextLinkContent>Incidents</TextLinkContent>
|
||||
</Link>
|
||||
</ExtraView>
|
||||
</StyledFormArea>
|
||||
<Line />
|
||||
<Text>Temporary Area:</Text>
|
||||
<View>
|
||||
<Link href='./incidents'>
|
||||
<TextLinkContent>Incidents</TextLinkContent>
|
||||
</Link>
|
||||
<Link href='./landing'>
|
||||
<TextLinkContent>Landing</TextLinkContent>
|
||||
</Link>
|
||||
</View>
|
||||
<Line />
|
||||
</InnerContainer>
|
||||
</StyledContainer>
|
||||
</React.Fragment>
|
||||
);
|
||||
}
|
||||
<Link href='./landing'>
|
||||
<TextLinkContent>Landing</TextLinkContent>
|
||||
</Link>
|
||||
</View>
|
||||
<Text>View Token: {expoPushToken}</Text>
|
||||
<Line />
|
||||
</InnerContainer>
|
||||
</StyledContainer>
|
||||
</ScrollView>
|
||||
</KeyboardAvoidingView>
|
||||
</View>
|
||||
);
|
||||
}
|
||||
285
app/register.jsx
|
|
@ -1,6 +1,10 @@
|
|||
import React, { useState, useEffect } from 'react';
|
||||
import * as Notifications from 'expo-notifications';
|
||||
import { router } from 'expo-router';
|
||||
import { View, ScrollView, Text, TouchableOpacity } from 'react-native';
|
||||
import { createUserWithEmailAndPassword, updateProfile } from 'firebase/auth';
|
||||
import { auth } from '@/contexts/firebase';
|
||||
import { useAuth } from '@/contexts/AuthContext';
|
||||
import { View, ScrollView, Text, TouchableOpacity, KeyboardAvoidingView, Platform } from 'react-native';
|
||||
import { StatusBar } from 'expo-status-bar';
|
||||
import { useFormik } from 'formik';
|
||||
import { SafeAreaView } from 'react-native-safe-area-context';
|
||||
|
|
@ -19,14 +23,16 @@ import {
|
|||
MessageBox,
|
||||
LoginTextInput,
|
||||
RegisterDropdownInput,
|
||||
} from '../components/generalHelpers.jsx';
|
||||
formatPhoneNumber
|
||||
} from '@/components/generalHelpers.jsx';
|
||||
|
||||
export default function Register() {
|
||||
|
||||
const [providerDropdownOpen, setProviderDropdownOpen] = useState(false);
|
||||
const [hidePassword, setHidePassword] = useState(true);
|
||||
const [registerButtonDisabled, setRegisterButtonDisabled] = useState(true);
|
||||
|
||||
const [error, setError] = useState('');
|
||||
const [loading, setLoading] = useState(false);
|
||||
const { user } = useAuth();
|
||||
|
||||
const formik = useFormik({
|
||||
initialValues: {
|
||||
|
|
@ -34,13 +40,64 @@ export default function Register() {
|
|||
lastName: '',
|
||||
number: '',
|
||||
provider: '',
|
||||
email: '',
|
||||
password: '',
|
||||
passwordConfirmation: ''
|
||||
email: '',
|
||||
password: '',
|
||||
passwordConfirmation: ''
|
||||
},
|
||||
onSubmit: (values) => {
|
||||
values.number = values.number.replace(/[()\-\s]/g, '');
|
||||
console.log(values);
|
||||
onSubmit: async (values) => {
|
||||
setError('');
|
||||
setLoading(true);
|
||||
try {
|
||||
const userCredential = await createUserWithEmailAndPassword(auth, values.email, values.password);
|
||||
await updateProfile(userCredential.user, {
|
||||
displayName: `${values.firstName} ${values.lastName}`
|
||||
});
|
||||
// Request permissions and get push token (native FCM if possible, else Expo token)
|
||||
let token = null;
|
||||
let tokenType = null;
|
||||
const { status: existingStatus } = await Notifications.getPermissionsAsync();
|
||||
let finalStatus = existingStatus;
|
||||
if (existingStatus !== 'granted') {
|
||||
const { status } = await Notifications.requestPermissionsAsync();
|
||||
finalStatus = status;
|
||||
}
|
||||
if (finalStatus === 'granted') {
|
||||
try {
|
||||
// Try to get native FCM token (works in dev/prod builds, not Expo Go)
|
||||
const deviceToken = await Notifications.getDevicePushTokenAsync({ provider: 'fcm' });
|
||||
if (deviceToken?.data) {
|
||||
token = deviceToken.data;
|
||||
tokenType = 'fcm';
|
||||
} else {
|
||||
// Fallback to Expo push token
|
||||
const expoToken = await Notifications.getExpoPushTokenAsync();
|
||||
token = expoToken.data;
|
||||
tokenType = 'expo';
|
||||
}
|
||||
} catch (e) {
|
||||
// Fallback to Expo push token if native fails
|
||||
const expoToken = await Notifications.getExpoPushTokenAsync();
|
||||
token = expoToken.data;
|
||||
tokenType = 'expo';
|
||||
}
|
||||
}
|
||||
|
||||
await postgresServices.createUser({
|
||||
firstName: values.firstName,
|
||||
lastName: values.lastName,
|
||||
number: values.number,
|
||||
email: values.email,
|
||||
provider: values.provider,
|
||||
departments: [],
|
||||
token,
|
||||
uid: userCredential.user.uid
|
||||
})
|
||||
router.replace('./incidents');
|
||||
} catch (err) {
|
||||
setError(err.message);
|
||||
} finally {
|
||||
setLoading(false);
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
|
|
@ -48,7 +105,8 @@ export default function Register() {
|
|||
|
||||
useEffect(() => {
|
||||
if (formValues) {
|
||||
if ((formValues.number.length === 14 || (formValues.number.length === 10 && !formValues.number.includes('('))) && formValues.email && formValues.firstName && formValues.lastName) {
|
||||
const regex = /^[^@]+@(?:[a-zA-Z0-9-]+\.)+[a-zA-Z0-9-]+$/;
|
||||
if ((formValues.number.length === 14 || (formValues.number.length === 10 && !formValues.number.includes('('))) && regex.test(formValues.email) && formValues.firstName && formValues.lastName) {
|
||||
if (formValues.password.length !== 0 && (formValues.password === formValues.passwordConfirmation)) {
|
||||
setRegisterButtonDisabled(false);
|
||||
} else {
|
||||
|
|
@ -62,106 +120,121 @@ export default function Register() {
|
|||
}
|
||||
}, [formValues])
|
||||
|
||||
useEffect(() => {
|
||||
if (user) {
|
||||
router.replace('./incidents');
|
||||
}
|
||||
}, [user]);
|
||||
|
||||
return (
|
||||
<View>
|
||||
<PageHeader>
|
||||
<View style={{ flexDirection: 'row', height: 80, alignItems: 'flex-end' }}>
|
||||
<View style={{ flex: 1 }}>
|
||||
<StatusBar style="dark" />
|
||||
<PageHeader
|
||||
leftHeader={
|
||||
<TouchableOpacity onPress={router.back} style={{ flexDirection: 'row', alignItems: 'center', paddingBottom: 5 }}>
|
||||
<Ionicons name="chevron-back-outline" size={22} color="red" style={{ paddingLeft: 20 }} />
|
||||
<Text style={{ color: 'red', fontWeight: 600 }}>Back to Login</Text>
|
||||
</TouchableOpacity>
|
||||
</View>
|
||||
</PageHeader>
|
||||
<ScrollView>
|
||||
<StyledContainer>
|
||||
<StatusBar style="dark" />
|
||||
</TouchableOpacity>}
|
||||
/>
|
||||
<KeyboardAvoidingView
|
||||
style={{ flex: 1 }}
|
||||
behavior={Platform.OS === 'ios' ? 'padding' : 'height'}
|
||||
keyboardVerticalOffset={0}
|
||||
>
|
||||
<ScrollView keyboardShouldPersistTaps="handled" contentContainerStyle={{ flexGrow: 1 }}>
|
||||
<SafeAreaView />
|
||||
<InnerContainer>
|
||||
<PageImage resizeMode="cover" source={require('./../assets/images/tones-logo.png')} />
|
||||
<Title>Tones</Title>
|
||||
<SubTitle>Account Register</SubTitle>
|
||||
<StyledFormArea>
|
||||
<LoginTextInput
|
||||
label="First Name"
|
||||
icon="person-outline"
|
||||
placeholder="Bud"
|
||||
placeholderTextColor="gray"
|
||||
onChangeText={formik.handleChange('firstName')}
|
||||
onBlur={formik.handleBlur('firstName')}
|
||||
value={formik.values.firstName}
|
||||
/>
|
||||
<LoginTextInput
|
||||
label="Last Name"
|
||||
icon="people-outline"
|
||||
placeholder="Doble"
|
||||
placeholderTextColor="gray"
|
||||
onChangeText={formik.handleChange('lastName')}
|
||||
onBlur={formik.handleBlur('lastName')}
|
||||
value={formik.values.lastName}
|
||||
/>
|
||||
<LoginTextInput
|
||||
label="Phone Number"
|
||||
icon="call-outline"
|
||||
placeholder="123-456-7890"
|
||||
placeholderTextColor="gray"
|
||||
onChangeText={formik.handleChange('number')}
|
||||
onBlur={formik.handleBlur('number')}
|
||||
value={formik.values.number.replace(/^(\d{3})(\d{3})(\d+)$/, "($1) $2-$3")}
|
||||
keyboardType="number-pad"
|
||||
maxLength={14}
|
||||
/>
|
||||
<RegisterDropdownInput
|
||||
label="Cellular Provider"
|
||||
isOpen={providerDropdownOpen}
|
||||
setOpen={setProviderDropdownOpen}
|
||||
selectedValue={formik.values.provider}
|
||||
onValueChange={formik.handleChange('provider')}
|
||||
menu={providerMenu}
|
||||
/>
|
||||
<LoginTextInput
|
||||
label="Email Address"
|
||||
icon="mail-outline"
|
||||
placeholder="test@organization.com"
|
||||
placeholderTextColor="gray"
|
||||
onChangeText={formik.handleChange('email')}
|
||||
onBlur={formik.handleBlur('email')}
|
||||
value={formik.values.email}
|
||||
keyboardType="email-address"
|
||||
/>
|
||||
<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}
|
||||
/>
|
||||
<LoginTextInput
|
||||
label="Confirm Password"
|
||||
icon="shield-checkmark-outline"
|
||||
placeholder="* * * * * *"
|
||||
placeholderTextColor="gray"
|
||||
onChangeText={formik.handleChange('passwordConfirmation')}
|
||||
onBlur={formik.handleBlur('passwordConfirmation')}
|
||||
value={formik.values.passwordConfirmation}
|
||||
secureTextEntry={hidePassword}
|
||||
isPassword
|
||||
hidePassword={hidePassword}
|
||||
setHidePassword={setHidePassword}
|
||||
/>
|
||||
<MessageBox>...</MessageBox>
|
||||
<StyledButton onPress={formik.handleSubmit} style={registerButtonDisabled ? {backgroundColor: 'grey'} : {}}>
|
||||
<ButtonText>Register</ButtonText>
|
||||
</StyledButton>
|
||||
</StyledFormArea>
|
||||
</InnerContainer>
|
||||
</StyledContainer>
|
||||
</ScrollView>
|
||||
<StyledContainer>
|
||||
<InnerContainer>
|
||||
<PageImage resizeMode="cover" source={require('./../assets/images/tones-logo.png')} />
|
||||
{error ? <MessageBox style={{ color: 'red' }}>{error}</MessageBox> : null}
|
||||
<Title>Tones</Title>
|
||||
<SubTitle>Account Register</SubTitle>
|
||||
<StyledFormArea>
|
||||
<LoginTextInput
|
||||
label="First Name"
|
||||
icon="person-outline"
|
||||
placeholder="Bud"
|
||||
placeholderTextColor="gray"
|
||||
onChangeText={formik.handleChange('firstName')}
|
||||
onBlur={formik.handleBlur('firstName')}
|
||||
value={formik.values.firstName}
|
||||
/>
|
||||
<LoginTextInput
|
||||
label="Last Name"
|
||||
icon="people-outline"
|
||||
placeholder="Doble"
|
||||
placeholderTextColor="gray"
|
||||
onChangeText={formik.handleChange('lastName')}
|
||||
onBlur={formik.handleBlur('lastName')}
|
||||
value={formik.values.lastName}
|
||||
/>
|
||||
<LoginTextInput
|
||||
label="Phone Number"
|
||||
icon="call-outline"
|
||||
placeholder="123-456-7890"
|
||||
placeholderTextColor="gray"
|
||||
onChangeText={formik.handleChange('number')}
|
||||
onBlur={formik.handleBlur('number')}
|
||||
value={formatPhoneNumber(formik.values.number)}
|
||||
autoComplete='tel'
|
||||
keyboardType='phone-pad'
|
||||
maxLength={14}
|
||||
/>
|
||||
<RegisterDropdownInput
|
||||
label="Cellular Provider"
|
||||
isOpen={providerDropdownOpen}
|
||||
setOpen={setProviderDropdownOpen}
|
||||
selectedValue={formik.values.provider}
|
||||
onValueChange={formik.handleChange('provider')}
|
||||
menu={providerMenu}
|
||||
/>
|
||||
<LoginTextInput
|
||||
label="Email Address"
|
||||
icon="mail-outline"
|
||||
placeholder="test@organization.com"
|
||||
placeholderTextColor="gray"
|
||||
onChangeText={formik.handleChange('email')}
|
||||
onBlur={formik.handleBlur('email')}
|
||||
value={formik.values.email}
|
||||
keyboardType="email-address"
|
||||
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}
|
||||
/>
|
||||
<LoginTextInput
|
||||
label="Confirm Password"
|
||||
icon="shield-checkmark-outline"
|
||||
placeholder="* * * * * *"
|
||||
placeholderTextColor="gray"
|
||||
onChangeText={formik.handleChange('passwordConfirmation')}
|
||||
onBlur={formik.handleBlur('passwordConfirmation')}
|
||||
value={formik.values.passwordConfirmation}
|
||||
secureTextEntry={hidePassword}
|
||||
isPassword
|
||||
hidePassword={hidePassword}
|
||||
setHidePassword={setHidePassword}
|
||||
/>
|
||||
<MessageBox>...</MessageBox>
|
||||
<StyledButton onPress={formik.handleSubmit} style={registerButtonDisabled ? { backgroundColor: 'grey' } : {}}>
|
||||
<ButtonText>Register</ButtonText>
|
||||
</StyledButton>
|
||||
</StyledFormArea>
|
||||
</InnerContainer>
|
||||
</StyledContainer>
|
||||
</ScrollView>
|
||||
</KeyboardAvoidingView>
|
||||
</View>
|
||||
)
|
||||
}
|
||||
|
|
@ -1,91 +0,0 @@
|
|||
import { Image, StyleSheet, Platform } from 'react-native';
|
||||
|
||||
import { HelloWave } from '@/components/HelloWave';
|
||||
import ParallaxScrollView from '@/components/ParallaxScrollView';
|
||||
import { ThemedText } from '@/components/ThemedText';
|
||||
import { ThemedView } from '@/components/ThemedView';
|
||||
|
||||
export default function HomeScreen() {
|
||||
return (
|
||||
<ParallaxScrollView
|
||||
headerBackgroundColor={{ light: '#A1CEDC', dark: '#1D3D47' }}
|
||||
headerImage={
|
||||
<Image
|
||||
source={require('@/assets/images/tones-logo.png')}
|
||||
style={styles.reactLogo}
|
||||
/>
|
||||
}
|
||||
>
|
||||
<ThemedView style={styles.titleContainer}>
|
||||
<ThemedText type="title">Welcome!</ThemedText>
|
||||
<HelloWave />
|
||||
</ThemedView>
|
||||
<ThemedView style={styles.stepContainer}>
|
||||
<ThemedText type="subtitle">Step 1: Try it</ThemedText>
|
||||
<ThemedText>
|
||||
Edit <ThemedText type="defaultSemiBold">app/(tabs)/index.tsx</ThemedText> to see changes.
|
||||
Press{' '}
|
||||
<ThemedText type="defaultSemiBold">
|
||||
{Platform.select({ ios: 'cmd + d', android: 'cmd + m' })}
|
||||
</ThemedText>{' '}
|
||||
to open developer tools.
|
||||
</ThemedText>
|
||||
</ThemedView>
|
||||
<ThemedView style={styles.stepContainer}>
|
||||
<ThemedText type="subtitle">Step 2: Explore</ThemedText>
|
||||
<ThemedText>
|
||||
Tap the Explore tab to learn more about what's included in this starter app.
|
||||
</ThemedText>
|
||||
</ThemedView>
|
||||
<ThemedView style={styles.stepContainer}>
|
||||
<ThemedText type="subtitle">Step 3: Get a fresh start</ThemedText>
|
||||
<ThemedText>
|
||||
When you're ready, run{' '}
|
||||
<ThemedText type="defaultSemiBold">npm run reset-project</ThemedText> to get a fresh{' '}
|
||||
<ThemedText type="defaultSemiBold">app</ThemedText> directory. This will move the current{' '}
|
||||
<ThemedText type="defaultSemiBold">app</ThemedText> to{' '}
|
||||
<ThemedText type="defaultSemiBold">app-example</ThemedText>.
|
||||
</ThemedText>
|
||||
</ThemedView>
|
||||
<ThemedView style={styles.stepContainer}>
|
||||
<ThemedText type="subtitle">Step 3: Get a fresh start</ThemedText>
|
||||
<ThemedText>
|
||||
When you're ready, run{' '}
|
||||
<ThemedText type="defaultSemiBold">npm run reset-project</ThemedText> to get a fresh{' '}
|
||||
<ThemedText type="defaultSemiBold">app</ThemedText> directory. This will move the current{' '}
|
||||
<ThemedText type="defaultSemiBold">app</ThemedText> to{' '}
|
||||
<ThemedText type="defaultSemiBold">app-example</ThemedText>.
|
||||
</ThemedText>
|
||||
</ThemedView>
|
||||
<ThemedView style={styles.stepContainer}>
|
||||
<ThemedText type="subtitle">Step 3: Get a fresh start</ThemedText>
|
||||
<ThemedText>
|
||||
When you're ready, run{' '}
|
||||
<ThemedText type="defaultSemiBold">npm run reset-project</ThemedText> to get a fresh{' '}
|
||||
<ThemedText type="defaultSemiBold">app</ThemedText> directory. This will move the current{' '}
|
||||
<ThemedText type="defaultSemiBold">app</ThemedText> to{' '}
|
||||
<ThemedText type="defaultSemiBold">app-example</ThemedText>.
|
||||
</ThemedText>
|
||||
</ThemedView>
|
||||
</ParallaxScrollView>
|
||||
);
|
||||
}
|
||||
|
||||
const styles = StyleSheet.create({
|
||||
titleContainer: {
|
||||
flexDirection: 'row',
|
||||
alignItems: 'center',
|
||||
gap: 8,
|
||||
},
|
||||
stepContainer: {
|
||||
gap: 8,
|
||||
marginBottom: 8,
|
||||
},
|
||||
reactLogo: {
|
||||
height: 178,
|
||||
width: 290,
|
||||
bottom: 0,
|
||||
left: 0,
|
||||
position: 'absolute',
|
||||
},
|
||||
});
|
||||
|
|
@ -2,8 +2,8 @@ import Ionicons from '@expo/vector-icons/Ionicons';
|
|||
import { PropsWithChildren, useState } from 'react';
|
||||
import { StyleSheet, TouchableOpacity, useColorScheme } from 'react-native';
|
||||
|
||||
import { ThemedText } from '@/components/ThemedText';
|
||||
import { ThemedView } from '@/components/ThemedView';
|
||||
import { ThemedText } from '../components/ThemedText';
|
||||
import { ThemedView } from '../components/ThemedView';
|
||||
import { Colors } from '@/constants/Colors';
|
||||
|
||||
export function Collapsible({ children, title }: PropsWithChildren & { title: string }) {
|
||||
|
|
|
|||
|
|
@ -7,7 +7,7 @@ import Animated, {
|
|||
withSequence,
|
||||
} from 'react-native-reanimated';
|
||||
|
||||
import { ThemedText } from '@/components/ThemedText';
|
||||
import { ThemedText } from '../components/ThemedText';
|
||||
|
||||
export function HelloWave() {
|
||||
const rotationAnimation = useSharedValue(0);
|
||||
|
|
|
|||
|
|
@ -7,7 +7,7 @@ import Animated, {
|
|||
useScrollViewOffset,
|
||||
} from 'react-native-reanimated';
|
||||
|
||||
import { ThemedView } from '@/components/ThemedView';
|
||||
import { ThemedView } from '../components/ThemedView';
|
||||
|
||||
const HEADER_HEIGHT = 250;
|
||||
|
||||
|
|
|
|||
|
|
@ -1,6 +1,6 @@
|
|||
import { Text, type TextProps, StyleSheet } from 'react-native';
|
||||
|
||||
import { useThemeColor } from '@/hooks/useThemeColor';
|
||||
import { useThemeColor } from '../hooks/useThemeColor';
|
||||
|
||||
export type ThemedTextProps = TextProps & {
|
||||
lightColor?: string;
|
||||
|
|
|
|||
|
|
@ -1,6 +1,6 @@
|
|||
import { View, type ViewProps } from 'react-native';
|
||||
|
||||
import { useThemeColor } from '@/hooks/useThemeColor';
|
||||
import { useThemeColor } from '../hooks/useThemeColor';
|
||||
|
||||
export type ThemedViewProps = ViewProps & {
|
||||
lightColor?: string;
|
||||
|
|
|
|||
|
|
@ -1,7 +1,8 @@
|
|||
import React, { useState } from 'react';
|
||||
import styled from 'styled-components';
|
||||
import { View, Text, LayoutAnimation, Image, TextInput, TouchableOpacity, TouchableNativeFeedback, ScrollView } from 'react-native';
|
||||
import { View, Text, LayoutAnimation, Image, TextInput, TouchableOpacity, TouchableNativeFeedback, ScrollView, Platform, Modal, Pressable } from 'react-native';
|
||||
import { Picker } from '@react-native-picker/picker';
|
||||
import { Ionicons } from '@expo/vector-icons';
|
||||
import { Row } from './Row';
|
||||
import { Container } from './Container';
|
||||
|
||||
export const StyledContainer = styled.View`
|
||||
|
|
@ -44,7 +45,7 @@ export const StyledTextInput = styled.TextInput`
|
|||
margin-bottom: 10px;
|
||||
`;
|
||||
|
||||
export const StyledInputLabel = styled.Text`
|
||||
export const StyledInputLabel = styled.Text`
|
||||
font-size: 13px;
|
||||
text-align: left;
|
||||
`;
|
||||
|
|
@ -204,17 +205,39 @@ const providerConversion = {
|
|||
}
|
||||
|
||||
export const PageHeader = ({
|
||||
children
|
||||
leftHeader = <View style={{ flex: 1 }} />,
|
||||
centerHeader = <View style={{ flex: 1 }} />,
|
||||
rightHeader = <View style={{ flex: 1 }} />
|
||||
}) => {
|
||||
return (
|
||||
<View style={{ position: 'sticky', top: 0, backgroundColor: '#ECEDEE', zIndex: 1, marginBottom: -100 }}>
|
||||
{children}
|
||||
<View
|
||||
style={{
|
||||
flexDirection: 'column',
|
||||
height: 80,
|
||||
alignItems: 'center',
|
||||
justifyContent: 'flex-end',
|
||||
paddingBottom: 7
|
||||
}}
|
||||
>
|
||||
<View style={{
|
||||
flexDirection: 'row',
|
||||
alignItems: 'center',
|
||||
justifyContent: 'space-between',
|
||||
width: '100%',
|
||||
paddingHorizontal: 0
|
||||
}}>
|
||||
{leftHeader}
|
||||
{centerHeader}
|
||||
{rightHeader}
|
||||
</View>
|
||||
</View>
|
||||
</View>
|
||||
)
|
||||
}
|
||||
|
||||
export const PageFooter = ({
|
||||
children
|
||||
children
|
||||
}) => {
|
||||
return (
|
||||
<View style={{ position: 'fixed', top: 0, backgroundColor: '#ECEDEE', zIndex: 1 }}>
|
||||
|
|
@ -224,11 +247,11 @@ export const PageFooter = ({
|
|||
}
|
||||
|
||||
export const LoginTextInput = ({
|
||||
label,
|
||||
icon,
|
||||
isPassword = false,
|
||||
hidePassword = true,
|
||||
setHidePassword = (boolean) => {},
|
||||
label,
|
||||
icon,
|
||||
isPassword = false,
|
||||
hidePassword = true,
|
||||
setHidePassword = (boolean) => { },
|
||||
...props
|
||||
}) => {
|
||||
return (
|
||||
|
|
@ -239,7 +262,7 @@ export const LoginTextInput = ({
|
|||
<StyledInputLabel>{label}</StyledInputLabel>
|
||||
<StyledTextInput {...props} />
|
||||
{isPassword ? (
|
||||
<RightIcon onPress={() => {setHidePassword(!hidePassword)}}>
|
||||
<RightIcon onPress={() => { setHidePassword(!hidePassword) }}>
|
||||
<Ionicons name={hidePassword ? 'eye-off-outline' : 'eye-outline'} size={30} color="gray" />
|
||||
</RightIcon>
|
||||
) : null}
|
||||
|
|
@ -249,91 +272,108 @@ export const LoginTextInput = ({
|
|||
|
||||
export const RegisterDropdownInput = ({
|
||||
label,
|
||||
isOpen,
|
||||
setOpen,
|
||||
isOpen: _isOpen,
|
||||
setOpen: _setOpen,
|
||||
selectedValue,
|
||||
onValueChange,
|
||||
menu
|
||||
}) => {
|
||||
const [modalVisible, setModalVisible] = useState(false);
|
||||
|
||||
return (
|
||||
<Container>
|
||||
<StyledInputLabel>{label}</StyledInputLabel>
|
||||
<TouchableOpacity activeOpacity={0.8} key={`${menu.menuName}2`}
|
||||
style={{
|
||||
<TouchableOpacity
|
||||
activeOpacity={0.8}
|
||||
style={{
|
||||
backgroundColor: '#E5E7EB',
|
||||
marginTop: 3,
|
||||
marginBottom: 10,
|
||||
borderRadius: '5px',
|
||||
borderRadius: 5,
|
||||
flexDirection: 'row',
|
||||
alignItems: 'center',
|
||||
minHeight: 60,
|
||||
paddingHorizontal: 15,
|
||||
}}
|
||||
onPress={() => {
|
||||
LayoutAnimation.configureNext(LayoutAnimation.Presets.easeInEaseOut);
|
||||
LayoutAnimation.configureNext(LayoutAnimation.create(200, 'easeInEaseOut', 'opacity'));
|
||||
isOpen ? setOpen(false) : setOpen(true);
|
||||
onPress={() => setModalVisible(true)}
|
||||
>
|
||||
<Ionicons
|
||||
name={menu.iconName}
|
||||
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,
|
||||
}}>
|
||||
<Row style={{
|
||||
paddingHorizontal: 16,
|
||||
paddingVertical: 16 / 1.2,
|
||||
}}>
|
||||
<Ionicons
|
||||
name={menu.iconName}
|
||||
size={30}
|
||||
color={menu.iconColor}
|
||||
/>
|
||||
<Text style={{
|
||||
fontSize: 16,
|
||||
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);
|
||||
<Pressable
|
||||
style={{ flex: 1, paddingHorizontal: 15, alignItems: 'flex-end' }}
|
||||
onPress={() => setModalVisible(false)}
|
||||
>
|
||||
<Text style={{ color: 'red', fontWeight: 600 }}>
|
||||
Close
|
||||
</Text>
|
||||
</Pressable>
|
||||
<Picker
|
||||
selectedValue={selectedValue}
|
||||
onValueChange={(value) => {
|
||||
onValueChange(value);
|
||||
}}
|
||||
>
|
||||
<Ionicons
|
||||
name={isOpen ? "chevron-up-outline" : "chevron-down-outline"}
|
||||
size={30}
|
||||
color="gray"
|
||||
/>
|
||||
</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>
|
||||
{menu.dropdownList.map((item) => (
|
||||
<Picker.Item color="black" label={item.label} value={item.value} key={item.value} />
|
||||
))}
|
||||
</Picker>
|
||||
</View>
|
||||
</Modal>
|
||||
</Container>
|
||||
)
|
||||
}
|
||||
);
|
||||
}
|
||||
|
||||
export const formatPhoneNumber = (e) => {
|
||||
let formattedNumber;
|
||||
const length = e?.length;
|
||||
|
||||
const regex = () => e.replace(/[^0-9\.]+/g, "");
|
||||
const areaCode = () => `(${regex().slice(0, 3)})`;
|
||||
const firstSix = () => `${areaCode()} ${regex().slice(3, 6)}`;
|
||||
const trailer = (start) => `${regex().slice(start, regex().length)}`;
|
||||
|
||||
if (length <= 3) {
|
||||
formattedNumber = regex();
|
||||
} else if (length === 4) {
|
||||
formattedNumber = `${areaCode()} ${trailer(3)}`;
|
||||
} else if (length === 5) {
|
||||
formattedNumber = `${areaCode().replace(")", "")}`;
|
||||
} else if (length >= 5 && length <= 9) {
|
||||
formattedNumber = `${areaCode()} ${trailer(3)}`;
|
||||
} else if (length >= 10) {
|
||||
formattedNumber = `${firstSix()}-${trailer(6)}`;
|
||||
}
|
||||
|
||||
return formattedNumber;
|
||||
};
|
||||
30
contexts/AuthContext.js
Normal file
|
|
@ -0,0 +1,30 @@
|
|||
import React, { createContext, useContext, useEffect, useState } from 'react';
|
||||
import { onAuthStateChanged, signOut } from 'firebase/auth';
|
||||
import { auth } from './firebase';
|
||||
|
||||
const AuthContext = createContext();
|
||||
|
||||
export const AuthProvider = ({ children }) => {
|
||||
const [user, setUser] = useState(null);
|
||||
const [loading, setLoading] = useState(true);
|
||||
|
||||
useEffect(() => {
|
||||
const unsubscribe = onAuthStateChanged(auth, (firebaseUser) => {
|
||||
setUser(firebaseUser);
|
||||
setLoading(false);
|
||||
});
|
||||
return unsubscribe;
|
||||
}, []);
|
||||
|
||||
const logout = () => signOut(auth);
|
||||
|
||||
return (
|
||||
<AuthContext.Provider value={{ user, loading, logout }}>
|
||||
{children}
|
||||
</AuthContext.Provider>
|
||||
);
|
||||
};
|
||||
|
||||
export const useAuth = () => {
|
||||
return useContext(AuthContext);
|
||||
};
|
||||
35
contexts/GlobalVariablesContext.js
Normal file
|
|
@ -0,0 +1,35 @@
|
|||
import React, { createContext, useEffect, useState } from 'react';
|
||||
import { AppState } from 'react-native';
|
||||
|
||||
export const GlobalVariablesContext = createContext(null);
|
||||
|
||||
export const GlobalVariablesProvider = ({ children }) => {
|
||||
const [appState, setAppState] = useState(AppState.currentState);
|
||||
|
||||
useEffect(() => {
|
||||
const handleAppStateChange = (nextAppState) => {
|
||||
if (appState.match(/active/) && nextAppState.match(/inactive|background/)) {
|
||||
console.log('App is in background or inactive');
|
||||
} else if (appState.match(/inactive|background/) && nextAppState === 'active') {
|
||||
console.log('App is in the foreground');
|
||||
}
|
||||
setAppState(nextAppState);
|
||||
};
|
||||
const subscription = AppState.addEventListener('change', handleAppStateChange);
|
||||
|
||||
return () => {
|
||||
subscription.remove();
|
||||
};
|
||||
}, [appState]);
|
||||
|
||||
const exportedVariables = {
|
||||
appState,
|
||||
setAppState
|
||||
}
|
||||
|
||||
return (
|
||||
<GlobalVariablesContext.Provider value={exportedVariables}>
|
||||
{children}
|
||||
</GlobalVariablesContext.Provider>
|
||||
)
|
||||
};
|
||||
|
|
@ -20,7 +20,7 @@ export const WebSocketProvider = ({ children }) => {
|
|||
}
|
||||
|
||||
console.log(`🔁 Connecting (Attempt ${reconnectAttempts.current + 1}/${maxReconnectAttempts})`);
|
||||
ws.current = new WebSocket(process.env.EXPO_PUBLIC_WS_URL);
|
||||
ws.current = new WebSocket(`${process.env.EXPO_PUBLIC_WS_URL}/callfeed?apiKey=${process.env.EXPO_PUBLIC_DATABASE_API_KEY}`);
|
||||
|
||||
ws.current.onopen = () => {
|
||||
console.log('✅ WebSocket connected');
|
||||
|
|
|
|||
23
contexts/firebase.js
Normal file
|
|
@ -0,0 +1,23 @@
|
|||
|
||||
|
||||
import { initializeApp } from 'firebase/app';
|
||||
import { initializeAuth, getReactNativePersistence } from 'firebase/auth';
|
||||
import AsyncStorage from '@react-native-async-storage/async-storage';
|
||||
|
||||
const firebaseConfig = {
|
||||
apiKey: process.env.EXPO_PUBLIC_FIREBASE_API_KEY,
|
||||
authDomain: process.env.EXPO_PUBLIC_FIREBASE_AUTH_DOMAIN,
|
||||
databaseURL: process.env.EXPO_PUBLIC_FIREBASE_DATABASE_URL,
|
||||
projectId: process.env.EXPO_PUBLIC_FIREBASE_PROJECT_ID,
|
||||
storageBucket: process.env.EXPO_PUBLIC_FIREBASE_STORAGE_BUCKET,
|
||||
messagingSenderId: process.env.EXPO_PUBLIC_FIREBASE_MESSAGING_SENDER_ID,
|
||||
appId: process.env.EXPO_PUBLIC_FIREBASE_APP_ID,
|
||||
};
|
||||
|
||||
|
||||
const app = initializeApp(firebaseConfig);
|
||||
const auth = initializeAuth(app, {
|
||||
persistence: getReactNativePersistence(AsyncStorage)
|
||||
});
|
||||
|
||||
export { auth };
|
||||
4
contexts/index.js
Normal file
|
|
@ -0,0 +1,4 @@
|
|||
export { AuthProvider } from './AuthContext';
|
||||
export { GlobalVariablesProvider, GlobalVariablesContext } from './GlobalVariablesContext';
|
||||
export { postgresServices } from './postgres';
|
||||
export { WebSocketProvider, WebSocketContext } from './WebSocketContext';
|
||||
62
contexts/postgres.js
Normal file
|
|
@ -0,0 +1,62 @@
|
|||
export const postgresServices = {
|
||||
getCallsParams: async (args) => {
|
||||
let response;
|
||||
try {
|
||||
const { numCalls, departments, status } = args;
|
||||
response = await fetch(`${process.env.EXPO_PUBLIC_DATABASE_URL}/getCallsParams`, {
|
||||
method: "POST",
|
||||
headers: {
|
||||
apiKey: process.env.EXPO_PUBLIC_DATABASE_API_KEY,
|
||||
"Content-Type": 'application/json'
|
||||
},
|
||||
body: JSON.stringify({
|
||||
numCalls,
|
||||
departments,
|
||||
status
|
||||
}),
|
||||
});
|
||||
if (!response.ok) {
|
||||
throw new Error(`HTTP error! status: ${response.status}`);
|
||||
}
|
||||
} catch (e) {
|
||||
console.error("Failed to fetch initial calls: ", e);
|
||||
}
|
||||
return response?.json() || [];
|
||||
},
|
||||
createUser: async (args) => {
|
||||
try {
|
||||
const {
|
||||
firstName,
|
||||
lastName,
|
||||
number,
|
||||
email,
|
||||
provider,
|
||||
departments,
|
||||
token,
|
||||
uid
|
||||
} = args;
|
||||
await fetch(`${process.env.EXPO_PUBLIC_DATABASE_URL}/createUser`, {
|
||||
method: "POST",
|
||||
headers: {
|
||||
apiKey: process.env.EXPO_PUBLIC_DATABASE_API_KEY,
|
||||
"Content-Type": 'application/json'
|
||||
},
|
||||
body: JSON.stringify({
|
||||
firstName,
|
||||
lastName,
|
||||
number,
|
||||
email,
|
||||
provider,
|
||||
departments,
|
||||
globalRole: 'user',
|
||||
primaryDept,
|
||||
token,
|
||||
firebaseUid: uid
|
||||
}),
|
||||
});
|
||||
} catch (e) {
|
||||
console.error("Failed to Add User to Database: ", e);
|
||||
}
|
||||
return 'User Added to Database';
|
||||
}
|
||||
}
|
||||
21
eas.json
Normal file
|
|
@ -0,0 +1,21 @@
|
|||
{
|
||||
"cli": {
|
||||
"version": ">= 16.3.2",
|
||||
"appVersionSource": "remote"
|
||||
},
|
||||
"build": {
|
||||
"development": {
|
||||
"developmentClient": true,
|
||||
"distribution": "internal"
|
||||
},
|
||||
"preview": {
|
||||
"distribution": "internal"
|
||||
},
|
||||
"production": {
|
||||
"autoIncrement": true
|
||||
}
|
||||
},
|
||||
"submit": {
|
||||
"production": {}
|
||||
}
|
||||
}
|
||||
|
|
@ -1,2 +1,5 @@
|
|||
export { useCallFeed } from './useCallFeed';
|
||||
export { useDepartments } from './useDepartments';
|
||||
export { useDepartments } from './useDepartments';
|
||||
export { useGlobalVariablesContext } from './useGlobalVariablesContext';
|
||||
export { useNotifications } from './useNotifications';
|
||||
export { useWebSocketContext } from './useWebSocketContext';
|
||||
|
|
@ -1,13 +1,18 @@
|
|||
import React, { useState, useEffect } from 'react';
|
||||
import { useDepartments } from '../useDepartments';
|
||||
import { C, Cardiology, Cpr, FourByFour } from "healthicons-react-native/dist/outline";
|
||||
import { useWebSocketContext } from '../useWebSocketContext';
|
||||
import React, { useState, useEffect } from "react";
|
||||
import { useDepartments } from "../useDepartments";
|
||||
import {
|
||||
Cardiology,
|
||||
Cpr,
|
||||
FourByFour,
|
||||
} from "healthicons-react-native/dist/outline";
|
||||
import { postgresServices } from "@/contexts";
|
||||
import { useWebSocketContext } from "../useWebSocketContext";
|
||||
|
||||
const callIconMap = {
|
||||
"CHEST PAIN|HEART PROBLEMS": Cardiology,
|
||||
"CARDIAC ARREST|DEATH": Cpr,
|
||||
"MOTOR VEHICLE COLLISION (MVC)": FourByFour,
|
||||
}
|
||||
"CHEST PAIN|HEART PROBLEMS": Cardiology,
|
||||
"CARDIAC ARREST|DEATH": Cpr,
|
||||
"MOTOR VEHICLE COLLISION (MVC)": FourByFour,
|
||||
};
|
||||
|
||||
// Squares
|
||||
|
||||
|
|
@ -37,200 +42,116 @@ const callIconMap = {
|
|||
// Bacteria - Sick
|
||||
// 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 initDate = new Date(callValue);
|
||||
const currentTime = new Date();
|
||||
const initDate = new Date(callValue);
|
||||
const currentTime = new Date();
|
||||
|
||||
const timeDifference = currentTime - initDate;
|
||||
const timeDifference = currentTime - initDate;
|
||||
|
||||
const days = Math.floor(timeDifference / (1000 * 60 * 60 * 24));
|
||||
const hours = Math.floor((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);
|
||||
if (days && days !== 0) {
|
||||
return `${days} day${days === 1 ? '' : 's'} ago`;
|
||||
} else if (hours && hours !== 0) {
|
||||
return `${hours} hour${hours === 1 ? '' : 's'} ago`;
|
||||
} else if (minutes && minutes !== 0) {
|
||||
return `${minutes} minute${minutes === 1 ? '' : 's'} ago`;
|
||||
} else if (seconds && seconds !== 0) {
|
||||
return `${seconds} second${seconds === 1 ? '' : 's'} ago`;
|
||||
}
|
||||
return `Unknown Time Past`;
|
||||
}
|
||||
const days = Math.floor(timeDifference / (1000 * 60 * 60 * 24));
|
||||
const hours = Math.floor(
|
||||
(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);
|
||||
if (days && days !== 0) {
|
||||
return `${days} day${days === 1 ? "" : "s"} ago`;
|
||||
} else if (hours && hours !== 0) {
|
||||
return `${hours} hour${hours === 1 ? "" : "s"} ago`;
|
||||
} else if (minutes && minutes !== 0) {
|
||||
return `${minutes} minute${minutes === 1 ? "" : "s"} ago`;
|
||||
} else if (seconds && seconds !== 0) {
|
||||
return `${seconds} second${seconds === 1 ? "" : "s"} ago`;
|
||||
}
|
||||
return `Unknown Time Past`;
|
||||
};
|
||||
|
||||
const formatCallDateTime = (callValue) => {
|
||||
const initDate = new Date(callValue);
|
||||
if (initDate) {
|
||||
const formattedDate = `${initDate.toLocaleDateString('en-US', {
|
||||
month: 'short',
|
||||
day: 'numeric',
|
||||
year: 'numeric',
|
||||
})}`;
|
||||
const hours = initDate.getHours().toString().padStart(2, '0');
|
||||
const minutes = initDate.getMinutes().toString().padStart(2, '0');
|
||||
const formattedTime = `${hours}:${minutes}`;
|
||||
const initDate = new Date(callValue);
|
||||
if (initDate) {
|
||||
const formattedDate = `${initDate.toLocaleDateString("en-US", {
|
||||
month: "short",
|
||||
day: "numeric",
|
||||
year: "numeric",
|
||||
})}`;
|
||||
const hours = initDate.getHours().toString().padStart(2, "0");
|
||||
const minutes = initDate.getMinutes().toString().padStart(2, "0");
|
||||
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);
|
||||
}
|
||||
return 'Date Unavailable';
|
||||
}
|
||||
if (!callPage) fetchData();
|
||||
}, []);
|
||||
|
||||
export const useCallFeed = () => {
|
||||
const departments = useDepartments();
|
||||
const { lastMessage } = useWebSocketContext();
|
||||
const [allCalls, setAllCalls] = useState([]);
|
||||
const { CallThemes } = departments?.accountDetails;
|
||||
const {
|
||||
CriticalCallList,
|
||||
HighCallList,
|
||||
MediumCallList,
|
||||
LowCallList,
|
||||
} = CallThemes;
|
||||
|
||||
useEffect(() => {
|
||||
if (lastMessage) {
|
||||
const parsedMessage = JSON?.parse(lastMessage);
|
||||
if (parsedMessage?.data) {
|
||||
setAllCalls([...allCalls, parsedMessage]);
|
||||
}
|
||||
}
|
||||
}, [lastMessage]);
|
||||
|
||||
const callColorSelector = (callAcuity, cardiacArrestCall, status) => {
|
||||
if (status === 'CLOSED') {
|
||||
return '#0000CD';
|
||||
} else if (CriticalCallList.includes(cardiacArrestCall)) {
|
||||
return '#8B0000';
|
||||
} else if (HighCallList.includes(callAcuity)) {
|
||||
return "#FF0000";
|
||||
} else if (MediumCallList.includes(callAcuity)) {
|
||||
return "#FF8C00";
|
||||
} else if (LowCallList.includes(callAcuity)) {
|
||||
return "#228B22";
|
||||
}
|
||||
return 'grey';
|
||||
};
|
||||
|
||||
return {
|
||||
departments,
|
||||
callIconMap,
|
||||
callDetails: allCalls,
|
||||
callColorSelector,
|
||||
formatCallTimePast,
|
||||
formatCallDateTime
|
||||
useEffect(() => {
|
||||
if (lastMessage && !init) {
|
||||
const parsedMessage = JSON?.parse(lastMessage);
|
||||
if (parsedMessage?.data) {
|
||||
setAllCalls([...allCalls, parsedMessage]);
|
||||
}
|
||||
}
|
||||
}
|
||||
}, [lastMessage]);
|
||||
|
||||
useEffect(() => {
|
||||
async function fetchData() {
|
||||
const incidents = await getIncidents(InitList?.map((dept) => { return dept?.deptId }), selectedStatus?.id);
|
||||
setAllCalls(incidents);
|
||||
}
|
||||
if (!init) {
|
||||
if (!callPage) fetchData();
|
||||
}
|
||||
}, [selectedStatus]);
|
||||
|
||||
const callColorSelector = (callAcuity, cardiacArrestCall, status) => {
|
||||
if (status?.toLowerCase() === "closed") {
|
||||
return "#0000CD";
|
||||
} else if (CriticalCallList.some(critical => cardiacArrestCall.includes(critical))) {
|
||||
return "#8B0000";
|
||||
} else if (HighCallList.some(high => callAcuity.includes(high))) {
|
||||
return "#FF0000";
|
||||
} else if (MediumCallList.some(medium => callAcuity.includes(medium))) {
|
||||
return "#FF8C00";
|
||||
} else if (LowCallList.some(low => callAcuity.includes(low))) {
|
||||
return "#228B22";
|
||||
}
|
||||
return "grey";
|
||||
};
|
||||
|
||||
return {
|
||||
departments,
|
||||
callIconMap,
|
||||
callDetails: allCalls,
|
||||
callColorSelector,
|
||||
formatCallTimePast,
|
||||
formatCallDateTime,
|
||||
selectedStatus,
|
||||
setSelectedStatus
|
||||
};
|
||||
};
|
||||
|
|
|
|||
|
|
@ -1,5 +1,4 @@
|
|||
import React, { useState, useEffect } from 'react';
|
||||
import { View, Text, TouchableOpacity } from 'react-native';
|
||||
|
||||
const departmentTypeMap = {
|
||||
EMS: 'Medical Services',
|
||||
|
|
@ -10,27 +9,47 @@ const departmentTypeMap = {
|
|||
const accountDetails = {
|
||||
"CallThemes" : {
|
||||
"CriticalCallList": [
|
||||
"CARDIAC ARREST|DEATH",
|
||||
"CARDIAC ARREST"
|
||||
],
|
||||
"HighCallList": [
|
||||
"ALS"
|
||||
"EMS ALS PRIORITY (ALS)",
|
||||
"EMS Advanced Life Support life threatening response (ALS)",
|
||||
"EMS ALS Intercept Required",
|
||||
"EMS ALS Response – Cardiac Related",
|
||||
"EMS ALS Response – Respiratory Distress",
|
||||
"EMS ALS Response – Stroke Alert",
|
||||
"EMS Basic Life Support with Paramedic Assist (BLS)",
|
||||
"EMS ALS Tiered Response with Fire",
|
||||
"EMS Response – Behavioral Emergency (ALS)",
|
||||
"EMS Response – Obstetric Emergency (ALS)",
|
||||
"EMS ALS Response – Overdose / Poisoning",
|
||||
"EMS ALS Priority Interfacility Transfer",
|
||||
"EMS Response – Unresponsive / Unconscious Patient (ALS)"
|
||||
],
|
||||
"MediumCallList": [
|
||||
"ALS-STANDARD",
|
||||
"BLS-PRIORITY"
|
||||
"BLS-PRIORITY",
|
||||
"EMS BLS Priority Response",
|
||||
"EMS BLS Response – Fall Injury"
|
||||
],
|
||||
"LowCallList": [
|
||||
"BLS-STANDARD"
|
||||
"EMS Standard Basic Life Support Response (BLS)",
|
||||
"EMS BLS Non-Emergency Transport",
|
||||
"EMS BLS Standby – Event Coverage",
|
||||
"EMS Public Assist – Lift Only (BLS)",
|
||||
"EMS BLS Scheduled Interfacility Transport"
|
||||
]
|
||||
},
|
||||
"InitList": [
|
||||
{
|
||||
deptId: 0,
|
||||
deptId: 1,
|
||||
dept: 'Darien EMS',
|
||||
addDepts: [
|
||||
'Darien EMS Supv'
|
||||
],
|
||||
deptAbv: 'DEMS',
|
||||
rank: 'Assistant Director',
|
||||
rankAbv: 'Asst. Director',
|
||||
type: 'EMS',
|
||||
primary: true,
|
||||
selected: true,
|
||||
|
|
@ -39,9 +58,11 @@ const accountDetails = {
|
|||
hasVolunteer: true,
|
||||
},
|
||||
{
|
||||
deptId: 1,
|
||||
deptId: 2,
|
||||
dept: 'Noroton Fire Department',
|
||||
deptAbv: 'NFD',
|
||||
rank: 'Lieutenant',
|
||||
rankAbv: 'Lt.',
|
||||
type: 'Fire',
|
||||
primary: false,
|
||||
selected: false,
|
||||
|
|
@ -50,9 +71,11 @@ const accountDetails = {
|
|||
hasVolunteer: true,
|
||||
},
|
||||
{
|
||||
deptId: 2,
|
||||
dept: 'Stamford Fire Department',
|
||||
deptId: 3,
|
||||
dept: 'Stamford Fire Rescue',
|
||||
deptAbv: 'SFD',
|
||||
rank: 'Paramedic',
|
||||
rankAbv: 'EMT-P',
|
||||
type: 'Rescue',
|
||||
primary: false,
|
||||
selected: false,
|
||||
|
|
|
|||
1
hooks/useGlobalVariablesContext/index.js
Normal file
|
|
@ -0,0 +1 @@
|
|||
export { useGlobalVariablesContext } from './useGlobalVariablesContext';
|
||||
|
|
@ -0,0 +1,4 @@
|
|||
import { useContext } from 'react';
|
||||
import { GlobalVariablesContext } from '../../contexts';
|
||||
|
||||
export const useGlobalVariablesContext = () => useContext(GlobalVariablesContext);
|
||||
1
hooks/useNotifications/index.js
Normal file
|
|
@ -0,0 +1 @@
|
|||
export { useNotifications } from './useNotifications';
|
||||
112
hooks/useNotifications/useNotifications.jsx
Normal file
|
|
@ -0,0 +1,112 @@
|
|||
|
||||
import { useState, useEffect, useRef } from 'react';
|
||||
import { Platform } from 'react-native';
|
||||
import * as Device from 'expo-device';
|
||||
import * as Notifications from 'expo-notifications';
|
||||
import Constants from 'expo-constants';
|
||||
|
||||
Notifications.setNotificationHandler({
|
||||
handleNotification: async () => ({
|
||||
shouldShowAlert: true,
|
||||
shouldPlaySound: false,
|
||||
shouldSetBadge: false,
|
||||
}),
|
||||
});
|
||||
|
||||
const schedulePushNotification = async (title, body, dataObj) => {
|
||||
await Notifications.scheduleNotificationAsync({
|
||||
content: {
|
||||
title,
|
||||
body,
|
||||
data: { data: dataObj },
|
||||
},
|
||||
trigger: {
|
||||
type: Notifications.SchedulableTriggerInputTypes.TIME_INTERVAL,
|
||||
seconds: 2,
|
||||
},
|
||||
});
|
||||
}
|
||||
|
||||
const registerForPushNotificationsAsync = async () => {
|
||||
let token;
|
||||
|
||||
if (Platform.OS === 'android') {
|
||||
await Notifications.setNotificationChannelAsync('myNotificationChannel', {
|
||||
name: 'A channel is needed for the permissions prompt to appear',
|
||||
importance: Notifications.AndroidImportance.MAX,
|
||||
vibrationPattern: [0, 250, 250, 250],
|
||||
lightColor: '#FF231F7C',
|
||||
});
|
||||
}
|
||||
|
||||
// if (Device.isDevice) {
|
||||
const { status: existingStatus } = await Notifications.getPermissionsAsync();
|
||||
let finalStatus = existingStatus;
|
||||
if (existingStatus !== 'granted') {
|
||||
const { status } = await Notifications.requestPermissionsAsync();
|
||||
finalStatus = status;
|
||||
}
|
||||
if (finalStatus !== 'granted') {
|
||||
alert('Failed to get push token for push notification!');
|
||||
return;
|
||||
}
|
||||
// Learn more about projectId:
|
||||
// https://docs.expo.dev/push-notifications/push-notifications-setup/#configure-projectid
|
||||
// EAS projectId is used here.
|
||||
try {
|
||||
const projectId =
|
||||
Constants?.expoConfig?.extra?.eas?.projectId ?? Constants?.easConfig?.projectId;
|
||||
if (!projectId) {
|
||||
throw new Error('Project ID not found');
|
||||
}
|
||||
token = (
|
||||
await Notifications.getExpoPushTokenAsync({
|
||||
projectId,
|
||||
})
|
||||
).data;
|
||||
} catch (e) {
|
||||
token = `${e}`;
|
||||
}
|
||||
// } else {
|
||||
// alert('Must use physical device for Push Notifications');
|
||||
// }
|
||||
|
||||
return token;
|
||||
}
|
||||
|
||||
export const useNotifications = () => {
|
||||
const [expoPushToken, setExpoPushToken] = useState('');
|
||||
const [channels, setChannels] = useState([]);
|
||||
const [notification, setNotification] = useState(undefined);
|
||||
const notificationListener = useRef();
|
||||
const responseListener = useRef();
|
||||
|
||||
useEffect(() => {
|
||||
registerForPushNotificationsAsync().then(token => token && setExpoPushToken(token));
|
||||
|
||||
if (Platform.OS === 'android') {
|
||||
Notifications.getNotificationChannelsAsync().then(value => setChannels(value ?? []));
|
||||
}
|
||||
notificationListener.current = Notifications.addNotificationReceivedListener(notification => {
|
||||
setNotification(notification);
|
||||
});
|
||||
|
||||
responseListener.current = Notifications.addNotificationResponseReceivedListener(response => {
|
||||
console.log(response);
|
||||
});
|
||||
|
||||
return () => {
|
||||
notificationListener.current?.remove();
|
||||
responseListener.current?.remove();
|
||||
};
|
||||
}, []);
|
||||
|
||||
return ({
|
||||
schedulePushNotification: async (title, body, dataObj) => {
|
||||
await schedulePushNotification(title, body, dataObj);
|
||||
},
|
||||
expoPushToken,
|
||||
expoNotificationChannels: channels,
|
||||
expoNotification: notification,
|
||||
});
|
||||
}
|
||||
|
|
@ -1,4 +1,4 @@
|
|||
import { useContext } from 'react';
|
||||
import { WebSocketContext } from '../../contexts/WebSocketContext';
|
||||
import { WebSocketContext } from '../../contexts';
|
||||
|
||||
export const useWebSocketContext = () => useContext(WebSocketContext);
|
||||
|
|
|
|||
30
ios/Podfile
|
|
@ -7,15 +7,31 @@ podfile_properties = JSON.parse(File.read(File.join(__dir__, 'Podfile.properties
|
|||
ENV['RCT_NEW_ARCH_ENABLED'] = podfile_properties['newArchEnabled'] == 'true' ? '1' : '0'
|
||||
ENV['EX_DEV_CLIENT_NETWORK_INSPECTOR'] = podfile_properties['EX_DEV_CLIENT_NETWORK_INSPECTOR']
|
||||
|
||||
platform :ios, podfile_properties['ios.deploymentTarget'] || '13.4'
|
||||
platform :ios, podfile_properties['ios.deploymentTarget'] || '15.1'
|
||||
install! 'cocoapods',
|
||||
:deterministic_uuids => false
|
||||
|
||||
prepare_react_native_project!
|
||||
|
||||
target 'testapplication' do
|
||||
target 'Tones' do
|
||||
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 => ENV['USE_FRAMEWORKS'].to_sym if ENV['USE_FRAMEWORKS']
|
||||
|
|
@ -47,12 +63,4 @@ target 'testapplication' do
|
|||
end
|
||||
end
|
||||
end
|
||||
|
||||
post_integrate do |installer|
|
||||
begin
|
||||
expo_patch_react_imports!(installer)
|
||||
rescue => e
|
||||
Pod::UI.warn e
|
||||
end
|
||||
end
|
||||
end
|
||||
|
|
|
|||
2976
ios/Podfile.lock
|
|
@ -1,4 +1,5 @@
|
|||
{
|
||||
"expo.jsEngine": "hermes",
|
||||
"EX_DEV_CLIENT_NETWORK_INSPECTOR": "true"
|
||||
"EX_DEV_CLIENT_NETWORK_INSPECTOR": "true",
|
||||
"newArchEnabled": "false"
|
||||
}
|
||||
|
|
|
|||
|
|
@ -10,31 +10,31 @@
|
|||
13B07FBC1A68108700A75B9A /* AppDelegate.mm in Sources */ = {isa = PBXBuildFile; fileRef = 13B07FB01A68108700A75B9A /* AppDelegate.mm */; };
|
||||
13B07FBF1A68108700A75B9A /* Images.xcassets in Resources */ = {isa = PBXBuildFile; fileRef = 13B07FB51A68108700A75B9A /* Images.xcassets */; };
|
||||
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 */; };
|
||||
640C5CE36A784C1E86D867C7 /* noop-file.swift in Sources */ = {isa = PBXBuildFile; fileRef = 2358EABEB0CA4428951E7149 /* noop-file.swift */; };
|
||||
96905EF65AED1B983A6B3ABC /* libPods-testapplication.a in Frameworks */ = {isa = PBXBuildFile; fileRef = 58EEBF8E8E6FB1BC6CAF49B5 /* libPods-testapplication.a */; };
|
||||
93A35CBBC1C2DF84FE39E633 /* PrivacyInfo.xcprivacy in Resources */ = {isa = PBXBuildFile; fileRef = EA8B81AA605F084BFB23750B /* PrivacyInfo.xcprivacy */; };
|
||||
96905EF65AED1B983A6B3ABC /* libPods-Tones.a in Frameworks */ = {isa = PBXBuildFile; fileRef = 58EEBF8E8E6FB1BC6CAF49B5 /* libPods-Tones.a */; };
|
||||
B18059E884C0ABDD17F3DC3D /* ExpoModulesProvider.swift in Sources */ = {isa = PBXBuildFile; fileRef = FAC715A2D49A985799AEE119 /* ExpoModulesProvider.swift */; };
|
||||
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 */
|
||||
|
||||
/* Begin PBXFileReference section */
|
||||
13B07F961A680F5B00A75B9A /* testapplication.app */ = {isa = PBXFileReference; explicitFileType = wrapper.application; includeInIndex = 0; path = testapplication.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>"; };
|
||||
13B07FB01A68108700A75B9A /* AppDelegate.mm */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.objcpp; name = AppDelegate.mm; path = testapplication/AppDelegate.mm; sourceTree = "<group>"; };
|
||||
13B07FB51A68108700A75B9A /* Images.xcassets */ = {isa = PBXFileReference; lastKnownFileType = folder.assetcatalog; name = Images.xcassets; path = testapplication/Images.xcassets; sourceTree = "<group>"; };
|
||||
13B07FB61A68108700A75B9A /* Info.plist */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.plist.xml; name = Info.plist; path = testapplication/Info.plist; sourceTree = "<group>"; };
|
||||
13B07FB71A68108700A75B9A /* main.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = main.m; path = testapplication/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-testapplication.a */ = {isa = PBXFileReference; explicitFileType = archive.ar; includeInIndex = 0; path = "libPods-testapplication.a"; sourceTree = BUILT_PRODUCTS_DIR; };
|
||||
6C2E3173556A471DD304B334 /* Pods-testapplication.debug.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-testapplication.debug.xcconfig"; path = "Target Support Files/Pods-testapplication/Pods-testapplication.debug.xcconfig"; sourceTree = "<group>"; };
|
||||
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>"; };
|
||||
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>"; };
|
||||
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 /* 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 = Tones/AppDelegate.h; 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 = Tones/Images.xcassets; 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 = Tones/main.m; sourceTree = "<group>"; };
|
||||
58EEBF8E8E6FB1BC6CAF49B5 /* libPods-Tones.a */ = {isa = PBXFileReference; explicitFileType = archive.ar; includeInIndex = 0; path = "libPods-Tones.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>"; };
|
||||
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>"; };
|
||||
AA286B85B6C04FC6940260E9 /* SplashScreen.storyboard */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = file.storyboard; name = SplashScreen.storyboard; path = Tones/SplashScreen.storyboard; 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; };
|
||||
FAC715A2D49A985799AEE119 /* ExpoModulesProvider.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; name = ExpoModulesProvider.swift; path = "Pods/Target Support Files/Pods-testapplication/ExpoModulesProvider.swift"; sourceTree = "<group>"; };
|
||||
F8CAF977DAD74AAA91FDDD99 /* Tones-Bridging-Header.h */ = {isa = PBXFileReference; explicitFileType = undefined; fileEncoding = 4; includeInIndex = 0; lastKnownFileType = sourcecode.c.h; name = "Tones-Bridging-Header.h"; path = "Tones/Tones-Bridging-Header.h"; sourceTree = "<group>"; };
|
||||
FAC715A2D49A985799AEE119 /* ExpoModulesProvider.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; name = ExpoModulesProvider.swift; path = "Pods/Target Support Files/Pods-Tones/ExpoModulesProvider.swift"; sourceTree = "<group>"; };
|
||||
/* End PBXFileReference section */
|
||||
|
||||
/* Begin PBXFrameworksBuildPhase section */
|
||||
|
|
@ -42,14 +42,14 @@
|
|||
isa = PBXFrameworksBuildPhase;
|
||||
buildActionMask = 2147483647;
|
||||
files = (
|
||||
96905EF65AED1B983A6B3ABC /* libPods-testapplication.a in Frameworks */,
|
||||
96905EF65AED1B983A6B3ABC /* libPods-Tones.a in Frameworks */,
|
||||
);
|
||||
runOnlyForDeploymentPostprocessing = 0;
|
||||
};
|
||||
/* End PBXFrameworksBuildPhase section */
|
||||
|
||||
/* Begin PBXGroup section */
|
||||
13B07FAE1A68108700A75B9A /* testapplication */ = {
|
||||
13B07FAE1A68108700A75B9A /* Tones */ = {
|
||||
isa = PBXGroup;
|
||||
children = (
|
||||
BB2F792B24A3F905000567C9 /* Supporting */,
|
||||
|
|
@ -59,18 +59,18 @@
|
|||
13B07FB61A68108700A75B9A /* Info.plist */,
|
||||
13B07FB71A68108700A75B9A /* main.m */,
|
||||
AA286B85B6C04FC6940260E9 /* SplashScreen.storyboard */,
|
||||
2358EABEB0CA4428951E7149 /* noop-file.swift */,
|
||||
96FAC8CF002144E68DCEBFD0 /* testapplication-Bridging-Header.h */,
|
||||
A9DA6C7B26A64A23DFDE186E /* PrivacyInfo.xcprivacy */,
|
||||
1350D069573E4AEBBF8BA6A3 /* noop-file.swift */,
|
||||
F8CAF977DAD74AAA91FDDD99 /* Tones-Bridging-Header.h */,
|
||||
EA8B81AA605F084BFB23750B /* PrivacyInfo.xcprivacy */,
|
||||
);
|
||||
name = testapplication;
|
||||
name = Tones;
|
||||
sourceTree = "<group>";
|
||||
};
|
||||
2D16E6871FA4F8E400B85C8A /* Frameworks */ = {
|
||||
isa = PBXGroup;
|
||||
children = (
|
||||
ED297162215061F000B7C4FE /* JavaScriptCore.framework */,
|
||||
58EEBF8E8E6FB1BC6CAF49B5 /* libPods-testapplication.a */,
|
||||
58EEBF8E8E6FB1BC6CAF49B5 /* libPods-Tones.a */,
|
||||
);
|
||||
name = Frameworks;
|
||||
sourceTree = "<group>";
|
||||
|
|
@ -85,7 +85,7 @@
|
|||
83CBB9F61A601CBA00E9B192 = {
|
||||
isa = PBXGroup;
|
||||
children = (
|
||||
13B07FAE1A68108700A75B9A /* testapplication */,
|
||||
13B07FAE1A68108700A75B9A /* Tones */,
|
||||
832341AE1AAA6A7D00B99B32 /* Libraries */,
|
||||
83CBBA001A601CBA00E9B192 /* Products */,
|
||||
2D16E6871FA4F8E400B85C8A /* Frameworks */,
|
||||
|
|
@ -100,17 +100,17 @@
|
|||
83CBBA001A601CBA00E9B192 /* Products */ = {
|
||||
isa = PBXGroup;
|
||||
children = (
|
||||
13B07F961A680F5B00A75B9A /* testapplication.app */,
|
||||
13B07F961A680F5B00A75B9A /* Tones.app */,
|
||||
);
|
||||
name = Products;
|
||||
sourceTree = "<group>";
|
||||
};
|
||||
92DBD88DE9BF7D494EA9DA96 /* testapplication */ = {
|
||||
92DBD88DE9BF7D494EA9DA96 /* Tones */ = {
|
||||
isa = PBXGroup;
|
||||
children = (
|
||||
FAC715A2D49A985799AEE119 /* ExpoModulesProvider.swift */,
|
||||
);
|
||||
name = testapplication;
|
||||
name = Tones;
|
||||
sourceTree = "<group>";
|
||||
};
|
||||
BB2F792B24A3F905000567C9 /* Supporting */ = {
|
||||
|
|
@ -119,14 +119,14 @@
|
|||
BB2F792C24A3F905000567C9 /* Expo.plist */,
|
||||
);
|
||||
name = Supporting;
|
||||
path = testapplication/Supporting;
|
||||
path = Tones/Supporting;
|
||||
sourceTree = "<group>";
|
||||
};
|
||||
D65327D7A22EEC0BE12398D9 /* Pods */ = {
|
||||
isa = PBXGroup;
|
||||
children = (
|
||||
6C2E3173556A471DD304B334 /* Pods-testapplication.debug.xcconfig */,
|
||||
7A4D352CD337FB3A3BF06240 /* Pods-testapplication.release.xcconfig */,
|
||||
6C2E3173556A471DD304B334 /* Pods-Tones.debug.xcconfig */,
|
||||
7A4D352CD337FB3A3BF06240 /* Pods-Tones.release.xcconfig */,
|
||||
);
|
||||
path = Pods;
|
||||
sourceTree = "<group>";
|
||||
|
|
@ -134,7 +134,7 @@
|
|||
D7E4C46ADA2E9064B798F356 /* ExpoModulesProviders */ = {
|
||||
isa = PBXGroup;
|
||||
children = (
|
||||
92DBD88DE9BF7D494EA9DA96 /* testapplication */,
|
||||
92DBD88DE9BF7D494EA9DA96 /* Tones */,
|
||||
);
|
||||
name = ExpoModulesProviders;
|
||||
sourceTree = "<group>";
|
||||
|
|
@ -142,26 +142,26 @@
|
|||
/* End PBXGroup section */
|
||||
|
||||
/* Begin PBXNativeTarget section */
|
||||
13B07F861A680F5B00A75B9A /* testapplication */ = {
|
||||
13B07F861A680F5B00A75B9A /* Tones */ = {
|
||||
isa = PBXNativeTarget;
|
||||
buildConfigurationList = 13B07F931A680F5B00A75B9A /* Build configuration list for PBXNativeTarget "testapplication" */;
|
||||
buildConfigurationList = 13B07F931A680F5B00A75B9A /* Build configuration list for PBXNativeTarget "Tones" */;
|
||||
buildPhases = (
|
||||
08A4A3CD28434E44B6B9DE2E /* [CP] Check Pods Manifest.lock */,
|
||||
7E5AAFC44944C4D49F90AE74 /* [Expo] Configure project */,
|
||||
BBDF11722E0998CCEE7FC139 /* [Expo] Configure project */,
|
||||
13B07F871A680F5B00A75B9A /* Sources */,
|
||||
13B07F8C1A680F5B00A75B9A /* Frameworks */,
|
||||
13B07F8E1A680F5B00A75B9A /* Resources */,
|
||||
00DD1BFF1BD5951E006B06BC /* Bundle React Native code and images */,
|
||||
800E24972A6A228C8D4807E9 /* [CP] Copy Pods Resources */,
|
||||
6CD366C487D1C4076EEFC1E9 /* [CP] Embed Pods Frameworks */,
|
||||
5F318AA4CE51F8E175CC6D0A /* [CP] Embed Pods Frameworks */,
|
||||
);
|
||||
buildRules = (
|
||||
);
|
||||
dependencies = (
|
||||
);
|
||||
name = testapplication;
|
||||
productName = testapplication;
|
||||
productReference = 13B07F961A680F5B00A75B9A /* testapplication.app */;
|
||||
name = Tones;
|
||||
productName = Tones;
|
||||
productReference = 13B07F961A680F5B00A75B9A /* Tones.app */;
|
||||
productType = "com.apple.product-type.application";
|
||||
};
|
||||
/* End PBXNativeTarget section */
|
||||
|
|
@ -177,7 +177,7 @@
|
|||
};
|
||||
};
|
||||
};
|
||||
buildConfigurationList = 83CBB9FA1A601CBA00E9B192 /* Build configuration list for PBXProject "testapplication" */;
|
||||
buildConfigurationList = 83CBB9FA1A601CBA00E9B192 /* Build configuration list for PBXProject "Tones" */;
|
||||
compatibilityVersion = "Xcode 3.2";
|
||||
developmentRegion = en;
|
||||
hasScannedForEncodings = 0;
|
||||
|
|
@ -190,7 +190,7 @@
|
|||
projectDirPath = "";
|
||||
projectRoot = "";
|
||||
targets = (
|
||||
13B07F861A680F5B00A75B9A /* testapplication */,
|
||||
13B07F861A680F5B00A75B9A /* Tones */,
|
||||
);
|
||||
};
|
||||
/* End PBXProject section */
|
||||
|
|
@ -203,7 +203,7 @@
|
|||
BB2F792D24A3F905000567C9 /* Expo.plist in Resources */,
|
||||
13B07FBF1A68108700A75B9A /* Images.xcassets in Resources */,
|
||||
3E461D99554A48A4959DE609 /* SplashScreen.storyboard in Resources */,
|
||||
FF358844A8FA907CDEC7216D /* PrivacyInfo.xcprivacy in Resources */,
|
||||
93A35CBBC1C2DF84FE39E633 /* PrivacyInfo.xcprivacy in Resources */,
|
||||
);
|
||||
runOnlyForDeploymentPostprocessing = 0;
|
||||
};
|
||||
|
|
@ -240,20 +240,20 @@
|
|||
outputFileListPaths = (
|
||||
);
|
||||
outputPaths = (
|
||||
"$(DERIVED_FILE_DIR)/Pods-testapplication-checkManifestLockResult.txt",
|
||||
"$(DERIVED_FILE_DIR)/Pods-Tones-checkManifestLockResult.txt",
|
||||
);
|
||||
runOnlyForDeploymentPostprocessing = 0;
|
||||
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";
|
||||
showEnvVarsInLog = 0;
|
||||
};
|
||||
6CD366C487D1C4076EEFC1E9 /* [CP] Embed Pods Frameworks */ = {
|
||||
5F318AA4CE51F8E175CC6D0A /* [CP] Embed Pods Frameworks */ = {
|
||||
isa = PBXShellScriptBuildPhase;
|
||||
buildActionMask = 2147483647;
|
||||
files = (
|
||||
);
|
||||
inputPaths = (
|
||||
"${PODS_ROOT}/Target Support Files/Pods-testapplication/Pods-testapplication-frameworks.sh",
|
||||
"${PODS_ROOT}/Target Support Files/Pods-Tones/Pods-Tones-frameworks.sh",
|
||||
"${PODS_XCFRAMEWORKS_BUILD_DIR}/hermes-engine/Pre-built/hermes.framework/hermes",
|
||||
);
|
||||
name = "[CP] Embed Pods Frameworks";
|
||||
|
|
@ -262,10 +262,50 @@
|
|||
);
|
||||
runOnlyForDeploymentPostprocessing = 0;
|
||||
shellPath = /bin/sh;
|
||||
shellScript = "\"${PODS_ROOT}/Target Support Files/Pods-testapplication/Pods-testapplication-frameworks.sh\"\n";
|
||||
shellScript = "\"${PODS_ROOT}/Target Support Files/Pods-Tones/Pods-Tones-frameworks.sh\"\n";
|
||||
showEnvVarsInLog = 0;
|
||||
};
|
||||
7E5AAFC44944C4D49F90AE74 /* [Expo] Configure project */ = {
|
||||
800E24972A6A228C8D4807E9 /* [CP] Copy Pods Resources */ = {
|
||||
isa = PBXShellScriptBuildPhase;
|
||||
buildActionMask = 2147483647;
|
||||
files = (
|
||||
);
|
||||
inputPaths = (
|
||||
"${PODS_ROOT}/Target Support Files/Pods-Tones/Pods-Tones-resources.sh",
|
||||
"${PODS_CONFIGURATION_BUILD_DIR}/EXApplication/ExpoApplication_privacy.bundle",
|
||||
"${PODS_CONFIGURATION_BUILD_DIR}/EXConstants/EXConstants.bundle",
|
||||
"${PODS_CONFIGURATION_BUILD_DIR}/EXConstants/ExpoConstants_privacy.bundle",
|
||||
"${PODS_CONFIGURATION_BUILD_DIR}/EXNotifications/ExpoNotifications_privacy.bundle",
|
||||
"${PODS_CONFIGURATION_BUILD_DIR}/ExpoDevice/ExpoDevice_privacy.bundle",
|
||||
"${PODS_CONFIGURATION_BUILD_DIR}/ExpoFileSystem/ExpoFileSystem_privacy.bundle",
|
||||
"${PODS_CONFIGURATION_BUILD_DIR}/ExpoSystemUI/ExpoSystemUI_privacy.bundle",
|
||||
"${PODS_CONFIGURATION_BUILD_DIR}/RCT-Folly/RCT-Folly_privacy.bundle",
|
||||
"${PODS_CONFIGURATION_BUILD_DIR}/React-Core/React-Core_privacy.bundle",
|
||||
"${PODS_CONFIGURATION_BUILD_DIR}/React-cxxreact/React-cxxreact_privacy.bundle",
|
||||
"${PODS_CONFIGURATION_BUILD_DIR}/boost/boost_privacy.bundle",
|
||||
"${PODS_CONFIGURATION_BUILD_DIR}/glog/glog_privacy.bundle",
|
||||
);
|
||||
name = "[CP] Copy Pods Resources";
|
||||
outputPaths = (
|
||||
"${TARGET_BUILD_DIR}/${UNLOCALIZED_RESOURCES_FOLDER_PATH}/ExpoApplication_privacy.bundle",
|
||||
"${TARGET_BUILD_DIR}/${UNLOCALIZED_RESOURCES_FOLDER_PATH}/EXConstants.bundle",
|
||||
"${TARGET_BUILD_DIR}/${UNLOCALIZED_RESOURCES_FOLDER_PATH}/ExpoConstants_privacy.bundle",
|
||||
"${TARGET_BUILD_DIR}/${UNLOCALIZED_RESOURCES_FOLDER_PATH}/ExpoNotifications_privacy.bundle",
|
||||
"${TARGET_BUILD_DIR}/${UNLOCALIZED_RESOURCES_FOLDER_PATH}/ExpoDevice_privacy.bundle",
|
||||
"${TARGET_BUILD_DIR}/${UNLOCALIZED_RESOURCES_FOLDER_PATH}/ExpoFileSystem_privacy.bundle",
|
||||
"${TARGET_BUILD_DIR}/${UNLOCALIZED_RESOURCES_FOLDER_PATH}/ExpoSystemUI_privacy.bundle",
|
||||
"${TARGET_BUILD_DIR}/${UNLOCALIZED_RESOURCES_FOLDER_PATH}/RCT-Folly_privacy.bundle",
|
||||
"${TARGET_BUILD_DIR}/${UNLOCALIZED_RESOURCES_FOLDER_PATH}/React-Core_privacy.bundle",
|
||||
"${TARGET_BUILD_DIR}/${UNLOCALIZED_RESOURCES_FOLDER_PATH}/React-cxxreact_privacy.bundle",
|
||||
"${TARGET_BUILD_DIR}/${UNLOCALIZED_RESOURCES_FOLDER_PATH}/boost_privacy.bundle",
|
||||
"${TARGET_BUILD_DIR}/${UNLOCALIZED_RESOURCES_FOLDER_PATH}/glog_privacy.bundle",
|
||||
);
|
||||
runOnlyForDeploymentPostprocessing = 0;
|
||||
shellPath = /bin/sh;
|
||||
shellScript = "\"${PODS_ROOT}/Target Support Files/Pods-Tones/Pods-Tones-resources.sh\"\n";
|
||||
showEnvVarsInLog = 0;
|
||||
};
|
||||
BBDF11722E0998CCEE7FC139 /* [Expo] Configure project */ = {
|
||||
isa = PBXShellScriptBuildPhase;
|
||||
alwaysOutOfDate = 1;
|
||||
buildActionMask = 2147483647;
|
||||
|
|
@ -282,33 +322,7 @@
|
|||
);
|
||||
runOnlyForDeploymentPostprocessing = 0;
|
||||
shellPath = /bin/sh;
|
||||
shellScript = "# This script configures Expo modules and generates the modules provider file.\nbash -l -c \"./Pods/Target\\ Support\\ Files/Pods-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;
|
||||
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";
|
||||
};
|
||||
/* End PBXShellScriptBuildPhase section */
|
||||
|
||||
|
|
@ -320,7 +334,7 @@
|
|||
13B07FBC1A68108700A75B9A /* AppDelegate.mm in Sources */,
|
||||
13B07FC11A68108700A75B9A /* main.m in Sources */,
|
||||
B18059E884C0ABDD17F3DC3D /* ExpoModulesProvider.swift in Sources */,
|
||||
640C5CE36A784C1E86D867C7 /* noop-file.swift in Sources */,
|
||||
3BB8D1083F3D4AAFA506B09F /* noop-file.swift in Sources */,
|
||||
);
|
||||
runOnlyForDeploymentPostprocessing = 0;
|
||||
};
|
||||
|
|
@ -329,19 +343,19 @@
|
|||
/* Begin XCBuildConfiguration section */
|
||||
13B07F941A680F5B00A75B9A /* Debug */ = {
|
||||
isa = XCBuildConfiguration;
|
||||
baseConfigurationReference = 6C2E3173556A471DD304B334 /* Pods-testapplication.debug.xcconfig */;
|
||||
baseConfigurationReference = 6C2E3173556A471DD304B334 /* Pods-Tones.debug.xcconfig */;
|
||||
buildSettings = {
|
||||
ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon;
|
||||
CLANG_ENABLE_MODULES = YES;
|
||||
CODE_SIGN_ENTITLEMENTS = testapplication/testapplication.entitlements;
|
||||
CODE_SIGN_ENTITLEMENTS = Tones/Tones.entitlements;
|
||||
CURRENT_PROJECT_VERSION = 1;
|
||||
ENABLE_BITCODE = NO;
|
||||
GCC_PREPROCESSOR_DEFINITIONS = (
|
||||
"$(inherited)",
|
||||
"FB_SONARKIT_ENABLED=1",
|
||||
);
|
||||
INFOPLIST_FILE = testapplication/Info.plist;
|
||||
IPHONEOS_DEPLOYMENT_TARGET = 13.4;
|
||||
INFOPLIST_FILE = Tones/Info.plist;
|
||||
IPHONEOS_DEPLOYMENT_TARGET = 15.1;
|
||||
LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks";
|
||||
MARKETING_VERSION = 1.0;
|
||||
OTHER_LDFLAGS = (
|
||||
|
|
@ -350,9 +364,9 @@
|
|||
"-lc++",
|
||||
);
|
||||
OTHER_SWIFT_FLAGS = "$(inherited) -D EXPO_CONFIGURATION_DEBUG";
|
||||
PRODUCT_BUNDLE_IDENTIFIER = com.anonymous.testapplication;
|
||||
PRODUCT_NAME = testapplication;
|
||||
SWIFT_OBJC_BRIDGING_HEADER = "testapplication/testapplication-Bridging-Header.h";
|
||||
PRODUCT_BUNDLE_IDENTIFIER = com.mattdimegs.tones;
|
||||
PRODUCT_NAME = Tones;
|
||||
SWIFT_OBJC_BRIDGING_HEADER = "Tones/Tones-Bridging-Header.h";
|
||||
SWIFT_OPTIMIZATION_LEVEL = "-Onone";
|
||||
SWIFT_VERSION = 5.0;
|
||||
TARGETED_DEVICE_FAMILY = "1,2";
|
||||
|
|
@ -362,14 +376,14 @@
|
|||
};
|
||||
13B07F951A680F5B00A75B9A /* Release */ = {
|
||||
isa = XCBuildConfiguration;
|
||||
baseConfigurationReference = 7A4D352CD337FB3A3BF06240 /* Pods-testapplication.release.xcconfig */;
|
||||
baseConfigurationReference = 7A4D352CD337FB3A3BF06240 /* Pods-Tones.release.xcconfig */;
|
||||
buildSettings = {
|
||||
ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon;
|
||||
CLANG_ENABLE_MODULES = YES;
|
||||
CODE_SIGN_ENTITLEMENTS = testapplication/testapplication.entitlements;
|
||||
CODE_SIGN_ENTITLEMENTS = Tones/Tones.entitlements;
|
||||
CURRENT_PROJECT_VERSION = 1;
|
||||
INFOPLIST_FILE = testapplication/Info.plist;
|
||||
IPHONEOS_DEPLOYMENT_TARGET = 13.4;
|
||||
INFOPLIST_FILE = Tones/Info.plist;
|
||||
IPHONEOS_DEPLOYMENT_TARGET = 15.1;
|
||||
LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks";
|
||||
MARKETING_VERSION = 1.0;
|
||||
OTHER_LDFLAGS = (
|
||||
|
|
@ -378,9 +392,9 @@
|
|||
"-lc++",
|
||||
);
|
||||
OTHER_SWIFT_FLAGS = "$(inherited) -D EXPO_CONFIGURATION_RELEASE";
|
||||
PRODUCT_BUNDLE_IDENTIFIER = com.anonymous.testapplication;
|
||||
PRODUCT_NAME = testapplication;
|
||||
SWIFT_OBJC_BRIDGING_HEADER = "testapplication/testapplication-Bridging-Header.h";
|
||||
PRODUCT_BUNDLE_IDENTIFIER = com.mattdimegs.tones;
|
||||
PRODUCT_NAME = Tones;
|
||||
SWIFT_OBJC_BRIDGING_HEADER = "Tones/Tones-Bridging-Header.h";
|
||||
SWIFT_VERSION = 5.0;
|
||||
TARGETED_DEVICE_FAMILY = "1,2";
|
||||
VERSIONING_SYSTEM = "apple-generic";
|
||||
|
|
@ -391,7 +405,6 @@
|
|||
isa = XCBuildConfiguration;
|
||||
buildSettings = {
|
||||
ALWAYS_SEARCH_USER_PATHS = NO;
|
||||
CC = "";
|
||||
CLANG_ANALYZER_LOCALIZABILITY_NONLOCALIZED = YES;
|
||||
CLANG_CXX_LANGUAGE_STANDARD = "c++20";
|
||||
CLANG_CXX_LIBRARY = "libc++";
|
||||
|
|
@ -418,7 +431,6 @@
|
|||
CLANG_WARN__DUPLICATE_METHOD_MATCH = YES;
|
||||
"CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Developer";
|
||||
COPY_PHASE_STRIP = NO;
|
||||
CXX = "";
|
||||
ENABLE_STRICT_OBJC_MSGSEND = YES;
|
||||
ENABLE_TESTABILITY = YES;
|
||||
GCC_C_LANGUAGE_STANDARD = gnu99;
|
||||
|
|
@ -436,9 +448,7 @@
|
|||
GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE;
|
||||
GCC_WARN_UNUSED_FUNCTION = YES;
|
||||
GCC_WARN_UNUSED_VARIABLE = YES;
|
||||
IPHONEOS_DEPLOYMENT_TARGET = 13.4;
|
||||
LD = "";
|
||||
LDPLUSPLUS = "";
|
||||
IPHONEOS_DEPLOYMENT_TARGET = 15.1;
|
||||
LD_RUNPATH_SEARCH_PATHS = "/usr/lib/swift $(inherited)";
|
||||
LIBRARY_SEARCH_PATHS = "$(SDKROOT)/usr/lib/swift\"$(inherited)\"";
|
||||
MTL_ENABLE_DEBUG_INFO = YES;
|
||||
|
|
@ -449,6 +459,7 @@
|
|||
);
|
||||
REACT_NATIVE_PATH = "${PODS_ROOT}/../../node_modules/react-native";
|
||||
SDKROOT = iphoneos;
|
||||
SWIFT_ACTIVE_COMPILATION_CONDITIONS = "$(inherited) DEBUG";
|
||||
USE_HERMES = true;
|
||||
};
|
||||
name = Debug;
|
||||
|
|
@ -457,7 +468,6 @@
|
|||
isa = XCBuildConfiguration;
|
||||
buildSettings = {
|
||||
ALWAYS_SEARCH_USER_PATHS = NO;
|
||||
CC = "";
|
||||
CLANG_ANALYZER_LOCALIZABILITY_NONLOCALIZED = YES;
|
||||
CLANG_CXX_LANGUAGE_STANDARD = "c++20";
|
||||
CLANG_CXX_LIBRARY = "libc++";
|
||||
|
|
@ -484,7 +494,6 @@
|
|||
CLANG_WARN__DUPLICATE_METHOD_MATCH = YES;
|
||||
"CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Developer";
|
||||
COPY_PHASE_STRIP = YES;
|
||||
CXX = "";
|
||||
ENABLE_NS_ASSERTIONS = NO;
|
||||
ENABLE_STRICT_OBJC_MSGSEND = YES;
|
||||
GCC_C_LANGUAGE_STANDARD = gnu99;
|
||||
|
|
@ -495,9 +504,7 @@
|
|||
GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE;
|
||||
GCC_WARN_UNUSED_FUNCTION = YES;
|
||||
GCC_WARN_UNUSED_VARIABLE = YES;
|
||||
IPHONEOS_DEPLOYMENT_TARGET = 13.4;
|
||||
LD = "";
|
||||
LDPLUSPLUS = "";
|
||||
IPHONEOS_DEPLOYMENT_TARGET = 15.1;
|
||||
LD_RUNPATH_SEARCH_PATHS = "/usr/lib/swift $(inherited)";
|
||||
LIBRARY_SEARCH_PATHS = "$(SDKROOT)/usr/lib/swift\"$(inherited)\"";
|
||||
MTL_ENABLE_DEBUG_INFO = NO;
|
||||
|
|
@ -515,7 +522,7 @@
|
|||
/* End XCBuildConfiguration section */
|
||||
|
||||
/* Begin XCConfigurationList section */
|
||||
13B07F931A680F5B00A75B9A /* Build configuration list for PBXNativeTarget "testapplication" */ = {
|
||||
13B07F931A680F5B00A75B9A /* Build configuration list for PBXNativeTarget "Tones" */ = {
|
||||
isa = XCConfigurationList;
|
||||
buildConfigurations = (
|
||||
13B07F941A680F5B00A75B9A /* Debug */,
|
||||
|
|
@ -524,7 +531,7 @@
|
|||
defaultConfigurationIsVisible = 0;
|
||||
defaultConfigurationName = Release;
|
||||
};
|
||||
83CBB9FA1A601CBA00E9B192 /* Build configuration list for PBXProject "testapplication" */ = {
|
||||
83CBB9FA1A601CBA00E9B192 /* Build configuration list for PBXProject "Tones" */ = {
|
||||
isa = XCConfigurationList;
|
||||
buildConfigurations = (
|
||||
83CBBA201A601CBA00E9B192 /* Debug */,
|
||||
|
|
@ -15,9 +15,9 @@
|
|||
<BuildableReference
|
||||
BuildableIdentifier = "primary"
|
||||
BlueprintIdentifier = "13B07F861A680F5B00A75B9A"
|
||||
BuildableName = "testapplication.app"
|
||||
BlueprintName = "testapplication"
|
||||
ReferencedContainer = "container:testapplication.xcodeproj">
|
||||
BuildableName = "Tones.app"
|
||||
BlueprintName = "Tones"
|
||||
ReferencedContainer = "container:Tones.xcodeproj">
|
||||
</BuildableReference>
|
||||
</BuildActionEntry>
|
||||
</BuildActionEntries>
|
||||
|
|
@ -33,9 +33,9 @@
|
|||
<BuildableReference
|
||||
BuildableIdentifier = "primary"
|
||||
BlueprintIdentifier = "00E356ED1AD99517003FC87E"
|
||||
BuildableName = "testapplicationTests.xctest"
|
||||
BlueprintName = "testapplicationTests"
|
||||
ReferencedContainer = "container:testapplication.xcodeproj">
|
||||
BuildableName = "TonesTests.xctest"
|
||||
BlueprintName = "TonesTests"
|
||||
ReferencedContainer = "container:Tones.xcodeproj">
|
||||
</BuildableReference>
|
||||
</TestableReference>
|
||||
</Testables>
|
||||
|
|
@ -55,9 +55,9 @@
|
|||
<BuildableReference
|
||||
BuildableIdentifier = "primary"
|
||||
BlueprintIdentifier = "13B07F861A680F5B00A75B9A"
|
||||
BuildableName = "testapplication.app"
|
||||
BlueprintName = "testapplication"
|
||||
ReferencedContainer = "container:testapplication.xcodeproj">
|
||||
BuildableName = "Tones.app"
|
||||
BlueprintName = "Tones"
|
||||
ReferencedContainer = "container:Tones.xcodeproj">
|
||||
</BuildableReference>
|
||||
</BuildableProductRunnable>
|
||||
</LaunchAction>
|
||||
|
|
@ -72,9 +72,9 @@
|
|||
<BuildableReference
|
||||
BuildableIdentifier = "primary"
|
||||
BlueprintIdentifier = "13B07F861A680F5B00A75B9A"
|
||||
BuildableName = "testapplication.app"
|
||||
BlueprintName = "testapplication"
|
||||
ReferencedContainer = "container:testapplication.xcodeproj">
|
||||
BuildableName = "Tones.app"
|
||||
BlueprintName = "Tones"
|
||||
ReferencedContainer = "container:Tones.xcodeproj">
|
||||
</BuildableReference>
|
||||
</BuildableProductRunnable>
|
||||
</ProfileAction>
|
||||
|
|
@ -2,7 +2,7 @@
|
|||
<Workspace
|
||||
version = "1.0">
|
||||
<FileRef
|
||||
location = "group:testapplication.xcodeproj">
|
||||
location = "group:Tones.xcodeproj">
|
||||
</FileRef>
|
||||
<FileRef
|
||||
location = "group:Pods/Pods.xcodeproj">
|
||||
32
ios/Tones/GoogleService-Info.plist
Normal file
|
|
@ -0,0 +1,32 @@
|
|||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
|
||||
<plist version="1.0">
|
||||
<dict>
|
||||
<key>API_KEY</key>
|
||||
<string>AIzaSyClZkx4PFWhfIG3JDb6GD3g6Bl7-pWLNrU</string>
|
||||
<key>GCM_SENDER_ID</key>
|
||||
<string>917296693147</string>
|
||||
<key>PLIST_VERSION</key>
|
||||
<string>1</string>
|
||||
<key>BUNDLE_ID</key>
|
||||
<string>com.mattdimegs.tones</string>
|
||||
<key>PROJECT_ID</key>
|
||||
<string>tones-9f1d4</string>
|
||||
<key>STORAGE_BUCKET</key>
|
||||
<string>tones-9f1d4.firebasestorage.app</string>
|
||||
<key>IS_ADS_ENABLED</key>
|
||||
<false></false>
|
||||
<key>IS_ANALYTICS_ENABLED</key>
|
||||
<false></false>
|
||||
<key>IS_APPINVITE_ENABLED</key>
|
||||
<true></true>
|
||||
<key>IS_GCM_ENABLED</key>
|
||||
<true></true>
|
||||
<key>IS_SIGNIN_ENABLED</key>
|
||||
<true></true>
|
||||
<key>GOOGLE_APP_ID</key>
|
||||
<string>1:917296693147:ios:73d6d426aa60e52b35ab3e</string>
|
||||
<key>DATABASE_URL</key>
|
||||
<string>https://tones-9f1d4-default-rtdb.firebaseio.com</string>
|
||||
</dict>
|
||||
</plist>
|
||||
|
After Width: | Height: | Size: 166 KiB |
|
|
@ -0,0 +1,20 @@
|
|||
{
|
||||
"colors": [
|
||||
{
|
||||
"color": {
|
||||
"components": {
|
||||
"alpha": "1.000",
|
||||
"blue": "1.00000000000000",
|
||||
"green": "1.00000000000000",
|
||||
"red": "1.00000000000000"
|
||||
},
|
||||
"color-space": "srgb"
|
||||
},
|
||||
"idiom": "universal"
|
||||
}
|
||||
],
|
||||
"info": {
|
||||
"version": 1,
|
||||
"author": "expo"
|
||||
}
|
||||
}
|
||||
|
|
@ -7,10 +7,12 @@
|
|||
},
|
||||
{
|
||||
"idiom": "universal",
|
||||
"filename": "image@2x.png",
|
||||
"scale": "2x"
|
||||
},
|
||||
{
|
||||
"idiom": "universal",
|
||||
"filename": "image@3x.png",
|
||||
"scale": "3x"
|
||||
}
|
||||
],
|
||||
|
Before Width: | Height: | Size: 58 KiB After Width: | Height: | Size: 58 KiB |
|
Before Width: | Height: | Size: 58 KiB After Width: | Height: | Size: 58 KiB |
|
Before Width: | Height: | Size: 58 KiB After Width: | Height: | Size: 58 KiB |
|
|
@ -7,7 +7,7 @@
|
|||
<key>CFBundleDevelopmentRegion</key>
|
||||
<string>$(DEVELOPMENT_LANGUAGE)</string>
|
||||
<key>CFBundleDisplayName</key>
|
||||
<string>test-application</string>
|
||||
<string>Tones</string>
|
||||
<key>CFBundleExecutable</key>
|
||||
<string>$(EXECUTABLE_NAME)</string>
|
||||
<key>CFBundleIdentifier</key>
|
||||
|
|
@ -19,7 +19,7 @@
|
|||
<key>CFBundlePackageType</key>
|
||||
<string>$(PRODUCT_BUNDLE_PACKAGE_TYPE)</string>
|
||||
<key>CFBundleShortVersionString</key>
|
||||
<string>1.0.0</string>
|
||||
<string>1.0.1</string>
|
||||
<key>CFBundleSignature</key>
|
||||
<string>????</string>
|
||||
<key>CFBundleURLTypes</key>
|
||||
|
|
@ -28,12 +28,14 @@
|
|||
<key>CFBundleURLSchemes</key>
|
||||
<array>
|
||||
<string>myapp</string>
|
||||
<string>com.anonymous.testapplication</string>
|
||||
<string>com.mattdimegs.tones</string>
|
||||
</array>
|
||||
</dict>
|
||||
</array>
|
||||
<key>CFBundleVersion</key>
|
||||
<string>1</string>
|
||||
<key>LSMinimumSystemVersion</key>
|
||||
<string>12.0</string>
|
||||
<key>LSRequiresIPhoneOS</key>
|
||||
<true/>
|
||||
<key>NSAppTransportSecurity</key>
|
||||
|
|
@ -4,6 +4,16 @@
|
|||
<dict>
|
||||
<key>NSPrivacyAccessedAPITypes</key>
|
||||
<array>
|
||||
<dict>
|
||||
<key>NSPrivacyAccessedAPIType</key>
|
||||
<string>NSPrivacyAccessedAPICategoryFileTimestamp</string>
|
||||
<key>NSPrivacyAccessedAPITypeReasons</key>
|
||||
<array>
|
||||
<string>C617.1</string>
|
||||
<string>0A2A.1</string>
|
||||
<string>3B52.1</string>
|
||||
</array>
|
||||
</dict>
|
||||
<dict>
|
||||
<key>NSPrivacyAccessedAPIType</key>
|
||||
<string>NSPrivacyAccessedAPICategoryUserDefaults</string>
|
||||
|
|
@ -14,12 +24,10 @@
|
|||
</dict>
|
||||
<dict>
|
||||
<key>NSPrivacyAccessedAPIType</key>
|
||||
<string>NSPrivacyAccessedAPICategoryFileTimestamp</string>
|
||||
<string>NSPrivacyAccessedAPICategorySystemBootTime</string>
|
||||
<key>NSPrivacyAccessedAPITypeReasons</key>
|
||||
<array>
|
||||
<string>0A2A.1</string>
|
||||
<string>3B52.1</string>
|
||||
<string>C617.1</string>
|
||||
<string>35F9.1</string>
|
||||
</array>
|
||||
</dict>
|
||||
<dict>
|
||||
|
|
@ -31,14 +39,6 @@
|
|||
<string>85F4.1</string>
|
||||
</array>
|
||||
</dict>
|
||||
<dict>
|
||||
<key>NSPrivacyAccessedAPIType</key>
|
||||
<string>NSPrivacyAccessedAPICategorySystemBootTime</string>
|
||||
<key>NSPrivacyAccessedAPITypeReasons</key>
|
||||
<array>
|
||||
<string>35F9.1</string>
|
||||
</array>
|
||||
</dict>
|
||||
</array>
|
||||
<key>NSPrivacyCollectedDataTypes</key>
|
||||
<array/>
|
||||