diff --git a/.github/actions/asa-go-setup/action.yml b/.github/actions/asa-go-setup/action.yml index f0ac48e64a..f9093544bc 100644 --- a/.github/actions/asa-go-setup/action.yml +++ b/.github/actions/asa-go-setup/action.yml @@ -37,8 +37,3 @@ runs: working-directory: ./mobile/asa-go shell: bash run: yarn install - - - name: Build - working-directory: ./mobile/asa-go - shell: bash - run: yarn build diff --git a/.github/workflows/asa_go_android_build.yml b/.github/workflows/asa_go_android_build.yml index 5fe0f0cb8f..056146a4d4 100644 --- a/.github/workflows/asa_go_android_build.yml +++ b/.github/workflows/asa_go_android_build.yml @@ -1,7 +1,7 @@ name: Build ASA Go Android env: - appBuildVersion: "1.0.2" + appBuildVersion: "1.0.3" on: workflow_dispatch: @@ -20,6 +20,7 @@ jobs: "KEY_ALIAS" "SIGNING_STORE_PASSWORD" "SIGNING_KEY_PASSWORD" + "GOOGLE_SERVICES_JSON" "VITE_BASEMAP_TILE_URL" "VITE_BASEMAP_STYLE_URL" ) @@ -34,6 +35,7 @@ jobs: KEY_ALIAS: ${{ secrets.ANDROID_KEY_ALIAS }} SIGNING_STORE_PASSWORD: ${{ secrets.ANDROID_SIGNING_STORE_PASSWORD }} SIGNING_KEY_PASSWORD: ${{ secrets.ANDROID_SIGNING_KEY_PASSWORD }} + GOOGLE_SERVICES_JSON: ${{ secrets.GOOGLE_SERVICES_JSON }} VITE_BASEMAP_TILE_URL: ${{ secrets.VITE_BASEMAP_TILE_URL }} VITE_BASEMAP_STYLE_URL: ${{ secrets.VITE_BASEMAP_STYLE_URL }} @@ -71,11 +73,15 @@ jobs: echo "VITE_BASEMAP_TILE_URL=${VITE_BASEMAP_TILE_URL}" >> .env.production echo "VITE_BASEMAP_STYLE_URL=${VITE_BASEMAP_STYLE_URL}" >> .env.production + - name: Create google-services.json + env: + GOOGLE_SERVICES_JSON: ${{ secrets.GOOGLE_SERVICES_JSON }} + run: | + echo "$GOOGLE_SERVICES_JSON" | base64 -d > ./mobile/asa-go/android/app/src/prod/google-services.json + - name: Build Capacitor and Sync working-directory: ./mobile/asa-go - run: | - yarn build:prod - yarn cap sync android + run: yarn cap:sync:android:prod - name: Set up Java uses: actions/setup-java@v5 @@ -104,11 +110,11 @@ jobs: ANDROID_SIGNING_STORE_PASSWORD: ${{ secrets.ANDROID_SIGNING_STORE_PASSWORD }} ANDROID_SIGNING_KEY_PASSWORD: ${{ secrets.ANDROID_SIGNING_KEY_PASSWORD }} run: | - ./gradlew bundleRelease + ./gradlew bundleProdRelease - uses: actions/upload-artifact@v7 with: name: ASA-Go-AAB - path: mobile/asa-go/android/app/build/outputs/bundle/release/*.aab + path: mobile/asa-go/android/app/build/outputs/bundle/prodRelease/*.aab retention-days: 1 if-no-files-found: error diff --git a/.github/workflows/asa_go_integration.yml b/.github/workflows/asa_go_integration.yml index dffff9ef09..84a13569b2 100644 --- a/.github/workflows/asa_go_integration.yml +++ b/.github/workflows/asa_go_integration.yml @@ -46,7 +46,7 @@ jobs: uses: ./.github/actions/asa-go-setup - name: Sync Capacitor iOS working-directory: ./mobile/asa-go - run: yarn cap sync ios + run: yarn cap:sync:ios:prod - name: Use Xcode latest stable uses: maxim-lobanov/setup-xcode@60606e260d2fc5762a71e64e74b2174e8ea3c8bd with: @@ -80,10 +80,10 @@ jobs: - name: Create google-services.json env: GOOGLE_SERVICES_JSON: ${{ secrets.GOOGLE_SERVICES_JSON }} - run: echo "$GOOGLE_SERVICES_JSON" | base64 -d > ./mobile/asa-go/android/app/google-services.json + run: echo "$GOOGLE_SERVICES_JSON" | base64 -d > ./mobile/asa-go/android/app/src/prod/google-services.json - name: Sync Capacitor Android working-directory: ./mobile/asa-go - run: yarn cap sync android + run: yarn cap:sync:android:prod - name: Set up Java uses: actions/setup-java@v5 with: diff --git a/.github/workflows/asa_go_ios_build_deploy.yml b/.github/workflows/asa_go_ios_build_deploy.yml index ce8d4cddbb..25bb22794e 100644 --- a/.github/workflows/asa_go_ios_build_deploy.yml +++ b/.github/workflows/asa_go_ios_build_deploy.yml @@ -2,7 +2,7 @@ name: Publish ASA Go iOS env: appBuildNumber: ${{ github.run_number }} - appBuildVersion: "1.0.2" + appBuildVersion: "1.0.3" permissions: contents: read @@ -21,6 +21,7 @@ jobs: "CERTIFICATE" "KEYCHAIN_PASSWD" "PROVISIONING_PROFILE" + "GOOGLE_SERVICES_PLIST" "VITE_BASEMAP_TILE_URL" "VITE_BASEMAP_STYLE_URL" ) @@ -34,6 +35,7 @@ jobs: CERTIFICATE: ${{ secrets.APPLE_APP_STORE_BUILD_CERTIFICATE_BASE64 }} KEYCHAIN_PASSWD: ${{ secrets.APPLE_APP_STORE_BUILD_CERTIFICATE_PASSWD }} PROVISIONING_PROFILE: ${{ secrets.IOS_PROVISION_PROFILE_BASE64 }} + GOOGLE_SERVICES_PLIST: ${{ secrets.GOOGLE_SERVICES_PLIST }} VITE_BASEMAP_TILE_URL: ${{ secrets.VITE_BASEMAP_TILE_URL }} VITE_BASEMAP_STYLE_URL: ${{ secrets.VITE_BASEMAP_STYLE_URL }} build-and-publish: @@ -69,11 +71,16 @@ jobs: echo "VITE_BASEMAP_TILE_URL=${VITE_BASEMAP_TILE_URL}" >>.env.production echo "VITE_BASEMAP_STYLE_URL=${VITE_BASEMAP_STYLE_URL}" >>.env.production - - name: Build Capacitor and Sync + - name: Copy GoogleService-Info.plist + env: + GOOGLE_SERVICES_PLIST: ${{ secrets.GOOGLE_SERVICES_PLIST }} working-directory: ./mobile/asa-go run: | - yarn build:prod - yarn cap sync ios + echo "$GOOGLE_SERVICES_PLIST" | base64 --decode > ./ios/App/App/Firebase/Prod/GoogleService-Info.plist + + - name: Build Capacitor and Sync + working-directory: ./mobile/asa-go + run: yarn cap:sync:ios:prod - name: Setup iOS Signing env: BUILD_CERTIFICATE_BASE64: ${{ secrets.APPLE_APP_STORE_BUILD_CERTIFICATE_BASE64 }} diff --git a/mobile/asa-go/Notifications.md b/mobile/asa-go/Notifications.md new file mode 100644 index 0000000000..67db29f6b0 --- /dev/null +++ b/mobile/asa-go/Notifications.md @@ -0,0 +1,131 @@ +# Notifications + +Short reference for the ASA Go mobile notification setup. + +## iOS app IDs + +We have two iOS app variants: + +- Prod bundle ID: `ca.bc.gov.asago` +- Dev bundle ID: `ca.bc.gov.asago.dev` + +These bundle IDs must match the Firebase iOS app registration exactly. + +## Android app IDs + +We also have two Android app variants: + +- Prod application ID: `ca.bc.gov.asago` +- Dev application ID: `ca.bc.gov.asago.dev` + +These application IDs must match the Firebase Android app registration exactly. + +## Firebase dev vs prod + +Current mapping: + +- Prod plist `BUNDLE_ID`: `ca.bc.gov.asago` +- Dev plist `BUNDLE_ID`: `ca.bc.gov.asago.dev` + +If the wrong plist is used, Firebase Messaging will not be configured for the installed app correctly. + +The same rule applies on Android: if the wrong `google-services.json` is used, Firebase Messaging will not be configured for the installed app correctly. + +## GoogleService-Info.plist + +`GoogleService-Info.plist` is the iOS Firebase app config file. + +It tells the app which Firebase project/app to talk to, including: + +- Firebase project ID +- iOS app ID +- sender ID +- API key +- expected iOS bundle ID + +It is required locally in the iOS project. + +## google-services.json + +`google-services.json` is the Android Firebase app config file. + +It tells the Android app which Firebase project/app to talk to, including: + +- Firebase project ID +- Android app ID +- sender ID +- API key +- expected Android application ID + +It is required locally in the Android project. + +## Google Play App Signing + +When distributing via the Play Store, Google re-signs your APK with their own App Signing Key rather than your local upload key. Firebase needs the SHA-1 of this key registered to validate the app's identity when requesting FCM tokens. +To get it: Play Console -> Test and release -> App Integrity -> App signing → copy the SHA-1 and add it to the app in Firebase Console under Project Settings. + +## APNs auth key + +The APNs auth key is the Apple push key used by Firebase to send iOS notifications through APNs. + +Important points: + +- It is only uploaded in Firebase Console. +- It can be used for both development and production APNs delivery. + +Because we have separate Firebase setups for dev and prod, make sure the Firebase project used by each app has APNs configured. + +## What lives where + +We use different Firebase app configs for prod and dev on both platforms. + +- Prod Firebase plist: `ios/App/App/Firebase/Prod/GoogleService-Info.plist` +- Dev Firebase plist: `ios/App/App/Firebase/Dev/GoogleService-Info.plist` +- Prod Android config: `android/app/src/prod/google-services.json` +- Dev Android config: `android/app/src/dev/google-services.json` + +In the app folder: + +- iOS bundle IDs +- Android application IDs / flavors +- Xcode targets/schemes (`ASA Go` and `ASA Go Dev`) +- `GoogleService-Info.plist` +- `google-services.json` +- Capacitor config + +In Firebase Console: + +- APNs auth key upload for iOS +- Android SHA-1 upload for Android +- Firebase app registration for each bundle ID + +## Why we use separate app IDs + +This repo uses separate app IDs for dev and prod instead of trying to inject only Firebase config into one app identity. + +This lets dev and prod be installed on the same device at the same time. It also keeps dev push notifications separate from +prod and makes the Firebase app registration clearer, because each app variant has its own app ID. + +On iOS, the current implementation uses separate Xcode targets and separate `Info.plist` files for those app identities. + +## Running dev vs prod + +`capacitor.config.ts` switches between dev and prod using `APP_ENV`. + +Examples: + +```bash +APP_ENV=dev yarn cap:sync:ios:dev +APP_ENV=prod yarn cap:sync:ios:prod +``` + +For live reload: + +```bash +APP_ENV=dev ionic capacitor run ios -l --external +APP_ENV=prod ionic capacitor run ios -l --external +APP_ENV=dev ionic capacitor run android -l --external +APP_ENV=prod ionic capacitor run android -l --external +``` + +On iOS, `APP_ENV=dev` selects the `ASA Go Dev` scheme and `APP_ENV=prod` selects `ASA Go`. diff --git a/mobile/asa-go/README.md b/mobile/asa-go/README.md index 244a8503e1..1dfdf6752a 100644 --- a/mobile/asa-go/README.md +++ b/mobile/asa-go/README.md @@ -2,6 +2,8 @@ Capacitor app using react/vite. +For iOS & Android Firebase push notification setup details, see [Notifications.md](Notifications.md). + ## Building The keycloak plugin must be built before installing asa-go dependencies, as asa-go resolves it as a local path dependency. @@ -26,8 +28,13 @@ yarn build 1. Make sure xcode is installed with `xcode-select --install` 2. Go to `mobile/asa-go` -3. Run `yarn cap sync ios` to synchronize app with iOS platform (handles `pod install`) -4. Build and run with live reload: `ionic cap run ios -l --external` +3. Run `APP_ENV=dev yarn cap:sync:ios:dev` or `APP_ENV=prod yarn cap:sync:ios:prod` +4. List available devices/simulators with `ionic capacitor run ios --list` +5. Build and run with live reload: + - `APP_ENV=dev ionic capacitor run ios -l --external` + - `APP_ENV=prod ionic capacitor run ios -l --external` + +`APP_ENV=dev` selects the `ASA Go Dev` iOS scheme and `APP_ENV=prod` selects `ASA Go`. ### Building/Running Android @@ -36,14 +43,20 @@ yarn build - With Jetbrains Toolbox it should be `/Users//Library/Android/sdk/` - Set `$ANDROID_HOME` to the path of the Android SDK 3. Go to `mobile/asa-go` -4. Run `yarn cap sync android` to synchronize app with Android platform -5. Build and run with live reload: `ionic cap run android -l --external` +4. Run `APP_ENV=dev yarn cap:sync:android:dev` or `APP_ENV=prod yarn cap:sync:android:prod` +5. If you are building from Android Studio, open the [`android`](/Users/breedwar/projects/other/wps/mobile/asa-go/android) project and choose the matching build variant in the `Build Variants` tool window: + - `devDebug` or `devRelease` after a dev sync + - `prodDebug` or `prodRelease` after a prod sync +6. Build and run with live reload: `APP_ENV=dev ionic capacitor run android -l --external` or `APP_ENV=prod ionic capacitor run android -l --external` + +If the selected Android Studio build variant does not match the last `cap sync` flavor, you can end up with mismatched native config and web assets. To build a debug APK directly: ```bash cd mobile/asa-go/android -./gradlew assembleDebug +./gradlew assembleDevDebug +./gradlew assembleProdDebug ``` #### Running on a physical Android device against your local API @@ -73,9 +86,24 @@ pmtiles extract https://build.protomaps.com/20250326.pmtiles bc_basemap_20250326 ### Distributing -Bump `appBuildVersion` appropriately via semvar, in `.github/workflows/asa_go_build_deploy.yml`. -Run: `gh workflow run "Publish ASA Go"` -This will build and publish the app that is on the `main` branch. +Bump `appBuildVersion` appropriately in: + +- `.github/workflows/asa_go_android_build.yml` +- `.github/workflows/asa_go_ios_build_deploy.yml` + +Run the Android build workflow: + +```bash +gh workflow run "Build ASA Go Android" --ref +``` + +Run the iOS build/deploy workflow: + +```bash +gh workflow run "Publish ASA Go iOS" --ref +``` + +These workflows build the app from the specified branch. ## CI Workflows @@ -91,7 +119,7 @@ All three jobs use the shared composite action `.github/actions/asa-go-setup`, w 1. Sets up Node.js 20 2. Caches and installs `mobile/keycloak` node_modules, then runs `yarn build` -3. Caches and installs `mobile/asa-go` node_modules, then runs `yarn build` +3. Caches and installs `mobile/asa-go` node_modules ### Android Release Build (`.github/workflows/asa_go_android_build.yml`) diff --git a/mobile/asa-go/android/app/build.gradle b/mobile/asa-go/android/app/build.gradle index a7dca220dc..44b5e0e0f0 100644 --- a/mobile/asa-go/android/app/build.gradle +++ b/mobile/asa-go/android/app/build.gradle @@ -1,12 +1,17 @@ apply plugin: 'com.android.application' apply plugin: 'jacoco' -apply plugin: 'com.google.gms.google-services' android { namespace "ca.bc.gov.asago" compileSdk rootProject.ext.compileSdkVersion + + buildFeatures { + buildConfig true + } + + flavorDimensions "env" + defaultConfig { - applicationId "ca.bc.gov.asago" minSdkVersion rootProject.ext.minSdkVersion targetSdkVersion rootProject.ext.targetSdkVersion versionCode System.getenv("VERSION_CODE") ? System.getenv("VERSION_CODE").toInteger() : 7 @@ -21,6 +26,23 @@ android { appAuthRedirectScheme: "ca.bc.gov.asago", appAuthManagementActivity: "ca.bc.gov.asago.MainActivity" ] + buildConfigField "String", "APP_AUTH_REDIRECT_SCHEME", "\"ca.bc.gov.asago\"" + } + productFlavors { + dev { + dimension "env" + applicationId "ca.bc.gov.asago.dev" + resValue "string", "app_name", "ASA Go Dev" + resValue "string", "title_activity_main", "ASA Go Dev" + resValue "string", "custom_url_scheme", "ca.bc.gov.asago" + } + prod { + dimension "env" + applicationId "ca.bc.gov.asago" + resValue "string", "app_name", "ASA Go" + resValue "string", "title_activity_main", "ASA Go" + resValue "string", "custom_url_scheme", "ca.bc.gov.asago" + } } signingConfigs { release { @@ -76,21 +98,24 @@ tasks.withType(Test) { jacoco.excludes = ['jdk.internal.*'] } -task jacocoTestReport(type: JacocoReport, dependsOn: ['testDebugUnitTest']) { +task jacocoTestReport(type: JacocoReport, dependsOn: ['testProdDebugUnitTest']) { reports { xml.required = true html.required = false } def fileFilter = ['**/R.class', '**/R$*.class', '**/BuildConfig.*', '**/Manifest*.*', '**/*Test*.*', 'android/**/*.*'] - def debugTree = fileTree(dir: "${buildDir}/intermediates/javac/debug/compileDebugJavaWithJavac/classes", excludes: fileFilter) + def debugTree = fileTree(dir: "${buildDir}/intermediates/javac/prodDebug/compileProdDebugJavaWithJavac/classes", excludes: fileFilter) sourceDirectories.setFrom(files(["${project.projectDir}/src/main/java"])) classDirectories.setFrom(files([debugTree])) - executionData.setFrom(fileTree(dir: "$buildDir", includes: ["jacoco/testDebugUnitTest.exec"])) + executionData.setFrom(fileTree(dir: "$buildDir", includes: ["jacoco/testProdDebugUnitTest.exec"])) } try { - def servicesJSON = file('google-services.json') - if (servicesJSON.text) { + def googleServicesFiles = [ + file('src/dev/google-services.json'), + file('src/prod/google-services.json') + ] + if (googleServicesFiles.any { it.exists() && it.text.trim() }) { apply plugin: 'com.google.gms.google-services' } } catch(Exception e) { diff --git a/mobile/asa-go/android/app/src/dev/.gitkeep b/mobile/asa-go/android/app/src/dev/.gitkeep new file mode 100644 index 0000000000..8b13789179 --- /dev/null +++ b/mobile/asa-go/android/app/src/dev/.gitkeep @@ -0,0 +1 @@ + diff --git a/mobile/asa-go/android/app/src/main/AndroidManifest.xml b/mobile/asa-go/android/app/src/main/AndroidManifest.xml index cf1969f6a9..856abc6603 100644 --- a/mobile/asa-go/android/app/src/main/AndroidManifest.xml +++ b/mobile/asa-go/android/app/src/main/AndroidManifest.xml @@ -33,7 +33,7 @@ - + mockedStatic = mockStatic(KeycloakPlugin.class)) { mockedStatic.when(KeycloakPlugin::getInstance).thenReturn(mockPlugin); - Uri testUri = Uri.parse("ca.bc.gov.asago://callback?code=testcode"); + Uri testUri = Uri.parse(authUri("callback?code=testcode")); KeycloakPlugin plugin = KeycloakPlugin.getInstance(); - if (plugin != null && "ca.bc.gov.asago".equals(testUri.getScheme())) { + if (plugin != null && AUTH_REDIRECT_SCHEME.equals(testUri.getScheme())) { plugin.handleAuthCallback(testUri); } @@ -109,7 +114,7 @@ public void testHandleAuthCallback_notCalledForWrongScheme() { Uri testUri = Uri.parse("https://example.com/callback"); KeycloakPlugin plugin = KeycloakPlugin.getInstance(); - if (plugin != null && "ca.bc.gov.asago".equals(testUri.getScheme())) { + if (plugin != null && AUTH_REDIRECT_SCHEME.equals(testUri.getScheme())) { plugin.handleAuthCallback(testUri); } @@ -122,11 +127,11 @@ public void testHandleAuthCallback_notCalledWhenPluginIsNull() { try (MockedStatic mockedStatic = mockStatic(KeycloakPlugin.class)) { mockedStatic.when(KeycloakPlugin::getInstance).thenReturn(null); - Uri testUri = Uri.parse("ca.bc.gov.asago://callback?code=test"); + Uri testUri = Uri.parse(authUri("callback?code=test")); KeycloakPlugin plugin = KeycloakPlugin.getInstance(); // This should not throw NullPointerException - if (plugin != null && "ca.bc.gov.asago".equals(testUri.getScheme())) { + if (plugin != null && AUTH_REDIRECT_SCHEME.equals(testUri.getScheme())) { plugin.handleAuthCallback(testUri); } @@ -144,7 +149,7 @@ public void testIntentData_canBeNull() { @Test public void testIntentData_canBeExtracted() { - Uri testUri = Uri.parse("ca.bc.gov.asago://callback"); + Uri testUri = Uri.parse(authUri("callback")); Intent intent = new Intent(Intent.ACTION_VIEW, testUri); Uri data = intent.getData(); @@ -155,16 +160,16 @@ public void testIntentData_canBeExtracted() { @Test public void testSchemeMatching_isCaseSensitive() { // Android URI schemes are case-sensitive - Uri correctScheme = Uri.parse("ca.bc.gov.asago://callback"); - Uri wrongCaseScheme = Uri.parse("CA.BC.GOV.ASAGO://callback"); + Uri correctScheme = Uri.parse(authUri("callback")); + Uri wrongCaseScheme = Uri.parse(AUTH_REDIRECT_SCHEME.toUpperCase() + "://callback"); - assertEquals("ca.bc.gov.asago", correctScheme.getScheme()); - assertNotEquals("ca.bc.gov.asago", wrongCaseScheme.getScheme()); + assertEquals(AUTH_REDIRECT_SCHEME, correctScheme.getScheme()); + assertNotEquals(AUTH_REDIRECT_SCHEME, wrongCaseScheme.getScheme()); } @Test public void testMultipleQueryParameters_canBeExtracted() { - Uri uri = Uri.parse("ca.bc.gov.asago://callback?code=abc&state=xyz&session_state=123"); + Uri uri = Uri.parse(authUri("callback?code=abc&state=xyz&session_state=123")); assertEquals("abc", uri.getQueryParameter("code")); assertEquals("xyz", uri.getQueryParameter("state")); @@ -173,9 +178,9 @@ public void testMultipleQueryParameters_canBeExtracted() { @Test public void testUriWithFragment_preservesFragment() { - Uri uri = Uri.parse("ca.bc.gov.asago://callback?code=test#fragment"); + Uri uri = Uri.parse(authUri("callback?code=test#fragment")); - assertEquals("ca.bc.gov.asago", uri.getScheme()); + assertEquals(AUTH_REDIRECT_SCHEME, uri.getScheme()); assertEquals("test", uri.getQueryParameter("code")); assertEquals("fragment", uri.getFragment()); } @@ -188,7 +193,7 @@ public void testHandleAuthorizationResponse_isCalledWithIntent() { mockedStatic.when(KeycloakPlugin::getInstance).thenReturn(mockPlugin); Intent intent = new Intent(); - intent.setData(Uri.parse("ca.bc.gov.asago://callback")); + intent.setData(Uri.parse(authUri("callback"))); KeycloakPlugin plugin = KeycloakPlugin.getInstance(); if (plugin != null) { @@ -202,7 +207,7 @@ public void testHandleAuthorizationResponse_isCalledWithIntent() { @Test public void testActivitySchemeConstant() { // Verify the expected scheme matches what's in AndroidManifest - String expectedScheme = "ca.bc.gov.asago"; + String expectedScheme = AUTH_REDIRECT_SCHEME; Uri uri = Uri.parse(expectedScheme + "://callback"); assertEquals(expectedScheme, uri.getScheme()); @@ -227,15 +232,15 @@ public void testPluginHandlesMultipleCallbacks() { try (MockedStatic mockedStatic = mockStatic(KeycloakPlugin.class)) { mockedStatic.when(KeycloakPlugin::getInstance).thenReturn(mockPlugin); - Uri uri1 = Uri.parse("ca.bc.gov.asago://callback?code=code1"); - Uri uri2 = Uri.parse("ca.bc.gov.asago://callback?code=code2"); + Uri uri1 = Uri.parse(authUri("callback?code=code1")); + Uri uri2 = Uri.parse(authUri("callback?code=code2")); KeycloakPlugin plugin = KeycloakPlugin.getInstance(); if (plugin != null) { - if ("ca.bc.gov.asago".equals(uri1.getScheme())) { + if (AUTH_REDIRECT_SCHEME.equals(uri1.getScheme())) { plugin.handleAuthCallback(uri1); } - if ("ca.bc.gov.asago".equals(uri2.getScheme())) { + if (AUTH_REDIRECT_SCHEME.equals(uri2.getScheme())) { plugin.handleAuthCallback(uri2); } } @@ -246,10 +251,10 @@ public void testPluginHandlesMultipleCallbacks() { @Test public void testUriPreservation_fullUriString() { - String uriString = "ca.bc.gov.asago://auth/callback?code=abc&state=xyz&session_state=123"; + String uriString = authUri("auth/callback?code=abc&state=xyz&session_state=123"); Uri uri = Uri.parse(uriString); - assertEquals("ca.bc.gov.asago", uri.getScheme()); + assertEquals(AUTH_REDIRECT_SCHEME, uri.getScheme()); // In custom schemes, the authority/host is "auth" and path is "/callback" assertEquals("/callback", uri.getPath()); assertEquals("code=abc&state=xyz&session_state=123", uri.getQuery()); diff --git a/mobile/asa-go/capacitor.config.ts b/mobile/asa-go/capacitor.config.ts index 6c361b61e2..3473f28eff 100644 --- a/mobile/asa-go/capacitor.config.ts +++ b/mobile/asa-go/capacitor.config.ts @@ -1,10 +1,18 @@ import type { CapacitorConfig } from "@capacitor/cli"; +const mode = process.env.APP_ENV ?? "dev"; +const isDev = mode === "dev"; + const config: CapacitorConfig = { - appId: "ca.bc.gov.asago", - appName: "asa-go", + appId: isDev ? "ca.bc.gov.asago.dev" : "ca.bc.gov.asago", + appName: isDev ? "ASA Go Dev" : "ASA Go", webDir: "dist", - ios: { scheme: "ASA Go" }, + android: { + flavor: isDev ? "dev" : "prod", + }, + ios: { + scheme: isDev ? "ASA Go Dev" : "ASA Go", + }, plugins: { FirebaseMessaging: { presentationOptions: ["alert", "badge", "sound"], // iOS only diff --git a/mobile/asa-go/ios/App/App.xcodeproj/project.pbxproj b/mobile/asa-go/ios/App/App.xcodeproj/project.pbxproj index 2e744a46c1..a0f05b14f7 100644 --- a/mobile/asa-go/ios/App/App.xcodeproj/project.pbxproj +++ b/mobile/asa-go/ios/App/App.xcodeproj/project.pbxproj @@ -3,11 +3,12 @@ archiveVersion = 1; classes = { }; - objectVersion = 54; + objectVersion = 48; objects = { /* Begin PBXBuildFile section */ 2FAD9763203C412B000D30F8 /* config.xml in Resources */ = {isa = PBXBuildFile; fileRef = 2FAD9762203C412B000D30F8 /* config.xml */; }; + 3051119718597F082FD266F3 /* Pods_ASA_Go.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 0146A60730585B7E7BDD0243 /* Pods_ASA_Go.framework */; }; 4309C9DBE16C4DF38D493C6C /* PrivacyInfo.xcprivacy in Resources */ = {isa = PBXBuildFile; fileRef = 1E60787A749448FB8E269E5A /* PrivacyInfo.xcprivacy */; }; 50379B232058CBB4000EE86E /* capacitor.config.json in Resources */ = {isa = PBXBuildFile; fileRef = 50379B222058CBB4000EE86E /* capacitor.config.json */; }; 504EC3081FED79650016851F /* AppDelegate.swift in Sources */ = {isa = PBXBuildFile; fileRef = 504EC3071FED79650016851F /* AppDelegate.swift */; }; @@ -15,11 +16,22 @@ 504EC30F1FED79650016851F /* Assets.xcassets in Resources */ = {isa = PBXBuildFile; fileRef = 504EC30E1FED79650016851F /* Assets.xcassets */; }; 504EC3121FED79650016851F /* LaunchScreen.storyboard in Resources */ = {isa = PBXBuildFile; fileRef = 504EC3101FED79650016851F /* LaunchScreen.storyboard */; }; 50B271D11FEDC1A000F3C39B /* public in Resources */ = {isa = PBXBuildFile; fileRef = 50B271D01FEDC1A000F3C39B /* public */; }; - 5D93CF492F57402300551A11 /* GoogleService-Info.plist in Resources */ = {isa = PBXBuildFile; fileRef = 5D93CF482F57402300551A11 /* GoogleService-Info.plist */; }; - D51D96E4043C4B4AB92C9174 /* Pods_ASA_Go.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = BEB1CB68C85A338353E59F87 /* Pods_ASA_Go.framework */; }; + A511FA762F630E36007AD49F /* AppDelegate.swift in Sources */ = {isa = PBXBuildFile; fileRef = 504EC3071FED79650016851F /* AppDelegate.swift */; }; + A511FA7A2F630E36007AD49F /* LaunchScreen.storyboard in Resources */ = {isa = PBXBuildFile; fileRef = 504EC3101FED79650016851F /* LaunchScreen.storyboard */; }; + A511FA7C2F630E36007AD49F /* public in Resources */ = {isa = PBXBuildFile; fileRef = 50B271D01FEDC1A000F3C39B /* public */; }; + A511FA7D2F630E36007AD49F /* Assets.xcassets in Resources */ = {isa = PBXBuildFile; fileRef = 504EC30E1FED79650016851F /* Assets.xcassets */; }; + A511FA7E2F630E36007AD49F /* capacitor.config.json in Resources */ = {isa = PBXBuildFile; fileRef = 50379B222058CBB4000EE86E /* capacitor.config.json */; }; + A511FA7F2F630E36007AD49F /* Main.storyboard in Resources */ = {isa = PBXBuildFile; fileRef = 504EC30B1FED79650016851F /* Main.storyboard */; }; + A511FA802F630E36007AD49F /* config.xml in Resources */ = {isa = PBXBuildFile; fileRef = 2FAD9762203C412B000D30F8 /* config.xml */; }; + A511FA812F630E36007AD49F /* PrivacyInfo.xcprivacy in Resources */ = {isa = PBXBuildFile; fileRef = 1E60787A749448FB8E269E5A /* PrivacyInfo.xcprivacy */; }; + A511FA8D2F631843007AD49F /* GoogleService-Info.plist in Resources */ = {isa = PBXBuildFile; fileRef = A511FA8C2F631843007AD49F /* GoogleService-Info.plist */; }; + A511FA8F2F631858007AD49F /* GoogleService-Info.plist in Resources */ = {isa = PBXBuildFile; fileRef = A511FA8E2F631858007AD49F /* GoogleService-Info.plist */; }; + ABA9EE54FF69B84C1D8E12CA /* Pods_ASA_Go_Dev.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = F8A4D9A6B1370E8B40A3B42E /* Pods_ASA_Go_Dev.framework */; }; + D51D96E4043C4B4AB92C9174 /* BuildFile in Frameworks */ = {isa = PBXBuildFile; }; /* End PBXBuildFile section */ /* Begin PBXFileReference section */ + 0146A60730585B7E7BDD0243 /* Pods_ASA_Go.framework */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; includeInIndex = 0; path = Pods_ASA_Go.framework; sourceTree = BUILT_PRODUCTS_DIR; }; 1E60787A749448FB8E269E5A /* PrivacyInfo.xcprivacy */ = {isa = PBXFileReference; explicitFileType = undefined; fileEncoding = 9; includeInIndex = 0; lastKnownFileType = unknown; path = PrivacyInfo.xcprivacy; sourceTree = ""; }; 2FAD9762203C412B000D30F8 /* config.xml */ = {isa = PBXFileReference; lastKnownFileType = text.xml; path = config.xml; sourceTree = ""; }; 50379B222058CBB4000EE86E /* capacitor.config.json */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.json; path = capacitor.config.json; sourceTree = ""; }; @@ -30,12 +42,17 @@ 504EC3111FED79650016851F /* Base */ = {isa = PBXFileReference; lastKnownFileType = file.storyboard; name = Base; path = Base.lproj/LaunchScreen.storyboard; sourceTree = ""; }; 504EC3131FED79650016851F /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = ""; }; 50B271D01FEDC1A000F3C39B /* public */ = {isa = PBXFileReference; lastKnownFileType = folder; path = public; sourceTree = ""; }; - 5D93CF482F57402300551A11 /* GoogleService-Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = "GoogleService-Info.plist"; sourceTree = ""; }; + 51207C9C622B9020DC600D92 /* Pods-ASA Go Dev.release.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-ASA Go Dev.release.xcconfig"; path = "Pods/Target Support Files/Pods-ASA Go Dev/Pods-ASA Go Dev.release.xcconfig"; sourceTree = ""; }; + 5DECCDBD9A33EE51D824DC98 /* Pods-ASA Go Dev.debug.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-ASA Go Dev.debug.xcconfig"; path = "Pods/Target Support Files/Pods-ASA Go Dev/Pods-ASA Go Dev.debug.xcconfig"; sourceTree = ""; }; 6654B5E52E29AC1C000DA498 /* App.entitlements */ = {isa = PBXFileReference; lastKnownFileType = text.plist.entitlements; path = App.entitlements; sourceTree = ""; }; + A511FA862F630E36007AD49F /* ASA Go Dev.app */ = {isa = PBXFileReference; explicitFileType = wrapper.application; includeInIndex = 0; path = "ASA Go Dev.app"; sourceTree = BUILT_PRODUCTS_DIR; }; + A511FA872F630E36007AD49F /* dev-Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = "dev-Info.plist"; sourceTree = ""; }; + A511FA8C2F631843007AD49F /* GoogleService-Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; name = "GoogleService-Info.plist"; path = "Firebase/Prod/GoogleService-Info.plist"; sourceTree = ""; }; + A511FA8E2F631858007AD49F /* GoogleService-Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; name = "GoogleService-Info.plist"; path = "Firebase/Dev/GoogleService-Info.plist"; sourceTree = ""; }; AF51FD2D460BCFE21FA515B2 /* Pods-App.release.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-App.release.xcconfig"; path = "Pods/Target Support Files/Pods-App/Pods-App.release.xcconfig"; sourceTree = ""; }; - BEB1CB68C85A338353E59F87 /* Pods_ASA_Go.framework */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; includeInIndex = 0; path = Pods_ASA_Go.framework; sourceTree = BUILT_PRODUCTS_DIR; }; E5BF8FB19E4A8C9DE7D16845 /* Pods-ASA Go.release.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-ASA Go.release.xcconfig"; path = "Pods/Target Support Files/Pods-ASA Go/Pods-ASA Go.release.xcconfig"; sourceTree = ""; }; F476C89842489D0CE7665883 /* Pods-ASA Go.debug.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-ASA Go.debug.xcconfig"; path = "Pods/Target Support Files/Pods-ASA Go/Pods-ASA Go.debug.xcconfig"; sourceTree = ""; }; + F8A4D9A6B1370E8B40A3B42E /* Pods_ASA_Go_Dev.framework */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; includeInIndex = 0; path = Pods_ASA_Go_Dev.framework; sourceTree = BUILT_PRODUCTS_DIR; }; FC68EB0AF532CFC21C3344DD /* Pods-App.debug.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-App.debug.xcconfig"; path = "Pods/Target Support Files/Pods-App/Pods-App.debug.xcconfig"; sourceTree = ""; }; /* End PBXFileReference section */ @@ -44,7 +61,16 @@ isa = PBXFrameworksBuildPhase; buildActionMask = 2147483647; files = ( - D51D96E4043C4B4AB92C9174 /* Pods_ASA_Go.framework in Frameworks */, + D51D96E4043C4B4AB92C9174 /* BuildFile in Frameworks */, + 3051119718597F082FD266F3 /* Pods_ASA_Go.framework in Frameworks */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; + A511FA772F630E36007AD49F /* Frameworks */ = { + isa = PBXFrameworksBuildPhase; + buildActionMask = 2147483647; + files = ( + ABA9EE54FF69B84C1D8E12CA /* Pods_ASA_Go_Dev.framework in Frameworks */, ); runOnlyForDeploymentPostprocessing = 0; }; @@ -54,7 +80,8 @@ 27E2DDA53C4D2A4D1A88CE4A /* Frameworks */ = { isa = PBXGroup; children = ( - BEB1CB68C85A338353E59F87 /* Pods_ASA_Go.framework */, + 0146A60730585B7E7BDD0243 /* Pods_ASA_Go.framework */, + F8A4D9A6B1370E8B40A3B42E /* Pods_ASA_Go_Dev.framework */, ); name = Frameworks; sourceTree = ""; @@ -74,6 +101,7 @@ isa = PBXGroup; children = ( 504EC3041FED79650016851F /* ASA Go.app */, + A511FA862F630E36007AD49F /* ASA Go Dev.app */, ); name = Products; sourceTree = ""; @@ -81,7 +109,8 @@ 504EC3061FED79650016851F /* App */ = { isa = PBXGroup; children = ( - 5D93CF482F57402300551A11 /* GoogleService-Info.plist */, + A511FA8E2F631858007AD49F /* GoogleService-Info.plist */, + A511FA8C2F631843007AD49F /* GoogleService-Info.plist */, 6654B5E52E29AC1C000DA498 /* App.entitlements */, 50379B222058CBB4000EE86E /* capacitor.config.json */, 504EC3071FED79650016851F /* AppDelegate.swift */, @@ -89,6 +118,7 @@ 504EC30E1FED79650016851F /* Assets.xcassets */, 504EC3101FED79650016851F /* LaunchScreen.storyboard */, 504EC3131FED79650016851F /* Info.plist */, + A511FA872F630E36007AD49F /* dev-Info.plist */, 2FAD9762203C412B000D30F8 /* config.xml */, 50B271D01FEDC1A000F3C39B /* public */, ); @@ -102,6 +132,8 @@ AF51FD2D460BCFE21FA515B2 /* Pods-App.release.xcconfig */, F476C89842489D0CE7665883 /* Pods-ASA Go.debug.xcconfig */, E5BF8FB19E4A8C9DE7D16845 /* Pods-ASA Go.release.xcconfig */, + 5DECCDBD9A33EE51D824DC98 /* Pods-ASA Go Dev.debug.xcconfig */, + 51207C9C622B9020DC600D92 /* Pods-ASA Go Dev.release.xcconfig */, ); name = Pods; sourceTree = ""; @@ -128,6 +160,25 @@ productReference = 504EC3041FED79650016851F /* ASA Go.app */; productType = "com.apple.product-type.application"; }; + A511FA732F630E36007AD49F /* ASA Go Dev */ = { + isa = PBXNativeTarget; + buildConfigurationList = A511FA832F630E36007AD49F /* Build configuration list for PBXNativeTarget "ASA Go Dev" */; + buildPhases = ( + A511FA742F630E36007AD49F /* [CP] Check Pods Manifest.lock */, + A511FA752F630E36007AD49F /* Sources */, + A511FA772F630E36007AD49F /* Frameworks */, + A511FA792F630E36007AD49F /* Resources */, + A511FA822F630E36007AD49F /* [CP] Embed Pods Frameworks */, + ); + buildRules = ( + ); + dependencies = ( + ); + name = "ASA Go Dev"; + productName = App; + productReference = A511FA862F630E36007AD49F /* ASA Go Dev.app */; + productType = "com.apple.product-type.application"; + }; /* End PBXNativeTarget section */ /* Begin PBXProject section */ @@ -142,6 +193,9 @@ LastSwiftMigration = 1100; ProvisioningStyle = Automatic; }; + A511FA732F630E36007AD49F = { + ProvisioningStyle = Automatic; + }; }; }; buildConfigurationList = 504EC2FF1FED79650016851F /* Build configuration list for PBXProject "App" */; @@ -158,6 +212,7 @@ projectRoot = ""; targets = ( 504EC3031FED79650016851F /* ASA Go */, + A511FA732F630E36007AD49F /* ASA Go Dev */, ); }; /* End PBXProject section */ @@ -168,7 +223,7 @@ buildActionMask = 2147483647; files = ( 504EC3121FED79650016851F /* LaunchScreen.storyboard in Resources */, - 5D93CF492F57402300551A11 /* GoogleService-Info.plist in Resources */, + A511FA8D2F631843007AD49F /* GoogleService-Info.plist in Resources */, 50B271D11FEDC1A000F3C39B /* public in Resources */, 504EC30F1FED79650016851F /* Assets.xcassets in Resources */, 50379B232058CBB4000EE86E /* capacitor.config.json in Resources */, @@ -178,6 +233,21 @@ ); runOnlyForDeploymentPostprocessing = 0; }; + A511FA792F630E36007AD49F /* Resources */ = { + isa = PBXResourcesBuildPhase; + buildActionMask = 2147483647; + files = ( + A511FA7A2F630E36007AD49F /* LaunchScreen.storyboard in Resources */, + A511FA8F2F631858007AD49F /* GoogleService-Info.plist in Resources */, + A511FA7C2F630E36007AD49F /* public in Resources */, + A511FA7D2F630E36007AD49F /* Assets.xcassets in Resources */, + A511FA7E2F630E36007AD49F /* capacitor.config.json in Resources */, + A511FA7F2F630E36007AD49F /* Main.storyboard in Resources */, + A511FA802F630E36007AD49F /* config.xml in Resources */, + A511FA812F630E36007AD49F /* PrivacyInfo.xcprivacy in Resources */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; /* End PBXResourcesBuildPhase section */ /* Begin PBXShellScriptBuildPhase section */ @@ -214,6 +284,39 @@ shellScript = "\"${PODS_ROOT}/Target Support Files/Pods-ASA Go/Pods-ASA Go-frameworks.sh\"\n"; showEnvVarsInLog = 0; }; + A511FA742F630E36007AD49F /* [CP] Check Pods Manifest.lock */ = { + isa = PBXShellScriptBuildPhase; + buildActionMask = 2147483647; + files = ( + ); + inputPaths = ( + "${PODS_PODFILE_DIR_PATH}/Podfile.lock", + "${PODS_ROOT}/Manifest.lock", + ); + name = "[CP] Check Pods Manifest.lock"; + outputPaths = ( + "$(DERIVED_FILE_DIR)/Pods-ASA Go Dev-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; + }; + A511FA822F630E36007AD49F /* [CP] Embed Pods Frameworks */ = { + isa = PBXShellScriptBuildPhase; + buildActionMask = 2147483647; + files = ( + ); + inputPaths = ( + ); + name = "[CP] Embed Pods Frameworks"; + outputPaths = ( + ); + runOnlyForDeploymentPostprocessing = 0; + shellPath = /bin/sh; + shellScript = "\"${PODS_ROOT}/Target Support Files/Pods-ASA Go Dev/Pods-ASA Go Dev-frameworks.sh\"\n"; + showEnvVarsInLog = 0; + }; /* End PBXShellScriptBuildPhase section */ /* Begin PBXSourcesBuildPhase section */ @@ -225,6 +328,14 @@ ); runOnlyForDeploymentPostprocessing = 0; }; + A511FA752F630E36007AD49F /* Sources */ = { + isa = PBXSourcesBuildPhase; + buildActionMask = 2147483647; + files = ( + A511FA762F630E36007AD49F /* AppDelegate.swift in Sources */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; /* End PBXSourcesBuildPhase section */ /* Begin PBXVariantGroup section */ @@ -349,8 +460,7 @@ IPHONEOS_DEPLOYMENT_TARGET = 14.0; MTL_ENABLE_DEBUG_INFO = NO; SDKROOT = iphoneos; - SWIFT_COMPILATION_MODE = wholemodule; - SWIFT_OPTIMIZATION_LEVEL = "-O"; + SWIFT_OPTIMIZATION_LEVEL = "-Owholemodule"; VALIDATE_PRODUCT = YES; }; name = Release; @@ -366,10 +476,7 @@ DEVELOPMENT_TEAM = L796QSLV3E; INFOPLIST_FILE = App/Info.plist; IPHONEOS_DEPLOYMENT_TARGET = 14.0; - LD_RUNPATH_SEARCH_PATHS = ( - "$(inherited)", - "@executable_path/Frameworks", - ); + LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks"; MARKETING_VERSION = 1.0; OTHER_SWIFT_FLAGS = "$(inherited) \"-D\" \"COCOAPODS\" \"-DDEBUG\""; PRODUCT_BUNDLE_IDENTIFIER = ca.bc.gov.asago; @@ -393,10 +500,7 @@ "DEVELOPMENT_TEAM[sdk=iphoneos*]" = L796QSLV3E; INFOPLIST_FILE = App/Info.plist; IPHONEOS_DEPLOYMENT_TARGET = 14.0; - LD_RUNPATH_SEARCH_PATHS = ( - "$(inherited)", - "@executable_path/Frameworks", - ); + LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks"; MARKETING_VERSION = 1.0; PRODUCT_BUNDLE_IDENTIFIER = ca.bc.gov.asago; PRODUCT_NAME = "$(TARGET_NAME)"; @@ -407,6 +511,53 @@ }; name = Release; }; + A511FA842F630E36007AD49F /* Debug */ = { + isa = XCBuildConfiguration; + baseConfigurationReference = 5DECCDBD9A33EE51D824DC98 /* Pods-ASA Go Dev.debug.xcconfig */; + buildSettings = { + ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon; + CODE_SIGN_ENTITLEMENTS = App/App.entitlements; + CODE_SIGN_STYLE = Automatic; + CURRENT_PROJECT_VERSION = 1; + DEVELOPMENT_TEAM = L796QSLV3E; + INFOPLIST_FILE = "App/dev-Info.plist"; + IPHONEOS_DEPLOYMENT_TARGET = 14.0; + LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks"; + MARKETING_VERSION = 1.0; + OTHER_SWIFT_FLAGS = "$(inherited) \"-D\" \"COCOAPODS\" \"-DDEBUG\""; + PRODUCT_BUNDLE_IDENTIFIER = ca.bc.gov.asago.dev; + PRODUCT_NAME = "$(TARGET_NAME)"; + SWIFT_ACTIVE_COMPILATION_CONDITIONS = DEBUG; + SWIFT_VERSION = 5.0; + TARGETED_DEVICE_FAMILY = "1,2"; + }; + name = Debug; + }; + A511FA852F630E36007AD49F /* Release */ = { + isa = XCBuildConfiguration; + baseConfigurationReference = 51207C9C622B9020DC600D92 /* Pods-ASA Go Dev.release.xcconfig */; + buildSettings = { + ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon; + CODE_SIGN_ENTITLEMENTS = App/App.entitlements; + CODE_SIGN_IDENTITY = "Apple Distribution: Government of British Columbia (L796QSLV3E)"; + CODE_SIGN_STYLE = Manual; + CURRENT_PROJECT_VERSION = 1; + DEVELOPMENT_TEAM = L796QSLV3E; + "DEVELOPMENT_TEAM[sdk=iphoneos*]" = L796QSLV3E; + INFOPLIST_FILE = "App/dev-Info.plist"; + IPHONEOS_DEPLOYMENT_TARGET = 14.0; + LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks"; + MARKETING_VERSION = 1.0; + PRODUCT_BUNDLE_IDENTIFIER = ca.bc.gov.asago.dev; + "PRODUCT_BUNDLE_IDENTIFIER[sdk=*]" = ca.bc.gov.asago.dev; + PRODUCT_NAME = "$(TARGET_NAME)"; + "PROVISIONING_PROFILE_SPECIFIER[sdk=iphoneos*]" = "ASA Go"; + SWIFT_ACTIVE_COMPILATION_CONDITIONS = ""; + SWIFT_VERSION = 5.0; + TARGETED_DEVICE_FAMILY = "1,2"; + }; + name = Release; + }; /* End XCBuildConfiguration section */ /* Begin XCConfigurationList section */ @@ -428,8 +579,16 @@ defaultConfigurationIsVisible = 0; defaultConfigurationName = Release; }; + A511FA832F630E36007AD49F /* Build configuration list for PBXNativeTarget "ASA Go Dev" */ = { + isa = XCConfigurationList; + buildConfigurations = ( + A511FA842F630E36007AD49F /* Debug */, + A511FA852F630E36007AD49F /* Release */, + ); + defaultConfigurationIsVisible = 0; + defaultConfigurationName = Release; + }; /* End XCConfigurationList section */ - }; rootObject = 504EC2FC1FED79650016851F /* Project object */; } diff --git a/mobile/asa-go/ios/App/App.xcworkspace/xcshareddata/swiftpm/Package.resolved b/mobile/asa-go/ios/App/App.xcworkspace/xcshareddata/swiftpm/Package.resolved deleted file mode 100644 index b50a21402d..0000000000 --- a/mobile/asa-go/ios/App/App.xcworkspace/xcshareddata/swiftpm/Package.resolved +++ /dev/null @@ -1,123 +0,0 @@ -{ - "originHash" : "c63c63846d9c539229e96de38d6af51417e28c0ee9a0bc48bd0f0f19d923c329", - "pins" : [ - { - "identity" : "abseil-cpp-binary", - "kind" : "remoteSourceControl", - "location" : "https://github.com/google/abseil-cpp-binary.git", - "state" : { - "revision" : "bbe8b69694d7873315fd3a4ad41efe043e1c07c5", - "version" : "1.2024072200.0" - } - }, - { - "identity" : "app-check", - "kind" : "remoteSourceControl", - "location" : "https://github.com/google/app-check.git", - "state" : { - "revision" : "61b85103a1aeed8218f17c794687781505fbbef5", - "version" : "11.2.0" - } - }, - { - "identity" : "firebase-ios-sdk", - "kind" : "remoteSourceControl", - "location" : "https://github.com/firebase/firebase-ios-sdk", - "state" : { - "revision" : "85560b48b0ff099ad83fe53d67df3c67fbc2b7a6", - "version" : "12.10.0" - } - }, - { - "identity" : "google-ads-on-device-conversion-ios-sdk", - "kind" : "remoteSourceControl", - "location" : "https://github.com/googleads/google-ads-on-device-conversion-ios-sdk", - "state" : { - "revision" : "a5cd95c80e8efdd02155c6cea1cecf743bb683a5", - "version" : "3.3.0" - } - }, - { - "identity" : "googleappmeasurement", - "kind" : "remoteSourceControl", - "location" : "https://github.com/google/GoogleAppMeasurement.git", - "state" : { - "revision" : "68ba955e540dcff5e0805970ef4b1fd0150be100", - "version" : "12.10.0" - } - }, - { - "identity" : "googledatatransport", - "kind" : "remoteSourceControl", - "location" : "https://github.com/google/GoogleDataTransport.git", - "state" : { - "revision" : "617af071af9aa1d6a091d59a202910ac482128f9", - "version" : "10.1.0" - } - }, - { - "identity" : "googleutilities", - "kind" : "remoteSourceControl", - "location" : "https://github.com/google/GoogleUtilities.git", - "state" : { - "revision" : "60da361632d0de02786f709bdc0c4df340f7613e", - "version" : "8.1.0" - } - }, - { - "identity" : "grpc-binary", - "kind" : "remoteSourceControl", - "location" : "https://github.com/google/grpc-binary.git", - "state" : { - "revision" : "75b31c842f664a0f46a2e590a570e370249fd8f6", - "version" : "1.69.1" - } - }, - { - "identity" : "gtm-session-fetcher", - "kind" : "remoteSourceControl", - "location" : "https://github.com/google/gtm-session-fetcher.git", - "state" : { - "revision" : "a883ddb9fd464216133a5ab441f1ae8995978573", - "version" : "5.1.0" - } - }, - { - "identity" : "interop-ios-for-google-sdks", - "kind" : "remoteSourceControl", - "location" : "https://github.com/google/interop-ios-for-google-sdks.git", - "state" : { - "revision" : "040d087ac2267d2ddd4cca36c757d1c6a05fdbfe", - "version" : "101.0.0" - } - }, - { - "identity" : "leveldb", - "kind" : "remoteSourceControl", - "location" : "https://github.com/firebase/leveldb.git", - "state" : { - "revision" : "a0bc79961d7be727d258d33d5a6b2f1023270ba1", - "version" : "1.22.5" - } - }, - { - "identity" : "nanopb", - "kind" : "remoteSourceControl", - "location" : "https://github.com/firebase/nanopb.git", - "state" : { - "revision" : "b7e1104502eca3a213b46303391ca4d3bc8ddec1", - "version" : "2.30910.0" - } - }, - { - "identity" : "promises", - "kind" : "remoteSourceControl", - "location" : "https://github.com/google/promises.git", - "state" : { - "revision" : "540318ecedd63d883069ae7f1ed811a2df00b6ac", - "version" : "2.4.0" - } - } - ], - "version" : 3 -} diff --git a/mobile/asa-go/ios/App/App/Firebase/Dev/.gitkeep b/mobile/asa-go/ios/App/App/Firebase/Dev/.gitkeep new file mode 100644 index 0000000000..e69de29bb2 diff --git a/mobile/asa-go/ios/App/App/Firebase/Prod/.gitkeep b/mobile/asa-go/ios/App/App/Firebase/Prod/.gitkeep new file mode 100644 index 0000000000..e69de29bb2 diff --git a/mobile/asa-go/ios/App/App/dev-Info.plist b/mobile/asa-go/ios/App/App/dev-Info.plist new file mode 100644 index 0000000000..13bb320d52 --- /dev/null +++ b/mobile/asa-go/ios/App/App/dev-Info.plist @@ -0,0 +1,72 @@ + + + + + CFBundleDevelopmentRegion + en + CFBundleDisplayName + ASA Go dev + CFBundleExecutable + $(EXECUTABLE_NAME) + CFBundleIdentifier + $(PRODUCT_BUNDLE_IDENTIFIER) + CFBundleInfoDictionaryVersion + 6.0 + CFBundleName + $(PRODUCT_NAME) + CFBundlePackageType + APPL + CFBundleShortVersionString + $(MARKETING_VERSION) + CFBundleURLTypes + + + CFBundleURLName + ca.bc.gov.asago.auth + CFBundleURLSchemes + + ca.bc.gov.asago + + + + CFBundleVersion + $(CURRENT_PROJECT_VERSION) + ITSAppUsesNonExemptEncryption + + LSRequiresIPhoneOS + + NSDocumentsFolderUsageDescription + Your app requires access to the Documents folder for file management. + NSLocationAlwaysAndWhenInUseUsageDescription + This app needs location access to show your position and provide location-based fire advisory information. + NSLocationWhenInUseUsageDescription + This app needs location access to show your position and provide location-based fire advisory information. + UIBackgroundModes + + remote-notification + + UILaunchStoryboardName + LaunchScreen + UIMainStoryboardFile + Main + UIRequiredDeviceCapabilities + + armv7 + + UISupportedInterfaceOrientations + + UIInterfaceOrientationPortrait + UIInterfaceOrientationLandscapeLeft + UIInterfaceOrientationLandscapeRight + + UISupportedInterfaceOrientations~ipad + + UIInterfaceOrientationPortrait + UIInterfaceOrientationPortraitUpsideDown + UIInterfaceOrientationLandscapeLeft + UIInterfaceOrientationLandscapeRight + + UIViewControllerBasedStatusBarAppearance + + + diff --git a/mobile/asa-go/ios/App/Podfile b/mobile/asa-go/ios/App/Podfile index e9e386b1a2..16a4313e7c 100644 --- a/mobile/asa-go/ios/App/Podfile +++ b/mobile/asa-go/ios/App/Podfile @@ -33,6 +33,12 @@ target 'ASA Go' do # Add your Pods here end +target 'ASA Go Dev' do + capacitor_pods + pod 'FirebaseMessaging' + # Add your Pods here +end + post_install do |installer| assertDeploymentTarget(installer) end diff --git a/mobile/asa-go/ios/App/Podfile.lock b/mobile/asa-go/ios/App/Podfile.lock index 13c2b441ce..8d8ba0cdf8 100644 --- a/mobile/asa-go/ios/App/Podfile.lock +++ b/mobile/asa-go/ios/App/Podfile.lock @@ -165,21 +165,21 @@ EXTERNAL SOURCES: SPEC CHECKSUMS: AppAuth: 1c1a8afa7e12f2ec3a294d9882dfa5ab7d3cb063 - Capacitor: 68ff8eabbcce387e69767c13b5fbcc1c5399eabc - CapacitorApp: 45cb7cbef4aa380b9236fd6980033eb5cde6fcd2 + Capacitor: bceb785fb78f5e81e4a9e37843bc1c24bd9c7194 + CapacitorApp: 9cb31064a6c6bb2b1438583733a7bf45557fc1da CapacitorCordova: 866217f32c1d25b326c568a10ea3ed0c36b13e29 - CapacitorDevice: ebd210e29ae690225291b8616e6cfaf419d2e866 - CapacitorEmailComposer: 6e06f75898334036cc95ada2238b3dcbb78932c0 - CapacitorFilesystem: f54cd6b76be06fa7ceb219cf313d32e0d626ea87 - CapacitorFirebaseMessaging: 798b7f8af4318b97b11eb9b84c8ebe9920237c17 - CapacitorGeolocation: de4b0ccf90140528184e31676dd5e3a328eb589a - CapacitorHaptics: 1fba3e460e7614349c6d5f868b1fccdc5c87b66d - CapacitorKeyboard: 2c26c6fccde35023c579fc37d4cae6326d5e6343 - CapacitorNetwork: 3d56050f929a8c86427a5b28558ce605e7cf61b3 - CapacitorPreferences: d82a7e3b95fcab43a553268b803356522910d153 - CapacitorScreenOrientation: 07503c9d633377427f1e122449b06b1dbc992d10 - CapacitorSplashScreen: b3d12b4324d93ce605fe57f05a199ade7f26189e - CapacitorStatusBar: 438e90beeeefa8276b24e6c5991cb02dd13e51bf + CapacitorDevice: ff033fa0c4ec19f5e059a073769a9b2347e69f57 + CapacitorEmailComposer: 47e488b85f3a4400e3b616fe56b5b9f65a4aa2f3 + CapacitorFilesystem: c63fc54df41e5a6761785a7f3c49dc696c22e296 + CapacitorFirebaseMessaging: 000e9eb39f2cebcf89afeff5c9e056980ed0014e + CapacitorGeolocation: ab54d708e2fcf99a7bafe0219eaa6f7a932f001a + CapacitorHaptics: 7be406a91e4eb87287f321c6c68e1709d6837b3a + CapacitorKeyboard: 4db71e694e7afb5d7c0be09b05495c19f7d6c914 + CapacitorNetwork: b719d692a8d1310da8d26d6648d3aa1ef1e100e1 + CapacitorPreferences: 69d9991307507aeab8ef8019c10b9babfda0e9ca + CapacitorScreenOrientation: 6c3c84223ea1dd44aaa7184e2b416dd1192270d0 + CapacitorSplashScreen: 409eeaaeac603d264f209c0fcb718aa22fe1f7bb + CapacitorStatusBar: a8c4c83ed2e973bdafb979e80e4b00d027832cb7 FirebaseCore: c7b57863ce0859281a66d16ca36d665c45d332b5 FirebaseCoreInternal: 571a2dd8c975410966199623351db3a3265c874d FirebaseInstallations: 6d05424a046b68ca146b4de4376f05b4e9262fc3 @@ -188,10 +188,10 @@ SPEC CHECKSUMS: GoogleUtilities: 00c88b9a86066ef77f0da2fab05f65d7768ed8e1 IONFilesystemLib: dfa8706539ac9ab77ccfd6e5b3830ce9b5e57f6c IONGeolocationLib: 20f9d0248a0b5264511fb57a37e25dd2badf797a - Keycloak: c39abe3ec71f672fbf306a7f37b85d3858ae7f00 + Keycloak: ed7f0a99e83d402ed7bb91a5f5d15fa0249b6928 nanopb: fad817b59e0457d11a5dfbde799381cd727c1275 PromisesObjC: f5707f49cb48b9636751c5b2e7d227e43fba9f47 -PODFILE CHECKSUM: 628b81ca6723b5813c3d45a730d7dc8d60765b92 +PODFILE CHECKSUM: f85f8dbcd8b6731ed82c650c697ec343a8619f28 COCOAPODS: 1.16.2 diff --git a/mobile/asa-go/package.json b/mobile/asa-go/package.json index a713bd2248..9785344b6b 100644 --- a/mobile/asa-go/package.json +++ b/mobile/asa-go/package.json @@ -12,8 +12,12 @@ "preview": "vite preview", "build:dev": "vite build --mode development", "build:prod": "vite build --mode production", - "cap:sync:dev": "yarn build:dev && yarn cap sync", - "cap:sync:prod": "yarn build:prod && yarn cap sync" + "cap:sync:dev": "yarn build:dev && APP_ENV=dev yarn cap sync", + "cap:sync:prod": "yarn build:prod && APP_ENV=prod yarn cap sync", + "cap:sync:android:dev": "yarn build:dev && APP_ENV=dev yarn cap sync android", + "cap:sync:android:prod": "yarn build:prod && APP_ENV=prod yarn cap sync android", + "cap:sync:ios:dev": "yarn build:dev && APP_ENV=dev yarn cap sync ios", + "cap:sync:ios:prod": "yarn build:prod && APP_ENV=prod yarn cap sync ios" }, "dependencies": { "@capacitor-firebase/messaging": "^8.1.0", @@ -66,6 +70,7 @@ "@types/jest": "^30.0.0", "@types/lodash": "^4.17.14", "@types/luxon": "^3.4.2", + "@types/node": "^25.5.0", "@types/react": "^18.3.18", "@types/react-dom": "^18.3.5", "@types/sinon": "^21.0.0", diff --git a/mobile/asa-go/tsconfig.node.json b/mobile/asa-go/tsconfig.node.json index db0becc8b0..6a2082779e 100644 --- a/mobile/asa-go/tsconfig.node.json +++ b/mobile/asa-go/tsconfig.node.json @@ -4,6 +4,7 @@ "target": "ES2022", "lib": ["ES2023"], "module": "ESNext", + "types": ["node"], "skipLibCheck": true, /* Bundler mode */ @@ -20,5 +21,5 @@ "noFallthroughCasesInSwitch": true, "noUncheckedSideEffectImports": true }, - "include": ["vite.config.ts"] + "include": ["vite.config.ts", "capacitor.config.ts"] } diff --git a/mobile/asa-go/yarn.lock b/mobile/asa-go/yarn.lock index ff902d1593..babfd602dc 100644 --- a/mobile/asa-go/yarn.lock +++ b/mobile/asa-go/yarn.lock @@ -2128,6 +2128,13 @@ dependencies: undici-types "~7.18.0" +"@types/node@^25.5.0": + version "25.5.0" + resolved "https://registry.yarnpkg.com/@types/node/-/node-25.5.0.tgz#5c99f37c443d9ccc4985866913f1ed364217da31" + integrity sha512-jp2P3tQMSxWugkCUKLRPVUpGaL5MVFwF8RDuSRztfwgN1wmqJeMSbKlnEtQqU8UrhTmzEmZdu2I6v2dpp7XIxw== + dependencies: + undici-types "~7.18.0" + "@types/normalize-package-data@^2.4.0": version "2.4.4" resolved "https://registry.yarnpkg.com/@types/normalize-package-data/-/normalize-package-data-2.4.4.tgz#56e2cc26c397c038fab0e3a917a12d5c5909e901"