diff --git a/.re-natal b/.re-natal
index 1455b14c43..4fecaf5ca5 100644
--- a/.re-natal
+++ b/.re-natal
@@ -1,7 +1,7 @@
{
"name": "StatusIm",
"interface": "reagent",
- "androidHost": "localhost",
+ "androidHost": "10.0.3.2",
"modules": [
"react-native-contacts",
"react-native-invertible-scroll-view",
@@ -16,7 +16,9 @@
"react-native-randombytes",
"dismissKeyboard",
"react-native-linear-gradient",
- "react-native-android-sms-listener"
+ "react-native-android-sms-listener",
+ "react-native-camera",
+ "react-native-qrcode"
],
"imageDirs": [
"images"
diff --git a/android/app/build.gradle b/android/app/build.gradle
index 379551061c..21e197ea42 100644
--- a/android/app/build.gradle
+++ b/android/app/build.gradle
@@ -130,6 +130,7 @@ dependencies {
compile project(':react-native-i18n')
compile project(':react-native-linear-gradient')
compile project(':ReactNativeAndroidSmsListener')
+ compile project(':react-native-camera')
// compile(name:'geth', ext:'aar')
compile(group: 'status-im', name: 'android-geth', version: '1.4.0-201604110816-a97a114', ext: 'aar')
diff --git a/android/app/src/main/java/com/statusim/MainActivity.java b/android/app/src/main/java/com/statusim/MainActivity.java
index 3d411d9213..cf17707c29 100644
--- a/android/app/src/main/java/com/statusim/MainActivity.java
+++ b/android/app/src/main/java/com/statusim/MainActivity.java
@@ -8,30 +8,34 @@ import com.facebook.react.shell.MainReactPackage;
import com.rt2zz.reactnativecontacts.ReactNativeContacts;
import android.os.Bundle;
import android.os.Environment;
+import android.app.AlertDialog;
+import android.content.DialogInterface;
+import android.content.DialogInterface.OnClickListener;
+import android.content.DialogInterface.OnCancelListener;
import com.github.ethereum.go_ethereum.cmd.Geth;
import com.bitgo.randombytes.RandomBytesPackage;
import com.BV.LinearGradient.LinearGradientPackage;
import com.centaurwarchief.smslistener.SmsListener;
+import android.os.Handler;
+import android.util.Log;
+
import java.util.Arrays;
import java.util.List;
import java.util.Properties;
import java.io.File;
+import com.lwansbrough.RCTCamera.*;
import com.i18n.reactnativei18n.ReactNativeI18n;
import io.realm.react.RealmReactPackage;
+
public class MainActivity extends ReactActivity {
- @Override
- protected void onCreate(Bundle savedInstanceState) {
- super.onCreate(savedInstanceState);
+ final Handler handler = new Handler();
- // Required for android-16 (???)
- System.loadLibrary("gethraw");
- System.loadLibrary("geth");
-
- // Required because of crazy APN settings redirecting localhost
+ protected void startStatus() {
+ // 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");
@@ -43,11 +47,56 @@ public class MainActivity extends ReactActivity {
getApplicationInfo().dataDir;
// Launch!
+ final Runnable addPeer = new Runnable() {
+ public void run() {
+ Log.w("Geth", "adding peer");
+ Geth.run("--exec admin.addPeer(\"enode://e2f28126720452aa82f7d3083e49e6b3945502cb94d9750a15e27ee310eed6991618199f878e5fbc7dfa0e20f0af9554b41f491dc8f1dbae8f0f2d37a3a613aa@139.162.13.89:55555\") attach http://localhost:8545");
+ }
+ };
new Thread(new Runnable() {
public void run() {
- Geth.run("--bootnodes enode://e2f28126720452aa82f7d3083e49e6b3945502cb94d9750a15e27ee310eed6991618199f878e5fbc7dfa0e20f0af9554b41f491dc8f1dbae8f0f2d37a3a613aa@139.162.13.89:30303 --shh --ipcdisable --nodiscover --rpc --rpcapi db,eth,net,web3,shh,admin --fast --datadir=" + dataFolder);
+ Geth.run("--shh --ipcdisable --nodiscover --rpc --rpcapi db,eth,net,web3,shh,admin --fast --datadir=" + dataFolder);
+
}
}).start();
+ handler.postDelayed(addPeer, 5000);
+ }
+
+ @Override
+ protected void onCreate(Bundle savedInstanceState) {
+ super.onCreate(savedInstanceState);
+
+ // Required for android-16 (???)
+ // Crash if put in startStatus() ?
+ System.loadLibrary("gethraw");
+ System.loadLibrary("geth");
+
+ if(!RootUtil.isDeviceRooted()) {
+ startStatus();
+ } 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) {
+ dialog.dismiss();
+ startStatus();
+ }
+ }).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();
+ }
+
}
/**
@@ -82,6 +131,7 @@ public class MainActivity extends ReactActivity {
new ReactNativeI18n(),
new RandomBytesPackage(),
new LinearGradientPackage(),
+ new RCTCameraPackage(),
new SmsListener(this)
);
}
diff --git a/android/app/src/main/java/com/statusim/RootUtil.java b/android/app/src/main/java/com/statusim/RootUtil.java
new file mode 100644
index 0000000000..c5b9e88df0
--- /dev/null
+++ b/android/app/src/main/java/com/statusim/RootUtil.java
@@ -0,0 +1,41 @@
+package com.statusim;
+
+import java.io.File;
+import java.io.BufferedReader;
+import java.io.InputStreamReader;
+
+/** @author Kevin Kowalewski */
+public class RootUtil {
+
+ public static boolean isDeviceRooted() {
+ return checkRootMethod1() || checkRootMethod2() || checkRootMethod3();
+ }
+
+ private static boolean checkRootMethod1() {
+ String buildTags = android.os.Build.TAGS;
+ return buildTags != null && buildTags.contains("test-keys");
+ }
+
+ private static boolean checkRootMethod2() {
+ String[] paths = { "/system/app/Superuser.apk", "/sbin/su", "/system/bin/su", "/system/xbin/su", "/data/local/xbin/su", "/data/local/bin/su", "/system/sd/xbin/su",
+ "/system/bin/failsafe/su", "/data/local/su" };
+ for (String path : paths) {
+ if (new File(path).exists()) return true;
+ }
+ return false;
+ }
+
+ private static boolean checkRootMethod3() {
+ Process process = null;
+ try {
+ process = Runtime.getRuntime().exec(new String[] { "/system/xbin/which", "su" });
+ BufferedReader in = new BufferedReader(new InputStreamReader(process.getInputStream()));
+ if (in.readLine() != null) return true;
+ return false;
+ } catch (Throwable t) {
+ return false;
+ } finally {
+ if (process != null) process.destroy();
+ }
+ }
+}
diff --git a/android/app/src/main/res/drawable-hdpi/corner_left_bottom.png b/android/app/src/main/res/drawable-hdpi/corner_left_bottom.png
new file mode 100644
index 0000000000..1c9c9b446d
Binary files /dev/null and b/android/app/src/main/res/drawable-hdpi/corner_left_bottom.png differ
diff --git a/android/app/src/main/res/drawable-hdpi/corner_left_top.png b/android/app/src/main/res/drawable-hdpi/corner_left_top.png
new file mode 100644
index 0000000000..1a0a4e57f8
Binary files /dev/null and b/android/app/src/main/res/drawable-hdpi/corner_left_top.png differ
diff --git a/android/app/src/main/res/drawable-hdpi/corner_right_bottom.png b/android/app/src/main/res/drawable-hdpi/corner_right_bottom.png
new file mode 100644
index 0000000000..e6071d1ae1
Binary files /dev/null and b/android/app/src/main/res/drawable-hdpi/corner_right_bottom.png differ
diff --git a/android/app/src/main/res/drawable-hdpi/corner_right_top.png b/android/app/src/main/res/drawable-hdpi/corner_right_top.png
new file mode 100644
index 0000000000..6eaca3cd9a
Binary files /dev/null and b/android/app/src/main/res/drawable-hdpi/corner_right_top.png differ
diff --git a/android/app/src/main/res/drawable-hdpi/icon_back_white.png b/android/app/src/main/res/drawable-hdpi/icon_back_white.png
new file mode 100644
index 0000000000..6bd5aec7c4
Binary files /dev/null and b/android/app/src/main/res/drawable-hdpi/icon_back_white.png differ
diff --git a/android/app/src/main/res/drawable-hdpi/icon_qr.png b/android/app/src/main/res/drawable-hdpi/icon_qr.png
new file mode 100644
index 0000000000..6b2f825374
Binary files /dev/null and b/android/app/src/main/res/drawable-hdpi/icon_qr.png differ
diff --git a/android/app/src/main/res/drawable-mdpi/corner_left_bottom.png b/android/app/src/main/res/drawable-mdpi/corner_left_bottom.png
new file mode 100644
index 0000000000..da09ea7a24
Binary files /dev/null and b/android/app/src/main/res/drawable-mdpi/corner_left_bottom.png differ
diff --git a/android/app/src/main/res/drawable-mdpi/corner_left_top.png b/android/app/src/main/res/drawable-mdpi/corner_left_top.png
new file mode 100644
index 0000000000..988d93651c
Binary files /dev/null and b/android/app/src/main/res/drawable-mdpi/corner_left_top.png differ
diff --git a/android/app/src/main/res/drawable-mdpi/corner_right_bottom.png b/android/app/src/main/res/drawable-mdpi/corner_right_bottom.png
new file mode 100644
index 0000000000..e74544e83b
Binary files /dev/null and b/android/app/src/main/res/drawable-mdpi/corner_right_bottom.png differ
diff --git a/android/app/src/main/res/drawable-mdpi/corner_right_top.png b/android/app/src/main/res/drawable-mdpi/corner_right_top.png
new file mode 100644
index 0000000000..33726dfa01
Binary files /dev/null and b/android/app/src/main/res/drawable-mdpi/corner_right_top.png differ
diff --git a/android/app/src/main/res/drawable-mdpi/icon_back_white.png b/android/app/src/main/res/drawable-mdpi/icon_back_white.png
new file mode 100644
index 0000000000..ac448ee920
Binary files /dev/null and b/android/app/src/main/res/drawable-mdpi/icon_back_white.png differ
diff --git a/android/app/src/main/res/drawable-mdpi/icon_qr.png b/android/app/src/main/res/drawable-mdpi/icon_qr.png
new file mode 100644
index 0000000000..c8b6ef10fd
Binary files /dev/null and b/android/app/src/main/res/drawable-mdpi/icon_qr.png differ
diff --git a/android/app/src/main/res/drawable-xhdpi/corner_left_bottom.png b/android/app/src/main/res/drawable-xhdpi/corner_left_bottom.png
new file mode 100644
index 0000000000..b43f25a58d
Binary files /dev/null and b/android/app/src/main/res/drawable-xhdpi/corner_left_bottom.png differ
diff --git a/android/app/src/main/res/drawable-xhdpi/corner_left_top.png b/android/app/src/main/res/drawable-xhdpi/corner_left_top.png
new file mode 100644
index 0000000000..f8180a9c1c
Binary files /dev/null and b/android/app/src/main/res/drawable-xhdpi/corner_left_top.png differ
diff --git a/android/app/src/main/res/drawable-xhdpi/corner_right_bottom.png b/android/app/src/main/res/drawable-xhdpi/corner_right_bottom.png
new file mode 100644
index 0000000000..ce0a7ab9c0
Binary files /dev/null and b/android/app/src/main/res/drawable-xhdpi/corner_right_bottom.png differ
diff --git a/android/app/src/main/res/drawable-xhdpi/corner_right_top.png b/android/app/src/main/res/drawable-xhdpi/corner_right_top.png
new file mode 100644
index 0000000000..2ae2e61860
Binary files /dev/null and b/android/app/src/main/res/drawable-xhdpi/corner_right_top.png differ
diff --git a/android/app/src/main/res/drawable-xhdpi/icon_back_white.png b/android/app/src/main/res/drawable-xhdpi/icon_back_white.png
new file mode 100644
index 0000000000..bcc735db8e
Binary files /dev/null and b/android/app/src/main/res/drawable-xhdpi/icon_back_white.png differ
diff --git a/android/app/src/main/res/drawable-xhdpi/icon_qr.png b/android/app/src/main/res/drawable-xhdpi/icon_qr.png
new file mode 100644
index 0000000000..c55551f687
Binary files /dev/null and b/android/app/src/main/res/drawable-xhdpi/icon_qr.png differ
diff --git a/android/app/src/main/res/drawable-xxhdpi/corner_left_bottom.png b/android/app/src/main/res/drawable-xxhdpi/corner_left_bottom.png
new file mode 100644
index 0000000000..0fff341220
Binary files /dev/null and b/android/app/src/main/res/drawable-xxhdpi/corner_left_bottom.png differ
diff --git a/android/app/src/main/res/drawable-xxhdpi/corner_left_top.png b/android/app/src/main/res/drawable-xxhdpi/corner_left_top.png
new file mode 100644
index 0000000000..e25037ece3
Binary files /dev/null and b/android/app/src/main/res/drawable-xxhdpi/corner_left_top.png differ
diff --git a/android/app/src/main/res/drawable-xxhdpi/corner_right_bottom.png b/android/app/src/main/res/drawable-xxhdpi/corner_right_bottom.png
new file mode 100644
index 0000000000..e542ec0d64
Binary files /dev/null and b/android/app/src/main/res/drawable-xxhdpi/corner_right_bottom.png differ
diff --git a/android/app/src/main/res/drawable-xxhdpi/corner_right_top.png b/android/app/src/main/res/drawable-xxhdpi/corner_right_top.png
new file mode 100644
index 0000000000..a6a65aedc9
Binary files /dev/null and b/android/app/src/main/res/drawable-xxhdpi/corner_right_top.png differ
diff --git a/android/app/src/main/res/drawable-xxhdpi/icon_back_white.png b/android/app/src/main/res/drawable-xxhdpi/icon_back_white.png
new file mode 100644
index 0000000000..166bc865a4
Binary files /dev/null and b/android/app/src/main/res/drawable-xxhdpi/icon_back_white.png differ
diff --git a/android/app/src/main/res/drawable-xxhdpi/icon_qr.png b/android/app/src/main/res/drawable-xxhdpi/icon_qr.png
new file mode 100644
index 0000000000..f7b3c5ad15
Binary files /dev/null and b/android/app/src/main/res/drawable-xxhdpi/icon_qr.png differ
diff --git a/android/app/src/main/res/drawable-xxxhdpi/corner_left_bottom.png b/android/app/src/main/res/drawable-xxxhdpi/corner_left_bottom.png
new file mode 100644
index 0000000000..79d8ff98d3
Binary files /dev/null and b/android/app/src/main/res/drawable-xxxhdpi/corner_left_bottom.png differ
diff --git a/android/app/src/main/res/drawable-xxxhdpi/corner_left_top.png b/android/app/src/main/res/drawable-xxxhdpi/corner_left_top.png
new file mode 100644
index 0000000000..8ccdd18d77
Binary files /dev/null and b/android/app/src/main/res/drawable-xxxhdpi/corner_left_top.png differ
diff --git a/android/app/src/main/res/drawable-xxxhdpi/corner_right_bottom.png b/android/app/src/main/res/drawable-xxxhdpi/corner_right_bottom.png
new file mode 100644
index 0000000000..1fa347dffe
Binary files /dev/null and b/android/app/src/main/res/drawable-xxxhdpi/corner_right_bottom.png differ
diff --git a/android/app/src/main/res/drawable-xxxhdpi/corner_right_top.png b/android/app/src/main/res/drawable-xxxhdpi/corner_right_top.png
new file mode 100644
index 0000000000..a26ebe0e61
Binary files /dev/null and b/android/app/src/main/res/drawable-xxxhdpi/corner_right_top.png differ
diff --git a/android/app/src/main/res/drawable-xxxhdpi/icon_back_white.png b/android/app/src/main/res/drawable-xxxhdpi/icon_back_white.png
new file mode 100644
index 0000000000..8992428891
Binary files /dev/null and b/android/app/src/main/res/drawable-xxxhdpi/icon_back_white.png differ
diff --git a/android/app/src/main/res/drawable-xxxhdpi/icon_qr.png b/android/app/src/main/res/drawable-xxxhdpi/icon_qr.png
new file mode 100644
index 0000000000..863a0a5eb1
Binary files /dev/null and b/android/app/src/main/res/drawable-xxxhdpi/icon_qr.png differ
diff --git a/android/app/src/main/res/values/strings.xml b/android/app/src/main/res/values/strings.xml
index fb87cafc71..428623ba43 100644
--- a/android/app/src/main/res/values/strings.xml
+++ b/android/app/src/main/res/values/strings.xml
@@ -1,3 +1,6 @@
- StatusIm
-
+ Status
+ Your phone appears to be ROOTED, by pressing CONTINUE you understand and accept the risks in using this software.
+ Continue
+ Exit
+
\ No newline at end of file
diff --git a/android/settings.gradle b/android/settings.gradle
index 141db02933..8dc71f3210 100644
--- a/android/settings.gradle
+++ b/android/settings.gradle
@@ -18,3 +18,5 @@ include ':react-native-linear-gradient'
project(':react-native-linear-gradient').projectDir = new File(rootProject.projectDir, '../node_modules/react-native-linear-gradient/android')
include ':ReactNativeAndroidSmsListener'
project(':ReactNativeAndroidSmsListener').projectDir = new File(rootProject.projectDir, '../node_modules/react-native-android-sms-listener/android')
+include ':react-native-camera'
+project(':react-native-camera').projectDir = new File(rootProject.projectDir, '../node_modules/react-native-camera/android')
diff --git a/env/dev/env/android/main.cljs b/env/dev/env/android/main.cljs
index 1bf474e505..f0c3d96fca 100644
--- a/env/dev/env/android/main.cljs
+++ b/env/dev/env/android/main.cljs
@@ -10,7 +10,7 @@
(def root-el (r/as-element [reloader]))
(figwheel/watch-and-reload
- :websocket-url "ws://localhost:3449/figwheel-ws"
+ :websocket-url "ws://10.0.3.2:3449/figwheel-ws"
:heads-up-display false
:jsload-callback #(swap! cnt inc))
diff --git a/package.json b/package.json
index f325b8e9f3..4bc3d4994d 100644
--- a/package.json
+++ b/package.json
@@ -11,12 +11,14 @@
"react-native": "^0.24.1",
"react-native-action-button": "^1.1.4",
"react-native-android-sms-listener": "^0.1.3",
+ "react-native-camera": "github:codyhazelwood/react-native-camera",
"react-native-circle-checkbox": "^0.1.3",
"react-native-contacts": "^0.2.4",
"react-native-i18n": "0.0.8",
"react-native-invertible-scroll-view": "^1.0.0",
"react-native-linear-gradient": "^1.5.7",
"react-native-loading-spinner-overlay": "0.0.8",
+ "react-native-qrcode": "^0.2.2",
"react-native-randombytes": "^2.0.0",
"react-native-vector-icons": "^1.3.4",
"realm": "^0.11.1"
diff --git a/src/status_im/android/core.cljs b/src/status_im/android/core.cljs
index 080a91fa54..154c7104ce 100644
--- a/src/status_im/android/core.cljs
+++ b/src/status_im/android/core.cljs
@@ -8,6 +8,8 @@
[status-im.components.react :refer [navigator app-registry]]
[status-im.components.main-tabs :refer [main-tabs]]
[status-im.contacts.screen :refer [contact-list]]
+ [status-im.contacts.views.new-contact :refer [new-contact]]
+ [status-im.qr-scanner.screen :refer [qr-scanner]]
[status-im.discovery.screen :refer [discovery]]
[status-im.discovery.tag :refer [discovery-tag]]
[status-im.chat.screen :refer [chat]]
@@ -44,6 +46,8 @@
:new-group [new-group]
:group-settings [group-settings]
:contact-list [main-tabs]
+ :new-contact [new-contact]
+ :qr-scanner [qr-scanner]
:chat [chat]
:profile [profile]
:my-profile [my-profile]))))
diff --git a/src/status_im/chats_list/screen.cljs b/src/status_im/chats_list/screen.cljs
index a82849d7e6..572f0ac5a9 100644
--- a/src/status_im/chats_list/screen.cljs
+++ b/src/status_im/chats_list/screen.cljs
@@ -36,7 +36,7 @@
[drawer-view
[view st/chats-container
[chats-list-toolbar]
- [list-view {:dataSource (to-datasource (vals @chats))
+ [list-view {:dataSource (to-datasource @chats)
:renderRow (fn [row _ _]
(list-item [chat-list-item row]))
:style st/list-container}]
diff --git a/src/status_im/chats_list/views/chat_list_item.cljs b/src/status_im/chats_list/views/chat_list_item.cljs
index 0c343f9b59..a7877e5e82 100644
--- a/src/status_im/chats_list/views/chat_list_item.cljs
+++ b/src/status_im/chats_list/views/chat_list_item.cljs
@@ -1,17 +1,18 @@
(ns status-im.chats-list.views.chat-list-item
(:require [re-frame.core :refer [subscribe dispatch dispatch-sync]]
[status-im.components.react :refer [view
- text
- image
- touchable-highlight]]
+ text
+ image
+ touchable-highlight]]
[status-im.components.styles :refer [font]]
[status-im.chats-list.views.inner-item :refer
[chat-list-item-inner-view]]))
-(defn chat-list-item [{:keys [chat-id] :as chat}]
+(defn chat-list-item [[chat-id chat]]
[touchable-highlight
{:on-press #(dispatch [:navigate-to :chat chat-id])}
[view [chat-list-item-inner-view (merge chat
;; TODO stub data
- {:new-messages-count 3
+ {:chat-id chat-id
+ :new-messages-count 3
:online true})]]])
diff --git a/src/status_im/components/camera.cljs b/src/status_im/components/camera.cljs
new file mode 100644
index 0000000000..f53b70ffae
--- /dev/null
+++ b/src/status_im/components/camera.cljs
@@ -0,0 +1,7 @@
+(ns status-im.components.camera
+ (:require [reagent.core :as r]))
+
+(def class (.-default (js/require "react-native-camera")))
+
+(defn camera [props]
+ (r/create-element class (clj->js (merge {:inverted true} props))))
\ No newline at end of file
diff --git a/src/status_im/components/qr-code.cljs b/src/status_im/components/qr-code.cljs
new file mode 100644
index 0000000000..6c1d7d066d
--- /dev/null
+++ b/src/status_im/components/qr-code.cljs
@@ -0,0 +1,7 @@
+(ns status-im.components.qr-code
+ (:require [reagent.core :as r]))
+
+(def class (js/require "react-native-qrcode"))
+
+(defn qr-code [props]
+ (r/create-element class (clj->js (merge {:inverted true} props))))
\ No newline at end of file
diff --git a/src/status_im/components/styles.cljs b/src/status_im/components/styles.cljs
index 5aa0bf675d..70e907c631 100644
--- a/src/status_im/components/styles.cljs
+++ b/src/status_im/components/styles.cljs
@@ -19,6 +19,7 @@
(def text1-color color-black)
(def text2-color color-gray)
(def text3-color color-blue)
+(def text4-color color-white)
(def online-color color-blue)
(def new-messages-count-color color-blue-transparent)
(def chat-background color-light-gray)
@@ -28,5 +29,73 @@
(def toolbar-background2 color-light-gray)
(def default-chat-color color-purple)
+(def toolbar-height 56)
+
(def flex
{:style {:flex 1}})
+
+(def hamburger-icon
+ {:width 16
+ :height 12})
+
+(def icon-search
+ {:width 17
+ :height 17})
+
+(def create-icon
+ {:fontSize 20
+ :height 22
+ :color :white})
+
+(def icon-back
+ {:width 8
+ :height 14})
+
+(def icon-add
+ {:width 14
+ :height 14})
+
+(def icon-ok
+ {:width 18
+ :height 14})
+
+(def icon-qr
+ {:width 23
+ :height 22})
+
+(def icon-plus
+ {:width 18
+ :height 18})
+
+(def form-text-input
+ {:marginLeft -4
+ :fontSize 14
+ :fontFamily font
+ :color text1-color})
+
+(def white-form-text-input
+ {:marginLeft -4
+ :fontSize 14
+ :fontFamily font
+ :color color-white})
+
+(def toolbar-title-container
+ {:flex 1
+ :alignItems :center
+ :justifyContent :center})
+
+(def toolbar-title-text
+ {:marginTop -2.5
+ :color text1-color
+ :fontSize 16
+ :fontFamily font})
+
+(def button-input-container
+ {:flex 1
+ :flexDirection :row
+ :height 50})
+
+(def button-input
+ {:flex 1
+ :flexDirection :column
+ :height 50})
\ No newline at end of file
diff --git a/src/status_im/components/toolbar.cljs b/src/status_im/components/toolbar.cljs
index 0591c1aba1..820b338b9c 100644
--- a/src/status_im/components/toolbar.cljs
+++ b/src/status_im/components/toolbar.cljs
@@ -1,24 +1,28 @@
(ns status-im.components.toolbar
(:require [re-frame.core :refer [subscribe dispatch]]
[status-im.components.react :refer [view
- text-input
- icon
- text
- image
- touchable-highlight]]
+ text-input
+ icon
+ text
+ image
+ touchable-highlight]]
[status-im.components.styles :refer [font
- title-font
- color-white
- color-purple
- text1-color
- text2-color
- toolbar-background1]]))
+ title-font
+ color-white
+ color-purple
+ text1-color
+ text2-color
+ toolbar-background1
+ toolbar-title-container
+ toolbar-title-text
+ icon-back
+ toolbar-height]]))
(defn toolbar [{:keys [title nav-action hide-nav? action custom-action
background-color custom-content style]}]
(let [style (merge {:flexDirection :row
:backgroundColor (or background-color toolbar-background1)
- :height 56
+ :height toolbar-height
:elevation 2} style)]
[view {:style style}
(when (not hide-nav?)
@@ -31,20 +35,14 @@
[image (:image nav-action)]]]
[touchable-highlight {:on-press #(dispatch [:navigate-back])}
[view {:width 56
- :height 56}
+ :height 56
+ :alignItems :center
+ :justifyContent :center}
[image {:source {:uri :icon_back}
- :style {:marginTop 21
- :marginLeft 23
- :width 8
- :height 14}}]]]))
+ :style icon-back}]]]))
(or custom-content
- [view {:style {:flex 1
- :alignItems :center
- :justifyContent :center}}
- [text {:style {:marginTop -2.5
- :color text1-color
- :fontSize 16
- :fontFamily font}}
+ [view {:style toolbar-title-container}
+ [text {:style toolbar-title-text}
title]])
custom-action
(when action
diff --git a/src/status_im/contacts/handlers.cljs b/src/status_im/contacts/handlers.cljs
index acb9be9b6c..ac11cf33a2 100644
--- a/src/status_im/contacts/handlers.cljs
+++ b/src/status_im/contacts/handlers.cljs
@@ -104,3 +104,21 @@
(register-handler :add-contacts
(after save-contacts!)
add-new-contacts)
+
+(defn add-new-contact [db [_ {:keys [whisper-identity] :as contact}]]
+ (-> db
+ (update :contacts assoc whisper-identity contact)
+ (assoc :new-contact {:name ""
+ :address ""
+ :whisper-identity ""
+ :phone-number ""})))
+
+(register-handler :add-new-contact
+ (after save-contact)
+ add-new-contact)
+
+(defn set-new-contact-from-qr
+ [{:keys [new-contact] :as db} [_ _ qr-contact]]
+ (assoc db :new-contact (merge new-contact qr-contact)))
+
+(register-handler :set-new-contact-from-qr set-new-contact-from-qr)
diff --git a/src/status_im/contacts/screen.cljs b/src/status_im/contacts/screen.cljs
index b8672807da..a763c2ea50 100644
--- a/src/status_im/contacts/screen.cljs
+++ b/src/status_im/contacts/screen.cljs
@@ -6,9 +6,18 @@
touchable-highlight
list-view
list-item]]
+ [status-im.components.action-button :refer [action-button
+ action-button-item]]
[status-im.contacts.views.contact :refer [contact-view]]
[status-im.components.styles :refer [toolbar-background2]]
[status-im.components.toolbar :refer [toolbar]]
+ [status-im.components.drawer.view :refer [drawer-view open-drawer]]
+ [status-im.components.icons.ionicons :refer [icon]]
+ [status-im.components.styles :refer [color-blue
+ hamburger-icon
+ icon-search
+ create-icon
+ toolbar-background2]]
[status-im.contacts.styles :as st]
[status-im.utils.listview :as lw]
[status-im.i18n :refer [label]]))
@@ -17,20 +26,34 @@
(list-item [contact-view row]))
(defn contact-list-toolbar []
- [toolbar {:title (label :t/contacts)
+ [toolbar {:nav-action {:image {:source {:uri :icon_hamburger}
+ :style hamburger-icon}
+ :handler open-drawer}
+ :title (label :t/contacts)
:background-color toolbar-background2
:action {:image {:source {:uri :icon_search}
- :style st/search-icon}
+ :style icon-search}
:handler (fn [])}}])
(defview contact-list []
[contacts [:get-contacts]]
- [view st/contacts-list-container
- [contact-list-toolbar]
- ;; todo what if there is no contacts, should we show some information
- ;; about this?
- (when contacts
- [list-view {:dataSource (lw/to-datasource contacts)
- :enableEmptySections true
- :renderRow render-row
- :style st/contacts-list}])])
+ [drawer-view
+ [view st/contacts-list-container
+ [contact-list-toolbar]
+ ;; todo what if there is no contacts, should we show some information
+ ;; about this?
+ (when contacts
+ [list-view {:dataSource (lw/to-datasource contacts)
+ :enableEmptySections true
+ :renderRow render-row
+ :style st/contacts-list}])
+ [action-button {:buttonColor color-blue
+ :offsetY 16
+ :offsetX 16}
+ [action-button-item
+ {:title (label :t/new-contact)
+ :buttonColor :#9b59b6
+ :onPress #(dispatch [:navigate-to :new-contact])}
+ [icon {:name :android-create
+ :style create-icon}]]
+ ]]])
diff --git a/src/status_im/contacts/styles.cljs b/src/status_im/contacts/styles.cljs
index 4cbec2cdff..4b64148fc9 100644
--- a/src/status_im/contacts/styles.cljs
+++ b/src/status_im/contacts/styles.cljs
@@ -1,13 +1,12 @@
(ns status-im.contacts.styles
(:require [status-im.components.styles :refer [font
- title-font
- text1-color
- color-white
- online-color]]))
+ title-font
+ text1-color
+ color-white
+ toolbar-background2
+ online-color]]))
+
-(def search-icon
- {:width 17
- :height 17})
(def contacts-list-container
{:flex 1
@@ -67,3 +66,20 @@
:fontSize 16
:fontFamily font
:color text1-color})
+
+; new contact
+
+(def contact-form-container
+ {:flex 1
+ :color :white})
+
+(def gradient-background
+ {:position :absolute
+ :top 0
+ :right 0
+ :bottom 0
+ :left 0})
+
+(def form-container
+ {:marginLeft 16
+ :margin-top 50})
\ No newline at end of file
diff --git a/src/status_im/contacts/views/new_contact.cljs b/src/status_im/contacts/views/new_contact.cljs
new file mode 100644
index 0000000000..469ed6b914
--- /dev/null
+++ b/src/status_im/contacts/views/new_contact.cljs
@@ -0,0 +1,78 @@
+(ns status-im.contacts.views.new-contact
+ (:require-macros [status-im.utils.views :refer [defview]])
+ (:require [re-frame.core :refer [subscribe dispatch dispatch-sync]]
+ [status-im.components.react :refer [view
+ text
+ text-input
+ image
+ linear-gradient
+ touchable-highlight]]
+ [status-im.components.toolbar :refer [toolbar]]
+ [status-im.components.drawer.view :refer [drawer-view open-drawer]]
+ [status-im.components.styles :refer [color-purple
+ color-white
+ icon-search
+ icon-back
+ icon-qr
+ toolbar-background1
+ toolbar-title-container
+ toolbar-title-text
+ button-input-container
+ button-input
+ white-form-text-input]]
+ [status-im.qr-scanner.views.import-button :refer [import-button]]
+ [status-im.i18n :refer [label]]
+ [status-im.contacts.styles :as st]))
+
+
+
+(def toolbar-title
+ [view toolbar-title-container
+ [text {:style (merge toolbar-title-text {:color color-white})}
+ (label :t/new-contact)]])
+
+(defview contact-name-input [name]
+ []
+ [text-input
+ {:underlineColorAndroid color-white
+ :placeholderTextColor color-white
+ :style white-form-text-input
+ :autoFocus true
+ :placeholder (label :t/contact-name)
+ :onChangeText #(dispatch [:set-in [:new-contact :name] %])}
+ name])
+
+(defview contact-whisper-id-input [whisper-identity]
+ [view button-input-container
+ [text-input
+ {:underlineColorAndroid color-white
+ :placeholderTextColor color-white
+ :style (merge white-form-text-input button-input)
+ :autoFocus true
+ :placeholder (label :t/whisper-identity)
+ :onChangeText #(dispatch [:set-in [:new-contact :whisper-identity] %])}
+ whisper-identity]
+ [import-button #(dispatch [:scan-qr-code {:toolbar-title (label :t/new-contact)} :set-new-contact-from-qr])]])
+
+(defview new-contact []
+ [{:keys [name whisper-identity phone-number] :as new-contact} [:get :new-contact]]
+ [drawer-view
+ [view st/contact-form-container
+ [linear-gradient {:colors ["rgba(182, 116, 241, 1)" "rgba(107, 147, 231, 1)" "rgba(43, 171, 238, 1)"]
+ :start [0, 0]
+ :end [0.5, 1]
+ :locations [0, 0.8 ,1]
+ :style st/gradient-background}]
+
+ [toolbar {:background-color :transparent
+ :nav-action {:image {:source {:uri :icon_back_white}
+ :style icon-back}
+ :handler #(dispatch [:navigate-back])}
+ :custom-content toolbar-title
+ :action {:image {:source {:uri :icon_add}
+ :style icon-search}
+ :handler #(dispatch [:add-new-contact new-contact])}}]
+ [view st/form-container
+ [contact-whisper-id-input whisper-identity]
+ [contact-name-input name]
+ ]]])
diff --git a/src/status_im/db.cljs b/src/status_im/db.cljs
index c79babb995..2b3ad6f88f 100644
--- a/src/status_im/db.cljs
+++ b/src/status_im/db.cljs
@@ -31,6 +31,11 @@
:email "myemail@gmail.com"
:status "Hi, this is my status"
:current-tag nil
+ :qr-codes {}
+ :new-contact {:name ""
+ :address ""
+ :whisper-identity ""
+ :phone-number ""}
:disable-group-creation false
:animations {;; mutable data
:to-response-height nil
diff --git a/src/status_im/handlers.cljs b/src/status_im/handlers.cljs
index 6aa74b5c5f..5d43f80031 100644
--- a/src/status_im/handlers.cljs
+++ b/src/status_im/handlers.cljs
@@ -17,6 +17,7 @@
status-im.discovery.handlers
status-im.new-group.handlers
status-im.participants.handlers
+ status-im.qr-scanner.handlers
status-im.protocol.handlers))
;; -- Middleware ------------------------------------------------------------
diff --git a/src/status_im/i18n.cljs b/src/status_im/i18n.cljs
index bdc113852c..f07f1d6d24 100644
--- a/src/status_im/i18n.cljs
+++ b/src/status_im/i18n.cljs
@@ -9,13 +9,15 @@
(set! (.-translations i18n) (clj->js {:en en/translations}))
-(defn label [path & options]
- (if (exists? i18n.t)
- (.t i18n (name path) (clj->js options))
- (name path)))
+(defn label
+ ([path] (label path {}))
+ ([path options]
+ (if (exists? i18n.t)
+ (.t i18n (name path) (clj->js options))
+ (name path))))
+
(defn label-pluralize [count path & options]
(if (exists? i18n.t)
(.p i18n count (name path) (clj->js options))
- (name path)))
-
+ (name path)))
\ No newline at end of file
diff --git a/src/status_im/profile/screen.cljs b/src/status_im/profile/screen.cljs
index bb0c52a1d8..ffff2d2e47 100644
--- a/src/status_im/profile/screen.cljs
+++ b/src/status_im/profile/screen.cljs
@@ -11,6 +11,8 @@
[status-im.components.chat-icon.screen :refer [profile-icon
my-profile-icon]]
[status-im.profile.styles :as st]
+ [status-im.components.qr-code :refer [qr-code]]
+ [status-im.utils.types :refer [clj->json]]
[status-im.i18n :refer [label]]))
(defn profile-property-view [{:keys [name value]}]
@@ -64,7 +66,8 @@
photo-path [:get :photo-path]
phone-number [:get :phone-number]
email [:get :email]
- status [:get :status]]
+ status [:get :status]
+ identity [:get-in [:user-identity :public]]]
[scroll-view {:style st/profile}
[touchable-highlight {:style st/back-btn-touchable
:on-press #(dispatch [:navigate-back])}
@@ -81,10 +84,14 @@
[my-profile-icon]]
[text {:style st/user-name} username]
[text {:style st/status} status]]
- [view st/profile-properties-container
+ [scroll-view st/profile-properties-container
[profile-property-view {:name (label :t/username)
:value username}]
[profile-property-view {:name (label :t/phone-number)
:value phone-number}]
[profile-property-view {:name (label :t/email)
- :value email}]]])
+ :value email}]
+ [view st/qr-code-container
+ [qr-code {:value (clj->json {:name username
+ :whisper-identity identity})
+ :size 200}]]]])
diff --git a/src/status_im/profile/styles.cljs b/src/status_im/profile/styles.cljs
index 95d230920e..fcaaad9b54 100644
--- a/src/status_im/profile/styles.cljs
+++ b/src/status_im/profile/styles.cljs
@@ -135,3 +135,8 @@
:color text2-color
;; IOS:
:letterSpacing 0.5})
+
+(def qr-code-container
+ {:flex 1
+ :alignItems :center
+ :margin 15})
diff --git a/src/status_im/qr_scanner/handlers.cljs b/src/status_im/qr_scanner/handlers.cljs
new file mode 100644
index 0000000000..be05d7fb65
--- /dev/null
+++ b/src/status_im/qr_scanner/handlers.cljs
@@ -0,0 +1,38 @@
+(ns status-im.qr-scanner.handlers
+ (:require [re-frame.core :refer [register-handler after dispatch debug enrich]]
+ [status-im.navigation.handlers :as nav]
+ [status-im.utils.handlers :as u]))
+
+(defmethod nav/preload-data! :qr-scanner
+ [db [_ _ identifier]]
+ (assoc db :current-qr-context identifier))
+
+(defn set-current-identifier [db [_ identifier handler]]
+ (assoc-in db [:qr-codes identifier] handler))
+
+(defn navigate-to-scanner
+ [_ [_ identifier]]
+ (dispatch [:navigate-to :qr-scanner identifier]))
+
+(register-handler :scan-qr-code
+ (after navigate-to-scanner)
+ set-current-identifier)
+
+(register-handler :clear-qr-code
+ (fn [db [_ identifier]]
+ (update db :qr-codes dissoc identifier)))
+
+(defn handle-qr-request
+ [db [_ context data]]
+ (let [handler (get-in db [:qr-codes context])]
+ (dispatch [handler context data])))
+
+(defn clear-qr-request [db [_ context]]
+ (-> db
+ (update :qr-codes dissoc context)
+ (dissoc :current-qr-context)))
+
+(register-handler :set-qr-code
+ (-> (u/side-effect! handle-qr-request)
+ ((enrich clear-qr-request))
+ ((after #(dispatch [:navigate-back])))))
diff --git a/src/status_im/qr_scanner/screen.cljs b/src/status_im/qr_scanner/screen.cljs
new file mode 100644
index 0000000000..2f27d30b9f
--- /dev/null
+++ b/src/status_im/qr_scanner/screen.cljs
@@ -0,0 +1,37 @@
+(ns status-im.qr-scanner.screen
+ (:require-macros [status-im.utils.views :refer [defview]])
+ (:require [re-frame.core :refer [subscribe dispatch dispatch-sync]]
+ [status-im.components.react :refer [view
+ image]]
+ [status-im.components.camera :refer [camera]]
+ [status-im.components.styles :refer [toolbar-background1
+ icon-search]]
+ [status-im.components.toolbar :refer [toolbar]]
+ [status-im.qr-scanner.styles :as st]
+ [status-im.utils.types :refer [json->clj]]))
+
+(defn qr-scanner-toolbar [title]
+ [toolbar {:title title
+ :background-color toolbar-background1
+ :action {:image {:source {:uri :icon_lock_white}
+ :style icon-search}
+ :handler #()}}])
+
+(defview qr-scanner []
+ [identifier [:get :current-qr-context]]
+ [view st/barcode-scanner-container
+ [qr-scanner-toolbar (:toolbar-title identifier)]
+ [camera {;:on-bar-code-read #(js/alert "ok")
+ :onBarCodeRead #(let [data (json->clj (.-data %))]
+ (dispatch [:set-qr-code identifier data]))
+ :style st/barcode-scanner}]
+ [view st/rectangle-container
+ [view st/rectangle
+ [image {:source {:uri :corner_left_top}
+ :style st/corner-left-top}]
+ [image {:source {:uri :corner_right_top}
+ :style st/corner-right-top}]
+ [image {:source {:uri :corner_right_bottom}
+ :style st/corner-right-bottom}]
+ [image {:source {:uri :corner_left_bottom}
+ :style st/corner-left-bottom}]]]])
diff --git a/src/status_im/qr_scanner/styles.cljs b/src/status_im/qr_scanner/styles.cljs
new file mode 100644
index 0000000000..05198031b1
--- /dev/null
+++ b/src/status_im/qr_scanner/styles.cljs
@@ -0,0 +1,76 @@
+(ns status-im.qr-scanner.styles
+ (:require [status-im.components.styles :refer [toolbar-height
+ color-white]]))
+
+(def barcode-scanner-container
+ {:flex 1
+ :backgroundColor :white})
+
+(def barcode-scanner
+ {:flex 1
+ :justifyContent :flex-end
+ :alignItems :center})
+
+(def rectangle-container
+ {:position :absolute
+ :left 0
+ :top toolbar-height
+ :bottom 0
+ :right 0
+ :flex 1
+ :alignItems :center
+ :justifyContent :center
+ :backgroundColor :transparent})
+
+(def rectangle
+ {:height 250
+ :width 250
+ :backgroundColor :transparent})
+
+(def corner-left-top
+ {:position :absolute
+ :left 0
+ :top 0
+ :width 56
+ :height 56})
+
+(def corner-right-top
+ {:position :absolute
+ :right 0
+ :top 0
+ :width 56
+ :height 56})
+
+(def corner-right-bottom
+ {:position :absolute
+ :right 0
+ :bottom 0
+ :width 56
+ :height 56})
+
+(def corner-left-bottom
+ {:position :absolute
+ :left 0
+ :bottom 0
+ :width 56
+ :height 56})
+
+(def import-button
+ {:position :absolute
+ :right 16
+ :flex 1
+ :height 50
+ :alignItems :center})
+
+(def import-button-content
+ {:flex 1
+ :flexDirection :row
+ :height 50
+ :alignItems :center
+ :alignSelf :center})
+
+(def import-text
+ {:flex 1
+ :flexDirection :column
+ :color color-white
+ :margin-left 8})
diff --git a/src/status_im/qr_scanner/views/import-qr-button.cljs b/src/status_im/qr_scanner/views/import-qr-button.cljs
new file mode 100644
index 0000000000..99b7dbc7b7
--- /dev/null
+++ b/src/status_im/qr_scanner/views/import-qr-button.cljs
@@ -0,0 +1,23 @@
+(ns status-im.qr-scanner.views.import-button
+ (:require-macros [status-im.utils.views :refer [defview]])
+ (:require [re-frame.core :refer [subscribe dispatch dispatch-sync]]
+ [status-im.components.react :refer [view
+ text
+ image
+ touchable-highlight]]
+ [status-im.components.toolbar :refer [toolbar]]
+ [status-im.components.drawer.view :refer [drawer-view open-drawer]]
+ [status-im.components.styles :refer [icon-qr]]
+ [status-im.i18n :refer [label]]
+ [status-im.qr-scanner.styles :as st]))
+
+
+(defview import-button [handler]
+ []
+ [view st/import-button
+ [touchable-highlight
+ {:on-press handler}
+ [view st/import-button-content
+ [image {:source {:uri :icon_qr}
+ :style icon-qr}]
+ [text {:style st/import-text} (label :t/import-qr)]]]])
\ No newline at end of file
diff --git a/src/status_im/translations/en.cljs b/src/status_im/translations/en.cljs
index 588332922d..8ec3ba3fb7 100644
--- a/src/status_im/translations/en.cljs
+++ b/src/status_im/translations/en.cljs
@@ -115,8 +115,18 @@
:You "You"
;new-contact
- :import-qr "Import from QR"
+ :import-qr "Import"
:contact-name "Contact Name"
- :contact-address "Contact Address"
+ :whisper-identity "Whisper Identity"
+
+ ;login
+ :recover-from-passphrase "Recover from passphrase"
+ :connect "Connect"
+ :address "Address"
+ :password "Password"
+ :login "Login"
+
+ ;users
+ :add-account "Add account"
})
\ No newline at end of file
diff --git a/src/status_im/utils/types.cljs b/src/status_im/utils/types.cljs
index aa256f0056..93c942df77 100644
--- a/src/status_im/utils/types.cljs
+++ b/src/status_im/utils/types.cljs
@@ -6,4 +6,10 @@
s))
(defn to-edn-string [value]
- (with-out-str (pr value)))
\ No newline at end of file
+ (with-out-str (pr value)))
+
+(defn clj->json [data]
+ (.stringify js/JSON (clj->js data)))
+
+(defn json->clj [data]
+ (js->clj (.parse js/JSON data) :keywordize-keys true))