diff --git a/.github/actions/setup-composite/action.yml b/.github/actions/setup-composite/action.yml index 3fc22d90904..1d181fc5f81 100644 --- a/.github/actions/setup-composite/action.yml +++ b/.github/actions/setup-composite/action.yml @@ -1,5 +1,5 @@ name: Actions to setup environment for all workflows -description: 'This action collects the steps to setup any job' +description: "This action collects the steps to setup any job" runs: using: "composite" steps: @@ -9,7 +9,7 @@ runs: - id: setup-node uses: actions/setup-node@1a4442cacd436585916779262731d5b162bc6ec7 # v3.8.2 with: - node-version-file: '.node-version' + node-version-file: ".node-version" - id: yarn-cache uses: actions/cache@88522ab9f39a2ea568f7027eddc7d8d8bc9d59c8 # v3.3.1 with: @@ -20,9 +20,18 @@ runs: ${{ runner.os }}-yarn-${{ hashFiles('**/yarn.lock') }} ${{ runner.os }}-yarn- - name: Install dependencies - if: steps.yarn-cache.outputs.cache-hit != 'true' run: yarn install --frozen-lockfile shell: bash - id: generate-api-client run: yarn generate - shell: bash \ No newline at end of file + shell: bash + - id: upload-locales-artifact + uses: actions/upload-artifact@26f96dfa697d77e81fd5907df203aa23a56210a8 + with: + name: locales + path: locales/ + - id: upload-clients-artifact + uses: actions/upload-artifact@26f96dfa697d77e81fd5907df203aa23a56210a8 + with: + name: api-client + path: definitions/ diff --git a/.github/scripts/package-name-replacer.sh b/.github/scripts/package-name-replacer.sh deleted file mode 100755 index 5350eb7e160..00000000000 --- a/.github/scripts/package-name-replacer.sh +++ /dev/null @@ -1,32 +0,0 @@ -#!/bin/bash - -# Controllo se ci sono abbastanza parametri -if [ "$#" -ne 3 ]; then - echo "How To use: $0 " - exit 1 -fi - -# Assegna i parametri posizionali a variabili -CHECK="$1" -REPLACE="$2" -DIRECTORY="$3" - -# Verifica se la directory esiste -if [ ! -d "$DIRECTORY" ]; then - echo "Error: Directory '$DIRECTORY' doesn't exists." - exit 1 -fi - -if [ "$DIRECTORY" == "android" ]; then - echo "Moving all to new subfolder canary" - mkdir ./android/app/src/debug/java/it/pagopa/io/app/canary - mv -v ./android/app/src/debug/java/it/pagopa/io/app/* ./android/app/src/debug/java/it/pagopa/io/app/canary - mkdir ./android/app/src/main/java/it/pagopa/io/app/canary - mv -v ./android/app/src/main/java/it/pagopa/io/app/* ./android/app/src/main/java/it/pagopa/io/app/canary - mkdir ./android/app/src/release/java/it/pagopa/io/app/canary - mv -v ./android/app/src/release/java/it/pagopa/io/app/* ./android/app/src/release/java/it/pagopa/io/app/canary -fi - -echo "Renaming $CHECK into $REPLACE in directory $DIRECTORY" -# Cerca i file contenenti la stringa e sostituisci -grep -rl "$CHECK" "$DIRECTORY" | xargs sed -i "" "s/$CHECK/$REPLACE/g" \ No newline at end of file diff --git a/.github/scripts/package-name-restore.sh b/.github/scripts/package-name-restore.sh deleted file mode 100755 index 11afdd3d8c6..00000000000 --- a/.github/scripts/package-name-restore.sh +++ /dev/null @@ -1,32 +0,0 @@ -#!/bin/bash - -# Controllo se ci sono abbastanza parametri -if [ "$#" -ne 3 ]; then - echo "How To use: $0 " - exit 1 -fi - -# Assegna i parametri posizionali a variabili -CHECK="$1" -REPLACE="$2" -DIRECTORY="$3" - -# Verifica se la directory esiste -if [ ! -d "$DIRECTORY" ]; then - echo "Error: Directory '$DIRECTORY' doesn't exists." - exit 1 -fi - -if [ "$DIRECTORY" == "android" ]; then - echo "Moving all from subfolder canary to default" - mv -v ./android/app/src/debug/java/it/pagopa/io/app/canary/* ./android/app/src/debug/java/it/pagopa/io/app - rm -rf ./android/app/src/debug/java/it/pagopa/io/app/canary - mv -v ./android/app/src/main/java/it/pagopa/io/app/canary/* ./android/app/src/main/java/it/pagopa/io/app - rm -rf ./android/app/src/main/java/it/pagopa/io/app/canary - mv -v ./android/app/src/release/java/it/pagopa/io/app/canary/* ./android/app/src/release/java/it/pagopa/io/app - rm -rf ./android/app/src/release/java/it/pagopa/io/app/canary -fi - -echo "Renaming package $CHECK into $REPLACE in directory $DIRECTORY" -# Cerca i file contenenti la stringa e sostituisci -grep -rl "$CHECK" "$DIRECTORY" | xargs sed -i "" "s/$CHECK/$REPLACE/g" \ No newline at end of file diff --git a/.github/workflows/release-canary.yml b/.github/workflows/release-canary.yml index 1a401949e44..e32905d2faf 100644 --- a/.github/workflows/release-canary.yml +++ b/.github/workflows/release-canary.yml @@ -1,51 +1,46 @@ name: Canary release on: - workflow_dispatch: issue_comment: - types: [created, edited, deleted] + types: [created] jobs: run-static-checks: if: contains(github.event.comment.html_url, '/pull/') && contains(github.event.comment.body, '/canary') uses: ./.github/workflows/staticcheck.yaml prepare-canary-release: needs: run-static-checks - environment: canary runs-on: ubuntu-latest outputs: - currentAppVersion: ${{ steps.store-current-version.outputs.CURRENT_APP_VERSION }} - currentAppBuildCode: ${{ steps.store-current-version.outputs.CURRENT_APP_BUILD_CODE }} + canaryVersion: ${{ steps.github-release-creation.outputs.CANARY_VERSION }} steps: - id: checkout uses: actions/checkout@8e5e7e5ab8b370d6c329ec480221332ada57f0ab #v3.5.2 with: fetch-depth: 0 - - id: store-current-version - run: | - APP_VERSION=$(node -p -e "require('./package.json').version") - echo "CURRENT_APP_VERSION=$APP_VERSION" >> $GITHUB_OUTPUT - BUILD_CODE=$(node ./scripts/canary/readAndroidBuildCode.js) - echo "CURRENT_APP_BUILD_CODE=$BUILD_CODE" >> $GITHUB_OUTPUT + - id: setup + uses: ./.github/actions/setup-composite - id: replace-version-with-canary run: | - node scripts/canary/replaceCanaryVersion.js ${{ vars.CANARY_VERSION }} ${{ vars.CANARY_BUILD_CODE }} - bash ./.github/scripts/package-name-replacer.sh it.pagopa.io.app it.pagopa.io.app.canary android - bash ./.github/scripts/package-name-replacer.sh it.pagopa.app.io it.pagopa.app.io.canary ios - bash ./.github/scripts/package-name-replacer.sh "git\@github.com:pagopa\/IO-App-certs.git" "git\@github.com:pagopa\/IO-App-canary-certs.git" ios + UPDATED_BUILD_CODE=$(git rev-list HEAD --count) + node scripts/canary/replaceCanaryVersion.js $UPDATED_BUILD_CODE + mv ios/fastlane/Matchfile ios/fastlane/Matchfile_prod + mv ios/fastlane/Matchfile_canary ios/fastlane/Matchfile - id: bump-version run: | git config --local user.email "github-actions[bot]@users.noreply.github.com" git config --local user.name "github-actions[bot]" + git add .; git commit -m "Replace Matchfile for canary" --no-verify; yarn release-canary - id: push-tags run: | - git push --no-verify --follow-tags origin HEAD:${{ github.head_ref }} + APP_VERSION=$(node -p -e "require('./package.json').version") + git push --no-verify origin tag $APP_VERSION - id: github-release-creation run: | APP_VERSION=$(node -p -e "require('./package.json').version") - gh release create "(Canary) $APP_VERSION" --generate-notes - gh variable set CANARY_VERSION -b "$APP_VERSION" -e canary - BUILD_CODE=$(node ./scripts/canary/readAndroidBuildCode.js) - gh variable set CANARY_BUILD_CODE -b "$BUILD_CODE" -e canary + gh release create $APP_VERSION --generate-notes + echo "CANARY_VERSION=$APP_VERSION" >> $GITHUB_OUTPUT + env: + GH_TOKEN: ${{ secrets.GITHUB_TOKEN }} release-android: needs: prepare-canary-release environment: canary @@ -55,7 +50,7 @@ jobs: uses: actions/checkout@8e5e7e5ab8b370d6c329ec480221332ada57f0ab #v3.5.2 with: fetch-depth: 0 - ref: ${{ needs.prepare-canary-release.outputs.currentAppVersion }} + ref: ${{ needs.prepare-canary-release.outputs.canaryVersion }} - id: setup uses: ./.github/actions/setup-composite - id: setup-jdk-17 @@ -73,7 +68,7 @@ jobs: - id: build-release-android run: | ./scripts/android-release.sh ./android/app - cd android && bundle exec fastlane alpha + cd android && bundle exec fastlane alpha_canary shell: bash env: RUBYOPT: '-rostruct' # TODO: Remove when https://github.com/fastlane/fastlane/pull/21950 gets released @@ -93,7 +88,7 @@ jobs: cd android VERSION_CODE=$(sed -n 's/.*versionCode \(.*\)/\1/p' "app/build.gradle") echo "VERSION_CODE=$VERSION_CODE" >> $GITHUB_ENV - bundle exec fastlane download_apk + bundle exec fastlane download_canary_apk env: RUBYOPT: '-rostruct' # TODO: Remove when https://github.com/fastlane/fastlane/pull/21950 gets released ENCODED_IOAPP_JSON_KEY_FILE: ${{ secrets.ENCODED_IOAPP_JSON_KEY_FILE }} @@ -103,20 +98,20 @@ jobs: continue-on-error: true uses: actions/upload-artifact@26f96dfa697d77e81fd5907df203aa23a56210a8 with: - name: io-app-universal.apk - path: android/io-app-universal.apk + name: io-app-canary-universal.apk + path: android/io-app-canary-universal.apk - id: upload-aab # We don't want to fail whole job if the AAB upload step fails continue-on-error: true uses: actions/upload-artifact@26f96dfa697d77e81fd5907df203aa23a56210a8 with: - name: app-release.aab - path: android/app/build/outputs/bundle/release/app-release.aab + name: app-canary-release.aab + path: android/app/build/outputs/bundle/canaryRelease/app-canary-release.aab - id: upload-android-assets-release continue-on-error: true run: | APP_VERSION=$(node -p -e "require('./package.json').version") - gh release upload "(Canary) $APP_VERSION" android/app/build/outputs/bundle/release/app-release.aab#android-app-release.aab android/io-app-universal.apk#io-app-universal.apk + gh release upload $APP_VERSION android/app/build/outputs/bundle/canaryRelease/app-canary-release.aab#android-app-canary-release.aab android/io-app-canary-universal.apk#io-app-canary-universal.apk env: GH_TOKEN: ${{ secrets.GITHUB_TOKEN }} release-ios: @@ -131,7 +126,7 @@ jobs: uses: actions/checkout@8e5e7e5ab8b370d6c329ec480221332ada57f0ab #v3.5.2 with: fetch-depth: 0 - ref: ${{ needs.prepare-canary-release.outputs.currentAppVersion }} + ref: ${{ needs.prepare-canary-release.outputs.canaryVersion }} - id: setup uses: ./.github/actions/setup-composite - id: setup-ruby @@ -158,7 +153,7 @@ jobs: name: Build & submit to App store run: | cd ios - bundle exec fastlane beta_circleci_testflight + bundle exec fastlane canary_ci_testflight env: LC_ALL: en_US.UTF-8 LANG: en_US.UTF-8 @@ -189,7 +184,7 @@ jobs: continue-on-error: true run: | APP_VERSION=$(node -p -e "require('./package.json').version") - gh release upload "(Canary) $APP_VERSION" ios/IO.ipa#IO-iOS.ipa + gh release upload $APP_VERSION ios/IO.ipa#IO-canary-iOS.ipa env: GH_TOKEN: ${{ secrets.GITHUB_TOKEN }} notify-new-version: @@ -201,20 +196,9 @@ jobs: steps: - id: checkout uses: actions/checkout@8e5e7e5ab8b370d6c329ec480221332ada57f0ab #v3.5.2 - - id: revert-package-and-version - run: | - git config --local user.email "github-actions[bot]@users.noreply.github.com" - git config --local user.name "github-actions[bot]" - node scripts/canary/replaceCanaryVersion.js ${{ needs.prepare-canary-release.outputs.currentAppVersion }} ${{ needs.prepare-canary-release.outputs.currentAppBuildCode }} - bash ./.github/scripts/package-name-restore.sh it.pagopa.io.app.canary it.pagopa.io.app android - bash ./.github/scripts/package-name-restore.sh it.pagopa.app.io.canary it.pagopa.app.io ios - bash ./.github/scripts/package-name-replacer.sh "git\@github.com:pagopa\/IO-App-canary-certs.git" "git\@github.com:pagopa\/IO-App-certs.git" ios - git add . - git commit -m "revert: restoring repository to default package name and version" --no-verify - git push --no-verify origin HEAD:${{ github.head_ref }} - id: comment-process-end if: github.event.issue.number run: | - gh issue comment ${{ github.event.issue.number }} -b "Release correctly created, check it at the [release list](https://github.com/pagopa/io-app/releases)" + gh issue comment ${{ github.event.issue.number }} -b "Release correctly created, [${{ needs.prepare-canary-release.outputs.canaryVersion }}](https://github.com/pagopa/io-app/releases/tag/${{ needs.prepare-canary-release.outputs.canaryVersion }})" env: GH_TOKEN: ${{ secrets.GITHUB_TOKEN }} \ No newline at end of file diff --git a/.github/workflows/release-nightly.yml b/.github/workflows/release-nightly.yml index 2cd300c0252..7b4c0fbe805 100644 --- a/.github/workflows/release-nightly.yml +++ b/.github/workflows/release-nightly.yml @@ -100,12 +100,12 @@ jobs: uses: actions/upload-artifact@26f96dfa697d77e81fd5907df203aa23a56210a8 with: name: app-release.aab - path: android/app/build/outputs/bundle/release/app-release.aab + path: android/app/build/outputs/bundle/productionRelease/app-production-release.aab - id: upload-android-assets-release continue-on-error: true run: | APP_VERSION=$(node -p -e "require('./package.json').version") - gh release upload $APP_VERSION android/app/build/outputs/bundle/release/app-release.aab#android-app-release.aab android/io-app-universal.apk#io-app-universal.apk + gh release upload $APP_VERSION android/app/build/outputs/bundle/productionRelease/app-production-release.aab#android-app-release.aab android/io-app-universal.apk#io-app-universal.apk env: GH_TOKEN: ${{ secrets.GITHUB_TOKEN }} release-ios: diff --git a/.github/workflows/staticcheck.yaml b/.github/workflows/staticcheck.yaml index affc86909b1..d7bd4815f7b 100644 --- a/.github/workflows/staticcheck.yaml +++ b/.github/workflows/staticcheck.yaml @@ -2,9 +2,8 @@ on: - pull_request - workflow_call jobs: - checks: + static-checks: runs-on: ubuntu-latest - environment: dev concurrency: group: ${{ github.workflow }}-pr-staticcheck-${{ github.head_ref || github.run_id }} cancel-in-progress: true @@ -19,9 +18,43 @@ jobs: run: yarn lint - id: run-prettier run: yarn prettier:check + unit-test: + runs-on: ubuntu-latest + environment: dev + needs: static-checks + strategy: + matrix: + shard: [1, 2, 3, 4, 5, 6, 7, 8, 9, 10] + steps: + - id: checkout + uses: actions/checkout@8e5e7e5ab8b370d6c329ec480221332ada57f0ab # v3.5.2 + - id: setup-node + uses: actions/setup-node@64ed1c7eab4cce3362f8c340dee64e5eaeef8f7c # v3.6.0 + with: + node-version-file: ".node-version" + - id: yarn-cache + uses: actions/cache@88522ab9f39a2ea568f7027eddc7d8d8bc9d59c8 # v3.3.1 + env: + cache-name: cache-node-modules + with: + # npm cache files are stored in `~/.npm` on Linux/macOS + path: ~/.npm + key: ${{ runner.os }}-build-${{ env.cache-name }}-${{ hashFiles('**/yarn.lock') }} + - id: install-packages + run: yarn install --frozen-lockfile + - id: download-locales + uses: actions/download-artifact@6b208ae046db98c579e8a3aa621ab581ff575935 # v4.1.1 + with: + name: locales + path: locales/ + - id: download-api-client + uses: actions/download-artifact@6b208ae046db98c579e8a3aa621ab581ff575935 # v4.1.1 + with: + name: api-client + path: definitions/ - id: run-test - run: yarn test:ci + run: yarn test:ci --shard=${{ matrix.shard }}/${{ strategy.job-total }} - id: codecov-script uses: codecov/codecov-action@84508663e988701840491b86de86b666e8a86bed # v4.3.0 with: - token: ${{ secrets.CODECOV_TOKEN }} + token: ${{ secrets.CODECOV_TOKEN }} \ No newline at end of file diff --git a/CHANGELOG.md b/CHANGELOG.md index 6abbfe98558..5b90ff95da7 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -2,6 +2,26 @@ All notable changes to this project will be documented in this file. See [standard-version](https://github.com/conventional-changelog/standard-version) for commit guidelines. +## [2.80.0-rc.5](https://github.com/pagopa/io-app/compare/2.80.0-rc.4...2.80.0-rc.5) (2024-12-18) + + +### Bug Fixes + +* [[IOPLT-812](https://pagopa.atlassian.net/browse/IOPLT-812)] Exclude lib riscv64 on android build ([#6564](https://github.com/pagopa/io-app/issues/6564)) ([a06dc5f](https://github.com/pagopa/io-app/commit/a06dc5fe334debf7a1e3578982c3acf8748ee454)), closes [/github.com/mrousavy/react-native-vision-camera/issues/3177#issuecomment-2385366758](https://github.com/pagopa//github.com/mrousavy/react-native-vision-camera/issues/3177/issues/issuecomment-2385366758) + + +### Chores + +* **Cross:** [[IOAPPX-206](https://pagopa.atlassian.net/browse/IOAPPX-206)] Add dynamic card effect based on device rotation ([#5715](https://github.com/pagopa/io-app/issues/5715)) ([c959d6a](https://github.com/pagopa/io-app/commit/c959d6abcc2d6dc98e02f75f4d8ab5f352325d16)) +* **Cross:** [[IOAPPX-437](https://pagopa.atlassian.net/browse/IOAPPX-437)] Add support for Material You by adding a new adaptive launcher icon for Android ([#6434](https://github.com/pagopa/io-app/issues/6434)) ([db8121f](https://github.com/pagopa/io-app/commit/db8121f10c29843ac706f9fc2bfe2abbab89a4ba)) + +## [2.80.0-rc.4](https://github.com/pagopa/io-app/compare/2.80.0-rc.3...2.80.0-rc.4) (2024-12-18) + + +### Bug Fixes + +* ffi version mismatch on linux environment ([#6563](https://github.com/pagopa/io-app/issues/6563)) ([082241e](https://github.com/pagopa/io-app/commit/082241eec664fb751b5bc7b8289469326b663167)) + ## [2.80.0-rc.3](https://github.com/pagopa/io-app/compare/2.80.0-rc.2...2.80.0-rc.3) (2024-12-17) diff --git a/Gemfile b/Gemfile index 11a4ae7a528..7a3394c22eb 100644 --- a/Gemfile +++ b/Gemfile @@ -5,6 +5,10 @@ source "https://rubygems.org" ruby '>=2.6.10' # Exclude problematic versions of cocoapods and activesupport that causes build failures. -gem 'cocoapods', '>= 1.13', '!= 1.15.0', '!= 1.15.1' +gem 'cocoapods', '>= 1.13', '!= 1.15.1', '!= 1.15.0' gem 'activesupport', '>= 6.1.7.5', '!= 7.1.0' gem "fastlane", "~> 2.223.1" + +# fixes an issue on linux env for android release +# see https://github.com/ffi/ffi/issues/1103#issuecomment-2186974923 +gem "ffi", "< 1.17.0" diff --git a/Gemfile.lock b/Gemfile.lock index 78a09dfe76b..c3e5e992e39 100644 --- a/Gemfile.lock +++ b/Gemfile.lock @@ -170,7 +170,7 @@ GEM xcodeproj (>= 1.13.0, < 2.0.0) xcpretty (~> 0.3.0) xcpretty-travis-formatter (>= 0.0.3, < 2.0.0) - ffi (1.17.0) + ffi (1.16.3) fourflusher (2.3.1) fuzzy_match (2.0.4) gh_inspector (1.1.3) @@ -290,8 +290,9 @@ PLATFORMS DEPENDENCIES activesupport (>= 6.1.7.5, != 7.1.0) - cocoapods (>= 1.13, != 1.15.0, != 1.15.1) + cocoapods (>= 1.13, != 1.15.1, != 1.15.0) fastlane (~> 2.223.1) + ffi (< 1.17.0) RUBY VERSION ruby 2.7.7p221 diff --git a/README.md b/README.md index eb1890e6b33..a8e28c60403 100644 --- a/README.md +++ b/README.md @@ -434,7 +434,7 @@ Then, from your command line, run these commands: $ adb reverse tcp:8081 tcp:8081;adb reverse tcp:3000 tcp:3000;adb reverse tcp:9090 tcp:9090 # Run Android build -$ yarn run-android +$ yarn dev:run-android ``` ### iOS Simulator diff --git a/android/app/build.gradle b/android/app/build.gradle index be3fe880b33..320024561f8 100644 --- a/android/app/build.gradle +++ b/android/app/build.gradle @@ -108,6 +108,7 @@ android { pickFirst 'lib/arm64-v8a/libc++_shared.so' pickFirst 'lib/x86_64/libc++_shared.so' pickFirst 'lib/armeabi-v7a/libc++_shared.so' + exclude "lib/riscv64/**" // Exclude riscv64 libraries due to https://github.com/mrousavy/react-native-vision-camera/issues/3177 } dexOptions { @@ -118,8 +119,8 @@ android { applicationId "it.pagopa.io.app" minSdkVersion rootProject.ext.minSdkVersion targetSdkVersion rootProject.ext.targetSdkVersion - versionCode 100154898 - versionName "2.80.0.3" + versionCode 100154900 + versionName "2.80.0.5" multiDexEnabled true // The resConfigs attribute will remove all not required localized resources while building the application, // including the localized resources from libraries. @@ -151,6 +152,18 @@ android { } } + flavorDimensions += "version" + productFlavors { + create("production") { + applicationIdSuffix = "" // Nessun suffisso per la produzione + versionNameSuffix = "" + } + create("canary") { + applicationIdSuffix = ".canary" // Suffix per identificare la build Canary + versionNameSuffix = "" + } + } + // The Android App Bundle read this section to create different bundles bundle { language { diff --git a/android/app/src/main/ic_launcher-playstore.png b/android/app/src/main/ic_launcher-playstore.png new file mode 100644 index 00000000000..3717619dec4 Binary files /dev/null and b/android/app/src/main/ic_launcher-playstore.png differ diff --git a/android/app/src/main/res/drawable/ic_launcher_foreground.xml b/android/app/src/main/res/drawable/ic_launcher_foreground.xml new file mode 100644 index 00000000000..eca38b02934 --- /dev/null +++ b/android/app/src/main/res/drawable/ic_launcher_foreground.xml @@ -0,0 +1,25 @@ + + + + + + + + + + diff --git a/android/app/src/main/res/drawable/io_app_icon_foreground.xml b/android/app/src/main/res/drawable/io_app_icon_foreground.xml new file mode 100644 index 00000000000..ff6e291a503 --- /dev/null +++ b/android/app/src/main/res/drawable/io_app_icon_foreground.xml @@ -0,0 +1,20 @@ + + + + + + + + diff --git a/android/app/src/main/res/mipmap-anydpi-v26/ic_launcher.xml b/android/app/src/main/res/mipmap-anydpi-v26/ic_launcher.xml new file mode 100644 index 00000000000..7005cb8e14c --- /dev/null +++ b/android/app/src/main/res/mipmap-anydpi-v26/ic_launcher.xml @@ -0,0 +1,6 @@ + + + + + + \ No newline at end of file diff --git a/android/app/src/main/res/mipmap-anydpi-v26/ic_launcher_round.xml b/android/app/src/main/res/mipmap-anydpi-v26/ic_launcher_round.xml new file mode 100644 index 00000000000..7005cb8e14c --- /dev/null +++ b/android/app/src/main/res/mipmap-anydpi-v26/ic_launcher_round.xml @@ -0,0 +1,6 @@ + + + + + + \ No newline at end of file diff --git a/android/app/src/main/res/mipmap-hdpi/ic_launcher.png b/android/app/src/main/res/mipmap-hdpi/ic_launcher.png deleted file mode 100644 index c64a2c9bb60..00000000000 Binary files a/android/app/src/main/res/mipmap-hdpi/ic_launcher.png and /dev/null differ diff --git a/android/app/src/main/res/mipmap-hdpi/ic_launcher.webp b/android/app/src/main/res/mipmap-hdpi/ic_launcher.webp new file mode 100644 index 00000000000..d6fc0d21fdb Binary files /dev/null and b/android/app/src/main/res/mipmap-hdpi/ic_launcher.webp differ diff --git a/android/app/src/main/res/mipmap-hdpi/ic_launcher_round.png b/android/app/src/main/res/mipmap-hdpi/ic_launcher_round.png deleted file mode 100644 index c64a2c9bb60..00000000000 Binary files a/android/app/src/main/res/mipmap-hdpi/ic_launcher_round.png and /dev/null differ diff --git a/android/app/src/main/res/mipmap-hdpi/ic_launcher_round.webp b/android/app/src/main/res/mipmap-hdpi/ic_launcher_round.webp new file mode 100644 index 00000000000..8e96af59bac Binary files /dev/null and b/android/app/src/main/res/mipmap-hdpi/ic_launcher_round.webp differ diff --git a/android/app/src/main/res/mipmap-mdpi/ic_launcher.png b/android/app/src/main/res/mipmap-mdpi/ic_launcher.png deleted file mode 100644 index a1d406d4d27..00000000000 Binary files a/android/app/src/main/res/mipmap-mdpi/ic_launcher.png and /dev/null differ diff --git a/android/app/src/main/res/mipmap-mdpi/ic_launcher.webp b/android/app/src/main/res/mipmap-mdpi/ic_launcher.webp new file mode 100644 index 00000000000..b3f0b4693ac Binary files /dev/null and b/android/app/src/main/res/mipmap-mdpi/ic_launcher.webp differ diff --git a/android/app/src/main/res/mipmap-mdpi/ic_launcher_round.png b/android/app/src/main/res/mipmap-mdpi/ic_launcher_round.png deleted file mode 100644 index f5ac44b673b..00000000000 Binary files a/android/app/src/main/res/mipmap-mdpi/ic_launcher_round.png and /dev/null differ diff --git a/android/app/src/main/res/mipmap-mdpi/ic_launcher_round.webp b/android/app/src/main/res/mipmap-mdpi/ic_launcher_round.webp new file mode 100644 index 00000000000..fffcb80dad0 Binary files /dev/null and b/android/app/src/main/res/mipmap-mdpi/ic_launcher_round.webp differ diff --git a/android/app/src/main/res/mipmap-xhdpi/ic_launcher.png b/android/app/src/main/res/mipmap-xhdpi/ic_launcher.png deleted file mode 100644 index 16bed9a854c..00000000000 Binary files a/android/app/src/main/res/mipmap-xhdpi/ic_launcher.png and /dev/null differ diff --git a/android/app/src/main/res/mipmap-xhdpi/ic_launcher.webp b/android/app/src/main/res/mipmap-xhdpi/ic_launcher.webp new file mode 100644 index 00000000000..69d6bd98a55 Binary files /dev/null and b/android/app/src/main/res/mipmap-xhdpi/ic_launcher.webp differ diff --git a/android/app/src/main/res/mipmap-xhdpi/ic_launcher_round.png b/android/app/src/main/res/mipmap-xhdpi/ic_launcher_round.png deleted file mode 100644 index 683b3844e2f..00000000000 Binary files a/android/app/src/main/res/mipmap-xhdpi/ic_launcher_round.png and /dev/null differ diff --git a/android/app/src/main/res/mipmap-xhdpi/ic_launcher_round.webp b/android/app/src/main/res/mipmap-xhdpi/ic_launcher_round.webp new file mode 100644 index 00000000000..9acf31dfe3e Binary files /dev/null and b/android/app/src/main/res/mipmap-xhdpi/ic_launcher_round.webp differ diff --git a/android/app/src/main/res/mipmap-xxhdpi/ic_launcher.png b/android/app/src/main/res/mipmap-xxhdpi/ic_launcher.png deleted file mode 100644 index c903c727590..00000000000 Binary files a/android/app/src/main/res/mipmap-xxhdpi/ic_launcher.png and /dev/null differ diff --git a/android/app/src/main/res/mipmap-xxhdpi/ic_launcher.webp b/android/app/src/main/res/mipmap-xxhdpi/ic_launcher.webp new file mode 100644 index 00000000000..810eced67e9 Binary files /dev/null and b/android/app/src/main/res/mipmap-xxhdpi/ic_launcher.webp differ diff --git a/android/app/src/main/res/mipmap-xxhdpi/ic_launcher_round.png b/android/app/src/main/res/mipmap-xxhdpi/ic_launcher_round.png deleted file mode 100644 index 61addf5da49..00000000000 Binary files a/android/app/src/main/res/mipmap-xxhdpi/ic_launcher_round.png and /dev/null differ diff --git a/android/app/src/main/res/mipmap-xxhdpi/ic_launcher_round.webp b/android/app/src/main/res/mipmap-xxhdpi/ic_launcher_round.webp new file mode 100644 index 00000000000..1f8ea5c3d88 Binary files /dev/null and b/android/app/src/main/res/mipmap-xxhdpi/ic_launcher_round.webp differ diff --git a/android/app/src/main/res/mipmap-xxxhdpi/ic_launcher.png b/android/app/src/main/res/mipmap-xxxhdpi/ic_launcher.png deleted file mode 100644 index f5d4fd922a6..00000000000 Binary files a/android/app/src/main/res/mipmap-xxxhdpi/ic_launcher.png and /dev/null differ diff --git a/android/app/src/main/res/mipmap-xxxhdpi/ic_launcher.webp b/android/app/src/main/res/mipmap-xxxhdpi/ic_launcher.webp new file mode 100644 index 00000000000..297a59aa42b Binary files /dev/null and b/android/app/src/main/res/mipmap-xxxhdpi/ic_launcher.webp differ diff --git a/android/app/src/main/res/mipmap-xxxhdpi/ic_launcher_round.png b/android/app/src/main/res/mipmap-xxxhdpi/ic_launcher_round.png deleted file mode 100644 index 9f9870483a1..00000000000 Binary files a/android/app/src/main/res/mipmap-xxxhdpi/ic_launcher_round.png and /dev/null differ diff --git a/android/app/src/main/res/mipmap-xxxhdpi/ic_launcher_round.webp b/android/app/src/main/res/mipmap-xxxhdpi/ic_launcher_round.webp new file mode 100644 index 00000000000..5a8b26bcf00 Binary files /dev/null and b/android/app/src/main/res/mipmap-xxxhdpi/ic_launcher_round.webp differ diff --git a/android/app/src/main/res/values/ic_launcher_background.xml b/android/app/src/main/res/values/ic_launcher_background.xml new file mode 100644 index 00000000000..a1c9af0bebf --- /dev/null +++ b/android/app/src/main/res/values/ic_launcher_background.xml @@ -0,0 +1,4 @@ + + + #0B3EE3 + \ No newline at end of file diff --git a/android/fastlane/Fastfile b/android/fastlane/Fastfile index f7e61652b80..f903e4f0bee 100644 --- a/android/fastlane/Fastfile +++ b/android/fastlane/Fastfile @@ -41,6 +41,20 @@ platform :android do gradle( task: "bundle", + flavor: "production", + build_type: "Release", + # flags: "-x bundleReleaseJsAndAssets --no-daemon" + ) + end + + desc "Build the App in release mode for Canary" + lane :build_canary_release do + # Ensure that your git status is not dirty + #ensure_git_status_clean + + gradle( + task: "bundle", + flavor: "canary", build_type: "Release", # flags: "-x bundleReleaseJsAndAssets --no-daemon" ) @@ -62,6 +76,23 @@ platform :android do ) end + desc "Build the App in release mode and deploy a new alpha version to the Google Play Store (Canary)" + lane :alpha_canary do + build_canary_release + + # Generate the changelog from the last commit message + changelog_from_git_commits( + commits_count: 1 + ) + + upload_to_play_store( + track: "internal", + package_name: "it.pagopa.io.app.canary", + skip_upload_screenshots: true, + skip_upload_images: true + ) + end + desc "Promote the internal version to alpha" lane :promote_internal_to_alpha do upload_to_play_store(track: "internal", track_promote_to: "alpha") @@ -83,6 +114,16 @@ platform :android do ) end + desc "Download universal APK file from Google Play (Canary)" + lane :download_canary_apk do + version_code = ENV['VERSION_CODE'].to_i + download_universal_apk_from_google_play( + package_name: "it.pagopa.io.app.canary", + destination: "io-app-canary-universal.apk", + version_code: version_code + ) + end + # You can define as many lanes as you want after_all do |lane| diff --git a/img/dynamicCardRotation/driver-license-background.png b/img/dynamicCardRotation/driver-license-background.png new file mode 100644 index 00000000000..7dfe0b1aaef Binary files /dev/null and b/img/dynamicCardRotation/driver-license-background.png differ diff --git a/ios/ItaliaApp.xcodeproj/project.pbxproj b/ios/ItaliaApp.xcodeproj/project.pbxproj index a472e421808..7e4990bdbc0 100644 --- a/ios/ItaliaApp.xcodeproj/project.pbxproj +++ b/ios/ItaliaApp.xcodeproj/project.pbxproj @@ -108,6 +108,7 @@ 7206342A24764B138D864DFF /* Titillio-LightItalic.otf */ = {isa = PBXFileReference; explicitFileType = undefined; fileEncoding = 9; includeInIndex = 0; lastKnownFileType = unknown; name = "Titillio-LightItalic.otf"; path = "../assets/fonts/Titillio/Titillio-LightItalic.otf"; sourceTree = ""; }; 722056DF161D843DD91D88A7 /* Pods-ItaliaApp.debug.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-ItaliaApp.debug.xcconfig"; path = "Target Support Files/Pods-ItaliaApp/Pods-ItaliaApp.debug.xcconfig"; sourceTree = ""; }; 7A83F0572152B12C000C6389 /* ItaliaApp.entitlements */ = {isa = PBXFileReference; lastKnownFileType = text.plist.entitlements; name = ItaliaApp.entitlements; path = ItaliaApp/ItaliaApp.entitlements; sourceTree = ""; }; + 817062FA493BD2CA4732436F /* Pods-ItaliaApp.canary.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-ItaliaApp.canary.xcconfig"; path = "Target Support Files/Pods-ItaliaApp/Pods-ItaliaApp.canary.xcconfig"; sourceTree = ""; }; 872A6A79E0CF4C4DA0AEAF3E /* TitilliumSansPro-BoldItalic.otf */ = {isa = PBXFileReference; explicitFileType = undefined; fileEncoding = 9; includeInIndex = 0; lastKnownFileType = unknown; name = "TitilliumSansPro-BoldItalic.otf"; path = "../assets/fonts/TitilliumSansPro/TitilliumSansPro-BoldItalic.otf"; sourceTree = ""; }; 875B0C3A5326413494A9311A /* DMMono-Medium.ttf */ = {isa = PBXFileReference; explicitFileType = undefined; fileEncoding = 9; includeInIndex = 0; lastKnownFileType = unknown; name = "DMMono-Medium.ttf"; path = "../assets/fonts/DMMono/DMMono-Medium.ttf"; sourceTree = ""; }; 9205B2AD16D94BDAA69E880E /* Titillio-Black.otf */ = {isa = PBXFileReference; explicitFileType = undefined; fileEncoding = 9; includeInIndex = 0; lastKnownFileType = unknown; name = "Titillio-Black.otf"; path = "../assets/fonts/Titillio/Titillio-Black.otf"; sourceTree = ""; }; @@ -119,6 +120,7 @@ B58BBAC865EA4651B828C92B /* Titillio-Bold.otf */ = {isa = PBXFileReference; explicitFileType = undefined; fileEncoding = 9; includeInIndex = 0; lastKnownFileType = unknown; name = "Titillio-Bold.otf"; path = "../assets/fonts/Titillio/Titillio-Bold.otf"; sourceTree = ""; }; C9E629838F224B4F9823D692 /* Titillio-Thin.otf */ = {isa = PBXFileReference; explicitFileType = undefined; fileEncoding = 9; includeInIndex = 0; lastKnownFileType = unknown; name = "Titillio-Thin.otf"; path = "../assets/fonts/Titillio/Titillio-Thin.otf"; sourceTree = ""; }; D688263BB87C4DFBA007CD92 /* Titillio-SemiboldItalic.otf */ = {isa = PBXFileReference; explicitFileType = undefined; fileEncoding = 9; includeInIndex = 0; lastKnownFileType = unknown; name = "Titillio-SemiboldItalic.otf"; path = "../assets/fonts/Titillio/Titillio-SemiboldItalic.otf"; sourceTree = ""; }; + E0D9AB8BF7C01F793A53F1D0 /* Pods-ItaliaApp-ItaliaAppTests.canary.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-ItaliaApp-ItaliaAppTests.canary.xcconfig"; path = "Target Support Files/Pods-ItaliaApp-ItaliaAppTests/Pods-ItaliaApp-ItaliaAppTests.canary.xcconfig"; sourceTree = ""; }; E8C4B91357FA47018EE5ACF0 /* Titillio-BlackItalic.otf */ = {isa = PBXFileReference; explicitFileType = undefined; fileEncoding = 9; includeInIndex = 0; lastKnownFileType = unknown; name = "Titillio-BlackItalic.otf"; path = "../assets/fonts/Titillio/Titillio-BlackItalic.otf"; sourceTree = ""; }; ED297162215061F000B7C4FE /* JavaScriptCore.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = JavaScriptCore.framework; path = System/Library/Frameworks/JavaScriptCore.framework; sourceTree = SDKROOT; }; F0625E792326820B00EDEF90 /* libReact-RCTImage.a */ = {isa = PBXFileReference; explicitFileType = archive.ar; path = "libReact-RCTImage.a"; sourceTree = BUILT_PRODUCTS_DIR; }; @@ -243,6 +245,8 @@ 6F8C6AF94C801CE01EC3D81A /* Pods-ItaliaApp.release.xcconfig */, 6D0115BDF703AEBFD8B86A12 /* Pods-ItaliaApp-ItaliaAppTests.debug.xcconfig */, 058F4F4927B1B1C84C7F1137 /* Pods-ItaliaApp-ItaliaAppTests.release.xcconfig */, + 817062FA493BD2CA4732436F /* Pods-ItaliaApp.canary.xcconfig */, + E0D9AB8BF7C01F793A53F1D0 /* Pods-ItaliaApp-ItaliaAppTests.canary.xcconfig */, ); path = Pods; sourceTree = ""; @@ -794,7 +798,7 @@ CODE_SIGN_ENTITLEMENTS = ItaliaApp/ItaliaApp.entitlements; CODE_SIGN_IDENTITY = "iPhone Developer"; "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Developer"; - CURRENT_PROJECT_VERSION = 3; + CURRENT_PROJECT_VERSION = 5; DEAD_CODE_STRIPPING = YES; DEVELOPMENT_TEAM = M2X5YQ4BJ7; ENABLE_BITCODE = NO; @@ -831,7 +835,7 @@ CODE_SIGN_ENTITLEMENTS = ItaliaApp/ItaliaApp.entitlements; CODE_SIGN_IDENTITY = "iPhone Distribution"; "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Distribution"; - CURRENT_PROJECT_VERSION = 3; + CURRENT_PROJECT_VERSION = 5; DEAD_CODE_STRIPPING = YES; DEVELOPMENT_TEAM = M2X5YQ4BJ7; ENABLE_BITCODE = NO; @@ -995,6 +999,134 @@ }; name = Release; }; + B5B0AB482D09EF680022D03F /* Canary */ = { + isa = XCBuildConfiguration; + buildSettings = { + ALWAYS_SEARCH_USER_PATHS = NO; + CC = ""; + CLANG_ANALYZER_LOCALIZABILITY_NONLOCALIZED = YES; + CLANG_CXX_LANGUAGE_STANDARD = "c++20"; + CLANG_CXX_LIBRARY = "libc++"; + CLANG_ENABLE_MODULES = YES; + CLANG_ENABLE_OBJC_ARC = YES; + CLANG_WARN_BLOCK_CAPTURE_AUTORELEASING = YES; + CLANG_WARN_BOOL_CONVERSION = YES; + CLANG_WARN_COMMA = YES; + CLANG_WARN_CONSTANT_CONVERSION = YES; + CLANG_WARN_DEPRECATED_OBJC_IMPLEMENTATIONS = YES; + CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR; + CLANG_WARN_EMPTY_BODY = YES; + CLANG_WARN_ENUM_CONVERSION = YES; + CLANG_WARN_INFINITE_RECURSION = YES; + CLANG_WARN_INT_CONVERSION = YES; + CLANG_WARN_NON_LITERAL_NULL_CONVERSION = YES; + CLANG_WARN_OBJC_IMPLICIT_RETAIN_SELF = YES; + CLANG_WARN_OBJC_LITERAL_CONVERSION = YES; + CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; + CLANG_WARN_RANGE_LOOP_ANALYSIS = YES; + CLANG_WARN_STRICT_PROTOTYPES = YES; + CLANG_WARN_SUSPICIOUS_MOVE = YES; + CLANG_WARN_UNREACHABLE_CODE = YES; + 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; + "EXCLUDED_ARCHS[sdk=iphonesimulator*]" = i386; + GCC_C_LANGUAGE_STANDARD = gnu99; + GCC_NO_COMMON_BLOCKS = YES; + GCC_PREPROCESSOR_DEFINITIONS = ( + "$(inherited)", + _LIBCPP_ENABLE_CXX17_REMOVED_UNARY_BINARY_FUNCTION, + ); + GCC_WARN_64_TO_32_BIT_CONVERSION = YES; + GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR; + GCC_WARN_UNDECLARED_SELECTOR = YES; + GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE; + GCC_WARN_UNUSED_FUNCTION = YES; + GCC_WARN_UNUSED_VARIABLE = YES; + IPHONEOS_DEPLOYMENT_TARGET = 14.0; + LD = ""; + LDPLUSPLUS = ""; + LD_RUNPATH_SEARCH_PATHS = "/usr/lib/swift $(inherited)"; + LIBRARY_SEARCH_PATHS = ( + "\"$(TOOLCHAIN_DIR)/usr/lib/swift/$(PLATFORM_NAME)\"", + "\"$(inherited)\"", + "\"$(SDKROOT)/usr/lib/swift\"", + ); + MTL_ENABLE_DEBUG_INFO = NO; + OTHER_CFLAGS = "$(inherited)"; + OTHER_CPLUSPLUSFLAGS = "$(inherited)"; + OTHER_LDFLAGS = "$(inherited)"; + REACT_NATIVE_PATH = "${PODS_ROOT}/../../node_modules/react-native"; + SDKROOT = iphoneos; + USE_HERMES = true; + VALIDATE_PRODUCT = YES; + }; + name = Canary; + }; + B5B0AB492D09EF680022D03F /* Canary */ = { + isa = XCBuildConfiguration; + baseConfigurationReference = 817062FA493BD2CA4732436F /* Pods-ItaliaApp.canary.xcconfig */; + buildSettings = { + ALWAYS_EMBED_SWIFT_STANDARD_LIBRARIES = YES; + ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon; + CLANG_ENABLE_MODULES = YES; + CODE_SIGN_ENTITLEMENTS = ItaliaApp/ItaliaApp.entitlements; + CODE_SIGN_IDENTITY = "Apple Development"; + "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Distribution"; + CODE_SIGN_STYLE = Manual; + CURRENT_PROJECT_VERSION = 6; + DEAD_CODE_STRIPPING = YES; + DEVELOPMENT_TEAM = ""; + "DEVELOPMENT_TEAM[sdk=iphoneos*]" = M2X5YQ4BJ7; + ENABLE_BITCODE = NO; + HEADER_SEARCH_PATHS = "$(inherited)"; + INFOPLIST_FILE = ItaliaApp/Info.plist; + INFOPLIST_OTHER_PREPROCESSOR_FLAGS = "-traditional"; + INFOPLIST_PREFIX_HEADER = "${BUILD_DIR}/GeneratedInfoPlistDotEnv.h"; + INFOPLIST_PREPROCESS = NO; + IPHONEOS_DEPLOYMENT_TARGET = 14.0; + LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks"; + OTHER_LDFLAGS = ( + "$(inherited)", + "-ObjC", + "-lc++", + ); + PRODUCT_BUNDLE_IDENTIFIER = it.pagopa.app.io.canary; + PRODUCT_NAME = IO; + PROVISIONING_PROFILE = "0848c226-68ec-4314-ad27-50803db95257"; + PROVISIONING_PROFILE_SPECIFIER = ""; + "PROVISIONING_PROFILE_SPECIFIER[sdk=iphoneos*]" = "match AppStore it.pagopa.app.io.canary"; + SWIFT_OBJC_BRIDGING_HEADER = "ItaliaApp-Bridging-Header.h"; + SWIFT_VERSION = 5.2; + VERSIONING_SYSTEM = "apple-generic"; + }; + name = Canary; + }; + B5B0AB4A2D09EF680022D03F /* Canary */ = { + isa = XCBuildConfiguration; + baseConfigurationReference = E0D9AB8BF7C01F793A53F1D0 /* Pods-ItaliaApp-ItaliaAppTests.canary.xcconfig */; + buildSettings = { + BUNDLE_LOADER = "$(TEST_HOST)"; + COPY_PHASE_STRIP = NO; + DEVELOPMENT_TEAM = QWLSX4D6KP; + HEADER_SEARCH_PATHS = "$(inherited)"; + INFOPLIST_FILE = ItaliaAppTests/Info.plist; + IPHONEOS_DEPLOYMENT_TARGET = 12.4; + LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks @loader_path/Frameworks"; + LIBRARY_SEARCH_PATHS = "$(SDKROOT)/usr/lib/swift$(inherited)"; + OTHER_LDFLAGS = ( + "-ObjC", + "-lc++", + ); + PRODUCT_BUNDLE_IDENTIFIER = "it.teamdigitale.app.$(PRODUCT_NAME:rfc1034identifier)"; + PRODUCT_NAME = "$(TARGET_NAME)"; + TEST_HOST = "$(BUILT_PRODUCTS_DIR)/IO.app/IO"; + }; + name = Canary; + }; /* End XCBuildConfiguration section */ /* Begin XCConfigurationList section */ @@ -1003,6 +1135,7 @@ buildConfigurations = ( 00E356F61AD99517003FC87E /* Debug */, 00E356F71AD99517003FC87E /* Release */, + B5B0AB4A2D09EF680022D03F /* Canary */, ); defaultConfigurationIsVisible = 0; defaultConfigurationName = Release; @@ -1012,6 +1145,7 @@ buildConfigurations = ( 13B07F941A680F5B00A75B9A /* Debug */, 13B07F951A680F5B00A75B9A /* Release */, + B5B0AB492D09EF680022D03F /* Canary */, ); defaultConfigurationIsVisible = 0; defaultConfigurationName = Release; @@ -1021,6 +1155,7 @@ buildConfigurations = ( 83CBBA201A601CBA00E9B192 /* Debug */, 83CBBA211A601CBA00E9B192 /* Release */, + B5B0AB482D09EF680022D03F /* Canary */, ); defaultConfigurationIsVisible = 0; defaultConfigurationName = Release; diff --git a/ios/ItaliaApp/Info.plist b/ios/ItaliaApp/Info.plist index 684efe60abb..fffb2ffee8b 100644 --- a/ios/ItaliaApp/Info.plist +++ b/ios/ItaliaApp/Info.plist @@ -36,7 +36,7 @@ CFBundleVersion - 3 + 5 ITSAppUsesNonExemptEncryption LSApplicationQueriesSchemes diff --git a/ios/ItaliaAppTests/Info.plist b/ios/ItaliaAppTests/Info.plist index e3f793fc72b..8256df486f4 100644 --- a/ios/ItaliaAppTests/Info.plist +++ b/ios/ItaliaAppTests/Info.plist @@ -19,6 +19,6 @@ CFBundleSignature ???? CFBundleVersion - 3 + 5 \ No newline at end of file diff --git a/ios/fastlane/Fastfile b/ios/fastlane/Fastfile index 754d02bc723..57bba79b5dc 100644 --- a/ios/fastlane/Fastfile +++ b/ios/fastlane/Fastfile @@ -202,7 +202,7 @@ platform :ios do ) end - desc "Submit a new Beta Build to TestFlight, using CircleCI" + desc "Submit a new Beta Build to TestFlight" lane :beta_circleci_testflight do |options| # xCode 14.2, prevents altool to fail with error "Could not @@ -253,6 +253,58 @@ platform :ios do ) end + desc "Submit a new Canary Build to TestFlight" + lane :canary_ci_testflight do |options| + + # xCode 14.2, prevents altool to fail with error "Could not + # determine the package’s bundle ID" during the "pilot" step + # See https://github.com/fastlane/fastlane/issues/20741 + ENV['ITMSTRANSPORTER_FORCE_ITMS_PACKAGE_UPLOAD'] = 'false' + + # Setup the CI environment + setup_ci() + + # use the App Store API Key to authenticate + api_key = app_store_connect_api_key( + key_id: "#{ENV['APP_STORE_API_KEY_ID']}", + issuer_id: "#{ENV['APP_STORE_API_KEY_ISSUER_ID']}", + key_filepath: "./fastlane/AuthKey_#{ENV['APP_STORE_API_KEY_ID']}.p8", + duration: 1200, + ) + + sync_code_signing(type: "appstore", app_identifier:"it.pagopa.app.io.canary", api_key: api_key) + + # Install pods + cocoapods + + # build the app + gym( + scheme: "ItaliaApp", + clean: true, + export_method: "app-store", + configuration: "Canary", + workspace: "ItaliaApp.xcworkspace", + include_symbols: false + ) + + previous_tag = sh("git tag --sort=-taggerdate | grep \\\\-canary\\\\. | sed -n '2 p' | tr -d '\n'") + + # generate the changelog based on last commits + changelog = changelog_from_git_commits( + tag_match_pattern: "*" +previous_tag + "*" , + pretty:"- %s", + merge_commit_filtering: "exclude_merges" + ) + + # upload to App store + pilot( + api_key: api_key, + changelog: changelog, + # max wait for App Store Connect processing (30 min) + wait_processing_timeout_duration: 1800 + ) + end + desc "Distribute previously uploaded beta to TestFlight, using GA" lane :distribute_beta_testflight do |options| diff --git a/ios/fastlane/Matchfile_canary b/ios/fastlane/Matchfile_canary new file mode 100644 index 00000000000..58f6997824c --- /dev/null +++ b/ios/fastlane/Matchfile_canary @@ -0,0 +1,9 @@ +git_url "git@github.com:pagopa/IO-App-canary-certs.git" + +type "development" # The default type, can be: appstore, adhoc, enterprise or development + +# app_identifier ["tools.fastlane.app", "tools.fastlane.app2"] +# username "user@fastlane.tools" # Your Apple Developer Portal username + +# For all available options run `fastlane match --help` +# Remove the # in the beginning of the line to enable the other options diff --git a/locales/en/index.yml b/locales/en/index.yml index 0351bdc8b29..4e1a03a7de4 100644 --- a/locales/en/index.yml +++ b/locales/en/index.yml @@ -3363,9 +3363,13 @@ features: primaryAction: Apri impostazioni secondaryAction: Continua notMatchingIdentityScreen: - title: "Tutti i documenti saranno rimossi da IO" - subtitle: "Se accedi con una nuova identità, le versioni digitali dei documenti che hai aggiunto al Portafoglio saranno rimosse e Documenti su IO disattivata." - action: "Continua con la nuova identità" + title: "Stai accedendo con un nuovo dispositivo" + message: "Quando accedi all'app IO da un dispositivo diverso da quello abituale (ad esempio quello di un'altra persona) per motivi di sicurezza queste funzionalità vengono reimpostate:\n\n- Documenti su IO" + banner: + title: Ti suggeriamo di accedere all'app solo dal tuo dispositivo. + alert: + title: Vuoi davvero uscire? + message: Dovrai entrare di nuovo con SPID o CIE per usare l'app. loading: cieId: title: Connessione con la tua app CieID in corso... diff --git a/locales/it/index.yml b/locales/it/index.yml index 38adc05833c..32ec5c05be3 100644 --- a/locales/it/index.yml +++ b/locales/it/index.yml @@ -3363,9 +3363,13 @@ features: primaryAction: Apri impostazioni secondaryAction: Continua notMatchingIdentityScreen: - title: "Tutti i documenti saranno rimossi da IO" - subtitle: "Se accedi con una nuova identità, le versioni digitali dei documenti che hai aggiunto al Portafoglio saranno rimosse e Documenti su IO disattivata." - action: "Continua con la nuova identità" + title: "Stai accedendo con un nuovo dispositivo" + message: "Quando accedi all'app IO da un dispositivo diverso da quello abituale (ad esempio quello di un'altra persona) per motivi di sicurezza queste funzionalità vengono reimpostate:\n\n- Documenti su IO" + banner: + title: Ti suggeriamo di accedere all'app solo dal tuo dispositivo. + alert: + title: Vuoi davvero uscire? + message: Dovrai entrare di nuovo con SPID o CIE per usare l'app. loading: cieId: title: Connessione con la tua app CieID in corso... diff --git a/package.json b/package.json index 72886deaf1b..10129d02238 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "italia-app", - "version": "2.80.0-rc.3", + "version": "2.80.0-rc.5", "private": true, "scripts": { "start": "react-native start", @@ -8,6 +8,7 @@ "sync": "yarn setup && bundle && (cd ios && bundle exec pod install) && yarn generate", "run-ios": "react-native run-ios", "run-android": "react-native run-android", + "dev:run-android": "yarn run-android --mode=productionDebug", "push-hint": "echo \"To publish changes without checks run:\ngit push --no-verify --follow-tags origin $(git rev-parse --abbrev-ref HEAD)\"", "pre-cycle": "scripts/changelog/check_git_status.sh && node scripts/changelog/prepare_to_new_cycle.js", "release-rc": "scripts/changelog/check_git_status.sh && standard-version -t \"\" --prerelease rc --no-verify && yarn push-hint", diff --git a/publiccode.yml b/publiccode.yml index fe4ac9ff7d2..e9c51e4b7cf 100644 --- a/publiccode.yml +++ b/publiccode.yml @@ -9,7 +9,7 @@ releaseDate: "2024-11-21" url: "https://github.com/pagopa/io-app" applicationSuite: IO landingURL: "https://io.italia.it/" -softwareVersion: 2.80.0-rc.3 +softwareVersion: 2.80.0-rc.5 developmentStatus: beta softwareType: standalone/mobile roadmap: "https://io.italia.it/" diff --git a/scripts/canary/replaceCanaryVersion.js b/scripts/canary/replaceCanaryVersion.js index 6a2e5ca39aa..d524cabbeb5 100644 --- a/scripts/canary/replaceCanaryVersion.js +++ b/scripts/canary/replaceCanaryVersion.js @@ -20,17 +20,23 @@ const replaceCanaryVersion = () => { const package = JSON.parse(fs.readFileSync(packagePath).toString("utf8")); const versionSplit = package.version.split("-"); - const canarySplit = process.argv[2].split("-"); // replace the version, removing the rc part - package.version = `${versionSplit[0]}-${canarySplit[1]}`; + package.version = `${versionSplit[0]}-canary.${parseInt( + process.argv[2], + 10 + )}`; const contents = fs.readFileSync(gradlePath).toString("utf8"); const updatedGradleContents = contents.replace( versionCodeRegex, (substr, ...args) => - replaceVersionCode(substr, parseInt(process.argv[3], 10), ...args) + replaceVersionCode( + substr, + `20000${parseInt(process.argv[2], 10)}`, + ...args + ) ); fs.writeFileSync(packagePath, JSON.stringify(package, undefined, 2)); fs.writeFileSync(gradlePath, updatedGradleContents); diff --git a/ts/features/design-system/core/DSDynamicCardRotation.tsx b/ts/features/design-system/core/DSDynamicCardRotation.tsx new file mode 100644 index 00000000000..0532ceacfe8 --- /dev/null +++ b/ts/features/design-system/core/DSDynamicCardRotation.tsx @@ -0,0 +1,429 @@ +/* eslint-disable functional/immutable-data */ +import { H6, IOColors, VSpacer, hexToRgba } from "@pagopa/io-app-design-system"; +import { + Canvas, + Color, + DiffRect, + Image, + LinearGradient, + Mask, + RoundedRect, + Circle as SkiaCircle, + Group as SkiaGroup, + RadialGradient as SkiaRadialGradient, + rect, + rrect, + useImage, + vec +} from "@shopify/react-native-skia"; +import * as React from "react"; +import { useState } from "react"; +import { + ColorValue, + LayoutChangeEvent, + LayoutRectangle, + StyleSheet, + Text, + View, + ViewStyle +} from "react-native"; +import Animated, { + Extrapolation, + SensorType, + interpolate, + useAnimatedReaction, + useAnimatedSensor, + useAnimatedStyle, + useDerivedValue, + useSharedValue, + withSpring +} from "react-native-reanimated"; +import Svg, { Circle, Defs, RadialGradient, Stop } from "react-native-svg"; + +type CardSize = { + width: LayoutRectangle["width"]; + height: LayoutRectangle["height"]; +}; + +type LightSize = { + value: LayoutRectangle["width"]; +}; + +/* LIGHT + Visual parameters */ +const lightSizePercentage: ViewStyle["width"] = "90%"; +const lightScaleMultiplier: number = 1; +const lightOpacity: ViewStyle["opacity"] = 0.9; +const lightSkiaOpacity: number = 0.4; +/* Percentage of visible light when it's near +card boundaries */ +const visibleLightPercentage: number = 0.25; + +/* CARD + Visual parameters */ +const cardAspectRatio: ViewStyle["aspectRatio"] = 7 / 4; +const cardBorderRadius: number = 24; +const cardBorderWidth: number = 1; +const cardBorderColor: ColorValue = IOColors["hanPurple-500"]; +const cardBorderHighlighted: ColorValue = IOColors.white; +const cardBorderOpacity: number = 0.65; +// Drivers' License +const cardGradient: Array = ["#F4ACD5", "#FCE6F2"]; +// Flag +// const flagDistanceFromEdge: number = 16; +// const flagSize: number = 32; + +/* MOVEMENT + Spring config for the light movement */ +const springConfig = { + mass: 1, + damping: 50, + stiffness: 200, + overshootClamping: false +}; + +export const DSDynamicCardRotation = () => { + /* On first render, store the current device orientation + using quaternions */ + const rotationSensor = useAnimatedSensor(SensorType.ROTATION); + const { roll: initialRoll, pitch: initialPitch } = + rotationSensor.sensor.value; + + const roll = useSharedValue(0); + const pitch = useSharedValue(0); + const skiaTranslateX = useSharedValue(0); + const skiaTranslateY = useSharedValue(0); + + useAnimatedReaction( + () => rotationSensor.sensor.value, + sensor => { + roll.value = sensor.roll; + pitch.value = sensor.pitch; + }, + [] + ); + /* Not all devices are in an initial flat position on a surface + (e.g. a table) then we use relative rotation values, + not absolute ones */ + const relativeRoll = useDerivedValue(() => -(initialRoll - roll.value)); + const relativePitch = useDerivedValue(() => initialPitch - pitch.value); + + // eslint-disable-next-line no-console + console.log("Sensor values:", `qx: ${roll.value}, qy: ${pitch.value}`); + + /* Get both card and light sizes to set the basic boundaries */ + const [cardSize, setCardSize] = useState(); + const [lightSize, setLightSize] = useState(); + + const getCardSize = (event: LayoutChangeEvent) => { + const { width, height } = event.nativeEvent.layout; + setCardSize({ width, height }); + }; + + const getLightSize = (event: LayoutChangeEvent) => { + const { width: newLightSize } = event.nativeEvent.layout; + setLightSize({ value: newLightSize }); + }; + + /* Set translate boundaries */ + const maxTranslateX = + ((cardSize?.width ?? 0) - + (lightSize?.value ?? 0) * visibleLightPercentage) / + 2; + + const maxTranslateY = + ((cardSize?.height ?? 0) - + (lightSize?.value ?? 0) * visibleLightPercentage) / + 2; + + /* We don't need to consider the whole + sensor range, just the 1/10 */ + const sensorRange: number = 0.1; + + /* Calculate the light position using quaternions */ + const lightAnimatedStyle = useAnimatedStyle(() => { + const translateX = interpolate( + relativeRoll.value, + [-sensorRange, sensorRange], + [maxTranslateX, -maxTranslateX], + Extrapolation.CLAMP + ); + + const translateY = interpolate( + relativePitch.value, + [-sensorRange, sensorRange], + [-maxTranslateY, maxTranslateY], + Extrapolation.CLAMP + ); + + return { + transform: [ + { translateX: withSpring(translateX, springConfig) }, + { translateY: withSpring(translateY, springConfig) }, + { scale: lightScaleMultiplier } + ] + }; + }); + + const skiaLightTranslateValues = useDerivedValue(() => { + skiaTranslateX.value = withSpring( + interpolate( + relativeRoll.value, + [-sensorRange, sensorRange], + [maxTranslateX, -maxTranslateX], + Extrapolation.CLAMP + ), + springConfig + ); + + skiaTranslateY.value = withSpring( + interpolate( + relativePitch.value, + [-sensorRange, sensorRange], + [-maxTranslateY, maxTranslateY], + Extrapolation.CLAMP + ), + springConfig + ); + + return [ + { translateX: skiaTranslateX.value }, + { translateY: skiaTranslateY.value }, + { scale: lightScaleMultiplier } + ]; + }); + + // Inner card (border excluded) + const CardInnerMask = () => ( + + ); + + const CardLight = () => ( + + + + + + ); + + const CardBorder = ({ + color = cardBorderColor, + opacity = cardBorderOpacity + }: { + color?: Color; + opacity?: number; + }) => { + const outerRect = rrect( + rect(0, 0, cardSize?.width ?? 0, cardSize?.height ?? 0), + cardBorderRadius, + cardBorderRadius + ); + + const innerRect = rrect( + rect( + cardBorderWidth, + cardBorderWidth, + (cardSize?.width ?? 0) - cardBorderWidth * 2, + (cardSize?.height ?? 0) - cardBorderWidth * 2 + ), + cardBorderRadius - cardBorderWidth, + cardBorderRadius - cardBorderWidth + ); + + return ( + + ); + }; + + const CardPatternMask = () => { + const cardPattern = useImage( + // eslint-disable-next-line @typescript-eslint/no-var-requires + require("../../../../img/dynamicCardRotation/driver-license-background.png") + ); + + return ( + }> + {/* eslint-disable react-native-a11y/has-valid-accessibility-ignores-invert-colors */} + + + ); + }; + + const CardBorderMask = () => ( + }> + + + ); + + return ( + + + + + + + {/* There are many stops because it's an easing gradient. + To learn more: https://larsenwork.com/easing-gradients/ */} + + + + + + + + + + + + + + + + + + + + + + + Using React Native engine + + + + + + + + + + + {/* */} + + + + Using Skia engine + + +
Card
+ {`Size: ${cardSize?.width} × ${cardSize?.height}`} + +
Light (Circle)
+ {`Size: ${lightSize?.value}`} +
+
+ ); +}; + +const styles = StyleSheet.create({ + container: { + alignItems: "center", + paddingTop: 24, + paddingHorizontal: 24 + }, + + light: { + alignSelf: "center", + width: lightSizePercentage, + aspectRatio: 1, + opacity: lightOpacity, + borderRadius: 400 + }, + cardDebugLabel: { + fontSize: 11, + marginTop: 4 + }, + box: { + justifyContent: "center", + width: "100%", + aspectRatio: cardAspectRatio, + borderRadius: 24, + borderCurve: "continuous", + backgroundColor: IOColors["hanPurple-250"] + }, + debugInfo: { + alignSelf: "flex-start", + position: "relative", + top: 16 + } +}); diff --git a/ts/features/design-system/navigation/navigator.tsx b/ts/features/design-system/navigation/navigator.tsx index 46cd117c8ca..cd15ac8b7f0 100644 --- a/ts/features/design-system/navigation/navigator.tsx +++ b/ts/features/design-system/navigation/navigator.tsx @@ -68,6 +68,7 @@ import { DSTextFields } from "../core/DSTextFields"; import { DSToastNotifications } from "../core/DSToastNotifications"; import { DSTypography } from "../core/DSTypography"; import { DSWallet } from "../core/DSWallet"; +import { DSDynamicCardRotation } from "../core/DSDynamicCardRotation"; import { DesignSystemParamsList } from "./params"; import DESIGN_SYSTEM_ROUTES from "./routes"; @@ -365,6 +366,17 @@ export const DesignSystemNavigator = () => { }} /> + + { useAvoidHardwareBackButton(); + useItwDisableGestureNavigation(); useFocusEffect(trackItwIdNotMatch); @@ -26,33 +32,66 @@ export const ItwIdentityNotMatchingScreen = () => { }; const handleCancel = () => { - dispatch(logoutRequest({ withApiCall: true })); + Alert.alert( + I18n.t( + "features.itWallet.identification.notMatchingIdentityScreen.alert.title" + ), + I18n.t( + "features.itWallet.identification.notMatchingIdentityScreen.alert.message" + ), + [ + { + text: I18n.t("global.buttons.exit"), + style: "destructive", + onPress: () => dispatch(logoutRequest({ withApiCall: true })) + }, + { + text: I18n.t("global.buttons.cancel"), + onPress: constNull // Do nothing, just dismiss the alert + } + ], + { cancelable: false } + ); }; return ( - + > + + + + + + + ); }; diff --git a/ts/features/itwallet/navigation/ItwStackNavigator.tsx b/ts/features/itwallet/navigation/ItwStackNavigator.tsx index 9be76c3d77d..ebbf4174a5b 100644 --- a/ts/features/itwallet/navigation/ItwStackNavigator.tsx +++ b/ts/features/itwallet/navigation/ItwStackNavigator.tsx @@ -218,7 +218,7 @@ const InnerNavigator = () => {