diff --git a/.github/ISSUE_TEMPLATE/bug-report.yml b/.github/ISSUE_TEMPLATE/bug-report.yml
index f92f51a43..dcbba0597 100644
--- a/.github/ISSUE_TEMPLATE/bug-report.yml
+++ b/.github/ISSUE_TEMPLATE/bug-report.yml
@@ -1,7 +1,7 @@
name: "\U0001F41E Bug report"
description: Create a report to help us improve.
title: "[Bug]: "
-labels: ["bug"]
+type: Bug # Retained to categorize the issue as per organization-level type
body:
- type: markdown
attributes:
@@ -70,7 +70,7 @@ body:
required: false
- type: textarea
attributes:
- label: Screen-shots
+ label: Screenshots
description: Add screenshots related to the issue (if available). Can be created by pressing the Volume Down and Power Button at the same time on Android 4.0 and higher.
validations:
required: false
diff --git a/.github/workflows/android.yml b/.github/workflows/android.yml
index 6760a312e..bc8b03c9e 100644
--- a/.github/workflows/android.yml
+++ b/.github/workflows/android.yml
@@ -1,6 +1,6 @@
name: Android CI
-on: [push, pull_request]
+on: [push, pull_request, workflow_dispatch]
concurrency:
group: build-${{ github.event.pull_request.number || github.ref }}
@@ -12,17 +12,17 @@ jobs:
runs-on: ubuntu-latest
steps:
- name: Checkout code
- uses: actions/checkout@v2.4.0
+ uses: actions/checkout@v4
- name: Set up JDK
- uses: actions/setup-java@v2.5.0
+ uses: actions/setup-java@v4
with:
- distribution: "temurin"
- java-version: 11
+ distribution: 'temurin'
+ java-version: '17'
- name: Cache packages
id: cache-packages
- uses: actions/cache@v2.1.7
+ uses: actions/cache@v4
with:
path: |
~/.gradle/caches
@@ -37,7 +37,7 @@ jobs:
- name: AVD cache
if: github.event_name != 'pull_request'
- uses: actions/cache@v2
+ uses: actions/cache@v4
id: avd-cache
with:
path: |
@@ -89,7 +89,7 @@ jobs:
run: bash ./gradlew assembleBetaDebug --stacktrace
- name: Upload betaDebug APK
- uses: actions/upload-artifact@v2.3.1
+ uses: actions/upload-artifact@v4
with:
name: betaDebugAPK
path: app/build/outputs/apk/beta/debug/app-*.apk
@@ -98,7 +98,17 @@ jobs:
run: bash ./gradlew assembleProdDebug --stacktrace
- name: Upload prodDebug APK
- uses: actions/upload-artifact@v2.3.1
+ uses: actions/upload-artifact@v4
with:
name: prodDebugAPK
path: app/build/outputs/apk/prod/debug/app-*.apk
+
+ - name: Create and PR number artifact
+ run: |
+ echo "{\"pr_number\": ${{ github.event.pull_request.number || 'null' }}}" > pr_number.json
+
+ - name: Upload PR number artifact
+ uses: actions/upload-artifact@v4
+ with:
+ name: pr_number
+ path: ./pr_number.json
diff --git a/.github/workflows/build-beta.yml b/.github/workflows/build-beta.yml
new file mode 100644
index 000000000..8e1a26e15
--- /dev/null
+++ b/.github/workflows/build-beta.yml
@@ -0,0 +1,41 @@
+name: Build beta only
+
+on: [workflow_dispatch]
+
+jobs:
+ build:
+
+ runs-on: ubuntu-latest
+
+ steps:
+ - uses: actions/checkout@v4
+ - name: set up JDK 17
+ uses: actions/setup-java@v4
+ with:
+ java-version: '17'
+ distribution: 'temurin'
+ cache: gradle
+
+ - name: Access test login credentials
+ run: |
+ echo "TEST_USER_NAME=${{ secrets.TEST_USER_NAME }}" >> local.properties
+ echo "TEST_USER_PASSWORD=${{ secrets.TEST_USER_PASSWORD }}" >> local.properties
+
+ - name: Grant execute permission for gradlew
+ run: chmod +x gradlew
+
+ - name: Set env
+ run: echo "COMMIT_SHA=$(git log -n 1 --format='%h')" >> $GITHUB_ENV
+
+ - name: Generate betaDebug APK
+ run: ./gradlew assembleBetaDebug --stacktrace
+
+ - name: Rename betaDebug APK
+ run: mv app/build/outputs/apk/beta/debug/app-*.apk app/build/outputs/apk/beta/debug/apps-android-commons-betaDebug-$COMMIT_SHA.apk
+
+ - name: Upload betaDebug APK
+ uses: actions/upload-artifact@v4
+ with:
+ name: apps-android-commons-betaDebugAPK-${{ env.COMMIT_SHA }}
+ path: app/build/outputs/apk/beta/debug/*.apk
+ retention-days: 30
diff --git a/.github/workflows/comment_artifacts_on_PR.yml b/.github/workflows/comment_artifacts_on_PR.yml
new file mode 100644
index 000000000..ee4ae7c46
--- /dev/null
+++ b/.github/workflows/comment_artifacts_on_PR.yml
@@ -0,0 +1,96 @@
+name: Comment Artifacts on PR
+
+on:
+ workflow_run:
+ workflows: [ "Android CI" ]
+ types: [ completed ]
+
+permissions:
+ pull-requests: write
+ contents: read
+
+concurrency:
+ group: comment-${{ github.event.workflow_run.id }}
+ cancel-in-progress: true
+
+jobs:
+ comment:
+ runs-on: ubuntu-latest
+ if: ${{ github.event.workflow_run.conclusion == 'success' && github.event.workflow_run.event == 'pull_request' }}
+ steps:
+ - name: Download and process artifacts
+ uses: actions/github-script@v7
+ with:
+ github-token: ${{ secrets.GITHUB_TOKEN }}
+ script: |
+ const fs = require('fs');
+ const runId = context.payload.workflow_run.id;
+
+ const allArtifacts = await github.rest.actions.listWorkflowRunArtifacts({
+ owner: context.repo.owner,
+ repo: context.repo.repo,
+ run_id: runId,
+ });
+
+ const prNumberArtifact = allArtifacts.data.artifacts.find(artifact => artifact.name === "pr_number");
+ if (!prNumberArtifact) {
+ console.log("pr_number artifact not found.");
+ return;
+ }
+
+ const download = await github.rest.actions.downloadArtifact({
+ owner: context.repo.owner,
+ repo: context.repo.repo,
+ artifact_id: prNumberArtifact.id,
+ archive_format: 'zip',
+ });
+
+ fs.writeFileSync(`${process.env.GITHUB_WORKSPACE}/pr_number.zip`, Buffer.from(download.data));
+ const { execSync } = require('child_process');
+ execSync('unzip -q pr_number.zip -d ./pr_number/');
+ fs.unlinkSync('pr_number.zip');
+
+ const prData = JSON.parse(fs.readFileSync('./pr_number/pr_number.json', 'utf8'));
+ const prNumber = prData.pr_number;
+
+ if (!prNumber || prNumber === 'null') {
+ console.log("No valid PR number found in pr_number.json. Skipping.");
+ return;
+ }
+
+ const artifactsToLink = allArtifacts.data.artifacts.filter(artifact => artifact.name !== "pr_number");
+ if (artifactsToLink.length === 0) {
+ console.log("No artifacts to link found.");
+ return;
+ }
+
+ const comments = await github.rest.issues.listComments({
+ owner: context.repo.owner,
+ repo: context.repo.repo,
+ issue_number: Number(prNumber),
+ });
+
+ const oldComments = comments.data.filter(comment =>
+ comment.body.startsWith("✅ Generated APK variants!")
+ );
+ for (const comment of oldComments) {
+ await github.rest.issues.deleteComment({
+ owner: context.repo.owner,
+ repo: context.repo.repo,
+ comment_id: comment.id,
+ });
+ console.log(`Deleted old comment ID: ${comment.id}`);
+ };
+
+ const commentBody = `✅ Generated APK variants!\n` +
+ artifactsToLink.map(artifact => {
+ const artifactUrl = `https://github.com/${context.repo.owner}/${context.repo.repo}/actions/runs/${runId}/artifacts/${artifact.id}`;
+ return `- 🤖 [Download ${artifact.name}](${artifactUrl})`;
+ }).join('\n');
+
+ await github.rest.issues.createComment({
+ owner: context.repo.owner,
+ repo: context.repo.repo,
+ issue_number: Number(prNumber),
+ body: commentBody
+ });
diff --git a/.gitignore b/.gitignore
index 418e4c380..7fa4767a7 100644
--- a/.gitignore
+++ b/.gitignore
@@ -43,3 +43,8 @@ app/src/main/jniLibs
#https://docs.opencv.org/3.3.0/
/libraries/opencv/javadoc/
captures/*
+
+# Test and other output
+app/jacoco.exec
+app/CommonsContributions
+app/.*
diff --git a/.idea/codeStyles/Project.xml b/.idea/codeStyles/Project.xml
index f277755ba..ea0cb3b07 100644
--- a/.idea/codeStyles/Project.xml
+++ b/.idea/codeStyles/Project.xml
@@ -16,6 +16,7 @@