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))