[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>
|
@ -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
|
||||
|
|
|
@ -0,0 +1,3 @@
|
|||
export default {
|
||||
BuildConfigs: null
|
||||
};
|
|
@ -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
|
||||
|
|
|
@ -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'
|
||||
}
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
|
||||
}
|
|
@ -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) {
|
||||
|
||||
}
|
||||
}
|
|
@ -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) {
|
||||
|
||||
}
|
||||
}
|
|
@ -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>
|
|
@ -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>
|
|
@ -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>
|
|
@ -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>
|
|
@ -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>
|
After Width: | Height: | Size: 1.9 KiB |
After Width: | Height: | Size: 367 B |
After Width: | Height: | Size: 3.7 KiB |
After Width: | Height: | Size: 1.3 KiB |
After Width: | Height: | Size: 233 B |
After Width: | Height: | Size: 2.4 KiB |
After Width: | Height: | Size: 2.7 KiB |
After Width: | Height: | Size: 508 B |
After Width: | Height: | Size: 5.3 KiB |
After Width: | Height: | Size: 4.0 KiB |
After Width: | Height: | Size: 897 B |
After Width: | Height: | Size: 8.3 KiB |
After Width: | Height: | Size: 5.6 KiB |
After Width: | Height: | Size: 1.3 KiB |
After Width: | Height: | Size: 12 KiB |
|
@ -0,0 +1,4 @@
|
|||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<resources>
|
||||
<item name="splashBackground" type="color">#000000</item>
|
||||
</resources>
|
|
@ -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>
|
|
@ -0,0 +1,4 @@
|
|||
<resources>
|
||||
<string name="app_name">Rocket.Chat</string>
|
||||
<string name="share_extension_name">Rocket.Chat</string>
|
||||
</resources>
|
|
@ -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>
|
|
@ -67,9 +67,6 @@
|
|||
<data android:mimeType="*/*" />
|
||||
</intent-filter>
|
||||
</activity>
|
||||
<meta-data
|
||||
android:name="com.bugsnag.android.API_KEY"
|
||||
android:value="${BugsnagAPIKey}" />
|
||||
</application>
|
||||
|
||||
</manifest>
|
||||
|
|
|
@ -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));
|
||||
|
|
|
@ -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>
|
|
@ -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;
|
||||
}
|
||||
}
|
|
@ -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"
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -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"
|
||||
|
|
|
@ -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
|
||||
|
||||
|
|
|
@ -0,0 +1,3 @@
|
|||
import RNConfigReader from 'react-native-config-reader';
|
||||
|
||||
export const isFDroidBuild = RNConfigReader.FDROID_BUILD;
|
|
@ -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 }`;
|
||||
|
|
|
@ -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(),
|
||||
|
|
|
@ -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
|
||||
});
|
||||
}
|
||||
};
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
|
|
|
@ -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();
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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",
|
||||
|
|
|
@ -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"
|
||||
|
|