diff --git a/.github/actions/prepare-android-build/action.yaml b/.github/actions/prepare-android-build/action.yaml
index cb0650869..5c534d3eb 100644
--- a/.github/actions/prepare-android-build/action.yaml
+++ b/.github/actions/prepare-android-build/action.yaml
@@ -27,7 +27,7 @@ runs:
- name: ci/checkout-private-repo
if: ${{ inputs.sign == 'true' }}
- uses: actions/checkout@ac593985615ec2ede58e132d2e21d2b1cbd6127c # v3.3.0
+ uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2
with:
repository: mattermost/mattermost-mobile-private
token: ${{ env.MATTERMOST_BUILD_GH_TOKEN }}
diff --git a/.github/actions/prepare-ios-build/action.yaml b/.github/actions/prepare-ios-build/action.yaml
index 57d8f026a..3b3d74c0e 100644
--- a/.github/actions/prepare-ios-build/action.yaml
+++ b/.github/actions/prepare-ios-build/action.yaml
@@ -16,7 +16,7 @@ runs:
echo "::endgroup::"
- name: Cache Pods
- uses: actions/cache@0c45773b623bea8c8e75f6c82b208c3cf94ea4f9 # v4.0.2
+ uses: actions/cache@0c907a75c2c80ebcb7f088228285e798b750cf8f # v4.2.1
with:
path: Pods
key: ${{ runner.os }}-pods-${{ hashFiles('**/Podfile.lock') }}
diff --git a/.github/actions/prepare-mobile-build/action.yaml b/.github/actions/prepare-mobile-build/action.yaml
index cf0031450..6bd6f7406 100644
--- a/.github/actions/prepare-mobile-build/action.yaml
+++ b/.github/actions/prepare-mobile-build/action.yaml
@@ -5,7 +5,7 @@ runs:
using: composite
steps:
# The required ruby version is mentioned in '.ruby-version'
- - uses: ruby/setup-ruby@ff740bc00a01b3a50fffc55a1071b1060eeae9dc # v1.180.0
+ - uses: ruby/setup-ruby@32110d4e311bd8996b2a82bf2a43b714ccc91777 # v1.221.0
- name: ci/setup-fastlane-dependencies
shell: bash
@@ -16,7 +16,7 @@ runs:
working-directory: ./fastlane
- name: Cache Ruby gems
- uses: actions/cache@0c45773b623bea8c8e75f6c82b208c3cf94ea4f9 # v4.0.2
+ uses: actions/cache@0c907a75c2c80ebcb7f088228285e798b750cf8f # v4.2.1
with:
path: vendor/bundle
key: ${{ runner.os }}-gems-${{ hashFiles('**/Gemfile.lock') }}
diff --git a/.github/actions/prepare-node-deps/action.yaml b/.github/actions/prepare-node-deps/action.yaml
index c50ce3bb5..187982588 100644
--- a/.github/actions/prepare-node-deps/action.yaml
+++ b/.github/actions/prepare-node-deps/action.yaml
@@ -5,7 +5,7 @@ runs:
using: composite
steps:
- name: ci/setup-node
- uses: actions/setup-node@60edb5dd545a775178f52524783378180af0d1f8 # v4.0.2
+ uses: actions/setup-node@1d0ff469b7ec7b3cb9d8673fde0c81c44821de2a # v4.2.0
with:
node-version-file: ".nvmrc"
cache: "npm"
@@ -22,7 +22,7 @@ runs:
echo "::endgroup::"
- name: Cache Node.js modules
- uses: actions/cache@0c45773b623bea8c8e75f6c82b208c3cf94ea4f9 # v4.0.2
+ uses: actions/cache@0c907a75c2c80ebcb7f088228285e798b750cf8f # v4.2.1
with:
path: ~/.npm
key: ${{ runner.os }}-node-${{ hashFiles('**/package-lock.json') }}
diff --git a/.github/workflows/build-android-beta.yml b/.github/workflows/build-android-beta.yml
index e24d6c663..d7a720e7d 100644
--- a/.github/workflows/build-android-beta.yml
+++ b/.github/workflows/build-android-beta.yml
@@ -16,7 +16,7 @@ jobs:
runs-on: ubuntu-22.04
steps:
- name: ci/checkout-repo
- uses: actions/checkout@b4ffde65f46336ab88eb53be808477a3936bae11 # v4.1.1
+ uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2
- name: ci/test
uses: ./.github/actions/test
@@ -26,7 +26,7 @@ jobs:
- test
steps:
- name: ci/checkout-repo
- uses: actions/checkout@b4ffde65f46336ab88eb53be808477a3936bae11 # v4.1.1
+ uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2
- name: ci/prepare-android-build
uses: ./.github/actions/prepare-android-build
@@ -54,7 +54,7 @@ jobs:
working-directory: ./fastlane
- name: ci/upload-android-beta-build
- uses: actions/upload-artifact@5d5d22a31266ced268874388b861e4b58bb5c2f3 # v4.3.1
+ uses: actions/upload-artifact@65c4c4a1ddee5b72f698fdd19549f0f0fb45cf08 # v4.6.0
with:
name: android-build-beta-${{ github.run_id }}
path: "*.apk"
diff --git a/.github/workflows/build-android-release.yml b/.github/workflows/build-android-release.yml
index cfdefb84b..2fe85f2bc 100644
--- a/.github/workflows/build-android-release.yml
+++ b/.github/workflows/build-android-release.yml
@@ -16,7 +16,7 @@ jobs:
runs-on: ubuntu-22.04
steps:
- name: ci/checkout-repo
- uses: actions/checkout@b4ffde65f46336ab88eb53be808477a3936bae11 # v4.1.1
+ uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2
- name: ci/test
uses: ./.github/actions/test
@@ -26,7 +26,7 @@ jobs:
- test
steps:
- name: ci/checkout-repo
- uses: actions/checkout@b4ffde65f46336ab88eb53be808477a3936bae11 # v4.1.1
+ uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2
- name: ci/prepare-android-build
uses: ./.github/actions/prepare-android-build
@@ -54,7 +54,7 @@ jobs:
working-directory: ./fastlane
- name: ci/upload-android-release-build
- uses: actions/upload-artifact@5d5d22a31266ced268874388b861e4b58bb5c2f3 # v4.3.1
+ uses: actions/upload-artifact@65c4c4a1ddee5b72f698fdd19549f0f0fb45cf08 # v4.6.0
with:
name: android-build-release-${{ github.run_id }}
path: "*.apk"
diff --git a/.github/workflows/build-ios-beta.yml b/.github/workflows/build-ios-beta.yml
index da4d289bd..4781ba5d4 100644
--- a/.github/workflows/build-ios-beta.yml
+++ b/.github/workflows/build-ios-beta.yml
@@ -17,7 +17,7 @@ jobs:
runs-on: ubuntu-22.04
steps:
- name: ci/checkout-repo
- uses: actions/checkout@b4ffde65f46336ab88eb53be808477a3936bae11 # v4.1.1
+ uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2
- name: ci/test
uses: ./.github/actions/test
@@ -28,7 +28,7 @@ jobs:
- test
steps:
- name: ci/checkout-repo
- uses: actions/checkout@b4ffde65f46336ab88eb53be808477a3936bae11 # v4.1.1
+ uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2
- name: ci/prepare-ios-build
uses: ./.github/actions/prepare-ios-build
@@ -44,7 +44,7 @@ jobs:
working-directory: ./fastlane
- name: ci/upload-ios-pr-simulator
- uses: actions/upload-artifact@5d5d22a31266ced268874388b861e4b58bb5c2f3 # v4.3.1
+ uses: actions/upload-artifact@65c4c4a1ddee5b72f698fdd19549f0f0fb45cf08 # v4.6.0
with:
name: ios-build-simulator-${{ github.run_id }}
path: Mattermost-simulator-x86_64.app.zip
@@ -56,7 +56,7 @@ jobs:
- test
steps:
- name: ci/checkout-repo
- uses: actions/checkout@b4ffde65f46336ab88eb53be808477a3936bae11 # v4.1.1
+ uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2
- name: ci/output-ssh-private-key
shell: bash
@@ -93,7 +93,7 @@ jobs:
working-directory: ./fastlane
- name: ci/upload-ios-beta-build
- uses: actions/upload-artifact@5d5d22a31266ced268874388b861e4b58bb5c2f3 # v4.3.1
+ uses: actions/upload-artifact@65c4c4a1ddee5b72f698fdd19549f0f0fb45cf08 # v4.6.0
with:
name: ios-build-beta-${{ github.run_id }}
path: "*.ipa"
diff --git a/.github/workflows/build-ios-release.yml b/.github/workflows/build-ios-release.yml
index ad1009e08..4c596491e 100644
--- a/.github/workflows/build-ios-release.yml
+++ b/.github/workflows/build-ios-release.yml
@@ -17,7 +17,7 @@ jobs:
runs-on: ubuntu-22.04
steps:
- name: ci/checkout-repo
- uses: actions/checkout@b4ffde65f46336ab88eb53be808477a3936bae11 # v4.1.1
+ uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2
- name: ci/test
uses: ./.github/actions/test
@@ -28,7 +28,7 @@ jobs:
- test
steps:
- name: ci/checkout-repo
- uses: actions/checkout@b4ffde65f46336ab88eb53be808477a3936bae11 # v4.1.1
+ uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2
- name: ci/prepare-ios-build
uses: ./.github/actions/prepare-ios-build
@@ -65,7 +65,7 @@ jobs:
working-directory: ./fastlane
- name: ci/upload-ios-release-build
- uses: actions/upload-artifact@5d5d22a31266ced268874388b861e4b58bb5c2f3 # v4.3.1
+ uses: actions/upload-artifact@65c4c4a1ddee5b72f698fdd19549f0f0fb45cf08 # v4.6.0
with:
name: ios-build-release-${{ github.run_id }}
path: "*.ipa"
@@ -77,7 +77,7 @@ jobs:
- test
steps:
- name: ci/checkout-repo
- uses: actions/checkout@b4ffde65f46336ab88eb53be808477a3936bae11 # v4.1.1
+ uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2
- name: ci/prepare-ios-build
uses: ./.github/actions/prepare-ios-build
@@ -93,7 +93,7 @@ jobs:
working-directory: ./fastlane
- name: ci/upload-ios-pr-simulator
- uses: actions/upload-artifact@5d5d22a31266ced268874388b861e4b58bb5c2f3 # v4.3.1
+ uses: actions/upload-artifact@65c4c4a1ddee5b72f698fdd19549f0f0fb45cf08 # v4.6.0
with:
name: ios-build-simulator-${{ github.run_id }}
path: Mattermost-simulator-x86_64.app.zip
diff --git a/.github/workflows/build-pr.yml b/.github/workflows/build-pr.yml
index 98757478d..177a22dec 100644
--- a/.github/workflows/build-pr.yml
+++ b/.github/workflows/build-pr.yml
@@ -15,7 +15,7 @@ jobs:
if: ${{ github.event.label.name == 'Build Apps for PR' || github.event.label.name == 'Build App for iOS' || github.event.label.name == 'Build App for Android' }}
steps:
- name: ci/checkout-repo
- uses: actions/checkout@b4ffde65f46336ab88eb53be808477a3936bae11 # v4.1.1
+ uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2
with:
ref: ${{ github.event.pull_request.head.sha }}
- name: ci/test
@@ -28,7 +28,7 @@ jobs:
- test
steps:
- name: ci/checkout-repo
- uses: actions/checkout@b4ffde65f46336ab88eb53be808477a3936bae11 # v4.1.1
+ uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2
with:
ref: ${{ github.event.pull_request.head.sha }}
@@ -60,7 +60,7 @@ jobs:
working-directory: ./fastlane
- name: ci/upload-ios-pr-build
- uses: actions/upload-artifact@5d5d22a31266ced268874388b861e4b58bb5c2f3 # v4.3.1
+ uses: actions/upload-artifact@65c4c4a1ddee5b72f698fdd19549f0f0fb45cf08 # v4.6.0
with:
name: ios-build-pr-${{ github.run_id }}
path: "*.ipa"
@@ -72,7 +72,7 @@ jobs:
- test
steps:
- name: ci/checkout-repo
- uses: actions/checkout@b4ffde65f46336ab88eb53be808477a3936bae11 # v4.1.1
+ uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2
with:
ref: ${{ github.event.pull_request.head.sha }}
@@ -94,7 +94,7 @@ jobs:
working-directory: ./fastlane
- name: ci/upload-android-pr-build
- uses: actions/upload-artifact@5d5d22a31266ced268874388b861e4b58bb5c2f3 # v4.3.1
+ uses: actions/upload-artifact@65c4c4a1ddee5b72f698fdd19549f0f0fb45cf08 # v4.6.0
with:
name: android-build-pr-${{ github.run_id }}
path: "*.apk"
diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml
index b9cecf7ec..4a4e84af4 100644
--- a/.github/workflows/ci.yml
+++ b/.github/workflows/ci.yml
@@ -16,6 +16,6 @@ jobs:
runs-on: ubuntu-22.04
steps:
- name: ci/checkout-repo
- uses: actions/checkout@b4ffde65f46336ab88eb53be808477a3936bae11 # v4.1.1
+ uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2
- name: ci/test
uses: ./.github/actions/test
diff --git a/.github/workflows/codeql-analysis.yml b/.github/workflows/codeql-analysis.yml
index c49e51154..8fe7c9859 100644
--- a/.github/workflows/codeql-analysis.yml
+++ b/.github/workflows/codeql-analysis.yml
@@ -26,17 +26,17 @@ jobs:
steps:
- name: Checkout repository
- uses: actions/checkout@v3
+ uses: actions/checkout@v4
- name: Initialize CodeQL
- uses: github/codeql-action/init@v2
+ uses: github/codeql-action/init@v3
with:
languages: ${{ matrix.language }}
config-file: ./.github/codeql/codeql-config.yml
# Autobuild attempts to build any compiled languages
- name: Autobuild
- uses: github/codeql-action/autobuild@v2
+ uses: github/codeql-action/autobuild@v3
- name: Perform CodeQL Analysis
- uses: github/codeql-action/analyze@v2
+ uses: github/codeql-action/analyze@v3
diff --git a/.github/workflows/compatibility-matrix-testing.yml b/.github/workflows/compatibility-matrix-testing.yml
index 7b7cac9e2..199369498 100644
--- a/.github/workflows/compatibility-matrix-testing.yml
+++ b/.github/workflows/compatibility-matrix-testing.yml
@@ -20,7 +20,7 @@ jobs:
run: echo '${{ inputs.CMT_MATRIX }}' > instance-details.json
- name: cmt/upload-instance-details
- uses: actions/upload-artifact@5d5d22a31266ced268874388b861e4b58bb5c2f3 # v4.3.1
+ uses: actions/upload-artifact@65c4c4a1ddee5b72f698fdd19549f0f0fb45cf08 # v4.6.0
with:
name: instance-details.json
path: instance-details.json
@@ -32,7 +32,7 @@ jobs:
MOBILE_SHA: ${{ steps.repo.outputs.MOBILE_SHA }}
steps:
- name: cmt/checkout-mobile
- uses: actions/checkout@b4ffde65f46336ab88eb53be808477a3936bae11 # v4.1.1
+ uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2
with:
ref: ${{ inputs.MOBILE_VERSION }}
@@ -74,7 +74,7 @@ jobs:
- update-initial-status
steps:
- name: Checkout Repository
- uses: actions/checkout@b4ffde65f46336ab88eb53be808477a3936bae11 # v4.1.1
+ uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2
with:
ref: ${{ inputs.MOBILE_VERSION }}
@@ -91,7 +91,7 @@ jobs:
working-directory: ./fastlane
- name: Upload iOS Simulator Build
- uses: actions/upload-artifact@5d5d22a31266ced268874388b861e4b58bb5c2f3 # v4.3.1
+ uses: actions/upload-artifact@65c4c4a1ddee5b72f698fdd19549f0f0fb45cf08 # v4.6.0
with:
name: ios-build-simulator-${{ github.run_id }}
path: Mattermost-simulator-x86_64.app.zip
diff --git a/.github/workflows/e2e-android-template.yml b/.github/workflows/e2e-android-template.yml
new file mode 100644
index 000000000..9f1fd7c7b
--- /dev/null
+++ b/.github/workflows/e2e-android-template.yml
@@ -0,0 +1,295 @@
+name: Detox Android E2E Tests Template
+
+on:
+ workflow_call:
+ inputs:
+ MM_TEST_SERVER_URL:
+ description: "The test server URL"
+ required: false
+ type: string
+ MM_TEST_USER_NAME:
+ description: "The admin username of the test instance"
+ required: false
+ type: string
+ MM_TEST_PASSWORD:
+ description: "The admin password of the test instance"
+ required: false
+ type: string
+ MOBILE_VERSION:
+ description: "The mobile version to test"
+ required: false
+ default: ${{ github.head_ref || github.ref }}
+ type: string
+ run-android-tests:
+ description: "Run Android tests"
+ required: true
+ type: boolean
+ run-type:
+ type: string
+ required: false
+ default: "PR"
+ testcase_failure_fatal:
+ description: "Should failures be considered fatal"
+ required: false
+ type: boolean
+ default: false
+ record_tests_in_zephyr:
+ description: "Record test results in Zephyr, typically for nightly and release runs"
+ required: false
+ type: string
+ default: 'false'
+ low_bandwidth_mode:
+ description: "Enable low bandwidth mode"
+ required: false
+ type: boolean
+ default: false
+ android_avd_name:
+ description: "Android Emulator name"
+ required: false
+ type: string
+ default: "detox_pixel_4_xl"
+ android_api_level:
+ description: "Android API level"
+ required: false
+ type: string
+ default: "33"
+ outputs:
+ STATUS:
+ value: ${{ jobs.generate-report.outputs.STATUS }}
+ TARGET_URL:
+ value: ${{ jobs.generate-report.outputs.TARGET_URL }}
+ FAILURES:
+ value: ${{ jobs.generate-report.outputs.FAILURES }}
+
+env:
+ AWS_REGION: "us-east-1"
+ ADMIN_EMAIL: ${{ secrets.MM_MOBILE_E2E_ADMIN_EMAIL }}
+ ADMIN_USERNAME: ${{ secrets.MM_MOBILE_E2E_ADMIN_USERNAME }}
+ ADMIN_PASSWORD: ${{ secrets.MM_MOBILE_E2E_ADMIN_PASSWORD }}
+ BRANCH: ${{ github.event_name == 'pull_request' && github.head_ref || github.ref_name }}
+ COMMIT_HASH: ${{ github.sha }}
+ DEVICE_NAME: ${{ inputs.android_avd_name }} # This is needed to split tests as same code is used in iOS job
+ DEVICE_OS_VERSION: ${{ inputs.android_api_level }}
+ DETOX_AWS_S3_BUCKET: "mattermost-detox-report"
+ HEADLESS: "true"
+ TYPE: ${{ inputs.run-type }}
+ PULL_REQUEST: "https://github.com/mattermost/mattermost-mobile/pull/${{ github.event.number }}"
+ SITE_1_URL: ${{ inputs.MM_TEST_SERVER_URL || 'https://mobile-e2e-site-1.test.mattermost.cloud' }}
+ SITE_2_URL: "https://mobile-e2e-site-2.test.mattermost.cloud"
+ SITE_3_URL: "https://mobile-e2e-site-3.test.mattermost.cloud"
+ ZEPHYR_ENABLE: ${{ inputs.record_tests_in_zephyr }}
+ JIRA_PROJECT_KEY: "MM"
+ ZEPHYR_API_KEY: ${{ secrets.MM_MOBILE_E2E_ZEPHYR_API_KEY }}
+ ZEPHYR_FOLDER_ID: "3233873"
+ TEST_CYCLE_LINK_PREFIX: ${{ secrets.MM_MOBILE_E2E_TEST_CYCLE_LINK_PREFIX }}
+ WEBHOOK_URL: ${{ secrets.MM_MOBILE_E2E_WEBHOOK_URL }}
+ FAILURE_MESSAGE: "Something has failed"
+ IOS: "false"
+ RUNNING_E2E: "true"
+ AVD_NAME: ${{ inputs.android_avd_name }}
+ SDK_VERSION: ${{ inputs.android_api_level }}
+
+jobs:
+ generate-specs:
+ runs-on: ubuntu-22.04
+ outputs:
+ specs: ${{ steps.generate-specs.outputs.specs }}
+ build_id: ${{ steps.resolve-device.outputs.BUILD_ID }}
+ mobile_sha: ${{ steps.resolve-device.outputs.MOBILE_SHA }}
+ mobile_ref: ${{ steps.resolve-device.outputs.MOBILE_REF }}
+ workflow_hash: ${{ steps.resolve-device.outputs.WORKFLOW_HASH }}
+ steps:
+ - name: Checkout Repository
+ uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2
+ with:
+ ref: ${{ inputs.MOBILE_VERSION }}
+
+ - name: Set Build ID
+ id: resolve-device
+ run: |
+ BUILD_ID="${{ github.run_id }}-${{ env.AVD_NAME }}-${{ env.SDK_VERSION}}"
+ WORKFLOW_HASH=$(tr -dc a-z0-9 > ${GITHUB_OUTPUT}
+
+ echo "BUILD_ID=$(echo ${BUILD_ID} | sed 's/ /_/g')" >> ${GITHUB_OUTPUT}
+ echo "MOBILE_SHA=$(git rev-parse HEAD)" >> ${GITHUB_OUTPUT}
+ echo "MOBILE_REF=$(git rev-parse --abbrev-ref HEAD)" >> ${GITHUB_OUTPUT}
+
+ - name: Generate Test Specs
+ id: generate-specs
+ uses: ./.github/actions/generate-specs
+ with:
+ parallelism: 10
+ search_path: detox/e2e/test
+ device_name: ${{ env.AVD_NAME }}
+ device_os_version: ${{ env.SDK_VERSION }}
+
+ e2e-android:
+ name: android-detox-e2e-${{ matrix.runId }}-${{ matrix.deviceName }}-${{ matrix.deviceOsVersion }}
+ runs-on: ubuntu-latest-8-cores
+ continue-on-error: true
+ timeout-minutes: 150
+ env:
+ ANDROID_HOME: /usr/local/lib/android/sdk
+ ANDROID_SDK_ROOT: /usr/local/lib/android/sdk
+ needs:
+ - generate-specs
+ strategy:
+ fail-fast: false
+ matrix: ${{ fromJSON(needs.generate-specs.outputs.specs) }}
+ steps:
+ - name: Checkout Repository
+ uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2
+ with:
+ ref: ${{ inputs.MOBILE_VERSION }}
+
+ - name: Install Dependencies
+ run: |
+ sudo apt-get update
+ sudo apt-get install -y libpulse0
+ sudo apt-get install -y scrot ffmpeg xvfb
+
+ - name: Enable KVM
+ run: |
+ echo 'KERNEL=="kvm", GROUP="kvm", MODE="0666", OPTIONS+="static_node=kvm"' | sudo tee /etc/udev/rules.d/99-kvm4all.rules
+ sudo udevadm control --reload-rules
+ sudo udevadm trigger --name-match=kvm
+
+ - name: Prepare Android Build
+ uses: ./.github/actions/prepare-android-build
+ env:
+ STORE_FILE: "${{ secrets.MM_MOBILE_STORE_FILE }}"
+ STORE_ALIAS: "${{ secrets.MM_MOBILE_STORE_ALIAS }}"
+ STORE_PASSWORD: "${{ secrets.MM_MOBILE_STORE_PASSWORD }}"
+ MATTERMOST_BUILD_GH_TOKEN: "${{ secrets.MATTERMOST_BUILD_GH_TOKEN }}"
+
+ - name: Install Detox Dependencies
+ run: |
+ cd detox
+ npm install
+
+ - name: Create destination path
+ run: mkdir -p android/app/build
+
+ - name: Download APK artifact
+ uses: actions/download-artifact@v4
+ with:
+ name: android-build-files-${{ github.run_id }}
+ path: android/app/build
+
+ - name: Set up Android SDK
+ run: |
+ export ANDROID_HOME=/usr/local/lib/android/sdk
+ export PATH=$ANDROID_HOME/cmdline-tools/latest/bin:$ANDROID_HOME/emulator:$ANDROID_HOME/tools/bin:$ANDROID_HOME/platform-tools:$PATH
+ echo "ANDROID_HOME=$ANDROID_HOME" >> $GITHUB_ENV
+ echo "PATH=$PATH" >> $GITHUB_ENV
+
+ - name: Start Xvfb
+ run: |
+ Xvfb :99 -screen 0 1920x1080x24 &
+ export DISPLAY=:99
+ echo "DISPLAY=:99" >> $GITHUB_ENV
+
+ - name: Accept Android licenses
+ run: |
+ yes | sdkmanager --licenses || true
+
+ - name: Install Android system image
+ run: |
+ sdkmanager "system-images;android-34;default;x86_64"
+ sdkmanager "platform-tools" "emulator"
+
+ - name: Create and run Android Emulator
+ run: |
+ cd detox
+ chmod +x ./create_android_emulator.sh
+ ./create_android_emulator.sh ${{ env.SDK_VERSION }} ${{ env.AVD_NAME }} ${{ matrix.specs }}
+ continue-on-error: true # We want to run all the tests
+
+ - name: Upload Android Test Report
+ if: always()
+ uses: actions/upload-artifact@65c4c4a1ddee5b72f698fdd19549f0f0fb45cf08 # v4.6.0
+ with:
+ name: android-results-${{ needs.generate-specs.outputs.workflow_hash }}-${{ matrix.runId }}
+ path: detox/artifacts/
+
+ generate-report:
+ runs-on: ubuntu-22.04
+ needs:
+ - generate-specs
+ - e2e-android
+ outputs:
+ TARGET_URL: ${{ steps.set-url.outputs.TARGET_URL }}
+ STATUS: ${{ steps.determine-status.outputs.STATUS }}
+ FAILURES: ${{ steps.summary.outputs.FAILURES }}
+ steps:
+ - name: Checkout Repository
+ uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2
+ with:
+ ref: ${{ inputs.MOBILE_VERSION }}
+
+ - name: ci/prepare-node-deps
+ uses: ./.github/actions/prepare-node-deps
+
+ - name: Download Android Artifacts
+ uses: actions/download-artifact@c850b930e6ba138125429b7e5c93fc707a7f8427 # v4.1.4
+ with:
+ path: detox/artifacts/
+ pattern: android-results-${{ needs.generate-specs.outputs.workflow_hash }}-*
+ continue-on-error: true
+
+ - name: Generate Report Path
+ id: s3
+ run: |
+ path="${{ needs.generate-specs.outputs.build_id }}-${{ needs.generate-specs.outputs.mobile_sha }}-${{ needs.generate-specs.outputs.mobile_ref }}"
+ echo "path=$(echo "${path}" | sed 's/\./-/g')" >> ${GITHUB_OUTPUT}
+
+ - name: Save report Detox Dependencies
+ id: report-link
+ run: |
+ cd detox
+ npm ci
+ npm run e2e:save-report
+ env:
+ DETOX_AWS_ACCESS_KEY_ID: ${{ secrets.MM_MOBILE_DETOX_AWS_ACCESS_KEY_ID }}
+ DETOX_AWS_SECRET_ACCESS_KEY: ${{ secrets.MM_MOBILE_DETOX_AWS_SECRET_ACCESS_KEY }}
+ BUILD_ID: ${{ needs.generate-specs.outputs.build_id }}
+ REPORT_PATH: ${{ steps.s3.outputs.path }}
+ ## These are needed for the MM Webhook report
+ COMMIT_HASH: ${{ needs.generate-specs.outputs.mobile_sha }}
+ BRANCH: ${{ needs.generate-specs.outputs.mobile_ref }}
+
+ - name: Calculate failures
+ id: summary
+ run: |
+ echo "FAILURES=$(cat detox/artifacts/summary.json | jq .stats.failures)" >> ${GITHUB_OUTPUT}
+ echo "PASSES=$(cat detox/artifacts/summary.json | jq .stats.passes)" >> ${GITHUB_OUTPUT}
+ echo "SKIPPED=$(cat detox/artifacts/summary.json | jq .stats.skipped)" >> ${GITHUB_OUTPUT}
+ echo "TOTAL=$(cat detox/artifacts/summary.json | jq .stats.tests)" >> ${GITHUB_OUTPUT}
+ echo "ERRORS=$(cat detox/artifacts/summary.json | jq .stats.errors)" >> ${GITHUB_OUTPUT}
+ echo "PERCENTAGE=$(cat detox/artifacts/summary.json | jq .stats.passPercent)" >> ${GITHUB_OUTPUT}
+
+ - name: Set Target URL
+ id: set-url
+ run: |
+ echo "TARGET_URL=https://${{ env.DETOX_AWS_S3_BUCKET }}.s3.amazonaws.com/${{ steps.s3.outputs.path }}/jest-stare/android-report.html" >> ${GITHUB_OUTPUT}
+
+ - name: Determine Status
+ id: determine-status
+ run: |
+ if [[ ${{ steps.summary.outputs.failures }} -gt 0 && "${{ inputs.testcase_failure_fatal }}" == "true" ]]; then
+ echo "STATUS=failure" >> ${GITHUB_OUTPUT}
+ else
+ echo "STATUS=success" >> ${GITHUB_OUTPUT}
+ fi
+
+ - name: Generate Summary
+ run: |
+ echo "| Tests | Passed :white_check_mark: | Failed :x: | Skipped :fast_forward: | Errors :warning: | " >> ${GITHUB_STEP_SUMMARY}
+ echo "|:---:|:---:|:---:|:---:|:---:|" >> ${GITHUB_STEP_SUMMARY}
+ echo "| ${{ steps.summary.outputs.TOTAL }} | ${{ steps.summary.outputs.PASSES }} | ${{ steps.summary.outputs.FAILURES }} | ${{ steps.summary.outputs.SKIPPED }} | ${{ steps.summary.outputs.ERRORS }} |" >> ${GITHUB_STEP_SUMMARY}
+ echo "" >> ${GITHUB_STEP_SUMMARY}
+ echo "You can check the full report [here](${{ steps.set-url.outputs.TARGET_URL }})" >> ${GITHUB_STEP_SUMMARY}
+ echo "There was **${{ steps.summary.outputs.PERCENTAGE }}%** success rate." >> ${GITHUB_STEP_SUMMARY}
diff --git a/.github/workflows/e2e-detox-pr.yml b/.github/workflows/e2e-detox-pr.yml
index 41429ecb2..bc9e241a7 100644
--- a/.github/workflows/e2e-detox-pr.yml
+++ b/.github/workflows/e2e-detox-pr.yml
@@ -34,7 +34,7 @@ jobs:
- update-initial-status
steps:
- name: Checkout Repository
- uses: actions/checkout@b4ffde65f46336ab88eb53be808477a3936bae11 # v4.1.1
+ uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2
- name: Prepare iOS Build
uses: ./.github/actions/prepare-ios-build
@@ -49,11 +49,53 @@ jobs:
working-directory: ./fastlane
- name: Upload iOS Simulator Build
- uses: actions/upload-artifact@5d5d22a31266ced268874388b861e4b58bb5c2f3 # v4.3.1
+ uses: actions/upload-artifact@65c4c4a1ddee5b72f698fdd19549f0f0fb45cf08 # v4.6.0
with:
name: ios-build-simulator-${{ github.run_id }}
path: Mattermost-simulator-x86_64.app.zip
+ build-android-apk:
+ runs-on: ubuntu-latest-8-cores
+ if: contains(github.event.label.name, 'E2E Android tests for PR')
+ needs:
+ - update-initial-status-android
+ env:
+ ORG_GRADLE_PROJECT_jvmargs: -Xmx8g
+ steps:
+ - name: Prune Docker to free up space
+ run: docker system prune -af
+
+ - name: Remove npm Temporary Files
+ run: |
+ rm -rf ~/.npm/_cacache
+
+ - name: Checkout Repository
+ uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2
+
+ - name: Prepare Android Build
+ uses: ./.github/actions/prepare-android-build
+ env:
+ STORE_FILE: "${{ secrets.MM_MOBILE_STORE_FILE }}"
+ STORE_ALIAS: "${{ secrets.MM_MOBILE_STORE_ALIAS }}"
+ STORE_PASSWORD: "${{ secrets.MM_MOBILE_STORE_PASSWORD }}"
+ MATTERMOST_BUILD_GH_TOKEN: "${{ secrets.MATTERMOST_BUILD_GH_TOKEN }}"
+
+ - name: Install Dependencies
+ run: sudo apt-get clean && sudo apt-get update && sudo apt-get install -y default-jdk
+
+ - name: Detox build
+ run: |
+ cd detox
+ npm install
+ npm install -g detox-cli
+ npm run e2e:android-build
+
+ - name: Upload Android Build
+ uses: actions/upload-artifact@65c4c4a1ddee5b72f698fdd19549f0f0fb45cf08 # v4.6.0
+ with:
+ name: android-build-files-${{ github.run_id }}
+ path: "android/app/build/**/*"
+
run-ios-tests-on-pr:
name: iOS Mobile Tests on PR
uses: ./.github/workflows/e2e-detox-template.yml
diff --git a/.github/workflows/e2e-detox-release.yml b/.github/workflows/e2e-detox-release.yml
index bb604de60..0b074c8c8 100644
--- a/.github/workflows/e2e-detox-release.yml
+++ b/.github/workflows/e2e-detox-release.yml
@@ -25,7 +25,7 @@ jobs:
- update-initial-status
steps:
- name: Checkout Repository
- uses: actions/checkout@b4ffde65f46336ab88eb53be808477a3936bae11 # v4.1.1
+ uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2
- name: Prepare iOS Build
uses: ./.github/actions/prepare-ios-build
@@ -40,11 +40,61 @@ jobs:
working-directory: ./fastlane
- name: Upload iOS Simulator Build
- uses: actions/upload-artifact@5d5d22a31266ced268874388b861e4b58bb5c2f3 # v4.3.1
+ uses: actions/upload-artifact@65c4c4a1ddee5b72f698fdd19549f0f0fb45cf08 # v4.6.0
with:
name: ios-build-simulator-${{ github.run_id }}
path: Mattermost-simulator-x86_64.app.zip
+ build-android-apk:
+ runs-on: ubuntu-latest-8-cores
+ needs:
+ - update-initial-status-android
+ env:
+ ORG_GRADLE_PROJECT_jvmargs: -Xmx8g
+ steps:
+ - name: Prune Docker to free up space
+ run: docker system prune -af
+
+ - name: Remove npm Temporary Files
+ run: |
+ rm -rf ~/.npm/_cacache
+
+ - name: Checkout Repository
+ uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2
+ with:
+ ref: ${{ inputs.MOBILE_VERSION }}
+
+ - name: Prepare Android Build
+ uses: ./.github/actions/prepare-android-build
+ env:
+ STORE_FILE: "${{ secrets.MM_MOBILE_STORE_FILE }}"
+ STORE_ALIAS: "${{ secrets.MM_MOBILE_STORE_ALIAS }}"
+ STORE_PASSWORD: "${{ secrets.MM_MOBILE_STORE_PASSWORD }}"
+ MATTERMOST_BUILD_GH_TOKEN: "${{ secrets.MATTERMOST_BUILD_GH_TOKEN }}"
+
+ - name: Install Dependencies
+ run: sudo apt-get clean && sudo apt-get update && sudo apt-get install -y default-jdk
+
+ - name: Cache Gradle dependencies
+ uses: actions/cache@v4
+ with:
+ path: ~/.gradle/caches/modules-2/
+ key: ${{ runner.os }}-gradle-${{ hashFiles('**/*.gradle*', '**/gradle-wrapper.properties') }}
+ restore-keys: ${{ runner.os }}-gradle-
+
+ - name: Detox build
+ run: |
+ cd detox
+ npm install
+ npm install -g detox-cli
+ npm run e2e:android-build
+
+ - name: Upload Android Build
+ uses: actions/upload-artifact@65c4c4a1ddee5b72f698fdd19549f0f0fb45cf08 # v4.6.0
+ with:
+ name: android-build-files-${{ github.run_id }}
+ path: "android/app/build/**/*"
+
run-ios-tests-on-release:
name: iOS Mobile Tests on Release
uses: ./.github/workflows/e2e-detox-template.yml
diff --git a/.github/workflows/e2e-detox-scheduled.yml b/.github/workflows/e2e-detox-scheduled.yml
index 10786f4d6..ea692aaef 100644
--- a/.github/workflows/e2e-detox-scheduled.yml
+++ b/.github/workflows/e2e-detox-scheduled.yml
@@ -24,7 +24,7 @@ jobs:
- update-initial-status
steps:
- name: Checkout Repository
- uses: actions/checkout@b4ffde65f46336ab88eb53be808477a3936bae11 # v4.1.1
+ uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2
- name: Prepare iOS Build
uses: ./.github/actions/prepare-ios-build
@@ -39,11 +39,61 @@ jobs:
working-directory: ./fastlane
- name: Upload iOS Simulator Build
- uses: actions/upload-artifact@5d5d22a31266ced268874388b861e4b58bb5c2f3 # v4.3.1
+ uses: actions/upload-artifact@65c4c4a1ddee5b72f698fdd19549f0f0fb45cf08 # v4.6.0
with:
name: ios-build-simulator-${{ github.run_id }}
path: Mattermost-simulator-x86_64.app.zip
+ build-android-apk:
+ runs-on: ubuntu-latest-8-cores
+ needs:
+ - update-initial-status-android
+ env:
+ ORG_GRADLE_PROJECT_jvmargs: -Xmx8g
+ steps:
+ - name: Prune Docker to free up space
+ run: docker system prune -af
+
+ - name: Remove npm Temporary Files
+ run: |
+ rm -rf ~/.npm/_cacache
+
+ - name: Checkout Repository
+ uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2
+ with:
+ ref: ${{ inputs.MOBILE_VERSION }}
+
+ - name: Prepare Android Build
+ uses: ./.github/actions/prepare-android-build
+ env:
+ STORE_FILE: "${{ secrets.MM_MOBILE_STORE_FILE }}"
+ STORE_ALIAS: "${{ secrets.MM_MOBILE_STORE_ALIAS }}"
+ STORE_PASSWORD: "${{ secrets.MM_MOBILE_STORE_PASSWORD }}"
+ MATTERMOST_BUILD_GH_TOKEN: "${{ secrets.MATTERMOST_BUILD_GH_TOKEN }}"
+
+ - name: Install Dependencies
+ run: sudo apt-get clean && sudo apt-get update && sudo apt-get install -y default-jdk
+
+ - name: Cache Gradle dependencies
+ uses: actions/cache@v4
+ with:
+ path: ~/.gradle/caches/modules-2/
+ key: ${{ runner.os }}-gradle-${{ hashFiles('**/*.gradle*', '**/gradle-wrapper.properties') }}
+ restore-keys: ${{ runner.os }}-gradle-
+
+ - name: Detox build
+ run: |
+ cd detox
+ npm install
+ npm install -g detox-cli
+ npm run e2e:android-build
+
+ - name: Upload Android Build
+ uses: actions/upload-artifact@65c4c4a1ddee5b72f698fdd19549f0f0fb45cf08 # v4.6.0
+ with:
+ name: android-build-files-${{ github.run_id }}
+ path: "android/app/build/**/*"
+
run-ios-tests-on-main-scheduled:
name: iOS Mobile Tests on Main (Scheduled)
uses: ./.github/workflows/e2e-detox-template.yml
diff --git a/.github/workflows/e2e-detox-template.yml b/.github/workflows/e2e-detox-template.yml
index 9465a2ef0..554be8669 100644
--- a/.github/workflows/e2e-detox-template.yml
+++ b/.github/workflows/e2e-detox-template.yml
@@ -97,7 +97,7 @@ jobs:
workflow_hash: ${{ steps.resolve-device.outputs.WORKFLOW_HASH }}
steps:
- name: Checkout Repository
- uses: actions/checkout@b4ffde65f46336ab88eb53be808477a3936bae11 # v4.1.1
+ uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2
with:
ref: ${{ inputs.MOBILE_VERSION }}
@@ -138,7 +138,7 @@ jobs:
matrix: ${{ fromJSON(needs.generate-specs.outputs.specs) }}
steps:
- name: Checkout Repository
- uses: actions/checkout@b4ffde65f46336ab88eb53be808477a3936bae11 # v4.1.1
+ uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2
with:
ref: ${{ inputs.MOBILE_VERSION }}
@@ -208,7 +208,7 @@ jobs:
- name: Upload mitmdump Flow Output
if: ${{ inputs.low_bandwidth_mode }}
- uses: actions/upload-artifact@5d5d22a31266ced268874388b861e4b58bb5c2f3 # v4.3.1
+ uses: actions/upload-artifact@65c4c4a1ddee5b72f698fdd19549f0f0fb45cf08 # v4.6.0
with:
name: ios-mitmdump-flow-output-${{ needs.generate-specs.outputs.workflow_hash }}-${{ matrix.runId }}
path: |
@@ -217,7 +217,7 @@ jobs:
- name: Upload iOS Test Report
if: always()
- uses: actions/upload-artifact@5d5d22a31266ced268874388b861e4b58bb5c2f3 # v4.3.1
+ uses: actions/upload-artifact@65c4c4a1ddee5b72f698fdd19549f0f0fb45cf08 # v4.6.0
with:
name: ios-results-${{ needs.generate-specs.outputs.workflow_hash }}-${{ matrix.runId }}
path: detox/artifacts/
@@ -234,7 +234,7 @@ jobs:
FAILURES: ${{ steps.summary.outputs.FAILURES }}
steps:
- name: Checkout Repository
- uses: actions/checkout@b4ffde65f46336ab88eb53be808477a3936bae11 # v4.1.1
+ uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2
with:
ref: ${{ inputs.MOBILE_VERSION }}
diff --git a/.github/workflows/github-release.yml b/.github/workflows/github-release.yml
index c3d1701df..845b9b020 100644
--- a/.github/workflows/github-release.yml
+++ b/.github/workflows/github-release.yml
@@ -10,7 +10,7 @@ jobs:
runs-on: ubuntu-22.04
steps:
- name: ci/checkout-repo
- uses: actions/checkout@b4ffde65f46336ab88eb53be808477a3936bae11 # v4.1.1
+ uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2
- name: ci/test
uses: ./.github/actions/test
@@ -20,7 +20,7 @@ jobs:
- test
steps:
- name: ci/checkout-repo
- uses: actions/checkout@b4ffde65f46336ab88eb53be808477a3936bae11 # v4.1.1
+ uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2
- name: ci/prepare-ios-build
uses: ./.github/actions/prepare-ios-build
@@ -42,7 +42,7 @@ jobs:
working-directory: ./fastlane
- name: ci/upload-ios-unsigned
- uses: actions/upload-artifact@65462800fd760344b1a7b4382951275a0abb4808 # v4.3.3
+ uses: actions/upload-artifact@65c4c4a1ddee5b72f698fdd19549f0f0fb45cf08 # v4.6.0
with:
path: Mattermost-unsigned.ipa
name: Mattermost-unsigned.ipa
@@ -53,7 +53,7 @@ jobs:
- test
steps:
- name: ci/checkout-repo
- uses: actions/checkout@b4ffde65f46336ab88eb53be808477a3936bae11 # v4.1.1
+ uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2
- name: ci/prepare-android-build
uses: ./.github/actions/prepare-android-build
@@ -68,7 +68,7 @@ jobs:
working-directory: ./fastlane
- name: ci/upload-android-unsigned-build
- uses: actions/upload-artifact@65462800fd760344b1a7b4382951275a0abb4808 # v4.3.3
+ uses: actions/upload-artifact@65c4c4a1ddee5b72f698fdd19549f0f0fb45cf08 # v4.6.0
with:
path: Mattermost-unsigned.apk
name: Mattermost-unsigned.apk
@@ -80,9 +80,9 @@ jobs:
- build-android-unsigned
steps:
- name: ci/checkout-repo
- uses: actions/checkout@b4ffde65f46336ab88eb53be808477a3936bae11 # v4.1.1
+ uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2
- - uses: ruby/setup-ruby@ff740bc00a01b3a50fffc55a1071b1060eeae9dc # v1.180.0
+ - uses: ruby/setup-ruby@32110d4e311bd8996b2a82bf2a43b714ccc91777 # v1.221.0
- name: release/setup-fastlane-dependencies
run: bundle install
diff --git a/app/context/extra_keyboard/index.tsx b/app/context/extra_keyboard/index.tsx
index cb14db6cc..69282bf08 100644
--- a/app/context/extra_keyboard/index.tsx
+++ b/app/context/extra_keyboard/index.tsx
@@ -54,6 +54,10 @@ export const ExtraKeyboardProvider = (({children}: {children: React.ReactElement
const [isTextInputFocused, setIsTextInputFocused] = useState(false);
const showExtraKeyboard = useCallback((newComponent: React.ReactElement|null) => {
+ // Do not use ExtraKeyboard on Android versions below 11
+ if (Platform.OS === 'android' && Platform.Version < 30) {
+ return;
+ }
setExtraKeyboardVisible(true);
setComponent(newComponent);
if (Keyboard.isVisible()) {
@@ -62,6 +66,10 @@ export const ExtraKeyboardProvider = (({children}: {children: React.ReactElement
}, []);
const hideExtraKeyboard = useCallback(() => {
+ // Do not use ExtraKeyboard on Android versions below 11
+ if (Platform.OS === 'android' && Platform.Version < 30) {
+ return;
+ }
setExtraKeyboardVisible(false);
setComponent(null);
if (Keyboard.isVisible()) {
@@ -70,6 +78,11 @@ export const ExtraKeyboardProvider = (({children}: {children: React.ReactElement
}, []);
const registerTextInputFocus = useCallback(() => {
+ // Do not use ExtraKeyboard on Android versions below 11
+ if (Platform.OS === 'android' && Platform.Version < 30) {
+ return;
+ }
+
// If the extra keyboard is opened if we don't do this
// we get a glitch in the UI that will animate the extra keyboard down
// and immediately bring the keyboard, by doing this
@@ -81,11 +94,21 @@ export const ExtraKeyboardProvider = (({children}: {children: React.ReactElement
}, []);
const registerTextInputBlur = useCallback(() => {
+ // Do not use ExtraKeyboard on Android versions below 11
+ if (Platform.OS === 'android' && Platform.Version < 30) {
+ return;
+ }
+
setIsTextInputFocused(false);
}, []);
useEffect(() => {
const keyboardHideListener = Keyboard.addListener('keyboardDidHide', () => {
+ // Do not use ExtraKeyboard on Android versions below 11
+ if (Platform.OS === 'android' && Platform.Version < 30) {
+ return;
+ }
+
if (isTextInputFocused) {
setExtraKeyboardVisible(false);
}
@@ -142,7 +165,7 @@ export const useHideExtraKeyboardIfNeeded = (callback: (...args: any) => void, d
}), [keyboardContext, ...dependencies]);
};
-export const ExtraKeyboard = () => {
+const ExtraKeyboardComponent = () => {
const keyb = useAnimatedKeyboard({isStatusBarTranslucentAndroid: true});
const defaultKeyboardHeight = Platform.select({ios: 291, default: 240});
const context = useExtraKeyboardContext();
@@ -181,3 +204,14 @@ export const ExtraKeyboard = () => {
);
};
+
+// Do not use ExtraKeyboard on Android versions below 11
+export const ExtraKeyboard = () => {
+ if (Platform.OS === 'android' && Platform.Version < 30) {
+ return null;
+ }
+
+ return (
+
+ );
+};
diff --git a/app/hooks/device.ts b/app/hooks/device.ts
index bf0313159..abca58490 100644
--- a/app/hooks/device.ts
+++ b/app/hooks/device.ts
@@ -61,10 +61,19 @@ export function useKeyboardHeightWithDuration() {
useEffect(() => {
const show = Keyboard.addListener(Platform.select({ios: 'keyboardWillShow', default: 'keyboardDidShow'}), async (event) => {
+ // Do not use set the height on Android versions below 11
+ if (Platform.OS === 'android' && Platform.Version < 30) {
+ return;
+ }
setKeyboardHeight({height: event.endCoordinates.height, duration: event.duration});
});
const hide = Keyboard.addListener(Platform.select({ios: 'keyboardWillHide', default: 'keyboardDidHide'}), (event) => {
+ // Do not use set the height on Android versions below 11
+ if (Platform.OS === 'android' && Platform.Version < 30) {
+ return;
+ }
+
if (updateTimeout.current != null) {
clearTimeout(updateTimeout.current);
updateTimeout.current = null;
diff --git a/app/screens/interactive_dialog/index.tsx b/app/screens/interactive_dialog/index.tsx
index eaa2042e2..97daff23f 100644
--- a/app/screens/interactive_dialog/index.tsx
+++ b/app/screens/interactive_dialog/index.tsx
@@ -3,7 +3,8 @@
import React, {useCallback, useEffect, useMemo, useReducer, useRef, useState} from 'react';
import {useIntl} from 'react-intl';
-import {Keyboard, ScrollView} from 'react-native';
+import {Keyboard} from 'react-native';
+import {KeyboardAwareScrollView} from 'react-native-keyboard-aware-scroll-view';
import {type ImageResource, Navigation} from 'react-native-navigation';
import {SafeAreaView} from 'react-native-safe-area-context';
@@ -106,7 +107,7 @@ function InteractiveDialog({
const serverUrl = useServerUrl();
const intl = useIntl();
- const scrollView = useRef(null);
+ const scrollView = useRef(null);
const onChange = useCallback((name: string, value: string | number | boolean) => {
dispatchValues({name, value});
@@ -185,7 +186,7 @@ function InteractiveDialog({
if (data.error) {
hasErrors = true;
setError(data.error);
- scrollView.current?.scrollTo({x: 0, y: 0});
+ scrollView.current?.scrollToPosition(0, 0, true);
} else {
setError('');
}
@@ -234,9 +235,19 @@ function InteractiveDialog({
testID='interactive_dialog.screen'
style={style.container}
>
-
{Boolean(error) && (
)}
{Boolean(introductionText) &&
-
+
}
{Boolean(elements) && elements.map((e) => {
const value = secureGetFromRecord(values, e.name);
@@ -271,7 +282,7 @@ function InteractiveDialog({
/>
);
})}
-
+
);
}
diff --git a/libraries/@mattermost/rnutils/android/src/main/java/com/mattermost/rnutils/RNUtilsModuleImpl.kt b/libraries/@mattermost/rnutils/android/src/main/java/com/mattermost/rnutils/RNUtilsModuleImpl.kt
index 60c2921e7..250ec3c45 100644
--- a/libraries/@mattermost/rnutils/android/src/main/java/com/mattermost/rnutils/RNUtilsModuleImpl.kt
+++ b/libraries/@mattermost/rnutils/android/src/main/java/com/mattermost/rnutils/RNUtilsModuleImpl.kt
@@ -2,6 +2,7 @@ package com.mattermost.rnutils
import android.app.Activity
import android.net.Uri
+import android.os.Build
import android.view.WindowManager
import androidx.core.view.OnApplyWindowInsetsListener
import com.facebook.react.bridge.Arguments
@@ -128,6 +129,9 @@ class RNUtilsModuleImpl(private val reactContext: ReactApplicationContext) {
fun setSoftKeyboardToAdjustNothing() {
val currentActivity: Activity = reactContext.currentActivity ?: return
+ if (Build.VERSION.SDK_INT <= Build.VERSION_CODES.Q) {
+ return
+ }
currentActivity.runOnUiThread {
currentActivity.window.setSoftInputMode(WindowManager.LayoutParams.SOFT_INPUT_ADJUST_NOTHING)
@@ -136,6 +140,9 @@ class RNUtilsModuleImpl(private val reactContext: ReactApplicationContext) {
fun setSoftKeyboardToAdjustResize() {
val currentActivity: Activity = reactContext.currentActivity ?: return
+ if (Build.VERSION.SDK_INT <= Build.VERSION_CODES.Q) {
+ return
+ }
currentActivity.runOnUiThread {
currentActivity.window.setSoftInputMode(WindowManager.LayoutParams.SOFT_INPUT_ADJUST_RESIZE)
diff --git a/patches/react-native-keyboard-aware-scroll-view+0.9.5.patch b/patches/react-native-keyboard-aware-scroll-view+0.9.5.patch
new file mode 100644
index 000000000..791a3260a
--- /dev/null
+++ b/patches/react-native-keyboard-aware-scroll-view+0.9.5.patch
@@ -0,0 +1,74 @@
+diff --git a/node_modules/react-native-keyboard-aware-scroll-view/index.d.ts b/node_modules/react-native-keyboard-aware-scroll-view/index.d.ts
+index bf03b26..e11063b 100644
+--- a/node_modules/react-native-keyboard-aware-scroll-view/index.d.ts
++++ b/node_modules/react-native-keyboard-aware-scroll-view/index.d.ts
+@@ -69,6 +69,7 @@ interface KeyboardAwareProps {
+ * @memberof KeyboardAwareProps
+ */
+ enableOnAndroid?: boolean
++ noPaddingBottomOnAndroid?: boolean
+
+ /**
+ * Adds an extra offset when focusing the TextInputs.
+diff --git a/node_modules/react-native-keyboard-aware-scroll-view/lib/KeyboardAwareHOC.js b/node_modules/react-native-keyboard-aware-scroll-view/lib/KeyboardAwareHOC.js
+index 03f46af..f58175f 100644
+--- a/node_modules/react-native-keyboard-aware-scroll-view/lib/KeyboardAwareHOC.js
++++ b/node_modules/react-native-keyboard-aware-scroll-view/lib/KeyboardAwareHOC.js
+@@ -57,6 +57,7 @@ export type KeyboardAwareHOCProps = {
+ update?: Function,
+ contentContainerStyle?: any,
+ enableOnAndroid?: boolean,
++ noPaddingBottomOnAndroid?: boolean,
+ innerRef?: Function,
+ ...keyboardAwareHOCTypeEvents
+ }
+@@ -92,6 +93,7 @@ export type ScrollIntoViewOptions = ?{
+
+ export type KeyboardAwareHOCOptions = ?{
+ enableOnAndroid: boolean,
++ noPaddingBottomOnAndroid: boolean,
+ contentContainerStyle: ?Object,
+ enableAutomaticScroll: boolean,
+ extraHeight: number,
+@@ -113,6 +115,7 @@ function getDisplayName(WrappedComponent: React$Component) {
+
+ const ScrollIntoViewDefaultOptions: KeyboardAwareHOCOptions = {
+ enableOnAndroid: false,
++ noPaddingBottomOnAndroid: false,
+ contentContainerStyle: undefined,
+ enableAutomaticScroll: true,
+ extraHeight: _KAM_EXTRA_HEIGHT,
+@@ -181,6 +184,7 @@ function KeyboardAwareHOC(
+ update: PropTypes.func,
+ contentContainerStyle: PropTypes.any,
+ enableOnAndroid: PropTypes.bool,
++ noPaddingBottomOnAndroid: PropTypes.bool,
+ innerRef: PropTypes.func,
+ ...keyboardEventPropTypes
+ }
+@@ -193,7 +197,8 @@ function KeyboardAwareHOC(
+ enableResetScrollToCoords: hocOptions.enableResetScrollToCoords,
+ keyboardOpeningTime: hocOptions.keyboardOpeningTime,
+ viewIsInsideTabBar: hocOptions.viewIsInsideTabBar,
+- enableOnAndroid: hocOptions.enableOnAndroid
++ enableOnAndroid: hocOptions.enableOnAndroid,
++ noPaddingBottomOnAndroid: hocOptions.noPaddingBottomOnAndroid
+ }
+
+ constructor(props: KeyboardAwareHOCProps) {
+@@ -523,13 +528,13 @@ function KeyboardAwareHOC(
+ }
+
+ render() {
+- const { enableOnAndroid, contentContainerStyle, onScroll } = this.props
++ const { enableOnAndroid, contentContainerStyle, noPaddingBottomOnAndroid, onScroll } = this.props
+ let newContentContainerStyle
+ if (Platform.OS === 'android' && enableOnAndroid) {
+ newContentContainerStyle = [].concat(contentContainerStyle).concat({
+ paddingBottom:
+ ((contentContainerStyle || {}).paddingBottom || 0) +
+- this.state.keyboardSpace
++ noPaddingBottomOnAndroid ? 0 : this.state.keyboardSpace
+ })
+ }
+ const refProps = { [hocOptions.refPropName]: this._handleRef }