Replace all the usage of the button without component Use quo Fix tests List item in multiaccounts Use list items in contacts Fix welcome screen button Experiment long press Big list item Remove old bottom sheet Use bottom sheet Keycard Add error to list item Stickers panel button Images panel Fix z-index in profile Fix android crash Fix signing list item Try fixing test iOs gas sheet keyboard Disable root alert in e2e keycard signing sheet height Clean up bottom sheet events Replace flat list in profile Memorise the manual-close value for bottom sheet Mailserver QR scanner Fix e2e tests E2e fix 2 Fix e2e 3 Remove extra fn Reduce bridging time for animation Trick android layout Try hooks Fix profile missing ens-name Disable press on control in list-view allow disabling animations in list item Use simple list in wallet assets settings TBD - this screen should be rewritten from scratch. Now on every interaction the full list is re-rendered, also it makes the wallet main screen to re-render. Fix send sheet Handle long press in main thread UI fixes perf Update e2e fix missing user name in image long press Signed-off-by: Gheorghe Pinzaru <feross95@gmail.com>
256 lines
10 KiB
Java
256 lines
10 KiB
Java
package im.status.ethereum;
|
|
|
|
import android.content.Context;
|
|
import android.annotation.TargetApi;
|
|
import androidx.annotation.Nullable;
|
|
import android.app.AlertDialog;
|
|
import android.app.ActivityManager;
|
|
import android.content.DialogInterface;
|
|
import android.content.DialogInterface.OnCancelListener;
|
|
import android.content.DialogInterface.OnClickListener;
|
|
import android.content.pm.PackageManager;
|
|
import android.net.Uri;
|
|
import android.os.Build;
|
|
import android.os.Looper;
|
|
import android.preference.PreferenceManager;
|
|
import androidx.core.app.ActivityCompat;
|
|
import android.util.Log;
|
|
import android.view.WindowManager;
|
|
import android.content.Intent;
|
|
import android.content.SharedPreferences;
|
|
import android.content.res.Configuration;
|
|
import android.provider.Settings;
|
|
import android.os.Bundle;
|
|
import com.facebook.react.ReactActivityDelegate;
|
|
import com.facebook.react.ReactRootView;
|
|
import com.swmansion.gesturehandler.react.RNGestureHandlerEnabledRootView;
|
|
|
|
import com.facebook.react.ReactFragmentActivity;
|
|
import com.facebook.react.ReactActivity;
|
|
import com.facebook.react.modules.core.PermissionListener;
|
|
import org.devio.rn.splashscreen.SplashScreen;
|
|
|
|
import java.util.Properties;
|
|
import im.status.ethereum.module.StatusThreadPoolExecutor;
|
|
|
|
public class MainActivity extends ReactFragmentActivity
|
|
implements ActivityCompat.OnRequestPermissionsResultCallback{
|
|
|
|
|
|
@Nullable private PermissionListener mPermissionListener;
|
|
|
|
private static void registerUncaughtExceptionHandler(final Context context) {
|
|
final Thread.UncaughtExceptionHandler defaultUncaughtExceptionHandler = Thread.getDefaultUncaughtExceptionHandler();
|
|
Thread.setDefaultUncaughtExceptionHandler(new Thread.UncaughtExceptionHandler() {
|
|
@Override
|
|
public void uncaughtException(final Thread thread, final Throwable t) {
|
|
// High priority, so don't use StatusThreadPoolExecutor
|
|
new Thread() {
|
|
@Override
|
|
public void run() {
|
|
Looper.prepare();
|
|
|
|
new AlertDialog.Builder(context)
|
|
.setTitle("Error")
|
|
.setMessage(t.toString())
|
|
.setNegativeButton("Exit", new DialogInterface.OnClickListener() {
|
|
public void onClick(final DialogInterface dialog, final int id) {
|
|
dialog.dismiss();
|
|
defaultUncaughtExceptionHandler.uncaughtException(thread, t);
|
|
}
|
|
}).show();
|
|
|
|
Looper.loop();
|
|
}
|
|
}.start();
|
|
}
|
|
});
|
|
}
|
|
|
|
private ActivityManager getActivityManager() {
|
|
return (ActivityManager) this.getSystemService(ACTIVITY_SERVICE);
|
|
}
|
|
|
|
private ActivityManager.MemoryInfo getAvailableMemory(final ActivityManager activityManager) {
|
|
final ActivityManager.MemoryInfo memoryInfo = new ActivityManager.MemoryInfo();
|
|
activityManager.getMemoryInfo(memoryInfo);
|
|
return memoryInfo;
|
|
}
|
|
|
|
protected void configureStatus() {
|
|
// Required because of crazy APN settings redirecting localhost (found in GB)
|
|
Properties properties = System.getProperties();
|
|
properties.setProperty("http.nonProxyHosts", "localhost|127.0.0.1");
|
|
properties.setProperty("https.nonProxyHosts", "localhost|127.0.0.1");
|
|
}
|
|
|
|
private Intent createNotificationSettingsIntent() {
|
|
final Intent intent = new Intent();
|
|
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
|
|
intent.setAction(Settings.ACTION_APP_NOTIFICATION_SETTINGS);
|
|
intent.putExtra(Settings.EXTRA_APP_PACKAGE, getPackageName());
|
|
} else {
|
|
intent.setAction(Settings.ACTION_APPLICATION_DETAILS_SETTINGS);
|
|
intent.addCategory(Intent.CATEGORY_DEFAULT);
|
|
intent.setData(Uri.parse("package:" + getPackageName()));
|
|
}
|
|
return intent;
|
|
}
|
|
|
|
@Override
|
|
public void onNewIntent(final Intent intent) {
|
|
super.onNewIntent(intent);
|
|
if (intent.getDataString() != null && intent.getData().getScheme().startsWith("app-settings")) {
|
|
startActivity(createNotificationSettingsIntent());
|
|
}
|
|
}
|
|
|
|
@Override
|
|
protected void onCreate(Bundle savedInstanceState) {
|
|
|
|
switch (getResources().getConfiguration().uiMode & Configuration.UI_MODE_NIGHT_MASK) {
|
|
case Configuration.UI_MODE_NIGHT_YES:
|
|
setTheme(R.style.DarkTheme);
|
|
|
|
break;
|
|
case Configuration.UI_MODE_NIGHT_NO:
|
|
setTheme(R.style.LightTheme);
|
|
break;
|
|
default:
|
|
setTheme(R.style.LightTheme);
|
|
}
|
|
// Make sure we get an Alert for every uncaught exceptions
|
|
registerUncaughtExceptionHandler(MainActivity.this);
|
|
|
|
// Report memory details for this application
|
|
final ActivityManager activityManager = getActivityManager();
|
|
Log.v("RNBootstrap", "Available system memory "+getAvailableMemory(activityManager).availMem + ", maximum usable application memory " + activityManager.getLargeMemoryClass()+"M");
|
|
|
|
setSecureFlag();
|
|
SplashScreen.show(this, true);
|
|
// NOTE: Try to not restore the state https://github.com/software-mansion/react-native-screens/issues/17
|
|
super.onCreate(null);
|
|
|
|
if (!shouldShowRootedNotification()) {
|
|
configureStatus();
|
|
} else {
|
|
AlertDialog dialog = new AlertDialog.Builder(MainActivity.this)
|
|
.setMessage(getResources().getString(R.string.root_warning))
|
|
.setPositiveButton(getResources().getString(R.string.root_okay), new OnClickListener() {
|
|
@Override
|
|
public void onClick(DialogInterface dialog, int which) {
|
|
rejectRootedNotification();
|
|
dialog.dismiss();
|
|
configureStatus();
|
|
}
|
|
})
|
|
.setNegativeButton(getResources().getString(R.string.root_cancel), new OnClickListener() {
|
|
@Override
|
|
public void onClick(DialogInterface dialog, int which) {
|
|
dialog.dismiss();
|
|
MainActivity.this.finishAffinity();
|
|
}
|
|
})
|
|
.setOnCancelListener(new OnCancelListener() {
|
|
@Override
|
|
public void onCancel(DialogInterface dialog) {
|
|
dialog.dismiss();
|
|
MainActivity.this.finishAffinity();
|
|
}
|
|
})
|
|
.create();
|
|
|
|
dialog.show();
|
|
}
|
|
|
|
Runnable r = new Runnable() {
|
|
@Override
|
|
public void run() {
|
|
System.loadLibrary("status-logs");
|
|
}
|
|
};
|
|
|
|
StatusThreadPoolExecutor.getInstance().execute(r);
|
|
}
|
|
|
|
@Override
|
|
protected void onDestroy() {
|
|
super.onDestroy();
|
|
}
|
|
|
|
/**
|
|
* Returns the name of the main component registered from JavaScript.
|
|
* This is used to schedule rendering of the component.
|
|
*/
|
|
@Override
|
|
protected String getMainComponentName() {
|
|
return "StatusIm";
|
|
}
|
|
|
|
@Override
|
|
public void onConfigurationChanged(Configuration newConfig) {
|
|
super.onConfigurationChanged(newConfig);
|
|
Intent intent = new Intent("onConfigurationChanged");
|
|
intent.putExtra("newConfig", newConfig);
|
|
this.sendBroadcast(intent);
|
|
}
|
|
|
|
private static final String REJECTED_ROOTED_NOTIFICATION = "rejectedRootedNotification";
|
|
private static final Integer FREQUENCY_OF_REMINDER_IN_PERCENT = 5;
|
|
|
|
private boolean shouldShowRootedNotification() {
|
|
if (RootUtil.isDeviceRooted() && BuildConfig.ENABLE_ROOT_ALERT == "1") {
|
|
if (userRejectedRootedNotification()) {
|
|
return ((Math.random() * 100) < FREQUENCY_OF_REMINDER_IN_PERCENT);
|
|
} else return true;
|
|
} else {
|
|
return false;
|
|
}
|
|
}
|
|
|
|
private boolean userRejectedRootedNotification() {
|
|
SharedPreferences preferences = getPreferences(0);
|
|
return preferences.getBoolean(REJECTED_ROOTED_NOTIFICATION, false);
|
|
}
|
|
|
|
private void rejectRootedNotification() {
|
|
SharedPreferences preferences = getPreferences(0);
|
|
SharedPreferences.Editor editor = preferences.edit();
|
|
editor.putBoolean(REJECTED_ROOTED_NOTIFICATION, true);
|
|
editor.commit();
|
|
}
|
|
|
|
private void setSecureFlag() {
|
|
final SharedPreferences sharedPrefs = PreferenceManager.getDefaultSharedPreferences(this);
|
|
final boolean setSecure = sharedPrefs.getBoolean("BLANK_PREVIEW", false);
|
|
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.ICE_CREAM_SANDWICH && setSecure) {
|
|
getWindow().addFlags(WindowManager.LayoutParams.FLAG_SECURE);
|
|
} else {
|
|
getWindow().clearFlags(WindowManager.LayoutParams.FLAG_SECURE);
|
|
}
|
|
}
|
|
|
|
@TargetApi(Build.VERSION_CODES.M)
|
|
public void requestPermissions(String[] permissions, int requestCode, PermissionListener listener) {
|
|
mPermissionListener = listener;
|
|
requestPermissions(permissions, requestCode);
|
|
}
|
|
|
|
@Override
|
|
public void onRequestPermissionsResult(int requestCode, String[] permissions, int[] grantResults) {
|
|
if (mPermissionListener != null && mPermissionListener.onRequestPermissionsResult(requestCode, permissions, grantResults)) {
|
|
mPermissionListener = null;
|
|
}
|
|
}
|
|
|
|
@Override
|
|
protected ReactActivityDelegate createReactActivityDelegate() {
|
|
return new ReactActivityDelegate(this, getMainComponentName()) {
|
|
@Override
|
|
protected ReactRootView createRootView() {
|
|
return new RNGestureHandlerEnabledRootView(MainActivity.this);
|
|
}
|
|
};
|
|
}
|
|
}
|