From 58a9c2935ceda13c737c11742446d0192668fc20 Mon Sep 17 00:00:00 2001 From: Adrian Tiberius Date: Thu, 16 Jun 2016 07:23:11 +0300 Subject: [PATCH 1/8] Moved geth to service --- android/app/src/main/AndroidManifest.xml | 5 + .../main/java/com/statusim/GethService.java | 149 ++++++++++++++++++ .../main/java/com/statusim/MainActivity.java | 110 +++++++++---- 3 files changed, 234 insertions(+), 30 deletions(-) create mode 100644 android/app/src/main/java/com/statusim/GethService.java diff --git a/android/app/src/main/AndroidManifest.xml b/android/app/src/main/AndroidManifest.xml index d8e1a14016..42b5ee2517 100644 --- a/android/app/src/main/AndroidManifest.xml +++ b/android/app/src/main/AndroidManifest.xml @@ -22,6 +22,11 @@ + diff --git a/android/app/src/main/java/com/statusim/GethService.java b/android/app/src/main/java/com/statusim/GethService.java new file mode 100644 index 0000000000..7033cd303e --- /dev/null +++ b/android/app/src/main/java/com/statusim/GethService.java @@ -0,0 +1,149 @@ +package com.statusim; + +import android.app.Service; +import android.content.Intent; +import android.os.Handler; +import android.os.AsyncTask; +import android.os.IBinder; +import android.os.Looper; +import android.os.Message; +import android.os.Messenger; +import android.support.annotation.Nullable; +import android.util.Log; +import android.os.Environment; + +import java.lang.ref.WeakReference; + +import com.facebook.react.common.ApplicationHolder; +import com.github.ethereum.go_ethereum.cmd.Geth; + +import java.io.File; + +public class GethService extends Service { + + private static final String TAG = "GethService"; + + private static boolean isGethStarted = false; + private static boolean isGethInitialized = false; + private final Handler handler = new Handler(); + + static class IncomingHandler extends Handler { + + private final WeakReference service; + + IncomingHandler(GethService service) { + + this.service = new WeakReference(service); + } + + @Override + public void handleMessage(Message message) { + + GethService service = this.service.get(); + if (service != null) { + if (!service.handleMessage(message)) { + super.handleMessage(message); + } + } + } + } + + final Messenger serviceMessenger = new Messenger(new IncomingHandler(this)); + + protected class StartTask extends AsyncTask { + + public StartTask() { + } + + protected Void doInBackground(Void... args) { + startGeth(); + return null; + } + + protected void onPostExecute(Void results) { + onGethStarted(); + } + } + + protected void onGethStarted() { + Log.d(TAG, "Geth Service started"); + isGethStarted = true; + //Log.w("Geth", "adding peer"); + //Geth.run("--exec admin.addPeer(\"enode://e2f28126720452aa82f7d3083e49e6b3945502cb94d9750a15e27ee310eed6991618199f878e5fbc7dfa0e20f0af9554b41f491dc8f1dbae8f0f2d37a3a613aa@139.162.13.89:55555\") attach http://localhost:8545"); + } + + protected void startGeth() { + Log.d(TAG, "Starting background Geth Service"); + + File extStore = Environment.getExternalStorageDirectory(); + + final String dataFolder = extStore.exists() ? + extStore.getAbsolutePath() : + getApplicationInfo().dataDir; + + 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("--shh --ipcdisable --nodiscover --rpc --rpcapi db,eth,net,web3,shh,admin --fast --datadir=" + dataFolder); + } + }).start(); + + handler.postDelayed(addPeer, 5000); + } + + @Nullable + @Override + public IBinder onBind(Intent intent) { + return serviceMessenger.getBinder(); + } + + @Override + public void onCreate() { + super.onCreate(); + //SoLoader.init(this, /* native exopackage */ false); + /* + try { + ApplicationHolder.getApplication(); + } + catch (AssertionError err) { + ApplicationHolder.setApplication(getApplication()); + } +*/ + System.loadLibrary("gethraw"); + System.loadLibrary("geth"); + + if (!isGethInitialized) { + isGethInitialized = true; + new StartTask().execute(); + } + } + + @Override + public void onDestroy() { + super.onDestroy(); + //stop geth + isGethStarted = false; + isGethInitialized = false; + Log.d(TAG, "Geth Service stopped !"); + } + + @Override + public int onStartCommand(Intent intent, int flags, int startId) { + return Service.START_STICKY; + } + + protected boolean handleMessage(Message message) { + return false; + } + + public static boolean isRunning() + { + return isGethInitialized; + } +} diff --git a/android/app/src/main/java/com/statusim/MainActivity.java b/android/app/src/main/java/com/statusim/MainActivity.java index cf17707c29..85348bec41 100644 --- a/android/app/src/main/java/com/statusim/MainActivity.java +++ b/android/app/src/main/java/com/statusim/MainActivity.java @@ -7,17 +7,24 @@ import com.facebook.react.ReactPackage; import com.facebook.react.shell.MainReactPackage; import com.rt2zz.reactnativecontacts.ReactNativeContacts; import android.os.Bundle; -import android.os.Environment; +import android.os.Handler; +import android.os.IBinder; +import android.os.Message; +import android.os.Messenger; 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 android.content.ComponentName; +import android.content.ServiceConnection; +import android.content.Intent; +import android.content.Context; + 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; @@ -32,45 +39,70 @@ import io.realm.react.RealmReactPackage; public class MainActivity extends ReactActivity { - final Handler handler = new Handler(); + /** + * Incoming message handler. Calls to its binder are sequential! + */ + protected final IncomingHandler handler = new IncomingHandler(); + + /** Flag indicating if the service is bound. */ + protected boolean isBound; + + /** Sends messages to the service. */ + protected Messenger serviceMessenger = null; + + /** Receives messages from the service. */ + protected Messenger clientMessenger = new Messenger(handler); + + class IncomingHandler extends Handler { + + @Override + public void handleMessage(Message message) { + + boolean isClaimed = false; + System.out.println("!!!!!!!!!!!!!! Received Service Message !!!!!!!!!!!!!!"); + super.handleMessage(message); + } + } + + protected ServiceConnection serviceConnection = new ServiceConnection() { + + public void onServiceConnected(ComponentName className, IBinder service) { + + // This is called when the connection with the service has been + // established, giving us the object we can use to + // interact with the service. We are communicating with the + // service using a Messenger, so here we get a client-side + // representation of that from the raw IBinder object. + serviceMessenger = new Messenger(service); + isBound = true; + onConnected(); + } + + public void onServiceDisconnected(ComponentName className) { + + // This is called when the connection with the service has been + // unexpectedly disconnected -- that is, its process crashed. + serviceMessenger = null; + isBound = false; + System.out.println("!!!!!!!!!!!!!! Geth Service Disconnected !!!!!!!!!!!!!!"); + } + }; + + protected void onConnected() { + System.out.println("!!!!!!!!!!!!!! Geth Service Connected !!!!!!!!!!!!!!"); + } 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"); - - File extStore = Environment.getExternalStorageDirectory(); - - final String dataFolder = extStore.exists() ? - extStore.getAbsolutePath() : - 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("--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 { @@ -96,9 +128,27 @@ public class MainActivity extends ReactActivity { }).create(); dialog.show(); } + Intent intent = new Intent(this, GethService.class); + if (!GethService.isRunning()) { + startService(intent); + } + if (serviceConnection != null && GethService.isRunning()) { + bindService(intent, serviceConnection, Context.BIND_AUTO_CREATE); + } } + @Override + protected void onDestroy() { + super.onDestroy(); + try { + unbindService(serviceConnection); + } + catch (Throwable t) { + Log.e("MainActivity", "Failed to unbind from the geth service", t); + } + } + /** * Returns the name of the main component registered from JavaScript. * This is used to schedule rendering of the component. From 3d68e6d48af0beb7ee386fb5a3b27c1113900531 Mon Sep 17 00:00:00 2001 From: Adrian Tiberius Date: Thu, 16 Jun 2016 07:27:58 +0300 Subject: [PATCH 2/8] code cleaning --- .../src/main/java/com/statusim/GethService.java | 17 ++--------------- .../main/java/com/statusim/MainActivity.java | 13 ++++++------- 2 files changed, 8 insertions(+), 22 deletions(-) diff --git a/android/app/src/main/java/com/statusim/GethService.java b/android/app/src/main/java/com/statusim/GethService.java index 7033cd303e..7967807cbd 100644 --- a/android/app/src/main/java/com/statusim/GethService.java +++ b/android/app/src/main/java/com/statusim/GethService.java @@ -14,7 +14,6 @@ import android.os.Environment; import java.lang.ref.WeakReference; -import com.facebook.react.common.ApplicationHolder; import com.github.ethereum.go_ethereum.cmd.Geth; import java.io.File; @@ -68,8 +67,6 @@ public class GethService extends Service { protected void onGethStarted() { Log.d(TAG, "Geth Service started"); isGethStarted = true; - //Log.w("Geth", "adding peer"); - //Geth.run("--exec admin.addPeer(\"enode://e2f28126720452aa82f7d3083e49e6b3945502cb94d9750a15e27ee310eed6991618199f878e5fbc7dfa0e20f0af9554b41f491dc8f1dbae8f0f2d37a3a613aa@139.162.13.89:55555\") attach http://localhost:8545"); } protected void startGeth() { @@ -106,15 +103,6 @@ public class GethService extends Service { @Override public void onCreate() { super.onCreate(); - //SoLoader.init(this, /* native exopackage */ false); - /* - try { - ApplicationHolder.getApplication(); - } - catch (AssertionError err) { - ApplicationHolder.setApplication(getApplication()); - } -*/ System.loadLibrary("gethraw"); System.loadLibrary("geth"); @@ -127,7 +115,7 @@ public class GethService extends Service { @Override public void onDestroy() { super.onDestroy(); - //stop geth + //TODO: stop geth isGethStarted = false; isGethInitialized = false; Log.d(TAG, "Geth Service stopped !"); @@ -142,8 +130,7 @@ public class GethService extends Service { return false; } - public static boolean isRunning() - { + public static boolean isRunning() { return isGethInitialized; } } diff --git a/android/app/src/main/java/com/statusim/MainActivity.java b/android/app/src/main/java/com/statusim/MainActivity.java index 85348bec41..341732d5d7 100644 --- a/android/app/src/main/java/com/statusim/MainActivity.java +++ b/android/app/src/main/java/com/statusim/MainActivity.java @@ -39,6 +39,8 @@ import io.realm.react.RealmReactPackage; public class MainActivity extends ReactActivity { + private static final String TAG = "MainActivity"; + /** * Incoming message handler. Calls to its binder are sequential! */ @@ -57,9 +59,8 @@ public class MainActivity extends ReactActivity { @Override public void handleMessage(Message message) { - boolean isClaimed = false; - System.out.println("!!!!!!!!!!!!!! Received Service Message !!!!!!!!!!!!!!"); + Log.d(TAG, "!!!!!!!!!!!!!! Received Service Message !!!!!!!!!!!!!!"); super.handleMessage(message); } } @@ -67,7 +68,6 @@ public class MainActivity extends ReactActivity { protected ServiceConnection serviceConnection = new ServiceConnection() { public void onServiceConnected(ComponentName className, IBinder service) { - // This is called when the connection with the service has been // established, giving us the object we can use to // interact with the service. We are communicating with the @@ -79,17 +79,16 @@ public class MainActivity extends ReactActivity { } public void onServiceDisconnected(ComponentName className) { - // This is called when the connection with the service has been // unexpectedly disconnected -- that is, its process crashed. serviceMessenger = null; isBound = false; - System.out.println("!!!!!!!!!!!!!! Geth Service Disconnected !!!!!!!!!!!!!!"); + Log.d(TAG, "!!!!!!!!!!!!!! Geth Service Disconnected !!!!!!!!!!!!!!"); } }; protected void onConnected() { - System.out.println("!!!!!!!!!!!!!! Geth Service Connected !!!!!!!!!!!!!!"); + Log.d(TAG, "!!!!!!!!!!!!!! Geth Service Connected !!!!!!!!!!!!!!"); } protected void startStatus() { @@ -145,7 +144,7 @@ public class MainActivity extends ReactActivity { unbindService(serviceConnection); } catch (Throwable t) { - Log.e("MainActivity", "Failed to unbind from the geth service", t); + Log.e(TAG, "Failed to unbind from the geth service", t); } } From 9ed4cc03e3e6852f47688fcd9bac39df2d12274d Mon Sep 17 00:00:00 2001 From: virvar Date: Wed, 15 Jun 2016 16:41:08 +0300 Subject: [PATCH 3/8] Grey action bar. Hide navbar on chat list scroll. --- src/status_im/chats_list/screen.cljs | 39 ++++++++++++++++---- src/status_im/components/tabs/styles.cljs | 19 ++++------ src/status_im/components/tabs/tabs.cljs | 45 +++++++++++++++++++---- 3 files changed, 76 insertions(+), 27 deletions(-) diff --git a/src/status_im/chats_list/screen.cljs b/src/status_im/chats_list/screen.cljs index 572f0ac5a9..afd8047b39 100644 --- a/src/status_im/chats_list/screen.cljs +++ b/src/status_im/chats_list/screen.cljs @@ -1,4 +1,5 @@ (ns status-im.chats-list.screen + (:require-macros [status-im.utils.views :refer [defview]]) (:require [re-frame.core :refer [subscribe dispatch]] [status-im.components.react :refer [list-view list-item @@ -13,33 +14,55 @@ action-button-item]] [status-im.components.drawer.view :refer [drawer-view open-drawer]] [status-im.components.styles :refer [color-blue + toolbar-background1 toolbar-background2]] [status-im.components.toolbar :refer [toolbar]] [status-im.components.icons.ionicons :refer [icon]] [status-im.i18n :refer [label]] - [status-im.chats-list.styles :as st])) + [status-im.chats-list.styles :as st] + [status-im.components.tabs.styles :refer [tabs-height]])) -(defn chats-list-toolbar [] +(defview chats-list-toolbar [] + [chats-scrolled? [:get :chats-scrolled?]] [toolbar {:nav-action {:image {:source {:uri :icon_hamburger} :style st/hamburger-icon} :handler open-drawer} :title (label :t/chats) - :background-color toolbar-background2 + :background-color (if chats-scrolled? + toolbar-background1 + toolbar-background2) ;; TODO implement search :action {:image {:source {:uri :icon_search} :style st/search-icon} :handler (fn [])}}]) (defn chats-list [] - (let [chats (subscribe [:get :chats])] + (let [chats (subscribe [:get :chats]) + chat-scrolled? (subscribe [:get :chats-scrolled?]) + container-height (r/atom 0) + content-height (r/atom 0)] + (dispatch [:set :chats-scrolled? false]) (fn [] [drawer-view [view st/chats-container [chats-list-toolbar] - [list-view {:dataSource (to-datasource @chats) - :renderRow (fn [row _ _] - (list-item [chat-list-item row])) - :style st/list-container}] + [list-view {:dataSource (to-datasource @chats) + :renderRow (fn [row _ _] + (list-item [chat-list-item row])) + :style st/list-container + ;;; if "maximazing" chat list will make scroll to 0, + ;;; then disable maximazing + :onLayout (fn [event] + (when-not @chat-scrolled? + (let [height (.. event -nativeEvent -layout -height)] + (reset! container-height height)))) + :onContentSizeChange (fn [width height] + (reset! content-height height)) + :onScroll (fn [e] + (let [offset (.. e -nativeEvent -contentOffset -y) + min-content-height (+ @container-height tabs-height) + scrolled? (and (< 0 offset) (< min-content-height @content-height))] + (dispatch [:set :chats-scrolled? scrolled?])))}] [action-button {:buttonColor color-blue :offsetY 16 :offsetX 16} diff --git a/src/status_im/components/tabs/styles.cljs b/src/status_im/components/tabs/styles.cljs index 45af60e439..7dc57d6d24 100644 --- a/src/status_im/components/tabs/styles.cljs +++ b/src/status_im/components/tabs/styles.cljs @@ -10,21 +10,19 @@ text2-color toolbar-background1]])) +(def tabs-height 59) (def tab-height 56) -(def tabs - {:flex 1 - :position :absolute - :bottom 0 - :right 0 - :left 0 - }) +(defn tabs-container [offset-y] + {:height tabs-height + :backgroundColor color-white + :marginBottom offset-y}) (def top-gradient {:flexDirection :row :height 3}) -(def tabs-container +(def tabs-inner-container {:flexDirection :row :height tab-height :opacity 1 @@ -55,10 +53,9 @@ :alignItems :center}) (defn tab-view-container [offset-x] - {:flex 1 - :position :absolute + {:position :absolute :top 0 :left 0 :right 0 - :bottom tab-height + :bottom 0 :transform [{:translateX offset-x}]}) diff --git a/src/status_im/components/tabs/tabs.cljs b/src/status_im/components/tabs/tabs.cljs index bd12614f3f..bc326a7d43 100644 --- a/src/status_im/components/tabs/tabs.cljs +++ b/src/status_im/components/tabs/tabs.cljs @@ -2,6 +2,7 @@ (:require-macros [status-im.utils.views :refer [defview]]) (:require [re-frame.core :refer [subscribe dispatch dispatch-sync]] [status-im.components.react :refer [view + animated-view text-input text image @@ -9,7 +10,8 @@ linear-gradient]] [reagent.core :as r] [status-im.components.tabs.styles :as st] - [status-im.components.tabs.tab :refer [tab]])) + [status-im.components.tabs.tab :refer [tab]] + [status-im.components.animation :as anim])) (defn create-tab [index data selected-view-id] (let [data (merge data {:key index @@ -17,10 +19,37 @@ :selected-view-id selected-view-id})] [tab data])) -(defview tabs [{:keys [style tab-list selected-view-id]}] - (let [style (merge st/tabs style)] - [view {:style style} - [linear-gradient {:colors ["rgba(24, 52, 76, 0.01)" "rgba(24, 52, 76, 0.085)" "rgba(24, 52, 76, 0.165)"] - :style st/top-gradient}] - [view st/tabs-container - (doall (map-indexed #(create-tab %1 %2 selected-view-id) tab-list))]])) +(defn animation-logic [{:keys [hidden? val]}] + (fn [_] + (let [to-value (if @hidden? (- st/tab-height) 0)] + (anim/start + (anim/timing val {:toValue to-value + :duration 300}) + (fn [e] + (when-not (.-finished e) + nil)))))) + +(defn tabs-container [& children] + (let [chats-scrolled? (subscribe [:get :chats-scrolled?]) + anim-value (anim/create-value 0) + context {:hidden? chats-scrolled? + :val anim-value} + on-update (animation-logic context)] + (r/create-class + {:component-did-mount + on-update + :component-did-update + on-update + :reagent-render + (fn [& children] + @chats-scrolled? + (into [animated-view {:style (st/tabs-container anim-value) + :pointerEvents (if @chats-scrolled? :none :auto)}] + children))}))) + +(defn tabs [{:keys [tab-list selected-view-id]}] + [tabs-container + [linear-gradient {:colors ["rgba(24, 52, 76, 0.01)" "rgba(24, 52, 76, 0.085)" "rgba(24, 52, 76, 0.165)"] + :style st/top-gradient}] + [view st/tabs-inner-container + (doall (map-indexed #(create-tab %1 %2 selected-view-id) tab-list))]]) From 8622859c3a1fc256c63b437c10ba2e6ce0d93824 Mon Sep 17 00:00:00 2001 From: virvar Date: Thu, 16 Jun 2016 12:44:56 +0300 Subject: [PATCH 4/8] Improve tabs bar animation --- src/status_im/chats_list/screen.cljs | 42 +++++++++++++---------- src/status_im/chats_list/styles.cljs | 11 +++++- src/status_im/components/tabs/styles.cljs | 6 ++-- src/status_im/components/tabs/tabs.cljs | 30 +++++++++------- src/status_im/db.cljs | 3 +- 5 files changed, 58 insertions(+), 34 deletions(-) diff --git a/src/status_im/chats_list/screen.cljs b/src/status_im/chats_list/screen.cljs index afd8047b39..ad4624f798 100644 --- a/src/status_im/chats_list/screen.cljs +++ b/src/status_im/chats_list/screen.cljs @@ -4,6 +4,7 @@ [status-im.components.react :refer [list-view list-item view + animated-view text image touchable-highlight]] @@ -38,7 +39,9 @@ (defn chats-list [] (let [chats (subscribe [:get :chats]) - chat-scrolled? (subscribe [:get :chats-scrolled?]) + chats-scrolled? (subscribe [:get :chats-scrolled?]) + animation? (subscribe [:animations :tabs-bar-animation?]) + tabs-bar-value (subscribe [:animations :tabs-bar-value]) container-height (r/atom 0) content-height (r/atom 0)] (dispatch [:set :chats-scrolled? false]) @@ -53,7 +56,7 @@ ;;; if "maximazing" chat list will make scroll to 0, ;;; then disable maximazing :onLayout (fn [event] - (when-not @chat-scrolled? + (when-not @chats-scrolled? (let [height (.. event -nativeEvent -layout -height)] (reset! container-height height)))) :onContentSizeChange (fn [width height] @@ -62,19 +65,22 @@ (let [offset (.. e -nativeEvent -contentOffset -y) min-content-height (+ @container-height tabs-height) scrolled? (and (< 0 offset) (< min-content-height @content-height))] - (dispatch [:set :chats-scrolled? scrolled?])))}] - [action-button {:buttonColor color-blue - :offsetY 16 - :offsetX 16} - [action-button-item - {:title (label :t/new-chat) - :buttonColor :#9b59b6 - :onPress #(dispatch [:navigate-to :contact-list])} - [icon {:name :android-create - :style st/create-icon}]] - [action-button-item - {:title (label :t/new-group-chat) - :buttonColor :#1abc9c - :onPress #(dispatch [:show-group-new])} - [icon {:name :person-stalker - :style st/person-stalker-icon}]]]]]))) + (dispatch [:set :chats-scrolled? scrolled?]) + (dispatch [:set-animation :tabs-bar-animation? true])))}] + [animated-view {:style (st/action-buttons-container @animation? (or @tabs-bar-value 0)) + :pointerEvents :box-none} + [action-button {:buttonColor color-blue + :offsetY 16 + :offsetX 16} + [action-button-item + {:title (label :t/new-chat) + :buttonColor :#9b59b6 + :onPress #(dispatch [:navigate-to :contact-list])} + [icon {:name :android-create + :style st/create-icon}]] + [action-button-item + {:title (label :t/new-group-chat) + :buttonColor :#1abc9c + :onPress #(dispatch [:show-group-new])} + [icon {:name :person-stalker + :style st/person-stalker-icon}]]]]]]))) diff --git a/src/status_im/chats_list/styles.cljs b/src/status_im/chats_list/styles.cljs index ca72f89042..6621aedfce 100644 --- a/src/status_im/chats_list/styles.cljs +++ b/src/status_im/chats_list/styles.cljs @@ -6,7 +6,8 @@ online-color text1-color text2-color - new-messages-count-color]])) + new-messages-count-color]] + [status-im.components.tabs.styles :refer [tabs-height]])) (def chat-container {:flexDirection :row @@ -113,3 +114,11 @@ {:fontSize 20 :height 22 :color :white}) + +(defn action-buttons-container [animation? offset-y] + {:position :absolute + :left 0 + :right 0 + :top 0 + :bottom 0 + :transform [{:translateY (if animation? offset-y 1)}]}) diff --git a/src/status_im/components/tabs/styles.cljs b/src/status_im/components/tabs/styles.cljs index 7dc57d6d24..2d873e88cd 100644 --- a/src/status_im/components/tabs/styles.cljs +++ b/src/status_im/components/tabs/styles.cljs @@ -13,10 +13,12 @@ (def tabs-height 59) (def tab-height 56) -(defn tabs-container [offset-y] +(defn tabs-container [hidden? animation? offset-y] {:height tabs-height :backgroundColor color-white - :marginBottom offset-y}) + :marginBottom (if (or hidden? animation?) + (- tabs-height) 0) + :transform [{:translateY (if animation? offset-y 1)}]}) (def top-gradient {:flexDirection :row diff --git a/src/status_im/components/tabs/tabs.cljs b/src/status_im/components/tabs/tabs.cljs index bc326a7d43..a6d10d5d8d 100644 --- a/src/status_im/components/tabs/tabs.cljs +++ b/src/status_im/components/tabs/tabs.cljs @@ -20,21 +20,27 @@ [tab data])) (defn animation-logic [{:keys [hidden? val]}] - (fn [_] - (let [to-value (if @hidden? (- st/tab-height) 0)] - (anim/start - (anim/timing val {:toValue to-value - :duration 300}) - (fn [e] - (when-not (.-finished e) - nil)))))) + (let [was-hidden? (atom (not @hidden?))] + (fn [_] + (when (not= @was-hidden? @hidden?) + (let [to-value (if @hidden? 0 (- st/tabs-height))] + (swap! was-hidden? not) + (anim/start + (anim/timing val {:toValue to-value + :duration 300}) + (fn [e] + ;; if to-value was changed, then new animation has started + (when (= to-value (if @hidden? 0 (- st/tabs-height))) + (dispatch [:set-animation :tabs-bar-animation? false]))))))))) (defn tabs-container [& children] (let [chats-scrolled? (subscribe [:get :chats-scrolled?]) - anim-value (anim/create-value 0) - context {:hidden? chats-scrolled? - :val anim-value} + animation? (subscribe [:animations :tabs-bar-animation?]) + tabs-bar-value (subscribe [:animations :tabs-bar-value]) + context {:hidden? chats-scrolled? + :val @tabs-bar-value} on-update (animation-logic context)] + (anim/set-value @tabs-bar-value 0) (r/create-class {:component-did-mount on-update @@ -43,7 +49,7 @@ :reagent-render (fn [& children] @chats-scrolled? - (into [animated-view {:style (st/tabs-container anim-value) + (into [animated-view {:style (st/tabs-container @chats-scrolled? @animation? @tabs-bar-value) :pointerEvents (if @chats-scrolled? :none :auto)}] children))}))) diff --git a/src/status_im/db.cljs b/src/status_im/db.cljs index 2b3ad6f88f..25772a58fa 100644 --- a/src/status_im/db.cljs +++ b/src/status_im/db.cljs @@ -44,7 +44,8 @@ :message-input-buttons-scale 1 :messages-offset 0 :commands-input-is-switching? false - :response-resize? false}}) + :response-resize? false + :tabs-bar-value (anim/create-value 0)}}) (def protocol-initialized-path [:protocol-initialized]) (defn chat-input-text-path [chat-id] From b216d7624a3bacdfcb72c391891b89b1bcf67038 Mon Sep 17 00:00:00 2001 From: virvar Date: Wed, 15 Jun 2016 11:39:38 +0300 Subject: [PATCH 5/8] Keep the keyboard open after message sending --- src/status_im/chat/views/message_input.cljs | 17 ++++++----------- src/status_im/chat/views/plain_message.cljs | 12 +++--------- 2 files changed, 9 insertions(+), 20 deletions(-) diff --git a/src/status_im/chat/views/message_input.cljs b/src/status_im/chat/views/message_input.cljs index 4c26e15eb8..e40cfa4f8f 100644 --- a/src/status_im/chat/views/message_input.cljs +++ b/src/status_im/chat/views/message_input.cljs @@ -6,8 +6,7 @@ animated-view icon touchable-highlight - text-input - dismiss-keyboard!]] + text-input]] [status-im.components.animation :as anim] [status-im.chat.views.plain-message :as plain-message] [status-im.chat.views.command :as command] @@ -61,8 +60,7 @@ staged-commands [:get-chat-staged-commands] typing-command? [:typing-command?] commands-input-is-switching? [:animations :commands-input-is-switching?]] - (let [dismiss-keyboard (not (or command typing-command?)) - response? (and command to-msg-id) + (let [response? (and command to-msg-id) message-input? (or (not command) commands-input-is-switching?) animation? commands-input-is-switching?] [text-input (merge {:style (cond @@ -72,7 +70,7 @@ :ref (fn [input] (dispatch [:set-message-input input])) :autoFocus false - :blurOnSubmit dismiss-keyboard + :blurOnSubmit false :onChangeText (fn [text] (when-not animation? ((if message-input? @@ -82,8 +80,7 @@ :onSubmitEditing #(when-not animation? (if message-input? (plain-message/try-send staged-commands - input-message - dismiss-keyboard) + input-message) (command/try-send input-command validator)))} (when command {:accessibility-label :command-input}) @@ -100,8 +97,7 @@ staged-commands [:get-chat-staged-commands] typing-command? [:typing-command?] commands-input-is-switching? [:animations :commands-input-is-switching?]] - (let [dismiss-keyboard (not (or command typing-command?)) - response? (and command to-msg-id) + (let [response? (and command to-msg-id) message-input? (or (not command) commands-input-is-switching?)] [view st/input-container [view st/input-view @@ -117,8 +113,7 @@ (if message-input? (when (plain-message/message-valid? staged-commands input-message) [send-button {:on-press #(plain-message/try-send staged-commands - input-message - dismiss-keyboard) + input-message) :accessibility-label :send-message}]) (if (command/valid? input-command validator) [send-button {:on-press command/send-command diff --git a/src/status_im/chat/views/plain_message.cljs b/src/status_im/chat/views/plain_message.cljs index 7c637ebbd0..0284e0e25f 100644 --- a/src/status_im/chat/views/plain_message.cljs +++ b/src/status_im/chat/views/plain_message.cljs @@ -5,8 +5,7 @@ [status-im.components.react :refer [view animated-view icon - touchable-highlight - dismiss-keyboard!]] + touchable-highlight]] [status-im.components.animation :as anim] [status-im.chat.styles.plain-message :as st] [status-im.constants :refer [response-input-hiding-duration]])) @@ -14,19 +13,14 @@ (defn set-input-message [message] (dispatch [:set-chat-input-text message])) -(defn send [dismiss-keyboard] - (when dismiss-keyboard - (dismiss-keyboard!)) - (dispatch [:send-chat-msg])) - (defn message-valid? [staged-commands message] (or (and (pos? (count message)) (not= "!" message)) (pos? (count staged-commands)))) -(defn try-send [staged-commands message dismiss-keyboard] +(defn try-send [staged-commands message] (when (message-valid? staged-commands message) - (send dismiss-keyboard))) + (dispatch [:send-chat-msg]))) (defn prepare-message-input [message-input] (when message-input From defc5a44b35e1b4baef3a24f218878143514a905 Mon Sep 17 00:00:00 2001 From: Jarrad Hope Date: Tue, 21 Jun 2016 13:46:46 +0200 Subject: [PATCH 6/8] set linear-gradient to last known working version --- package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package.json b/package.json index b26cf32faf..877b612afe 100644 --- a/package.json +++ b/package.json @@ -16,7 +16,7 @@ "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-linear-gradient": "1.5.7", "react-native-loading-spinner-overlay": "0.0.8", "react-native-qrcode": "^0.2.2", "react-native-randombytes": "^2.1.0", From eab8dd5ca21b851da7fa508b978a0fb1ffa79647 Mon Sep 17 00:00:00 2001 From: Adrian Tiberius Date: Tue, 21 Jun 2016 15:23:19 +0300 Subject: [PATCH 7/8] added identicons for default profile pictures --- .re-natal | 3 ++- package.json | 1 + src/status_im/contacts/views/new_contact.cljs | 3 ++- src/status_im/models/contacts.cljs | 5 +++-- src/status_im/utils/identicon.cljs | 9 +++++++++ 5 files changed, 17 insertions(+), 4 deletions(-) create mode 100644 src/status_im/utils/identicon.cljs diff --git a/.re-natal b/.re-natal index 4fecaf5ca5..a547f09695 100644 --- a/.re-natal +++ b/.re-natal @@ -18,7 +18,8 @@ "react-native-linear-gradient", "react-native-android-sms-listener", "react-native-camera", - "react-native-qrcode" + "react-native-qrcode", + "identicon.js" ], "imageDirs": [ "images" diff --git a/package.json b/package.json index b26cf32faf..dae27c270e 100644 --- a/package.json +++ b/package.json @@ -7,6 +7,7 @@ }, "dependencies": { "awesome-phonenumber": "^1.0.13", + "identicon.js": "github:status-im/identicon.js", "react": "^0.14.5", "react-native": "^0.24.1", "react-native-action-button": "^1.1.4", diff --git a/src/status_im/contacts/views/new_contact.cljs b/src/status_im/contacts/views/new_contact.cljs index 469ed6b914..8a6132f19d 100644 --- a/src/status_im/contacts/views/new_contact.cljs +++ b/src/status_im/contacts/views/new_contact.cljs @@ -7,6 +7,7 @@ image linear-gradient touchable-highlight]] + [status-im.utils.identicon :refer [identicon]] [status-im.components.toolbar :refer [toolbar]] [status-im.components.drawer.view :refer [drawer-view open-drawer]] [status-im.components.styles :refer [color-purple @@ -71,7 +72,7 @@ :custom-content toolbar-title :action {:image {:source {:uri :icon_add} :style icon-search} - :handler #(dispatch [:add-new-contact new-contact])}}] + :handler #(dispatch [:add-new-contact (merge new-contact {:photo-path (identicon whisper-identity 40)})])}}] [view st/form-container [contact-whisper-id-input whisper-identity] [contact-name-input name] diff --git a/src/status_im/models/contacts.cljs b/src/status_im/models/contacts.cljs index ec286b17a6..03194bc37c 100644 --- a/src/status_im/models/contacts.cljs +++ b/src/status_im/models/contacts.cljs @@ -1,5 +1,6 @@ (ns status-im.models.contacts (:require [status-im.persistence.realm :as r] + [status-im.utils.identicon :refer [identicon]] [status-im.persistence.realm-queries :refer [include-query exclude-query]])) @@ -8,9 +9,9 @@ (r/sorted :name :asc) r/collection->map)) -(defn create-contact [{:keys [name photo-path] :as contact}] +(defn create-contact [{:keys [name photo-path whisper-identity] :as contact}] (->> {:name (or name "") - :photo-path (or photo-path "")} + :photo-path (or photo-path (identicon whisper-identity 40))} (merge contact) (r/create :contacts))) diff --git a/src/status_im/utils/identicon.cljs b/src/status_im/utils/identicon.cljs new file mode 100644 index 0000000000..de585e4b04 --- /dev/null +++ b/src/status_im/utils/identicon.cljs @@ -0,0 +1,9 @@ +(ns status-im.utils.identicon + (:require [clojure.string :as s] + [status-im.utils.utils :as u])) + +(def identicon-js (u/require "identicon.js")) + +(defn identicon [hash options] + (str "data:image/png;base64," (.toString (new identicon-js hash options)))) + From 5a409ed6bf803c75c128ab74ad78fdcb84113bab Mon Sep 17 00:00:00 2001 From: Adrian Tiberius Date: Tue, 21 Jun 2016 16:05:46 +0300 Subject: [PATCH 8/8] cleanup --- src/status_im/contacts/views/new_contact.cljs | 2 +- src/status_im/models/contacts.cljs | 2 +- src/status_im/utils/identicon.cljs | 8 ++++++-- 3 files changed, 8 insertions(+), 4 deletions(-) diff --git a/src/status_im/contacts/views/new_contact.cljs b/src/status_im/contacts/views/new_contact.cljs index 8a6132f19d..4af9d3c5d4 100644 --- a/src/status_im/contacts/views/new_contact.cljs +++ b/src/status_im/contacts/views/new_contact.cljs @@ -72,7 +72,7 @@ :custom-content toolbar-title :action {:image {:source {:uri :icon_add} :style icon-search} - :handler #(dispatch [:add-new-contact (merge new-contact {:photo-path (identicon whisper-identity 40)})])}}] + :handler #(dispatch [:add-new-contact (merge {:photo-path (identicon whisper-identity)} new-contact)])}}] [view st/form-container [contact-whisper-id-input whisper-identity] [contact-name-input name] diff --git a/src/status_im/models/contacts.cljs b/src/status_im/models/contacts.cljs index 03194bc37c..6c3ea62a7a 100644 --- a/src/status_im/models/contacts.cljs +++ b/src/status_im/models/contacts.cljs @@ -11,7 +11,7 @@ (defn create-contact [{:keys [name photo-path whisper-identity] :as contact}] (->> {:name (or name "") - :photo-path (or photo-path (identicon whisper-identity 40))} + :photo-path (or photo-path (identicon whisper-identity))} (merge contact) (r/create :contacts))) diff --git a/src/status_im/utils/identicon.cljs b/src/status_im/utils/identicon.cljs index de585e4b04..2d8dac64e1 100644 --- a/src/status_im/utils/identicon.cljs +++ b/src/status_im/utils/identicon.cljs @@ -2,8 +2,12 @@ (:require [clojure.string :as s] [status-im.utils.utils :as u])) +(def default-size 40) + (def identicon-js (u/require "identicon.js")) -(defn identicon [hash options] - (str "data:image/png;base64," (.toString (new identicon-js hash options)))) +(defn identicon + ([hash] (identicon hash default-size)) + ([hash options] + (str "data:image/png;base64," (.toString (new identicon-js hash options)))))