[NEW] Add to F-Droid (#2171)

* create play and foss build

* update package.json to generate each build

* check1

* requested changes

* initial commit

* Update config.yml

* minor changes

* remove bugsnag from foss build

* remove bugsnag tasks from foss job

* fix stuck screen

* fixes

* update

* fix lint

* finalise 🚀

* requested changes

* share app for fdroid

* update

* use negation for builds

* requested change

* update share app

* fix issues due to latest sync

* add extra line

* fix lint

* update

* update

* fix bugsnag issue

* Update config.yml

* Fix store url

* Foss release instead of debug

* Add hold for foss

* Fix build

* requested changes

* update name and icons

* update

* fix

* Revert "Bump version to 4.11.0 (#2392)"

This reverts commit ea287980d9.

* finalise

Co-authored-by: Djorkaeff Alexandre <djorkaeff.unb@gmail.com>
Co-authored-by: Diego Mello <diegolmello@gmail.com>
This commit is contained in:
Govind Dixit 2020-08-24 17:54:10 +05:30 committed by GitHub
parent 15f174b47b
commit b80d8a0eca
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
54 changed files with 582 additions and 98 deletions

View File

@ -119,7 +119,7 @@ jobs:
- save_cache: *save-npm-cache-linux
# Android builds
android-build:
android-play-build:
<<: *defaults
docker:
- image: circleci/android:api-28-node
@ -178,12 +178,12 @@ jobs:
echo -e "export default { BUGSNAG_API_KEY: '$BUGSNAG_KEY' };" > ./config.js
- run:
name: Build Android App
name: Build Android Play App
command: |
if [[ $KEYSTORE ]]; then
bundle exec fastlane android release
bundle exec fastlane android playRelease
else
bundle exec fastlane android build
bundle exec fastlane android playBuild
fi
working_directory: android
@ -194,8 +194,8 @@ jobs:
yarn generate-source-maps-android upload \
--api-key=$BUGSNAG_KEY \
--app-version=$CIRCLE_BUILD_NUM \
--minifiedFile=android/app/build/generated/assets/react/release/app.bundle \
--source-map=android/app/build/generated/sourcemaps/react/release/app.bundle.map \
--minifiedFile=android/app/build/generated/assets/react/play/release/app.bundle \
--source-map=android/app/build/generated/sourcemaps/react/play/release/app.bundle.map \
--minified-url=app.bundle \
--upload-sources
fi
@ -213,6 +213,67 @@ jobs:
- android/fastlane/report.xml
- android/app/build/outputs
android-foss-build:
<<: *defaults
docker:
- image: circleci/android:api-28-node
environment:
JAVA_OPTS: '-Xms512m -Xmx2g'
GRADLE_OPTS: '-Xmx3g -Dorg.gradle.daemon=false -Dorg.gradle.jvmargs="-Xmx2g -XX:+HeapDumpOnOutOfMemoryError"'
TERM: dumb
<<: *bash-env
steps:
- checkout
- run: *install-node
- restore_cache: *restore-npm-cache-linux
- run: *install-npm-modules
- run: *update-fastlane-android
- restore_cache: *restore-gradle-cache
- run:
name: Configure Gradle
command: |
echo -e "" > ./gradle.properties
# echo -e "android.enableAapt2=false" >> ./gradle.properties
echo -e "android.useAndroidX=true" >> ./gradle.properties
echo -e "android.enableJetifier=true" >> ./gradle.properties
echo -e "FLIPPER_VERSION=0.51.0" >> ./gradle.properties
echo -e "VERSIONCODE=$CIRCLE_BUILD_NUM" >> ./gradle.properties
if [[ $KEYSTORE ]]; then
echo $KEYSTORE_BASE64 | base64 --decode > ./app/$KEYSTORE
echo -e "KEYSTORE=$KEYSTORE" >> ./gradle.properties
echo -e "KEYSTORE_PASSWORD=$KEYSTORE_PASSWORD" >> ./gradle.properties
echo -e "KEY_ALIAS=$KEY_ALIAS" >> ./gradle.properties
echo -e "KEY_PASSWORD=$KEYSTORE_PASSWORD" >> ./gradle.properties
fi
working_directory: android
- run:
name: Build Android Foss App
command: bundle exec fastlane android fossRelease
working_directory: android
- store_artifacts:
path: android/app/build/outputs
- save_cache: *save-npm-cache-linux
- save_cache: *save-gradle-cache
- persist_to_workspace:
root: .
paths:
- android/fastlane/report.xml
- android/app/build/outputs
android-google-play-beta:
<<: *defaults
docker:
@ -341,13 +402,20 @@ workflows:
requires:
- ios-hold-testflight
- android-build:
- android-play-build:
requires:
- lint-testunit
- android-hold-google-play-beta:
type: approval
requires:
- android-build
- android-play-build
- android-google-play-beta:
requires:
- android-hold-google-play-beta
- android-hold-foss-build:
type: approval
requires:
- lint-testunit
- android-foss-build:
requires:
- android-hold-foss-build

View File

@ -0,0 +1,3 @@
export default {
BuildConfigs: null
};

View File

@ -81,7 +81,6 @@ GEM
xcodeproj (>= 1.13.0, < 2.0.0)
xcpretty (~> 0.3.0)
xcpretty-travis-formatter (>= 0.0.3)
fastlane-plugin-appcenter (1.8.0)
gh_inspector (1.1.3)
google-api-client (0.36.4)
addressable (~> 2.5, >= 2.5.1)
@ -156,6 +155,7 @@ GEM
uber (0.1.0)
unf (0.1.4)
unf_ext
unf_ext (0.0.7.7)
unf_ext (0.0.7.7-x64-mingw32)
unicode-display_width (1.7.0)
word_wrap (1.0.0)
@ -171,11 +171,11 @@ GEM
xcpretty (~> 0.2, >= 0.0.7)
PLATFORMS
ruby
x64-mingw32
DEPENDENCIES
fastlane
fastlane-plugin-appcenter
BUNDLED WITH
2.0.2

View File

@ -1,8 +1,13 @@
def taskRequests = getGradle().getStartParameter().getTaskRequests().toString().toLowerCase()
def isPlay = !taskRequests.contains("foss")
apply plugin: "com.android.application"
apply plugin: 'com.google.gms.google-services'
apply plugin: 'com.google.firebase.crashlytics'
apply plugin: 'kotlin-android'
if (isPlay) {
apply plugin: 'com.google.firebase.crashlytics'
apply plugin: 'com.bugsnag.android.gradle'
}
import com.android.build.OutputFile
@ -141,7 +146,9 @@ android {
versionCode VERSIONCODE as Integer
versionName "4.11.0"
vectorDrawables.useSupportLibrary = true
if (isPlay) {
manifestPlaceholders = [BugsnagAPIKey: BugsnagAPIKey as String]
}
missingDimensionStrategy "RNNotifications.reactNativeVersion", "reactNative60" // See note below!
}
@ -168,11 +175,13 @@ android {
minifyEnabled enableProguardInReleaseBuilds
setProguardFiles([getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro'])
signingConfig signingConfigs.release
if (isPlay) {
firebaseCrashlytics {
nativeSymbolUploadEnabled true
}
}
}
}
// packagingOptions {
// pickFirst '**/armeabi-v7a/libc++_shared.so'
@ -182,6 +191,19 @@ android {
// }
// applicationVariants are e.g. debug, release
flavorDimensions "type"
productFlavors {
foss {
dimension = "type"
buildConfigField "boolean", "FDROID_BUILD", "true"
}
play {
dimension = "type"
buildConfigField "boolean", "FDROID_BUILD", "false"
}
}
applicationVariants.all { variant ->
variant.outputs.each { output ->
// For each separate APK per architecture, set a unique version code as described here:
@ -217,7 +239,7 @@ dependencies {
implementation fileTree(dir: "libs", include: ["*.jar"])
//noinspection GradleDynamicVersion
implementation "com.facebook.react:react-native:+" // From node_modules
implementation "com.google.firebase:firebase-messaging:18.0.0"
playImplementation "com.google.firebase:firebase-messaging:18.0.0"
implementation "androidx.swiperefreshlayout:swiperefreshlayout:1.0.0"
debugImplementation("com.facebook.flipper:flipper:${FLIPPER_VERSION}") {
exclude group:'com.facebook.fbjni'
@ -251,3 +273,6 @@ task copyDownloadableDepsToLibs(type: Copy) {
}
apply from: file("../../node_modules/@react-native-community/cli-platform-android/native_modules.gradle"); applyNativeModulesAppBuildGradle(project)
if (isPlay) {
apply plugin: 'com.google.gms.google-services'
}

View File

@ -0,0 +1,20 @@
package chat.rocket.reactnative;
import android.content.Context;
import android.os.Bundle;
import com.facebook.react.bridge.ReactApplicationContext;
import com.wix.reactnativenotifications.core.AppLaunchHelper;
import com.wix.reactnativenotifications.core.AppLifecycleFacade;
import com.wix.reactnativenotifications.core.JsIOHelper;
import com.wix.reactnativenotifications.core.notification.PushNotification;
public class CustomPushNotification extends PushNotification {
public static ReactApplicationContext reactApplicationContext;
public CustomPushNotification(Context context, Bundle bundle, AppLifecycleFacade appLifecycleFacade, AppLaunchHelper appLaunchHelper, JsIOHelper jsIoHelper) {
super(context, bundle, appLifecycleFacade, appLaunchHelper, jsIoHelper);
reactApplicationContext = new ReactApplicationContext(context);
}
}

View File

@ -0,0 +1,12 @@
package chat.rocket.reactnative;
import android.content.BroadcastReceiver;
import android.content.Context;
import android.content.Intent;
public class DismissNotification extends BroadcastReceiver {
@Override
public void onReceive(Context context, Intent intent) {
}
}

View File

@ -0,0 +1,13 @@
package chat.rocket.reactnative;
import android.content.BroadcastReceiver;
import android.content.Context;
import android.content.Intent;
public class ReplyBroadcast extends BroadcastReceiver {
@Override
public void onReceive(Context context, Intent intent) {
}
}

View File

@ -0,0 +1,9 @@
<vector xmlns:android="http://schemas.android.com/apk/res/android"
android:width="108dp"
android:height="108dp"
android:viewportWidth="512"
android:viewportHeight="512">
<path
android:pathData="M0,0h512v512h-512z"
android:fillColor="#ffffff"/>
</vector>

View File

@ -0,0 +1,19 @@
<vector xmlns:android="http://schemas.android.com/apk/res/android"
android:width="108dp"
android:height="108dp"
android:viewportWidth="512"
android:viewportHeight="512">
<group>
<clip-path android:pathData="M145,160h218v191.345h-218z M 0,0"/>
<path
android:pathData="M336.076,234.105L336.079,234.11C336.079,234.109 336.078,234.108 336.078,234.108C336.077,234.107 336.077,234.106 336.076,234.105ZM210.509,167.831C217.233,171.56 223.589,176.278 229.017,181.523C237.766,179.94 246.788,179.142 255.94,179.142C283.338,179.142 309.314,186.319 329.078,199.348C339.313,206.098 347.448,214.107 353.255,223.155C359.722,233.237 363,244.078 363,255.695C363,266.999 359.722,277.845 353.255,287.925C347.448,296.977 339.313,304.983 329.078,311.734C309.314,324.762 283.341,331.935 255.94,331.935C246.788,331.935 237.768,331.137 229.017,329.557C223.587,334.799 217.233,339.519 210.509,343.249C174.584,361.216 144.792,343.671 144.792,343.671C144.792,343.671 172.491,320.188 167.986,299.602C155.593,286.917 148.878,271.619 148.878,255.387C148.878,239.461 155.595,224.162 167.986,211.475C172.49,190.895 144.801,167.416 144.792,167.408C144.801,167.403 174.589,149.864 210.509,167.831Z"
android:fillColor="#DB2323"/>
<path
android:pathData="M189.04,291.26C176.71,281.543 169.31,269.108 169.31,255.555C169.31,224.456 208.278,199.245 256.348,199.245C304.418,199.245 343.386,224.456 343.386,255.555C343.386,286.655 304.418,311.866 256.348,311.866C244.501,311.866 233.206,310.335 222.912,307.561L215.386,314.82C211.296,318.765 206.503,322.334 201.507,325.147C194.884,328.399 188.345,330.174 181.875,330.715C182.24,330.052 182.576,329.379 182.937,328.715C190.478,314.822 192.512,302.337 189.04,291.26Z"
android:fillColor="#ffffff"
android:fillType="evenOdd"/>
<path
android:pathData="M214.708,268.127C207.625,268.127 201.883,262.413 201.883,255.364C201.883,248.316 207.625,242.602 214.708,242.602C221.791,242.602 227.533,248.316 227.533,255.364C227.533,262.413 221.791,268.127 214.708,268.127ZM255.998,268.127C248.915,268.127 243.173,262.413 243.173,255.364C243.173,248.316 248.915,242.602 255.998,242.602C263.08,242.602 268.822,248.316 268.822,255.364C268.822,262.413 263.08,268.127 255.998,268.127ZM297.287,268.127C290.204,268.127 284.462,262.413 284.462,255.364C284.462,248.316 290.204,242.602 297.287,242.602C304.37,242.602 310.112,248.316 310.112,255.364C310.112,262.413 304.37,268.127 297.287,268.127Z"
android:fillColor="#DB2323"/>
</group>
</vector>

View File

@ -0,0 +1,12 @@
<?xml version="1.0" encoding="utf-8"?>
<layer-list xmlns:android="http://schemas.android.com/apk/res/android" android:opacity="opaque">
<!-- the background color. it can be a system color or a custom one defined in colors.xml -->
<item android:drawable="@color/splashBackground" />
<item>
<!-- the app logo, centered horizontally and vertically -->
<bitmap
android:src="@drawable/splash"
android:gravity="center" />
</item>
</layer-list>

View File

@ -0,0 +1,5 @@
<?xml version="1.0" encoding="utf-8"?>
<adaptive-icon xmlns:android="http://schemas.android.com/apk/res/android">
<background android:drawable="@mipmap/ic_launcher_background"/>
<foreground android:drawable="@drawable/ic_launcher_foreground"/>
</adaptive-icon>

View File

@ -0,0 +1,5 @@
<?xml version="1.0" encoding="utf-8"?>
<adaptive-icon xmlns:android="http://schemas.android.com/apk/res/android">
<background android:drawable="@mipmap/ic_launcher_background"/>
<foreground android:drawable="@drawable/ic_launcher_foreground"/>
</adaptive-icon>

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.9 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 367 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 3.7 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.3 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 233 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.4 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.7 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 508 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 5.3 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 4.0 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 897 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 8.3 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 5.6 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.3 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 12 KiB

View File

@ -0,0 +1,4 @@
<?xml version="1.0" encoding="utf-8"?>
<resources>
<item name="splashBackground" type="color">#000000</item>
</resources>

View File

@ -0,0 +1,6 @@
<?xml version="1.0" encoding="utf-8"?>
<resources>
<color name="primary_dark">#660B0B0B</color>
<item name="splashBackground" type="color">#eeeff1</item>
<item name="notification_text" type="color">#CC3333</item>
</resources>

View File

@ -0,0 +1,4 @@
<resources>
<string name="app_name">Rocket.Chat</string>
<string name="share_extension_name">Rocket.Chat</string>
</resources>

View File

@ -0,0 +1,28 @@
<resources>
<style name="AppTheme" parent="Theme.AppCompat.Light.NoActionBar">
<item name="android:colorEdgeEffect">#aaaaaa</item>
<item name="colorPrimaryDark">@color/splashBackground</item>
<item name="android:navigationBarColor">@color/splashBackground</item>
</style>
<style name="Share.Window" parent="android:Theme">
<item name="android:windowEnterAnimation">@null</item>
<item name="android:windowExitAnimation">@null</item>
</style>
<style name="Theme.Share.Transparent" parent="android:Theme">
<item name="android:windowIsTranslucent">true</item>
<item name="android:windowBackground">@color/primary_dark</item>
<item name="android:windowContentOverlay">@null</item>
<item name="android:windowNoTitle">true</item>
<item name="android:windowIsFloating">true</item>
<item name="android:backgroundDimEnabled">true</item>
<item name="android:windowAnimationStyle">@style/Share.Window</item>
</style>
<style name="BootTheme" parent="AppTheme">
<item name="android:background">@drawable/launch_screen</item>
<item name="colorPrimaryDark">@color/splashBackground</item>
<item name="android:navigationBarColor">@color/splashBackground</item>
</style>
</resources>

View File

@ -67,9 +67,6 @@
<data android:mimeType="*/*" />
</intent-filter>
</activity>
<meta-data
android:name="com.bugsnag.android.API_KEY"
android:value="${BugsnagAPIKey}" />
</application>
</manifest>

View File

@ -49,8 +49,10 @@ public class MainApplication extends Application implements ReactApplication, IN
protected List<ReactPackage> getPackages() {
@SuppressWarnings("UnnecessaryLocalVariable")
List<ReactPackage> packages = new PackageList(this).getPackages();
packages.add(new KeyboardInputPackage(MainApplication.this));
if (!BuildConfig.FDROID_BUILD) {
packages.add(new RNNotificationsPackage(MainApplication.this));
}
packages.add(new KeyboardInputPackage(MainApplication.this));
packages.add(new WatermelonDBPackage());
packages.add(new RNCViewPagerPackage());
// packages.add(new ModuleRegistryAdapter(mModuleRegistryProvider));

View File

@ -0,0 +1,75 @@
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
package="chat.rocket.reactnative">
<uses-permission android:name="android.permission.INTERNET" />
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE"/>
<uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE" />
<application
android:name=".MainApplication"
android:allowBackup="true"
android:label="@string/app_name"
android:icon="@mipmap/ic_launcher"
android:theme="@style/AppTheme"
android:networkSecurityConfig="@xml/network_security_config"
>
<activity
android:name="com.zoontek.rnbootsplash.RNBootSplashActivity"
android:theme="@style/BootTheme">
<intent-filter>
<action android:name="android.intent.action.MAIN" />
<category android:name="android.intent.category.LAUNCHER" />
</intent-filter>
</activity>
<activity
android:name=".MainActivity"
android:label="@string/app_name"
android:configChanges="keyboard|keyboardHidden|orientation|screenSize|uiMode"
android:launchMode="singleTask"
android:windowSoftInputMode="adjustResize"
android:exported="true">
<intent-filter>
<action android:name="android.intent.action.DOWNLOAD_COMPLETE"/>
</intent-filter>
<intent-filter android:label="@string/app_name">
<action android:name="android.intent.action.VIEW" />
<category android:name="android.intent.category.DEFAULT" />
<category android:name="android.intent.category.BROWSABLE" />
<data android:scheme="https" android:host="go.rocket.chat" />
<data android:scheme="https" android:host="jitsi.rocket.chat" />
<data android:scheme="rocketchat" android:host="room" />
<data android:scheme="rocketchat" android:host="auth" />
<data android:scheme="rocketchat" android:host="jitsi.rocket.chat" />
</intent-filter>
</activity>
<activity android:name="com.facebook.react.devsupport.DevSettingsActivity" />
<receiver
android:name=".ReplyBroadcast"
android:enabled="true"
android:exported="false" />
<receiver
android:name=".DismissNotification"
android:enabled="true"
android:exported="false" >
</receiver>
<activity
android:noHistory="true"
android:name=".share.ShareActivity"
android:configChanges="keyboard|keyboardHidden|orientation|screenSize"
android:label="@string/share_extension_name"
android:screenOrientation="portrait"
android:theme="@style/AppTheme" >
<intent-filter>
<action android:name="android.intent.action.SEND" />
<action android:name="android.intent.action.SEND_MULTIPLE" />
<category android:name="android.intent.category.DEFAULT" />
<data android:mimeType="*/*" />
</intent-filter>
</activity>
<meta-data
android:name="com.bugsnag.android.API_KEY"
android:value="${BugsnagAPIKey}" />
</application>
</manifest>

View File

@ -0,0 +1,97 @@
package chat.rocket.reactnative;
import com.facebook.react.bridge.ReactApplicationContext;
import com.facebook.react.bridge.Callback;
import com.ammarahmed.mmkv.SecureKeystore;
import com.tencent.mmkv.MMKV;
import java.math.BigInteger;
class RNCallback implements Callback {
public void invoke(Object... args) {
}
}
class Utils {
static public String toHex(String arg) {
try {
return String.format("%x", new BigInteger(1, arg.getBytes("UTF-8")));
} catch (Exception e) {
return "";
}
}
}
public class Ejson {
String host;
String rid;
String type;
Sender sender;
String messageId;
String notificationType;
private MMKV mmkv;
private String TOKEN_KEY = "reactnativemeteor_usertoken-";
public Ejson() {
ReactApplicationContext reactApplicationContext = CustomPushNotification.reactApplicationContext;
// Start MMKV container
MMKV.initialize(reactApplicationContext);
SecureKeystore secureKeystore = new SecureKeystore(reactApplicationContext);
// https://github.com/ammarahm-ed/react-native-mmkv-storage/blob/master/src/loader.js#L31
String alias = Utils.toHex("com.MMKV.default");
// Retrieve container password
secureKeystore.getSecureKey(alias, new RNCallback() {
@Override
public void invoke(Object... args) {
String error = (String) args[0];
if (error == null) {
String password = (String) args[1];
mmkv = MMKV.mmkvWithID("default", MMKV.SINGLE_PROCESS_MODE, password);
}
}
});
}
public String getAvatarUri() {
if (type == null) {
return null;
}
return serverURL() + "/avatar/" + this.sender.username + "?rc_token=" + token() + "&rc_uid=" + userId();
}
public String token() {
String userId = userId();
if (mmkv != null && userId != null) {
return mmkv.decodeString(TOKEN_KEY.concat(userId));
}
return "";
}
public String userId() {
String serverURL = serverURL();
if (mmkv != null && serverURL != null) {
return mmkv.decodeString(TOKEN_KEY.concat(serverURL));
}
return "";
}
public String serverURL() {
String url = this.host;
if (url != null && url.endsWith("/")) {
url = url.substring(0, url.length() - 1);
}
return url;
}
public class Sender {
String username;
String _id;
}
}

View File

@ -17,15 +17,18 @@ buildscript {
url 'https://maven.fabric.io/public'
}
}
def taskRequests = getGradle().getStartParameter().getTaskRequests().toString().toLowerCase()
def isPlay = !taskRequests.contains("foss")
dependencies {
classpath 'com.android.tools.build:gradle:3.5.3'
if (isPlay) {
classpath 'com.google.gms:google-services:4.2.0'
classpath 'com.google.firebase:firebase-crashlytics-gradle:2.0.0'
classpath "org.jetbrains.kotlin:kotlin-gradle-plugin:$kotlin_version"
classpath 'com.bugsnag:bugsnag-android-gradle-plugin:4.+'
// NOTE: Do not place your application dependencies here; they belong
// in the individual module build.gradle files
}
classpath 'com.android.tools.build:gradle:3.5.3'
classpath "org.jetbrains.kotlin:kotlin-gradle-plugin:$kotlin_version"
}
}

View File

@ -16,14 +16,19 @@
default_platform(:android)
platform :android do
desc "Build App for development"
lane :build do
gradle(task: "assembleDebug")
desc "Play build for development"
lane :playBuild do
gradle(task: "assemblePlayDebug")
end
desc "Build App for release"
lane :release do
gradle(task: "bundleRelease")
desc "Foss build for release"
lane :fossRelease do
gradle(task: "assembleFossRelease")
end
desc "Play build for release"
lane :playRelease do
gradle(task: "bundlePlayRelease")
end
desc "Upload App to Play Store Internal"

View File

@ -16,19 +16,24 @@ or alternatively using `brew cask install fastlane`
# Available Actions
## Android
### android build
### android playBuild
```
fastlane android build
fastlane android playBuild
```
Build App for development
### android release
Play build for development
### android fossRelease
```
fastlane android release
fastlane android fossRelease
```
Build App for release
### android alpha
Foss build for release
### android playRelease
```
fastlane android alpha
fastlane android playRelease
```
Play build for release
### android playAlpha
```
fastlane android playAlpha
```
Upload App to Play store

View File

@ -0,0 +1,3 @@
import RNConfigReader from 'react-native-config-reader';
export const isFDroidBuild = RNConfigReader.FDROID_BUILD;

View File

@ -3,6 +3,7 @@ import { getBundleId, isIOS } from '../utils/deviceInfo';
const APP_STORE_ID = '1272915472';
export const PLAY_MARKET_LINK = `https://play.google.com/store/apps/details?id=${ getBundleId }`;
export const FDROID_MARKET_LINK = 'https://f-droid.org/en/packages/chat.rocket.android';
export const APP_STORE_LINK = `https://itunes.apple.com/app/id${ APP_STORE_ID }`;
export const LICENSE_LINK = 'https://github.com/RocketChat/Rocket.Chat.ReactNative/blob/develop/LICENSE';
export const STORE_REVIEW_LINK = isIOS ? `itms-apps://itunes.apple.com/app/id${ APP_STORE_ID }?action=write-review` : `market://details?id=${ getBundleId }`;

View File

@ -36,6 +36,7 @@ import Toast from './containers/Toast';
import InAppNotification from './containers/InAppNotification';
import { ActionSheetProvider } from './containers/ActionSheet';
import debounce from './utils/debounce';
import { isFDroidBuild } from './constants/environment';
RNScreens.enableScreens();
@ -64,7 +65,9 @@ export default class Root extends React.Component {
constructor(props) {
super(props);
this.init();
if (!isFDroidBuild) {
this.initCrashReport();
}
const { width, height, scale } = Dimensions.get('window');
this.state = {
theme: defaultTheme(),

View File

@ -1,8 +1,8 @@
import EJSON from 'ejson';
import PushNotification from './push';
import store from '../../lib/createStore';
import { deepLinkingOpen } from '../../actions/deepLinking';
import { isFDroidBuild } from '../../constants/environment';
export const onNotification = (notification) => {
if (notification) {
@ -38,8 +38,10 @@ export const onNotification = (notification) => {
export const getDeviceToken = () => PushNotification.getDeviceToken();
export const setBadgeCount = count => PushNotification.setBadgeCount(count);
export const initializePushNotifications = () => {
if (!isFDroidBuild) {
setBadgeCount();
return PushNotification.configure({
onNotification
});
}
};

View File

@ -1,10 +1,17 @@
import { Client } from 'bugsnag-react-native';
import analytics from '@react-native-firebase/analytics';
import crashlytics from '@react-native-firebase/crashlytics';
import firebaseAnalytics from '@react-native-firebase/analytics';
import { isFDroidBuild } from '../../constants/environment';
import config from '../../../config';
import events from './events';
const bugsnag = new Client(config.BUGSNAG_API_KEY);
const analytics = firebaseAnalytics || '';
let bugsnag = '';
let crashlytics;
if (!isFDroidBuild) {
const { Client } = require('bugsnag-react-native');
crashlytics = require('@react-native-firebase/crashlytics');
bugsnag = new Client(config.BUGSNAG_API_KEY);
}
export { analytics };
export const loggerConfig = bugsnag.config;
@ -21,20 +28,24 @@ export const logServerVersion = (serverVersion) => {
export const logEvent = (eventName, payload) => {
try {
if (!isFDroidBuild) {
analytics().logEvent(eventName, payload);
leaveBreadcrumb(eventName, payload);
}
} catch {
// Do nothing
}
};
export const setCurrentScreen = (currentScreen) => {
if (!isFDroidBuild) {
analytics().setCurrentScreen(currentScreen);
leaveBreadcrumb(currentScreen, { type: 'navigation' });
}
};
export default (e) => {
if (e instanceof Error && e.message !== 'Aborted' && !__DEV__) {
if (e instanceof Error && bugsnag && e.message !== 'Aborted' && !__DEV__) {
bugsnag.notify(e, (report) => {
report.metadata = {
details: {
@ -42,7 +53,9 @@ export default (e) => {
}
};
});
if (!isFDroidBuild) {
crashlytics().recordError(e);
}
} else {
console.log(e);
}

View File

@ -5,6 +5,7 @@ import { isIOS } from './deviceInfo';
import I18n from '../i18n';
import { showErrorAlert } from './info';
import { STORE_REVIEW_LINK } from '../constants/links';
import { isFDroidBuild } from '../constants/environment';
import { logEvent, events } from './log';
const store = isIOS ? 'App Store' : 'Play Store';
@ -87,6 +88,7 @@ class ReviewApp {
positiveEventCount = 0;
pushPositiveEvent = () => {
if (!isFDroidBuild) {
if (this.positiveEventCount >= numberOfPositiveEvent) {
return;
}
@ -96,5 +98,6 @@ class ReviewApp {
}
}
}
}
export const Review = new ReviewApp();

View File

@ -29,7 +29,9 @@ import styles from './styles';
import {
loggerConfig, analytics, logEvent, events
} from '../../utils/log';
import { PLAY_MARKET_LINK, APP_STORE_LINK, LICENSE_LINK } from '../../constants/links';
import {
PLAY_MARKET_LINK, FDROID_MARKET_LINK, APP_STORE_LINK, LICENSE_LINK
} from '../../constants/links';
import { withTheme } from '../../theme';
import SidebarView from '../SidebarView';
import { LISTENER } from '../../containers/Toast';
@ -37,6 +39,8 @@ import EventEmitter from '../../utils/events';
import { appStart as appStartAction, ROOT_LOADING } from '../../actions/app';
import { onReviewPress } from '../../utils/review';
import SafeAreaView from '../../containers/SafeAreaView';
import { isFDroidBuild } from '../../constants/environment';
const SectionSeparator = React.memo(({ theme }) => (
<View
@ -110,6 +114,7 @@ class SettingsView extends React.Component {
AsyncStorage.setItem(CRASH_REPORT_KEY, JSON.stringify(value));
const { toggleCrashReport } = this.props;
toggleCrashReport(value);
if (!isFDroidBuild) {
loggerConfig.autoNotify = value;
analytics().setAnalyticsCollectionEnabled(value);
if (value) {
@ -118,6 +123,7 @@ class SettingsView extends React.Component {
loggerConfig.registerBeforeSendCallback(() => false);
}
}
}
navigateToScreen = (screen) => {
logEvent(events[`SE_GO_${ screen.replace('View', '').toUpperCase() }`]);
@ -142,8 +148,16 @@ class SettingsView extends React.Component {
}
shareApp = () => {
logEvent(events.SE_SHARE_THIS_APP);
Share.share({ message: isAndroid ? PLAY_MARKET_LINK : APP_STORE_LINK });
let message;
if (isAndroid) {
message = PLAY_MARKET_LINK;
if (isFDroidBuild) {
message = FDROID_MARKET_LINK;
}
} else {
message = APP_STORE_LINK;
}
Share.share({ message });
}
copyServerVersion = () => {
@ -230,6 +244,8 @@ class SettingsView extends React.Component {
theme={theme}
/>
<Separator theme={theme} />
{!isFDroidBuild ? (
<>
<ListItem
title={I18n.t('Review_this_app')}
showActionIndicator
@ -238,6 +254,8 @@ class SettingsView extends React.Component {
right={this.renderDisclosure}
theme={theme}
/>
</>
) : null}
<Separator theme={theme} />
<ListItem
title={I18n.t('Share_this_app')}
@ -304,6 +322,20 @@ class SettingsView extends React.Component {
<SectionSeparator theme={theme} />
{this.showLivechat ? (
<>
<ListItem
title={I18n.t('Omnichannel')}
testID='settings-view-livechat'
right={() => this.renderLivechatSwitch()}
theme={theme}
/>
<SectionSeparator theme={theme} />
</>
) : null}
{!isFDroidBuild ? (
<>
<ListItem
title={I18n.t('Send_crash_report')}
testID='settings-view-crash-report'
@ -315,6 +347,8 @@ class SettingsView extends React.Component {
info={I18n.t('Crash_report_disclaimer')}
theme={theme}
/>
</>
) : null}
<Separator theme={theme} />
<ListItem

View File

@ -15,7 +15,9 @@
"precommit": "eslint . && jest",
"generate-source-maps-ios": "react-native bundle --platform ios --dev false --entry-file index.js --bundle-output ios-release.bundle --sourcemap-output ios-release.bundle.map",
"generate-source-maps-android": "bugsnag-sourcemaps",
"postinstall": "patch-package && jetify"
"postinstall": "patch-package && jetify",
"play": "npx react-native run-android --variant=playDebug",
"foss": "npx react-native run-android --variant=fossDebug"
},
"husky": {
"hooks": {
@ -69,6 +71,7 @@
"react-native-animatable": "^1.3.3",
"react-native-appearance": "0.3.4",
"react-native-background-timer": "2.2.0",
"react-native-config-reader": "^4.1.1",
"react-native-bootsplash": "2.2.5",
"react-native-console-time-polyfill": "^1.2.1",
"react-native-device-info": "5.6.2",

View File

@ -12731,6 +12731,11 @@ react-native-bootsplash@2.2.5:
jimp "0.14.0"
prompts "2.3.2"
react-native-config-reader@^4.1.1:
version "4.1.1"
resolved "https://registry.yarnpkg.com/react-native-config-reader/-/react-native-config-reader-4.1.1.tgz#478b69e32adcc2e9a14f6ef5fa2cbbe012b9a27e"
integrity sha512-f+I9DkmJS5UYE++vgSBIFG/TUxxCy9GSpcDFmVj7TDNW9w+Nozc98pdene/VYFzg9QRE7hejRoA6yV1Lv+QbCw==
react-native-console-time-polyfill@^1.2.1:
version "1.2.1"
resolved "https://registry.yarnpkg.com/react-native-console-time-polyfill/-/react-native-console-time-polyfill-1.2.1.tgz#3bf9a1d1d1ce3a05325fe1f2e5c4e5a1c25d910f"