Runtime permissions (#762)
This commit is contained in:
parent
d24e6d5a19
commit
504e3493ef
|
@ -106,7 +106,7 @@ android {
|
|||
defaultConfig {
|
||||
applicationId "im.status.ethereum"
|
||||
minSdkVersion 18
|
||||
targetSdkVersion 22
|
||||
targetSdkVersion 23
|
||||
versionCode getVersionCode()
|
||||
versionName getVersionName()
|
||||
ndk {
|
||||
|
|
|
@ -1,12 +1,31 @@
|
|||
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
xmlns:tools="http://schemas.android.com/tools"
|
||||
package="im.status.ethereum">
|
||||
|
||||
<!-- non-dangerous permissions -->
|
||||
<uses-permission android:name="android.permission.INTERNET"/>
|
||||
<uses-permission android:name="android.permission.READ_CONTACTS"/>
|
||||
<uses-permission android:name="android.permission.WRITE_CONTACTS"/>
|
||||
<uses-permission android:name="android.permission.READ_PROFILE"/>
|
||||
<uses-permission android:name="android.permission.ACCESS_FINE_LOCATION"/>
|
||||
<uses-permission android:name="android.permission.NFC"/>
|
||||
<uses-permission android:name="android.permission.ACCESS_NETWORK_STATE" />
|
||||
<uses-permission android:name="android.permission.ACCESS_WIFI_STATE" />
|
||||
<uses-permission android:name="android.permission.READ_PROFILE" />
|
||||
|
||||
<!-- dangerous permissions -->
|
||||
<uses-permission android:name="android.permission.CAMERA"/>
|
||||
<uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE"/>
|
||||
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE"/>
|
||||
<uses-permission android:name="android.permission.READ_CONTACTS"/>
|
||||
<uses-permission android:name="android.permission.RECEIVE_SMS"/>
|
||||
|
||||
<!-- these permissions should be removed -->
|
||||
<!-- react-native-orientation adds an unnecessary permission; here we remove it -->
|
||||
<uses-permission android:name="android.permission.BLUETOOTH" tools:node="remove"/>
|
||||
<!-- react-native-contacts -->
|
||||
<uses-permission android:name="android.permission.WRITE_CONTACTS" tools:node="remove"/>
|
||||
<!-- react-native-camera -->
|
||||
<uses-permission android:name="android.permission.RECORD_AUDIO" tools:node="remove"/>
|
||||
<uses-permission android:name="android.permission.RECORD_VIDEO" tools:node="remove"/>
|
||||
<!-- React Native unnecessary permissions (https://github.com/facebook/react-native/issues/5886) -->
|
||||
<uses-permission android:name="android.permission.READ_PHONE_STATE" tools:node="remove"/>
|
||||
|
||||
<application
|
||||
android:allowBackup="true"
|
||||
|
|
|
@ -0,0 +1,7 @@
|
|||
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
xmlns:tools="http://schemas.android.com/tools">
|
||||
|
||||
<!-- These are added by React Native for debug mode, but actually aren't needed in release mode -->
|
||||
<uses-permission tools:node="remove" android:name="android.permission.SYSTEM_ALERT_WINDOW"/>
|
||||
|
||||
</manifest>
|
|
@ -705,6 +705,14 @@ status.response({
|
|||
}
|
||||
});
|
||||
|
||||
status.response({
|
||||
name: "grant-permissions",
|
||||
color: "#7099e6",
|
||||
description: "Grant permissions",
|
||||
icon: "lock_white",
|
||||
executeImmediately: true
|
||||
});
|
||||
|
||||
status.addListener("on-message-input-change", function (params, context) {
|
||||
return jsSuggestions({code: params.message}, context);
|
||||
});
|
||||
|
|
|
@ -53,7 +53,6 @@
|
|||
9EE89E271E03FCB7007D3C25 /* libSplashScreen.a in Frameworks */ = {isa = PBXBuildFile; fileRef = B24FC7F21DE718EF00D694FF /* libSplashScreen.a */; };
|
||||
9EE89E2D1E03FD9F007D3C25 /* libimageCropPicker.a in Frameworks */ = {isa = PBXBuildFile; fileRef = 20A5C9531D927137002C4965 /* libimageCropPicker.a */; };
|
||||
A6AF670051B842249D520C7B /* Foundation.ttf in Resources */ = {isa = PBXBuildFile; fileRef = 7ED174A34D7D42358313368B /* Foundation.ttf */; };
|
||||
AD5063BC2B2A4C52ACE0A0B4 /* libUdpSockets.a in Frameworks */ = {isa = PBXBuildFile; fileRef = A96279092BEC4C4B93914F48 /* libUdpSockets.a */; };
|
||||
AE97D4B08C9F4821B8E9C50B /* Ionicons.ttf in Resources */ = {isa = PBXBuildFile; fileRef = 359B076A658B4FBAB5128B03 /* Ionicons.ttf */; };
|
||||
B23B48FF1E76917B006D4535 /* RobotoMono-Medium.ttf in Resources */ = {isa = PBXBuildFile; fileRef = B23B48FE1E76917B006D4535 /* RobotoMono-Medium.ttf */; };
|
||||
B24FC7FD1DE7195700D694FF /* Social.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = B24FC7FC1DE7195700D694FF /* Social.framework */; };
|
||||
|
@ -143,13 +142,6 @@
|
|||
remoteGlobalIDString = 134814201AA4EA6300B7C361;
|
||||
remoteInfo = TcpSockets;
|
||||
};
|
||||
201067711D477F5E00FA83B6 /* PBXContainerItemProxy */ = {
|
||||
isa = PBXContainerItemProxy;
|
||||
containerPortal = 2F0276A9E90843E996A0E762 /* UdpSockets.xcodeproj */;
|
||||
proxyType = 2;
|
||||
remoteGlobalIDString = 134814201AA4EA6300B7C361;
|
||||
remoteInfo = UdpSockets;
|
||||
};
|
||||
201067C31D4789F700FA83B6 /* PBXContainerItemProxy */ = {
|
||||
isa = PBXContainerItemProxy;
|
||||
containerPortal = 439B6B4B407A4E2AACAFE5BE /* RCTStatus.xcodeproj */;
|
||||
|
@ -452,7 +444,6 @@
|
|||
20B6B6861D92C42600CC5C6A /* QBImagePicker.framework */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; path = QBImagePicker.framework; sourceTree = BUILT_PRODUCTS_DIR; };
|
||||
2756305FAFF144C4A6B0A039 /* Zocial.ttf */ = {isa = PBXFileReference; explicitFileType = undefined; fileEncoding = 9; includeInIndex = 0; lastKnownFileType = unknown; name = Zocial.ttf; path = "../node_modules/react-native-vector-icons/Fonts/Zocial.ttf"; sourceTree = "<group>"; };
|
||||
2BEE3436791D42248F853999 /* libRCTImageResizer.a */ = {isa = PBXFileReference; explicitFileType = undefined; fileEncoding = 9; includeInIndex = 0; lastKnownFileType = archive.ar; path = libRCTImageResizer.a; sourceTree = "<group>"; };
|
||||
2F0276A9E90843E996A0E762 /* UdpSockets.xcodeproj */ = {isa = PBXFileReference; explicitFileType = undefined; fileEncoding = 9; includeInIndex = 0; lastKnownFileType = "wrapper.pb-project"; name = UdpSockets.xcodeproj; path = "../node_modules/react-native-udp/ios/UdpSockets.xcodeproj"; sourceTree = "<group>"; };
|
||||
305F194186D848FDB07AF34C /* RNFS.xcodeproj */ = {isa = PBXFileReference; explicitFileType = undefined; fileEncoding = 9; includeInIndex = 0; lastKnownFileType = "wrapper.pb-project"; name = RNFS.xcodeproj; path = "../node_modules/react-native-fs/RNFS.xcodeproj"; sourceTree = "<group>"; };
|
||||
359B076A658B4FBAB5128B03 /* Ionicons.ttf */ = {isa = PBXFileReference; explicitFileType = undefined; fileEncoding = 9; includeInIndex = 0; lastKnownFileType = unknown; name = Ionicons.ttf; path = "../node_modules/react-native-vector-icons/Fonts/Ionicons.ttf"; sourceTree = "<group>"; };
|
||||
38A44830EC5708E89387F641 /* Pods-StatusIm.release.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-StatusIm.release.xcconfig"; path = "Pods/Target Support Files/Pods-StatusIm/Pods-StatusIm.release.xcconfig"; sourceTree = "<group>"; };
|
||||
|
@ -486,7 +477,6 @@
|
|||
9ED2F45D1D9D52DD00B36508 /* SF-UI-Text-Regular.otf */ = {isa = PBXFileReference; lastKnownFileType = file; path = "SF-UI-Text-Regular.otf"; sourceTree = "<group>"; };
|
||||
9ED2F4601D9D577B00B36508 /* SF-UI-Text-Bold.otf */ = {isa = PBXFileReference; lastKnownFileType = file; path = "SF-UI-Text-Bold.otf"; sourceTree = "<group>"; };
|
||||
9F1854E6D9654226B1FC8308 /* RCTCamera.xcodeproj */ = {isa = PBXFileReference; explicitFileType = undefined; fileEncoding = 9; includeInIndex = 0; lastKnownFileType = "wrapper.pb-project"; name = RCTCamera.xcodeproj; path = "../node_modules/react-native-camera/ios/RCTCamera.xcodeproj"; sourceTree = "<group>"; };
|
||||
A96279092BEC4C4B93914F48 /* libUdpSockets.a */ = {isa = PBXFileReference; explicitFileType = undefined; fileEncoding = 9; includeInIndex = 0; lastKnownFileType = archive.ar; path = libUdpSockets.a; sourceTree = "<group>"; };
|
||||
ACA66A8F16CD2FE21F38738B /* Pods-StatusIm.debug.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-StatusIm.debug.xcconfig"; path = "Pods/Target Support Files/Pods-StatusIm/Pods-StatusIm.debug.xcconfig"; sourceTree = "<group>"; };
|
||||
B23B48FE1E76917B006D4535 /* RobotoMono-Medium.ttf */ = {isa = PBXFileReference; lastKnownFileType = file; path = "RobotoMono-Medium.ttf"; sourceTree = "<group>"; };
|
||||
B24FC7FC1DE7195700D694FF /* Social.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = Social.framework; path = System/Library/Frameworks/Social.framework; sourceTree = SDKROOT; };
|
||||
|
@ -554,7 +544,6 @@
|
|||
25DC9C9DC25846BD8D084888 /* libc++.tbd in Frameworks */,
|
||||
BA68A2377A20496EA737000D /* libz.tbd in Frameworks */,
|
||||
3E15DFEC1F6F4D7CAE088F49 /* libTcpSockets.a in Frameworks */,
|
||||
AD5063BC2B2A4C52ACE0A0B4 /* libUdpSockets.a in Frameworks */,
|
||||
E0AD9E8F495A4907B65104BF /* libRCTImageResizer.a in Frameworks */,
|
||||
5F8585D411844E5981B94F40 /* libRNInstabug.a in Frameworks */,
|
||||
8E55E6877F950B81C8D711C5 /* libPods-StatusIm.a in Frameworks */,
|
||||
|
@ -695,14 +684,6 @@
|
|||
name = Products;
|
||||
sourceTree = "<group>";
|
||||
};
|
||||
2010676E1D477F5E00FA83B6 /* Products */ = {
|
||||
isa = PBXGroup;
|
||||
children = (
|
||||
201067721D477F5E00FA83B6 /* libUdpSockets.a */,
|
||||
);
|
||||
name = Products;
|
||||
sourceTree = "<group>";
|
||||
};
|
||||
201067BA1D4789F700FA83B6 /* Products */ = {
|
||||
isa = PBXGroup;
|
||||
children = (
|
||||
|
@ -857,7 +838,6 @@
|
|||
8AE71EE8751F4652B13BFE83 /* RNVectorIcons.xcodeproj */,
|
||||
F090E261B9854867A728CE4F /* RealmReact.xcodeproj */,
|
||||
38E1A2C8D0734EE99E2B16CE /* TcpSockets.xcodeproj */,
|
||||
2F0276A9E90843E996A0E762 /* UdpSockets.xcodeproj */,
|
||||
439B6B4B407A4E2AACAFE5BE /* RCTStatus.xcodeproj */,
|
||||
5E5A7625B76441D984EA8C0D /* RCTImageResizer.xcodeproj */,
|
||||
F3548417D8DA4362B6796A54 /* RNInstabug.xcodeproj */,
|
||||
|
@ -1181,10 +1161,6 @@
|
|||
ProductGroup = 201067551D477F5E00FA83B6 /* Products */;
|
||||
ProjectRef = 38E1A2C8D0734EE99E2B16CE /* TcpSockets.xcodeproj */;
|
||||
},
|
||||
{
|
||||
ProductGroup = 2010676E1D477F5E00FA83B6 /* Products */;
|
||||
ProjectRef = 2F0276A9E90843E996A0E762 /* UdpSockets.xcodeproj */;
|
||||
},
|
||||
);
|
||||
projectRoot = "";
|
||||
targets = (
|
||||
|
@ -1258,13 +1234,6 @@
|
|||
remoteRef = 2010676C1D477F5E00FA83B6 /* PBXContainerItemProxy */;
|
||||
sourceTree = BUILT_PRODUCTS_DIR;
|
||||
};
|
||||
201067721D477F5E00FA83B6 /* libUdpSockets.a */ = {
|
||||
isa = PBXReferenceProxy;
|
||||
fileType = archive.ar;
|
||||
path = libUdpSockets.a;
|
||||
remoteRef = 201067711D477F5E00FA83B6 /* PBXContainerItemProxy */;
|
||||
sourceTree = BUILT_PRODUCTS_DIR;
|
||||
};
|
||||
201067C41D4789F700FA83B6 /* libRCTStatus.a */ = {
|
||||
isa = PBXReferenceProxy;
|
||||
fileType = archive.ar;
|
||||
|
@ -1813,7 +1782,6 @@
|
|||
"$(SRCROOT)/../node_modules/react-native-vector-icons/RNVectorIconsManager",
|
||||
"$(SRCROOT)/../node_modules/realm/src/**",
|
||||
"$(SRCROOT)/../node_modules/react-native-tcp/ios/**",
|
||||
"$(SRCROOT)/../node_modules/react-native-udp/ios/**",
|
||||
"$(SRCROOT)/../modules/react-native-status/ios/RCTStatus/**",
|
||||
"$(SRCROOT)/../node_modules/react-native-image-resizer/ios/RCTImageResizer",
|
||||
"$(SRCROOT)/../node_modules/instabug-reactnative/ios/RNInstabug",
|
||||
|
@ -1863,7 +1831,6 @@
|
|||
"$(SRCROOT)/../node_modules/react-native-vector-icons/RNVectorIconsManager",
|
||||
"$(SRCROOT)/../node_modules/realm/src/**",
|
||||
"$(SRCROOT)/../node_modules/react-native-tcp/ios/**",
|
||||
"$(SRCROOT)/../node_modules/react-native-udp/ios/**",
|
||||
"$(SRCROOT)/../modules/react-native-status/ios/RCTStatus/**",
|
||||
"$(SRCROOT)/../node_modules/react-native-image-resizer/ios/RCTImageResizer",
|
||||
"$(SRCROOT)/../node_modules/instabug-reactnative/ios/RNInstabug",
|
||||
|
@ -1934,7 +1901,6 @@
|
|||
"$(SRCROOT)/../node_modules/react-native-vector-icons/RNVectorIconsManager",
|
||||
"$(SRCROOT)/../node_modules/realm/src/**",
|
||||
"$(SRCROOT)/../node_modules/react-native-tcp/ios/**",
|
||||
"$(SRCROOT)/../node_modules/react-native-udp/ios/**",
|
||||
"$(SRCROOT)/../modules/react-native-status/ios/RCTStatus/**",
|
||||
"$(SRCROOT)/../modules/react-native-status/ios/RCTStatus/**",
|
||||
"$(SRCROOT)/../node_modules/react-native-image-resizer/ios/RCTImageResizer",
|
||||
|
@ -1993,7 +1959,6 @@
|
|||
"$(SRCROOT)/../node_modules/react-native-vector-icons/RNVectorIconsManager",
|
||||
"$(SRCROOT)/../node_modules/realm/src/**",
|
||||
"$(SRCROOT)/../node_modules/react-native-tcp/ios/**",
|
||||
"$(SRCROOT)/../node_modules/react-native-udp/ios/**",
|
||||
"$(SRCROOT)/../modules/react-native-status/ios/RCTStatus/**",
|
||||
"$(SRCROOT)/../modules/react-native-status/ios/RCTStatus/**",
|
||||
"$(SRCROOT)/../node_modules/react-native-image-resizer/ios/RCTImageResizer",
|
||||
|
|
|
@ -14,6 +14,10 @@ import com.github.status_im.status_go.cmd.Statusgo;
|
|||
|
||||
import java.io.File;
|
||||
import java.io.IOException;
|
||||
import java.io.InputStream;
|
||||
import java.io.FileInputStream;
|
||||
import java.io.OutputStream;
|
||||
import java.io.FileOutputStream;
|
||||
import java.util.HashMap;
|
||||
import java.util.UUID;
|
||||
import java.util.concurrent.ExecutorService;
|
||||
|
@ -103,10 +107,7 @@ class StatusModule extends ReactContextBaseJavaModule implements LifecycleEventL
|
|||
|
||||
Activity currentActivity = getCurrentActivity();
|
||||
|
||||
File extStore = Environment.getExternalStorageDirectory();
|
||||
String dataFolder = extStore.exists() ?
|
||||
extStore.getAbsolutePath() + "/ethereum/testnet" :
|
||||
currentActivity.getApplicationInfo().dataDir + "/ethereum/testnet";
|
||||
String dataFolder = currentActivity.getApplicationInfo().dataDir + "/ethereum/testnet";
|
||||
Log.d(TAG, "Starting Geth node in folder: " + dataFolder);
|
||||
|
||||
try {
|
||||
|
@ -158,6 +159,86 @@ class StatusModule extends ReactContextBaseJavaModule implements LifecycleEventL
|
|||
Log.d(TAG, "Geth node started");
|
||||
}
|
||||
|
||||
private String getOldExternalDir() {
|
||||
File extStore = Environment.getExternalStorageDirectory();
|
||||
return extStore.exists() ? extStore.getAbsolutePath() + "/ethereum/testnet" : getNewInternalDir();
|
||||
}
|
||||
|
||||
private String getNewInternalDir() {
|
||||
Activity currentActivity = getCurrentActivity();
|
||||
return currentActivity.getApplicationInfo().dataDir + "/ethereum/testnet";
|
||||
}
|
||||
|
||||
private void deleteDirectory(File folder) {
|
||||
File[] files = folder.listFiles();
|
||||
if (files != null) {
|
||||
for (File f : files) {
|
||||
if (f.isDirectory()) {
|
||||
deleteDirectory(f);
|
||||
} else {
|
||||
f.delete();
|
||||
}
|
||||
}
|
||||
}
|
||||
folder.delete();
|
||||
}
|
||||
|
||||
private void copyDirectory(File sourceLocation, File targetLocation) throws IOException {
|
||||
if (sourceLocation.isDirectory()) {
|
||||
if (!targetLocation.exists() && !targetLocation.mkdirs()) {
|
||||
throw new IOException("Cannot create dir " + targetLocation.getAbsolutePath());
|
||||
}
|
||||
|
||||
String[] children = sourceLocation.list();
|
||||
for (int i = 0; i < children.length; i++) {
|
||||
copyDirectory(new File(sourceLocation, children[i]), new File(targetLocation, children[i]));
|
||||
}
|
||||
} else {
|
||||
File directory = targetLocation.getParentFile();
|
||||
if (directory != null && !directory.exists() && !directory.mkdirs()) {
|
||||
throw new IOException("Cannot create dir " + directory.getAbsolutePath());
|
||||
}
|
||||
|
||||
InputStream in = new FileInputStream(sourceLocation);
|
||||
OutputStream out = new FileOutputStream(targetLocation);
|
||||
|
||||
byte[] buf = new byte[1024];
|
||||
int len;
|
||||
while ((len = in.read(buf)) > 0) {
|
||||
out.write(buf, 0, len);
|
||||
}
|
||||
in.close();
|
||||
out.close();
|
||||
}
|
||||
}
|
||||
|
||||
@ReactMethod
|
||||
public void shouldMoveToInternalStorage(Callback callback) {
|
||||
String oldDir = getOldExternalDir();
|
||||
String newDir = getNewInternalDir();
|
||||
|
||||
File oldDirFile = new File(oldDir);
|
||||
File newDirFile = new File(newDir);
|
||||
|
||||
callback.invoke(oldDirFile.exists() && !newDirFile.exists());
|
||||
}
|
||||
|
||||
@ReactMethod
|
||||
public void moveToInternalStorage(Callback callback) {
|
||||
String oldDir = getOldExternalDir();
|
||||
String newDir = getNewInternalDir();
|
||||
|
||||
try {
|
||||
File oldDirFile = new File(oldDir);
|
||||
copyDirectory(oldDirFile, new File(newDir));
|
||||
deleteDirectory(oldDirFile);
|
||||
} catch (IOException e) {
|
||||
Log.d(TAG, "Moving error: " + e);
|
||||
}
|
||||
|
||||
callback.invoke();
|
||||
}
|
||||
|
||||
@ReactMethod
|
||||
public void startNode(Callback callback) {
|
||||
Log.d(TAG, "startNode");
|
||||
|
|
|
@ -185,6 +185,22 @@ RCT_EXPORT_METHOD(startNode:(RCTResponseSenderBlock)onResultCallback) {
|
|||
}
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
#pragma mark - shouldMoveToInternalStorage
|
||||
//////////////////////////////////////////////////////////////////// shouldMoveToInternalStorage
|
||||
RCT_EXPORT_METHOD(shouldMoveToInternalStorage:(RCTResponseSenderBlock)onResultCallback) {
|
||||
// Android only
|
||||
onResultCallback(@[[NSNull null]]);
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
#pragma mark - moveToInternalStorage
|
||||
//////////////////////////////////////////////////////////////////// moveToInternalStorage
|
||||
RCT_EXPORT_METHOD(moveToInternalStorage:(RCTResponseSenderBlock)onResultCallback) {
|
||||
// Android only
|
||||
onResultCallback(@[[NSNull null]]);
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
#pragma mark - StartNodeRPCServer method
|
||||
//////////////////////////////////////////////////////////////////// createAccount
|
||||
|
|
|
@ -75,7 +75,7 @@
|
|||
"react-native-udp": "^2.0.0",
|
||||
"react-native-vector-icons": "^4.0.1",
|
||||
"react-native-webview-bridge": "github:status-im/react-native-webview-bridge#0.33.12",
|
||||
"readable-stream": "^1.0.33",
|
||||
"readable-stream": "1.0.33",
|
||||
"realm": "^0.14.3",
|
||||
"stream-browserify": "^1.0.0",
|
||||
"string_decoder": "^0.10.31",
|
||||
|
|
|
@ -2,10 +2,9 @@
|
|||
|
||||
# rn-nodeify
|
||||
# temporary hack due to https://github.com/facebook/react-native/issues/4968
|
||||
./node_modules/.bin/rn-nodeify --install --hack;
|
||||
./node_modules/.bin/rn-nodeify --install "assert,zlib,buffer,inherits,console,constants,crypto,dns,domain,events,http,https,os,path,process,punycode,querystring,fs,stream,string_decoder,timers,tty,url,util,net,vm" --hack;
|
||||
npm install --save react@16.0.0-alpha.6;
|
||||
npm install --save react-native-tcp@3.2.1;
|
||||
npm install --save react-native-udp@2.0.0;
|
||||
|
||||
# symlink for re-natal
|
||||
if ! [ -f re-natal ]; then
|
||||
|
|
|
@ -37,6 +37,7 @@ Command.prototype.create = function (com) {
|
|||
this["on-send"] = com.onSend;
|
||||
this.fullscreen = com.fullscreen;
|
||||
this.request = com.request;
|
||||
this["execute-immediately?"] = com.executeImmediately;
|
||||
this["sequential-params"] = com.sequentialParams;
|
||||
this.addToCatalog();
|
||||
|
||||
|
|
|
@ -3,7 +3,6 @@
|
|||
(def command-char "/")
|
||||
(def spacing-char " ")
|
||||
(def arg-wrapping-char "\"")
|
||||
(def masking-char "*")
|
||||
(def bot-char "@")
|
||||
|
||||
(def input-height 56)
|
||||
|
@ -11,6 +10,7 @@
|
|||
(def input-spacing-top 16)
|
||||
|
||||
(def crazy-math-message-id "crazy-math-message")
|
||||
(def move-to-internal-failure-message-id "move-to-internal-failure-message")
|
||||
(def passphrase-message-id "passphraze-message")
|
||||
(def intro-status-message-id "intro-status")
|
||||
(def intro-message1-id "intro-message1")
|
||||
|
|
|
@ -132,26 +132,42 @@
|
|||
(when-not (messages/get-by-id chat-consts/passphrase-message-id)
|
||||
(sign-up-service/account-generation-message)))))
|
||||
|
||||
(register-handler :move-to-internal-failure-message
|
||||
(u/side-effect!
|
||||
(fn [_]
|
||||
(when-not (messages/get-by-id chat-consts/move-to-internal-failure-message-id)
|
||||
(sign-up-service/move-to-internal-failure-message)))))
|
||||
|
||||
(register-handler :show-mnemonic
|
||||
(u/side-effect!
|
||||
(fn [_ [_ mnemonic]]
|
||||
(let [crazy-math-message? (messages/get-by-id chat-consts/crazy-math-message-id)]
|
||||
(sign-up-service/passphrase-messages mnemonic crazy-math-message?)))))
|
||||
|
||||
(defn- handle-sms [{body :body}]
|
||||
(when-let [matches (re-matches #"(\d{4})" body)]
|
||||
(dispatch [:sign-up-confirm (second matches)])))
|
||||
|
||||
(register-handler :sign-up
|
||||
(after (fn [_ [_ phone-number]]
|
||||
(dispatch [:account-update {:phone phone-number}])))
|
||||
(fn [db [_ phone-number message-id]]
|
||||
(sign-up-service/start-listening-confirmation-code-sms)
|
||||
(let [formatted (format-phone-number phone-number)]
|
||||
(-> db
|
||||
(assoc :user-phone-number formatted)
|
||||
sign-up-service/start-listening-confirmation-code-sms
|
||||
(server/sign-up formatted
|
||||
message-id
|
||||
sign-up-service/on-sign-up-response)))))
|
||||
|
||||
(register-handler :start-listening-confirmation-code-sms
|
||||
(fn [db [_ listener]]
|
||||
(if-not (:confirmation-code-sms-listener db)
|
||||
(assoc db :confirmation-code-sms-listener listener)
|
||||
db)))
|
||||
|
||||
(register-handler :stop-listening-confirmation-code-sms
|
||||
(fn [db [_]]
|
||||
(fn [db]
|
||||
(if (:confirmation-code-sms-listener db)
|
||||
(sign-up-service/stop-listening-confirmation-code-sms db)
|
||||
db)))
|
||||
|
|
|
@ -35,3 +35,13 @@
|
|||
(dispatch [:set-in [:message-data data-type message-id] result])
|
||||
(when on-requested (on-requested result)))]
|
||||
(status/call-jail jail-id path params callback)))))))
|
||||
|
||||
(handlers/register-handler :execute-command-immediately
|
||||
(handlers/side-effect!
|
||||
(fn [_ [_ {command-name :name :as command}]]
|
||||
(case (keyword command-name)
|
||||
:grant-permissions
|
||||
(dispatch [:request-permissions
|
||||
[:read-external-storage]
|
||||
#(dispatch [:initialize-geth])])
|
||||
(log/debug "ignoring command: " command)))))
|
||||
|
|
|
@ -97,7 +97,9 @@
|
|||
(fn [{:keys [current-chat-id] :as db} [_ chat-id text]]
|
||||
(let [chat-id (or chat-id current-chat-id)
|
||||
chat-text (or text (get-in db [:chats chat-id :input-text]) "")
|
||||
requests (suggestions/get-request-suggestions db chat-text)
|
||||
requests (->> (suggestions/get-request-suggestions db chat-text)
|
||||
(remove (fn [{:keys [type]}]
|
||||
(= type :grant-permissions))))
|
||||
suggestions (suggestions/get-command-suggestions db chat-text)
|
||||
global-commands (suggestions/get-global-command-suggestions db chat-text)
|
||||
{:keys [dapp?]} (get-in db [:contacts chat-id])]
|
||||
|
|
|
@ -42,14 +42,15 @@
|
|||
:from console-chat-id
|
||||
:to "me"}])))
|
||||
|
||||
(defn handle-sms [{body :body}]
|
||||
(when-let [matches (re-matches #"(\d{4})" body)]
|
||||
(dispatch [:sign-up-confirm (second matches)])))
|
||||
|
||||
(defn start-listening-confirmation-code-sms [db]
|
||||
(if-not (:confirmation-code-sms-listener db)
|
||||
(assoc db :confirmation-code-sms-listener (add-sms-listener handle-sms))
|
||||
db))
|
||||
(defn start-listening-confirmation-code-sms []
|
||||
(dispatch [:request-permissions
|
||||
[:receive-sms]
|
||||
(fn []
|
||||
(let [listener (add-sms-listener
|
||||
(fn [{body :body}]
|
||||
(when-let [matches (re-matches #"(\d{4})" body)]
|
||||
(dispatch [:sign-up-confirm (second matches)]))))]
|
||||
(dispatch [:start-listening-confirmation-code-sms listener])))]))
|
||||
|
||||
(defn stop-listening-confirmation-code-sms [db]
|
||||
(when-let [listener (:confirmation-code-sms-listener db)]
|
||||
|
@ -70,7 +71,9 @@
|
|||
|
||||
(defn sync-contacts []
|
||||
;; TODO 'on-sync-contacts' is never called
|
||||
(dispatch [:sync-contacts on-sync-contacts]))
|
||||
(dispatch [:request-permissions
|
||||
[:read-contacts]
|
||||
#(dispatch [:sync-contacts on-sync-contacts])]))
|
||||
|
||||
(defn on-send-code-response [body]
|
||||
(dispatch [:received-message
|
||||
|
@ -122,6 +125,18 @@
|
|||
:from console-chat-id
|
||||
:to "me"}]))
|
||||
|
||||
(defn move-to-internal-failure-message []
|
||||
(dispatch [:received-message
|
||||
{:message-id const/move-to-internal-failure-message-id
|
||||
:content (command-content
|
||||
:grant-permissions
|
||||
(label :t/move-to-internal-failure-message))
|
||||
:content-type content-type-command-request
|
||||
:outgoing false
|
||||
:chat-id console-chat-id
|
||||
:from console-chat-id
|
||||
:to "me"}]))
|
||||
|
||||
(defn passphrase-messages [mnemonic crazy-math-message?]
|
||||
(dispatch [:received-message
|
||||
{:message-id const/passphrase-message-id
|
||||
|
|
|
@ -56,11 +56,13 @@
|
|||
:component-will-unmount
|
||||
#(reset! loop? false)
|
||||
:reagent-render
|
||||
(fn [message-id {command-icon :icon :as command} status-initialized?]
|
||||
(fn [message-id {:keys [execute-immediately?] command-icon :icon :as command} status-initialized?]
|
||||
(when command
|
||||
[touchable-highlight
|
||||
{:on-press (when (and (not @answered?) status-initialized?)
|
||||
#(set-chat-command message-id command))
|
||||
{:on-press (if execute-immediately?
|
||||
#(dispatch [:execute-command-immediately command])
|
||||
(when (and (not @answered?) status-initialized?)
|
||||
#(set-chat-command message-id command)))
|
||||
:style (st/command-request-image-touchable)
|
||||
:accessibility-label (id/chat-request-message-button (:name command))}
|
||||
[animated-view {:style (st/command-request-image-view command scale-anim-val)}
|
||||
|
|
|
@ -0,0 +1,24 @@
|
|||
(ns status-im.components.permissions
|
||||
(:require [taoensso.timbre :as log]))
|
||||
|
||||
(def permissions-class (.-PermissionsAndroid js/ReactNative))
|
||||
|
||||
(def permissions-map
|
||||
{:read-external-storage "android.permission.READ_EXTERNAL_STORAGE"
|
||||
:write-external-storage "android.permission.WRITE_EXTERNAL_STORAGE"
|
||||
:read-contacts "android.permission.READ_CONTACTS"
|
||||
:camera "android.permission.CAMERA"
|
||||
:receive-sms "android.permission.RECEIVE_SMS"})
|
||||
|
||||
(defn all-granted? [permissions]
|
||||
(let [permission-vals (distinct (vals permissions))]
|
||||
(and (= (count permission-vals) 1)
|
||||
(not= (first permission-vals) "denied"))))
|
||||
|
||||
(defn request-permissions [permissions then else]
|
||||
(let [permissions (mapv #(get permissions-map %) permissions)
|
||||
result (.requestMultiple permissions-class (clj->js permissions))
|
||||
result (.then result #(if (all-granted? (js->clj %))
|
||||
(then)
|
||||
(when else (else))))
|
||||
result (.catch result #(else))]))
|
|
@ -61,6 +61,14 @@
|
|||
(.addListener r/device-event-emitter "gethEvent"
|
||||
#(dispatch [:signal-event (.-jsonEvent %)])))
|
||||
|
||||
(defn should-move-to-internal-storage? [on-result]
|
||||
(when status
|
||||
(call-module #(.shouldMoveToInternalStorage status on-result))))
|
||||
|
||||
(defn move-to-internal-storage [on-result]
|
||||
(when status
|
||||
(call-module #(.moveToInternalStorage status on-result))))
|
||||
|
||||
(defn start-node [on-result]
|
||||
(when status
|
||||
(call-module #(.startNode status on-result))))
|
||||
|
|
|
@ -6,6 +6,7 @@
|
|||
[taoensso.timbre :as log]
|
||||
[status-im.utils.crypt :refer [gen-random-bytes]]
|
||||
[status-im.components.status :as status]
|
||||
[status-im.components.permissions :as permissions]
|
||||
[status-im.utils.handlers :refer [register-handler] :as u]
|
||||
status-im.chat.handlers
|
||||
status-im.group-settings.handlers
|
||||
|
@ -122,11 +123,24 @@
|
|||
(log/debug "Started Node")
|
||||
(enet/get-network #(dispatch [:set :network %])))
|
||||
|
||||
(defn move-to-internal-storage [db]
|
||||
(status/move-to-internal-storage
|
||||
(fn []
|
||||
(status/start-node
|
||||
(fn [result]
|
||||
(node-started db result))))))
|
||||
|
||||
(register-handler :initialize-geth
|
||||
(u/side-effect!
|
||||
(fn [db _]
|
||||
(log/debug "Starting node")
|
||||
(status/start-node (fn [result] (node-started db result))))))
|
||||
(status/should-move-to-internal-storage?
|
||||
(fn [should-move?]
|
||||
(if should-move?
|
||||
(dispatch [:request-permissions
|
||||
[:read-external-storage]
|
||||
#(move-to-internal-storage db)
|
||||
#(dispatch [:move-to-internal-failure-message])])
|
||||
(status/start-node (fn [result] (node-started db result)))))))))
|
||||
|
||||
(register-handler :signal-event
|
||||
(u/side-effect!
|
||||
|
@ -168,6 +182,14 @@
|
|||
(.resetOkHttpClient webview-bridge)))
|
||||
nil))))
|
||||
|
||||
(register-handler :request-permissions
|
||||
(u/side-effect!
|
||||
(fn [_ [_ permissions then else]]
|
||||
(permissions/request-permissions
|
||||
permissions
|
||||
then
|
||||
else))))
|
||||
|
||||
;; -- User data --------------------------------------------------------------
|
||||
(register-handler :load-user-phone-number
|
||||
(fn [db [_]]
|
||||
|
|
|
@ -37,8 +37,13 @@
|
|||
:on-change-text #(dispatch [:set-in [:profile-edit :name] %])}]])
|
||||
|
||||
(def profile-icon-options
|
||||
[{:text (label :t/image-source-gallery) :value #(dispatch [:open-image-picker])}
|
||||
{:text (label :t/image-source-make-photo) :value #(dispatch [:navigate-to :profile-photo-capture])}])
|
||||
[{:text (label :t/image-source-gallery)
|
||||
:value #(dispatch [:open-image-picker])}
|
||||
{:text (label :t/image-source-make-photo)
|
||||
:value (fn []
|
||||
(dispatch [:request-permissions
|
||||
[:camera :write-external-storage]
|
||||
#(dispatch [:navigate-to :profile-photo-capture])]))}])
|
||||
|
||||
(defn edit-profile-bage [contact]
|
||||
[view st/edit-profile-bage
|
||||
|
|
|
@ -26,18 +26,6 @@
|
|||
(.log js/console type error))]
|
||||
(img->base64 path on-success on-error)))))))
|
||||
|
||||
(register-handler :open-image-source-selector
|
||||
(u/side-effect!
|
||||
(fn [_ [_ list-selection-fn]]
|
||||
(list-selection-fn {:title (label :t/image-source-title)
|
||||
:options [(label :t/image-source-make-photo) (label :t/image-source-gallery)]
|
||||
:callback (fn [index]
|
||||
(case index
|
||||
0 (dispatch [:navigate-to :profile-photo-capture])
|
||||
1 (dispatch [:open-image-picker])
|
||||
:default))
|
||||
:cancel-text (label :t/image-source-cancel)}))))
|
||||
|
||||
(register-handler :phone-number-change-requested
|
||||
;; Switch user to the console issuing the !phone command automatically to let him change his phone number.
|
||||
;; We allow to change phone number only from console because this requires entering SMS verification code.
|
||||
|
|
|
@ -122,6 +122,7 @@
|
|||
:intro-status "Chat with me to setup your account and change your settings!"
|
||||
:intro-message1 "Welcome to Status\nTap this message to set your password & get started!"
|
||||
:account-generation-message "Gimmie a sec, I gotta do some crazy math to generate your account!"
|
||||
:move-to-internal-failure-message "We need to move some important files from external to internal storage. To do this, we need your permission. We won't be using external storage in future versions."
|
||||
:debug-enabled "Debug server has been launched! Your IP address is {{ip}}. You can now add your DApp by running *status-dev-cli add-dapp --ip {{ip}}* from your computer"
|
||||
|
||||
;phone types
|
||||
|
|
Loading…
Reference in New Issue