Skip to content

Commit

Permalink
Merge pull request #399 from openedx/develop
Browse files Browse the repository at this point in the history
Develop to main. Release v2
  • Loading branch information
volodymyr-chekyrta authored Nov 11, 2024
2 parents 4d36310 + 88dfc54 commit 1fe8ee4
Show file tree
Hide file tree
Showing 479 changed files with 17,573 additions and 6,309 deletions.
2 changes: 1 addition & 1 deletion .github/workflows/unit_tests.yml
Original file line number Diff line number Diff line change
Expand Up @@ -42,7 +42,7 @@ jobs:
run: ./gradlew testProdDebugUnitTest $CI_GRADLE_ARG_PROPERTIES

- name: Upload reports
uses: actions/upload-artifact@v3
uses: actions/upload-artifact@v4
if: failure()
with:
name: failures
Expand Down
32 changes: 32 additions & 0 deletions .github/workflows/validate-english-strings.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,32 @@
name: Validate English strings.xml

on:
pull_request: { }
push:
branches: [ main, develop ]

jobs:
translation_strings:
name: Validate strings.xml
runs-on: ubuntu-latest

steps:
- name: Checkout
uses: actions/checkout@v4

- name: Use Python
uses: actions/setup-python@v5
with:
python-version: 3.11

- name: Install translations requirements
run: make translation_requirements

- name: Validate English plurals in strings.xml
run: make validate_english_plurals

- name: Test extract strings
run: |
make extract_translations
# Ensure the file is extracted
test -f i18n/src/main/res/values/strings.xml
3 changes: 3 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -16,3 +16,6 @@ local.properties
/.idea/
*.log
/config_settings.yaml
.venv/
i18n/
**/values-*/strings.xml
7 changes: 3 additions & 4 deletions Documentation/ConfigurationManagement.md
Original file line number Diff line number Diff line change
Expand Up @@ -49,7 +49,6 @@ TOKEN_TYPE: "JWT"

FIREBASE:
ENABLED: false
ANALYTICS_SOURCE: ''
CLOUD_MESSAGING_ENABLED: false
PROJECT_NUMBER: ''
PROJECT_ID: ''
Expand Down Expand Up @@ -82,14 +81,14 @@ android:
- **Facebook:** Sign in and Sign up via Facebook
- **Branch:** Deeplinks
- **Braze:** Cloud Messaging
- **SegmentIO:** Analytics

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

## Future Support
- To add config related to some other service, create a class, e.g. `ServiceNameConfig.kt`, to be able to populate related fields.
Expand Down
25 changes: 25 additions & 0 deletions Makefile
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
clean_translations_temp_directory:
rm -rf i18n/

translation_requirements:
pip3 install -r i18n_scripts/requirements.txt

pull_translations: clean_translations_temp_directory
atlas pull $(ATLAS_OPTIONS) translations/openedx-app-android/i18n:i18n
python3 i18n_scripts/translation.py --split --replace-underscore

extract_translations: clean_translations_temp_directory
python3 i18n_scripts/translation.py --combine

validate_english_plurals:
@if git grep 'quantity' -- '**/res/values/strings.xml' | grep -E 'quantity=.(zero|two|few|many)'; then \
echo ""; \
echo ""; \
echo "Error: Found invalid plurals in the files listed above."; \
echo " Please only use 'one' and 'other' in English strings.xml files,"; \
echo " otherwise Transifex fails to parse them."; \
echo ""; \
exit 1; \
else \
echo "strings.xml files are valid."; \
fi
42 changes: 42 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,48 @@ Modern vision of the mobile application for the Open edX platform from Raccoon G

6. Click the **Run** button.

## Translations

### Getting Translations for the App
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.

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:
```bash
make translation_requirements
```

Then, to get the latest translations for all languages use the following command:
```bash
make pull_translations
```
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`.

After this command is run the application can load the translations by changing the device (or the emulator) language in the settings.

### Using Custom Translations

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).

You can use custom translations on your fork of the openedx-translations repository by setting the following configuration parameters:

- `--revision` (default: `"main"`): Branch or git tag to pull translations from.
- `--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).

Arguments can be passed via the `ATLAS_OPTIONS` environment variable as shown below:
``` bash
make ATLAS_OPTIONS='--repository=<your-github-org>/<repository-name> --revision=<branch-name>' pull_translations
```
Additional arguments can be passed to `atlas pull`. Refer to the [atlas documentations ](https://github.com/openedx/openedx-atlas) for more information.

### How to Translate the App

Translations are managed in the [open-edx/openedx-translations](https://app.transifex.com/open-edx/openedx-translations/dashboard/) Transifex project.

To translate the app join the [Transifex project](https://app.transifex.com/open-edx/openedx-translations/dashboard/) and add your translations to the
[`openedx-app-android`](https://app.transifex.com/open-edx/openedx-translations/openedx-app-android/) resource.

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.

## API
This project targets on the latest Open edX release and rely on the relevant mobile APIs.

Expand Down
42 changes: 16 additions & 26 deletions app/build.gradle
Original file line number Diff line number Diff line change
@@ -1,13 +1,15 @@
def config = configHelper.fetchConfig()
def appId = config.getOrDefault("APPLICATION_ID", "org.openedx.app")
def platformName = config.getOrDefault("PLATFORM_NAME", "OpenEdx").toLowerCase()
def themeDirectory = config.getOrDefault("THEME_DIRECTORY", "openedx")
def firebaseConfig = config.get('FIREBASE')
def firebaseEnabled = firebaseConfig?.getOrDefault('ENABLED', false)

apply plugin: 'com.android.application'
apply plugin: 'org.jetbrains.kotlin.android'
apply plugin: 'kotlin-parcelize'
apply plugin: 'kotlin-kapt'
apply plugin: 'com.google.devtools.ksp'
apply plugin: 'org.jetbrains.kotlin.plugin.compose'

if (firebaseEnabled) {
apply plugin: 'com.google.gms.google-services'
apply plugin: 'com.google.firebase.crashlytics'
Expand Down Expand Up @@ -63,13 +65,13 @@ android {

sourceSets {
prod {
res.srcDirs = ["src/$platformName/res"]
res.srcDirs = ["src/$themeDirectory/res"]
}
develop {
res.srcDirs = ["src/$platformName/res"]
res.srcDirs = ["src/$themeDirectory/res"]
}
stage {
res.srcDirs = ["src/$platformName/res"]
res.srcDirs = ["src/$themeDirectory/res"]
}
}

Expand All @@ -91,15 +93,13 @@ android {
}
kotlinOptions {
jvmTarget = JavaVersion.VERSION_17
freeCompilerArgs = List.of("-Xstring-concat=inline")
}
buildFeatures {
viewBinding true
compose true
buildConfig true
}
composeOptions {
kotlinCompilerExtensionVersion = "$compose_compiler_version"
}
bundle {
language {
enableSplit = false
Expand All @@ -126,34 +126,24 @@ dependencies {
implementation project(path: ':discussion')
implementation project(path: ':whatsnew')

kapt "androidx.room:room-compiler:$room_version"
ksp "androidx.room:room-compiler:$room_version"

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

// Segment Library
implementation "com.segment.analytics.kotlin:android:1.14.2"
// Segment's Firebase integration
implementation 'com.segment.analytics.kotlin.destinations:firebase:1.5.2'
api platform("com.google.firebase:firebase-bom:$firebase_version")
api "com.google.firebase:firebase-messaging"

// Braze SDK Integration
implementation "com.braze:braze-segment-kotlin:1.4.2"
implementation "com.braze:android-sdk-ui:30.2.0"

// Firebase Cloud Messaging Integration for Braze
implementation 'com.google.firebase:firebase-messaging-ktx:23.4.1'

// Branch SDK Integration
implementation 'io.branch.sdk.android:library:5.9.0'
implementation 'com.google.android.gms:play-services-ads-identifier:18.0.1'
implementation "com.android.installreferrer:installreferrer:2.2"
// Plugins
implementation("com.github.openedx:openedx-app-firebase-analytics-android:1.0.0")

androidTestImplementation 'androidx.test.ext:junit:1.1.5'
androidTestImplementation 'androidx.test.espresso:espresso-core:3.5.1'
androidTestImplementation "androidx.compose.ui:ui-test-junit4:$compose_version"
debugImplementation "androidx.compose.ui:ui-test-manifest:$compose_version"
androidTestImplementation 'androidx.test.ext:junit:1.2.1'
androidTestImplementation 'androidx.test.espresso:espresso-core:3.6.1'
testImplementation "junit:junit:$junit_version"
testImplementation "io.mockk:mockk:$mockk_version"
testImplementation "io.mockk:mockk-android:$mockk_version"
testImplementation "org.jetbrains.kotlinx:kotlinx-coroutines-test:$coroutines_version"
testImplementation "androidx.arch.core:core-testing:$android_arch_version"
}

Expand Down
98 changes: 28 additions & 70 deletions app/proguard-rules.pro
Original file line number Diff line number Diff line change
@@ -1,66 +1,3 @@
# Add project specific ProGuard rules here.
# You can control the set of applied configuration files using the
# proguardFiles setting in build.gradle.
#
# For more details, see
# http://developer.android.com/guide/developing/tools/proguard.html

# If your project uses WebView with JS, uncomment the following
# and specify the fully qualified class name to the JavaScript interface
# class:
#-keepclassmembers class fqcn.of.javascript.interface.for.webview {
# public *;
#}

# Uncomment this to preserve the line number information for
# debugging stack traces.
#-keepattributes SourceFile,LineNumberTable

# If you keep the line number information, uncomment this to
# hide the original source file name.
#-renamesourcefileattribute SourceFile

#====================/////Retrofit Rules\\\\\===============
# Retrofit does reflection on generic parameters. InnerClasses is required to use Signature and
# EnclosingMethod is required to use InnerClasses.
-keepattributes Signature, InnerClasses, EnclosingMethod

# Retrofit does reflection on method and parameter annotations.
-keepattributes RuntimeVisibleAnnotations, RuntimeVisibleParameterAnnotations

# Keep annotation default values (e.g., retrofit2.http.Field.encoded).
-keepattributes AnnotationDefault

# Retain service method parameters when optimizing.
-keepclassmembers,allowshrinking,allowobfuscation interface * {
@retrofit2.http.* <methods>;
}

# Ignore JSR 305 annotations for embedding nullability information.
-dontwarn javax.annotation.**

# Guarded by a NoClassDefFoundError try/catch and only used when on the classpath.
-dontwarn kotlin.Unit

# Top-level functions that can only be used by Kotlin.
-dontwarn retrofit2.KotlinExtensions
-dontwarn retrofit2.KotlinExtensions$*

# With R8 full mode, it sees no subtypes of Retrofit interfaces since they are created with a Proxy
# and replaces all potential values with null. Explicitly keeping the interfaces prevents this.
-if interface * { @retrofit2.http.* <methods>; }
-keep,allowobfuscation interface <1>

# Keep generic signature of Call, Response (R8 full mode strips signatures from non-kept items).
-keep,allowobfuscation,allowshrinking interface retrofit2.Call
-keep,allowobfuscation,allowshrinking class retrofit2.Response

# With R8 full mode generic signatures are stripped for classes that are not
# kept. Suspend functions are wrapped in continuations where the type argument
# is used.
-keep,allowobfuscation,allowshrinking class kotlin.coroutines.Continuation

#===============/////GSON RULES \\\\\\\============
##---------------Begin: proguard configuration for Gson ----------
# Gson uses generic type information stored in a class file when working with fields. Proguard
# removes such information by default, so configure it to keep all of it.
Expand All @@ -69,12 +6,8 @@
# For using GSON @Expose annotation
-keepattributes *Annotation*

# Gson specific classes
-dontwarn sun.misc.**
#-keep class com.google.gson.stream.** { *; }

# Application classes that will be serialized/deserialized over Gson
-keep class org.openedx.*.data.model.** { <fields>; }
-keepclassmembers class org.openedx.**.data.model.** { *; }

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

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

# Retain generic signatures of TypeToken and its subclasses with R8 version 3.0 and higher.
-keep,allowobfuscation,allowshrinking class com.google.gson.reflect.TypeToken
-keep,allowobfuscation,allowshrinking class * extends com.google.gson.reflect.TypeToken

##---------------End: proguard configuration for Gson ----------

-keepclassmembers class * extends java.lang.Enum {
Expand All @@ -108,4 +41,29 @@
-dontwarn org.conscrypt.ConscryptHostnameVerifier
-dontwarn org.openjsse.javax.net.ssl.SSLParameters
-dontwarn org.openjsse.javax.net.ssl.SSLSocket
-dontwarn org.openjsse.net.ssl.OpenJSSE
-dontwarn org.openjsse.net.ssl.OpenJSSE
-dontwarn com.google.crypto.tink.subtle.Ed25519Sign$KeyPair
-dontwarn com.google.crypto.tink.subtle.Ed25519Sign
-dontwarn com.google.crypto.tink.subtle.Ed25519Verify
-dontwarn com.google.crypto.tink.subtle.X25519
-dontwarn edu.umd.cs.findbugs.annotations.NonNull
-dontwarn edu.umd.cs.findbugs.annotations.Nullable
-dontwarn edu.umd.cs.findbugs.annotations.SuppressFBWarnings
-dontwarn org.bouncycastle.asn1.ASN1Encodable
-dontwarn org.bouncycastle.asn1.pkcs.PrivateKeyInfo
-dontwarn org.bouncycastle.asn1.x509.AlgorithmIdentifier
-dontwarn org.bouncycastle.asn1.x509.SubjectPublicKeyInfo
-dontwarn org.bouncycastle.cert.X509CertificateHolder
-dontwarn org.bouncycastle.cert.jcajce.JcaX509CertificateHolder
-dontwarn org.bouncycastle.crypto.BlockCipher
-dontwarn org.bouncycastle.crypto.CipherParameters
-dontwarn org.bouncycastle.crypto.InvalidCipherTextException
-dontwarn org.bouncycastle.crypto.engines.AESEngine
-dontwarn org.bouncycastle.crypto.modes.GCMBlockCipher
-dontwarn org.bouncycastle.crypto.params.AEADParameters
-dontwarn org.bouncycastle.crypto.params.KeyParameter
-dontwarn org.bouncycastle.jcajce.provider.BouncyCastleFipsProvider
-dontwarn org.bouncycastle.jce.provider.BouncyCastleProvider
-dontwarn org.bouncycastle.openssl.PEMKeyPair
-dontwarn org.bouncycastle.openssl.PEMParser
-dontwarn org.bouncycastle.openssl.jcajce.JcaPEMKeyConverter
Loading

0 comments on commit 1fe8ee4

Please sign in to comment.