Skip to content

Commit 1fe8ee4

Browse files
Merge pull request #399 from openedx/develop
Develop to main. Release v2
2 parents 4d36310 + 88dfc54 commit 1fe8ee4

File tree

479 files changed

+17573
-6309
lines changed

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

479 files changed

+17573
-6309
lines changed

.github/workflows/unit_tests.yml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -42,7 +42,7 @@ jobs:
4242
run: ./gradlew testProdDebugUnitTest $CI_GRADLE_ARG_PROPERTIES
4343

4444
- name: Upload reports
45-
uses: actions/upload-artifact@v3
45+
uses: actions/upload-artifact@v4
4646
if: failure()
4747
with:
4848
name: failures
Lines changed: 32 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,32 @@
1+
name: Validate English strings.xml
2+
3+
on:
4+
pull_request: { }
5+
push:
6+
branches: [ main, develop ]
7+
8+
jobs:
9+
translation_strings:
10+
name: Validate strings.xml
11+
runs-on: ubuntu-latest
12+
13+
steps:
14+
- name: Checkout
15+
uses: actions/checkout@v4
16+
17+
- name: Use Python
18+
uses: actions/setup-python@v5
19+
with:
20+
python-version: 3.11
21+
22+
- name: Install translations requirements
23+
run: make translation_requirements
24+
25+
- name: Validate English plurals in strings.xml
26+
run: make validate_english_plurals
27+
28+
- name: Test extract strings
29+
run: |
30+
make extract_translations
31+
# Ensure the file is extracted
32+
test -f i18n/src/main/res/values/strings.xml

.gitignore

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -16,3 +16,6 @@ local.properties
1616
/.idea/
1717
*.log
1818
/config_settings.yaml
19+
.venv/
20+
i18n/
21+
**/values-*/strings.xml

Documentation/ConfigurationManagement.md

Lines changed: 3 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -49,7 +49,6 @@ TOKEN_TYPE: "JWT"
4949

5050
FIREBASE:
5151
ENABLED: false
52-
ANALYTICS_SOURCE: ''
5352
CLOUD_MESSAGING_ENABLED: false
5453
PROJECT_NUMBER: ''
5554
PROJECT_ID: ''
@@ -82,14 +81,14 @@ android:
8281
- **Facebook:** Sign in and Sign up via Facebook
8382
- **Branch:** Deeplinks
8483
- **Braze:** Cloud Messaging
85-
- **SegmentIO:** Analytics
8684

8785
## Available Feature Flags
8886
- **PRE_LOGIN_EXPERIENCE_ENABLED:** Enables the pre login courses discovery experience.
8987
- **WHATS_NEW_ENABLED:** Enables the "What's New" feature to present the latest changes to the user.
9088
- **SOCIAL_AUTH_ENABLED:** Enables SSO buttons on the SignIn and SignUp screens.
91-
- **COURSE_NESTED_LIST_ENABLED:** Enables an alternative visual representation for the course structure.
92-
- **COURSE_UNIT_PROGRESS_ENABLED:** Enables the display of the unit progress within the courseware.
89+
- **COURSE_DROPDOWN_NAVIGATION_ENABLED:** Enables an alternative navigation through units.
90+
- **COURSE_UNIT_PROGRESS_ENABLED:** Enables the display of the unit progress within the courseware.
91+
- **REGISTRATION_ENABLED:** Enables user registration from the app.
9392

9493
## Future Support
9594
- To add config related to some other service, create a class, e.g. `ServiceNameConfig.kt`, to be able to populate related fields.

Makefile

Lines changed: 25 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,25 @@
1+
clean_translations_temp_directory:
2+
rm -rf i18n/
3+
4+
translation_requirements:
5+
pip3 install -r i18n_scripts/requirements.txt
6+
7+
pull_translations: clean_translations_temp_directory
8+
atlas pull $(ATLAS_OPTIONS) translations/openedx-app-android/i18n:i18n
9+
python3 i18n_scripts/translation.py --split --replace-underscore
10+
11+
extract_translations: clean_translations_temp_directory
12+
python3 i18n_scripts/translation.py --combine
13+
14+
validate_english_plurals:
15+
@if git grep 'quantity' -- '**/res/values/strings.xml' | grep -E 'quantity=.(zero|two|few|many)'; then \
16+
echo ""; \
17+
echo ""; \
18+
echo "Error: Found invalid plurals in the files listed above."; \
19+
echo " Please only use 'one' and 'other' in English strings.xml files,"; \
20+
echo " otherwise Transifex fails to parse them."; \
21+
echo ""; \
22+
exit 1; \
23+
else \
24+
echo "strings.xml files are valid."; \
25+
fi

README.md

Lines changed: 42 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -20,6 +20,48 @@ Modern vision of the mobile application for the Open edX platform from Raccoon G
2020

2121
6. Click the **Run** button.
2222

23+
## Translations
24+
25+
### Getting Translations for the App
26+
Translations aren't included in the source code of this repository as of [OEP-58](https://docs.openedx.org/en/latest/developers/concepts/oep58.html). Therefore, they need to be pulled before testing or publishing to App Store.
27+
28+
Before retrieving the translations for the app, we need to install the requirements listed in the requirements.txt file located in the i18n_scripts directory. This can be done easily by running the following make command:
29+
```bash
30+
make translation_requirements
31+
```
32+
33+
Then, to get the latest translations for all languages use the following command:
34+
```bash
35+
make pull_translations
36+
```
37+
This command runs [`atlas pull`](https://github.com/openedx/openedx-atlas) to download the latest translations files from the [openedx/openedx-translations](https://github.com/openedx/openedx-translations) repository. These files contain the latest translations for all languages. In the [openedx/openedx-translations](https://github.com/openedx/openedx-translations) repository each language's translations are saved as a single file e.g. `i18n/src/main/res/values-uk/strings.xml` ([example](https://github.com/openedx/openedx-translations/blob/04ccea36b8e6a9889646dfb5a5acb99686fa9ae0/translations/openedx-app-android/i18n/src/main/res/values-uk/strings.xml)). After these are pulled, each language's translation file is split into the App's modules e.g. `auth/src/main/res/values-uk/strings.xml`.
38+
39+
After this command is run the application can load the translations by changing the device (or the emulator) language in the settings.
40+
41+
### Using Custom Translations
42+
43+
By default, the command `make pull_translations` runs [`atlas pull`](https://github.com/openedx/openedx-atlas) with no arguments which pulls translations from the [openedx-translations repository](https://github.com/openedx/openedx-translations).
44+
45+
You can use custom translations on your fork of the openedx-translations repository by setting the following configuration parameters:
46+
47+
- `--revision` (default: `"main"`): Branch or git tag to pull translations from.
48+
- `--repository` (default: `"openedx/openedx-translations"`): GitHub repository slug. There's a feature request to [support GitLab and other providers](https://github.com/openedx/openedx-atlas/issues/20).
49+
50+
Arguments can be passed via the `ATLAS_OPTIONS` environment variable as shown below:
51+
``` bash
52+
make ATLAS_OPTIONS='--repository=<your-github-org>/<repository-name> --revision=<branch-name>' pull_translations
53+
```
54+
Additional arguments can be passed to `atlas pull`. Refer to the [atlas documentations ](https://github.com/openedx/openedx-atlas) for more information.
55+
56+
### How to Translate the App
57+
58+
Translations are managed in the [open-edx/openedx-translations](https://app.transifex.com/open-edx/openedx-translations/dashboard/) Transifex project.
59+
60+
To translate the app join the [Transifex project](https://app.transifex.com/open-edx/openedx-translations/dashboard/) and add your translations to the
61+
[`openedx-app-android`](https://app.transifex.com/open-edx/openedx-translations/openedx-app-android/) resource.
62+
63+
Once the resource is both 100% translated and reviewed the [Transifex integration](https://github.com/apps/transifex-integration) will automatically push it to the [openedx-translations](https://github.com/openedx/openedx-translations) repository and developers can use the translations in their app.
64+
2365
## API
2466
This project targets on the latest Open edX release and rely on the relevant mobile APIs.
2567

app/build.gradle

Lines changed: 16 additions & 26 deletions
Original file line numberDiff line numberDiff line change
@@ -1,13 +1,15 @@
11
def config = configHelper.fetchConfig()
22
def appId = config.getOrDefault("APPLICATION_ID", "org.openedx.app")
3-
def platformName = config.getOrDefault("PLATFORM_NAME", "OpenEdx").toLowerCase()
3+
def themeDirectory = config.getOrDefault("THEME_DIRECTORY", "openedx")
44
def firebaseConfig = config.get('FIREBASE')
55
def firebaseEnabled = firebaseConfig?.getOrDefault('ENABLED', false)
66

77
apply plugin: 'com.android.application'
88
apply plugin: 'org.jetbrains.kotlin.android'
99
apply plugin: 'kotlin-parcelize'
10-
apply plugin: 'kotlin-kapt'
10+
apply plugin: 'com.google.devtools.ksp'
11+
apply plugin: 'org.jetbrains.kotlin.plugin.compose'
12+
1113
if (firebaseEnabled) {
1214
apply plugin: 'com.google.gms.google-services'
1315
apply plugin: 'com.google.firebase.crashlytics'
@@ -63,13 +65,13 @@ android {
6365

6466
sourceSets {
6567
prod {
66-
res.srcDirs = ["src/$platformName/res"]
68+
res.srcDirs = ["src/$themeDirectory/res"]
6769
}
6870
develop {
69-
res.srcDirs = ["src/$platformName/res"]
71+
res.srcDirs = ["src/$themeDirectory/res"]
7072
}
7173
stage {
72-
res.srcDirs = ["src/$platformName/res"]
74+
res.srcDirs = ["src/$themeDirectory/res"]
7375
}
7476
}
7577

@@ -91,15 +93,13 @@ android {
9193
}
9294
kotlinOptions {
9395
jvmTarget = JavaVersion.VERSION_17
96+
freeCompilerArgs = List.of("-Xstring-concat=inline")
9497
}
9598
buildFeatures {
9699
viewBinding true
97100
compose true
98101
buildConfig true
99102
}
100-
composeOptions {
101-
kotlinCompilerExtensionVersion = "$compose_compiler_version"
102-
}
103103
bundle {
104104
language {
105105
enableSplit = false
@@ -126,34 +126,24 @@ dependencies {
126126
implementation project(path: ':discussion')
127127
implementation project(path: ':whatsnew')
128128

129-
kapt "androidx.room:room-compiler:$room_version"
129+
ksp "androidx.room:room-compiler:$room_version"
130130

131131
implementation 'androidx.core:core-splashscreen:1.0.1'
132132

133-
// Segment Library
134-
implementation "com.segment.analytics.kotlin:android:1.14.2"
135-
// Segment's Firebase integration
136-
implementation 'com.segment.analytics.kotlin.destinations:firebase:1.5.2'
133+
api platform("com.google.firebase:firebase-bom:$firebase_version")
134+
api "com.google.firebase:firebase-messaging"
135+
137136
// Braze SDK Integration
138-
implementation "com.braze:braze-segment-kotlin:1.4.2"
139137
implementation "com.braze:android-sdk-ui:30.2.0"
140138

141-
// Firebase Cloud Messaging Integration for Braze
142-
implementation 'com.google.firebase:firebase-messaging-ktx:23.4.1'
143-
144-
// Branch SDK Integration
145-
implementation 'io.branch.sdk.android:library:5.9.0'
146-
implementation 'com.google.android.gms:play-services-ads-identifier:18.0.1'
147-
implementation "com.android.installreferrer:installreferrer:2.2"
139+
// Plugins
140+
implementation("com.github.openedx:openedx-app-firebase-analytics-android:1.0.0")
148141

149-
androidTestImplementation 'androidx.test.ext:junit:1.1.5'
150-
androidTestImplementation 'androidx.test.espresso:espresso-core:3.5.1'
151-
androidTestImplementation "androidx.compose.ui:ui-test-junit4:$compose_version"
152-
debugImplementation "androidx.compose.ui:ui-test-manifest:$compose_version"
142+
androidTestImplementation 'androidx.test.ext:junit:1.2.1'
143+
androidTestImplementation 'androidx.test.espresso:espresso-core:3.6.1'
153144
testImplementation "junit:junit:$junit_version"
154145
testImplementation "io.mockk:mockk:$mockk_version"
155146
testImplementation "io.mockk:mockk-android:$mockk_version"
156-
testImplementation "org.jetbrains.kotlinx:kotlinx-coroutines-test:$coroutines_version"
157147
testImplementation "androidx.arch.core:core-testing:$android_arch_version"
158148
}
159149

app/proguard-rules.pro

Lines changed: 28 additions & 70 deletions
Original file line numberDiff line numberDiff line change
@@ -1,66 +1,3 @@
1-
# Add project specific ProGuard rules here.
2-
# You can control the set of applied configuration files using the
3-
# proguardFiles setting in build.gradle.
4-
#
5-
# For more details, see
6-
# http://developer.android.com/guide/developing/tools/proguard.html
7-
8-
# If your project uses WebView with JS, uncomment the following
9-
# and specify the fully qualified class name to the JavaScript interface
10-
# class:
11-
#-keepclassmembers class fqcn.of.javascript.interface.for.webview {
12-
# public *;
13-
#}
14-
15-
# Uncomment this to preserve the line number information for
16-
# debugging stack traces.
17-
#-keepattributes SourceFile,LineNumberTable
18-
19-
# If you keep the line number information, uncomment this to
20-
# hide the original source file name.
21-
#-renamesourcefileattribute SourceFile
22-
23-
#====================/////Retrofit Rules\\\\\===============
24-
# Retrofit does reflection on generic parameters. InnerClasses is required to use Signature and
25-
# EnclosingMethod is required to use InnerClasses.
26-
-keepattributes Signature, InnerClasses, EnclosingMethod
27-
28-
# Retrofit does reflection on method and parameter annotations.
29-
-keepattributes RuntimeVisibleAnnotations, RuntimeVisibleParameterAnnotations
30-
31-
# Keep annotation default values (e.g., retrofit2.http.Field.encoded).
32-
-keepattributes AnnotationDefault
33-
34-
# Retain service method parameters when optimizing.
35-
-keepclassmembers,allowshrinking,allowobfuscation interface * {
36-
@retrofit2.http.* <methods>;
37-
}
38-
39-
# Ignore JSR 305 annotations for embedding nullability information.
40-
-dontwarn javax.annotation.**
41-
42-
# Guarded by a NoClassDefFoundError try/catch and only used when on the classpath.
43-
-dontwarn kotlin.Unit
44-
45-
# Top-level functions that can only be used by Kotlin.
46-
-dontwarn retrofit2.KotlinExtensions
47-
-dontwarn retrofit2.KotlinExtensions$*
48-
49-
# With R8 full mode, it sees no subtypes of Retrofit interfaces since they are created with a Proxy
50-
# and replaces all potential values with null. Explicitly keeping the interfaces prevents this.
51-
-if interface * { @retrofit2.http.* <methods>; }
52-
-keep,allowobfuscation interface <1>
53-
54-
# Keep generic signature of Call, Response (R8 full mode strips signatures from non-kept items).
55-
-keep,allowobfuscation,allowshrinking interface retrofit2.Call
56-
-keep,allowobfuscation,allowshrinking class retrofit2.Response
57-
58-
# With R8 full mode generic signatures are stripped for classes that are not
59-
# kept. Suspend functions are wrapped in continuations where the type argument
60-
# is used.
61-
-keep,allowobfuscation,allowshrinking class kotlin.coroutines.Continuation
62-
63-
#===============/////GSON RULES \\\\\\\============
641
##---------------Begin: proguard configuration for Gson ----------
652
# Gson uses generic type information stored in a class file when working with fields. Proguard
663
# removes such information by default, so configure it to keep all of it.
@@ -69,12 +6,8 @@
696
# For using GSON @Expose annotation
707
-keepattributes *Annotation*
718

72-
# Gson specific classes
73-
-dontwarn sun.misc.**
74-
#-keep class com.google.gson.stream.** { *; }
75-
769
# Application classes that will be serialized/deserialized over Gson
77-
-keep class org.openedx.*.data.model.** { <fields>; }
10+
-keepclassmembers class org.openedx.**.data.model.** { *; }
7811

7912
# Prevent proguard from stripping interface information from TypeAdapter, TypeAdapterFactory,
8013
# JsonSerializer, JsonDeserializer instances (so they can be used in @JsonAdapter)
@@ -85,13 +18,13 @@
8518

8619
# Prevent R8 from leaving Data object members always null
8720
-keepclassmembers,allowobfuscation class * {
21+
<init>();
8822
@com.google.gson.annotations.SerializedName <fields>;
8923
}
9024

9125
# Retain generic signatures of TypeToken and its subclasses with R8 version 3.0 and higher.
9226
-keep,allowobfuscation,allowshrinking class com.google.gson.reflect.TypeToken
9327
-keep,allowobfuscation,allowshrinking class * extends com.google.gson.reflect.TypeToken
94-
9528
##---------------End: proguard configuration for Gson ----------
9629

9730
-keepclassmembers class * extends java.lang.Enum {
@@ -108,4 +41,29 @@
10841
-dontwarn org.conscrypt.ConscryptHostnameVerifier
10942
-dontwarn org.openjsse.javax.net.ssl.SSLParameters
11043
-dontwarn org.openjsse.javax.net.ssl.SSLSocket
111-
-dontwarn org.openjsse.net.ssl.OpenJSSE
44+
-dontwarn org.openjsse.net.ssl.OpenJSSE
45+
-dontwarn com.google.crypto.tink.subtle.Ed25519Sign$KeyPair
46+
-dontwarn com.google.crypto.tink.subtle.Ed25519Sign
47+
-dontwarn com.google.crypto.tink.subtle.Ed25519Verify
48+
-dontwarn com.google.crypto.tink.subtle.X25519
49+
-dontwarn edu.umd.cs.findbugs.annotations.NonNull
50+
-dontwarn edu.umd.cs.findbugs.annotations.Nullable
51+
-dontwarn edu.umd.cs.findbugs.annotations.SuppressFBWarnings
52+
-dontwarn org.bouncycastle.asn1.ASN1Encodable
53+
-dontwarn org.bouncycastle.asn1.pkcs.PrivateKeyInfo
54+
-dontwarn org.bouncycastle.asn1.x509.AlgorithmIdentifier
55+
-dontwarn org.bouncycastle.asn1.x509.SubjectPublicKeyInfo
56+
-dontwarn org.bouncycastle.cert.X509CertificateHolder
57+
-dontwarn org.bouncycastle.cert.jcajce.JcaX509CertificateHolder
58+
-dontwarn org.bouncycastle.crypto.BlockCipher
59+
-dontwarn org.bouncycastle.crypto.CipherParameters
60+
-dontwarn org.bouncycastle.crypto.InvalidCipherTextException
61+
-dontwarn org.bouncycastle.crypto.engines.AESEngine
62+
-dontwarn org.bouncycastle.crypto.modes.GCMBlockCipher
63+
-dontwarn org.bouncycastle.crypto.params.AEADParameters
64+
-dontwarn org.bouncycastle.crypto.params.KeyParameter
65+
-dontwarn org.bouncycastle.jcajce.provider.BouncyCastleFipsProvider
66+
-dontwarn org.bouncycastle.jce.provider.BouncyCastleProvider
67+
-dontwarn org.bouncycastle.openssl.PEMKeyPair
68+
-dontwarn org.bouncycastle.openssl.PEMParser
69+
-dontwarn org.bouncycastle.openssl.jcajce.JcaPEMKeyConverter

0 commit comments

Comments
 (0)