diff --git a/.re-natal b/.re-natal index 36abebbe7a..9fc06c60ed 100644 --- a/.re-natal +++ b/.re-natal @@ -1,7 +1,7 @@ { "name": "StatusIm", "interface": "reagent", - "androidHost": "10.0.3.2", + "androidHost": "10.0.2.2", "modules": [ "react-native-contacts", "react-native-invertible-scroll-view", diff --git a/env/dev/env/android/main.cljs b/env/dev/env/android/main.cljs index d729fd654f..231444df12 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.2.2:3449/figwheel-ws" :heads-up-display false :jsload-callback #(swap! cnt inc)) diff --git a/src/status_im/android/platform.cljs b/src/status_im/android/platform.cljs index 65aabd41c0..0c21c619b5 100644 --- a/src/status_im/android/platform.cljs +++ b/src/status_im/android/platform.cljs @@ -13,6 +13,8 @@ :bar-style "default" :translucent? true :color styles/color-transparent}} + :chat {:new-message {:border-top-color styles/color-transparent + :border-top-width 0.5}} :bottom-gradient {:height 3} :input-label {:left 4} :input-error-text {:margin-left 4} diff --git a/src/status_im/chat/handlers.cljs b/src/status_im/chat/handlers.cljs index 16e56da248..6d9e484fd2 100644 --- a/src/status_im/chat/handlers.cljs +++ b/src/status_im/chat/handlers.cljs @@ -36,7 +36,8 @@ [cljs.core.async :as a] status-im.chat.handlers.webview-bridge status-im.chat.handlers.wallet-chat - status-im.chat.handlers.console)) + status-im.chat.handlers.console + [taoensso.timbre :as log])) (register-handler :set-chat-ui-props (fn [db [_ ui-element value]] @@ -154,6 +155,28 @@ (dispatch [:set-chat-command command type]) (dispatch [:set-chat-command-content text])))) +(register-handler :set-staged-commands-scroll-view + (fn [{:keys [current-chat-id] :as db} [_ view]] + (assoc-in db [:chats current-chat-id :staged-scroll-view] view))) + +(register-handler :set-staged-commands-scroll-height + (fn [{:keys [current-chat-id] :as db} [_ height]] + (assoc-in db [:chats current-chat-id :staged-scroll-height] height))) + +(register-handler :staged-commands-scroll-to + (u/side-effect! + (fn [{:keys [current-chat-id chats]} [_ height]] + (let [{:keys [staged-scroll-view staged-scroll-height]} (get chats current-chat-id)] + (when staged-scroll-view + (let [y (if (< 0 staged-scroll-height height) + (- height staged-scroll-height) + 0)] + (.scrollTo staged-scroll-view (clj->js {:x 0 :y y})))))))) + +(register-handler :set-message-input-view-height + (fn [{:keys [current-chat-id] :as db} [_ height]] + (assoc-in db [:chats current-chat-id :message-input-height] height))) + (register-handler ::check-suggestions [(after select-suggestion!) (after #(dispatch [:animate-command-suggestions]))] diff --git a/src/status_im/chat/handlers/animation.cljs b/src/status_im/chat/handlers/animation.cljs index 04f7cf4100..a6d6bf206d 100644 --- a/src/status_im/chat/handlers/animation.cljs +++ b/src/status_im/chat/handlers/animation.cljs @@ -1,11 +1,13 @@ (ns status-im.chat.handlers.animation - (:require [re-frame.core :refer [after dispatch debug path]] + (:require [re-frame.core :refer [after dispatch subscribe debug path]] [status-im.utils.handlers :refer [register-handler]] [status-im.chat.constants :refer [input-height request-info-height suggestions-header-height minimum-command-suggestions-height response-height-normal minimum-suggestion-height]] - [status-im.constants :refer [response-input-hiding-duration]])) + [status-im.utils.platform :refer [platform-specific]] + [status-im.constants :refer [response-input-hiding-duration]] + [taoensso.timbre :as log])) ;; todo magic value (def middle-height 270) @@ -71,7 +73,10 @@ (defn fix-height [height-key height-signal-key suggestions-key minimum] (fn [{:keys [current-chat-id] :as db} [_ vy current no-animation]] - (let [max-height (get-in db [:layout-height]) + (let [input-margin (subscribe [:input-margin]) + max-height (- (get-in db [:layout-height]) + (get-in platform-specific [:component-styles :status-bar :default :height]) + @input-margin) moving-down? (pos? vy) moving-up? (not moving-down?) under-middle-position? (<= current middle-height) diff --git a/src/status_im/chat/screen.cljs b/src/status_im/chat/screen.cljs index 19aea94cb7..2a5ecb6e19 100644 --- a/src/status_im/chat/screen.cljs +++ b/src/status_im/chat/screen.cljs @@ -20,19 +20,18 @@ [status-im.components.toolbar.view :refer [toolbar]] [status-im.chat.views.message :refer [chat-message]] [status-im.chat.views.datemark :refer [chat-datemark]] - [status-im.chat.views.suggestions :refer [suggestion-container]] [status-im.chat.views.response :refer [response-view]] - [status-im.chat.views.new-message :refer [chat-message-new]] + [status-im.chat.views.new-message :refer [chat-message-input-view]] + [status-im.chat.views.staged-commands :refer [staged-commands-view]] [status-im.chat.views.actions :refer [actions-view]] [status-im.chat.views.bottom-info :refer [bottom-info-view]] [status-im.chat.views.toolbar-content :refer [toolbar-content-view]] + [status-im.chat.views.suggestions :refer [suggestion-container]] [status-im.i18n :refer [label label-pluralize]] [status-im.components.animation :as anim] [status-im.components.sync-state.offline :refer [offline-view]] [status-im.constants :refer [content-type-status]] - [reagent.core :as r] - [cljs-time.core :as t] - [taoensso.timbre :as log])) + [reagent.core :as r])) (defn contacts-by-identity [contacts] (->> contacts @@ -171,14 +170,16 @@ :reagent-render (fn [messages] @offset - [animated-view {:style (st/messages-container messages-offset)} - messages])}))) + (let [staged-scroll-height (subscribe [:get-chat-staged-commands-scroll-height])] + [animated-view {:style (st/messages-container @staged-scroll-height messages-offset)} + messages]))}))) (defn chat [] (let [group-chat (subscribe [:chat :group-chat]) show-actions? (subscribe [:chat-ui-props :show-actions?]) show-bottom-info? (subscribe [:chat-ui-props :show-bottom-info?]) command? (subscribe [:command?]) + staged-commands (subscribe [:get-chat-staged-commands]) layout-height (subscribe [:get :layout-height])] (r/create-class {:component-did-mount #(dispatch [:check-autorun]) @@ -194,10 +195,12 @@ [messages-view @group-chat]] ;; todo uncomment this #_(when @group-chat [typing-all]) - [response-view] + (when (seq @staged-commands) + [staged-commands-view @staged-commands]) (when-not @command? [suggestion-container]) - [chat-message-new] + [response-view] + [chat-message-input-view] (when @show-actions? [actions-view]) (when @show-bottom-info? diff --git a/src/status_im/chat/styles/input.cljs b/src/status_im/chat/styles/input.cljs index cf8e6137b6..5ca4cb370b 100644 --- a/src/status_im/chat/styles/input.cljs +++ b/src/status_im/chat/styles/input.cljs @@ -12,8 +12,7 @@ (def command-input-container {:flexDirection :row :height 56 - :backgroundColor color-white - :elevation 4}) + :backgroundColor color-white}) (def command-container {:left 0 @@ -71,6 +70,15 @@ :width 12 :height 12}) +(defn staged-commands [message-input-height input-margin] + {:position :absolute + :background-color color-white + :bottom (+ message-input-height input-margin) + :left 0 + :right 0 + :max-height 150 + :elevation 5}) + (def staged-command-container {:flex 1 :alignItems :flex-start @@ -79,7 +87,9 @@ (def staged-command-background {:flexDirection :column - :margin 16 + :margin-top 16 + :margin-left 16 + :margin-right 16 :padding-bottom 12 :padding-left 12 :backgroundColor chat-background @@ -103,3 +113,7 @@ :marginHorizontal 0 :fontSize 14 :color color-black}) + +(def staged-commands-bottom + {:height 16 + :background-color "white"}) diff --git a/src/status_im/chat/styles/message.cljs b/src/status_im/chat/styles/message.cljs index 120ed222c9..773e408c00 100644 --- a/src/status_im/chat/styles/message.cljs +++ b/src/status_im/chat/styles/message.cljs @@ -264,7 +264,7 @@ (defn message-container [height] {:height height}) -(defn new-message-container [margin] - {:backgroundColor color-white - :elevation 4 - :margin-bottom margin}) +(defn new-message-container [margin on-top?] + {:background-color color-white + :margin-bottom margin + :elevation (if on-top? 6 5)}) \ No newline at end of file diff --git a/src/status_im/chat/styles/message_input.cljs b/src/status_im/chat/styles/message_input.cljs index 9f17e54bc1..a7cb57913a 100644 --- a/src/status_im/chat/styles/message_input.cljs +++ b/src/status_im/chat/styles/message_input.cljs @@ -26,7 +26,7 @@ :margin-right 0}) (def send-wrapper - {:margin-bottom 8 + {:margin-bottom 10 :margin-right 10 :width 36 :flex 1 diff --git a/src/status_im/chat/styles/response.cljs b/src/status_im/chat/styles/response.cljs index f76a1b8135..835d4906ff 100644 --- a/src/status_im/chat/styles/response.cljs +++ b/src/status_im/chat/styles/response.cljs @@ -49,15 +49,15 @@ :opacity 0.69 :color color-white}) -(defn response-view [keyboard-height height] +(defn response-view [height input-margin staged-commands] {:flexDirection :column :position :absolute + :elevation (if (seq staged-commands) 5 4) :left 0 :right 0 - :bottom keyboard-height + :bottom input-margin :height height - :backgroundColor color-white - :elevation 2}) + :backgroundColor color-white}) (def input-placeholder {:height input-height}) diff --git a/src/status_im/chat/styles/screen.cljs b/src/status_im/chat/styles/screen.cljs index 6d604b21d4..41863131e2 100644 --- a/src/status_im/chat/styles/screen.cljs +++ b/src/status_im/chat/styles/screen.cljs @@ -16,9 +16,10 @@ (def toolbar-container {}) -(defn messages-container [bottom] +(defn messages-container [staged-height bottom] {:flex 1 - :padding-bottom bottom}) + :padding-bottom bottom + :margin-bottom staged-height}) (def toolbar-view {:flexDirection :row diff --git a/src/status_im/chat/styles/suggestions.cljs b/src/status_im/chat/styles/suggestions.cljs index 83076d4ae9..672396d919 100644 --- a/src/status_im/chat/styles/suggestions.cljs +++ b/src/status_im/chat/styles/suggestions.cljs @@ -66,15 +66,15 @@ :fontSize 12 :color text2-color}) -(defn container [keyboard-height height] +(defn container [height input-margin staged-commands] {:flexDirection :column :position :absolute :left 0 :right 0 - :bottom keyboard-height + :bottom input-margin :height height :backgroundColor color-white - :elevation 2}) + :elevation (if (seq staged-commands) 5 4)}) (def request-container {:height 56 diff --git a/src/status_im/chat/subs.cljs b/src/status_im/chat/subs.cljs index 41027ddfe5..17468771d1 100644 --- a/src/status_im/chat/subs.cljs +++ b/src/status_im/chat/subs.cljs @@ -10,7 +10,8 @@ [status-im.chat.views.command :as command] [status-im.constants :refer [content-type-status]] [status-im.utils.datetime :as time] - [status-im.utils.platform :refer [platform-specific]])) + [status-im.utils.platform :refer [platform-specific]] + [taoensso.timbre :as log])) (register-sub :chat-properties (fn [db [_ properties]] @@ -79,6 +80,17 @@ vals (reaction)))) +(register-sub :get-chat-staged-commands-scroll-height + (fn [db _] + (let [{:keys [staged-commands + staged-scroll-height]} (get-in @db [:chats (:current-chat-id @db)])] + (reaction + (if (seq staged-commands) staged-scroll-height 0))))) + +(register-sub :get-message-input-view-height + (fn [db _] + (reaction (get-in @db [:chats (:current-chat-id @db) :message-input-height])))) + (register-sub :valid-plain-message? (fn [_ _] (let [input-message (subscribe [:get-chat-input-text]) @@ -145,17 +157,14 @@ (let [command? (subscribe [:command?]) type (subscribe [:command-type]) command-suggestions (subscribe [:get-content-suggestions]) - suggestions (subscribe [:get-suggestions])] + staged-commands (subscribe [:get-chat-staged-commands])] (reaction - (cond (and @command? (= @type :response)) + (cond (and @command? (= @type :response) (not (seq @staged-commands))) c/request-info-height (and @command? (= @type :command) (seq @command-suggestions)) c/suggestions-header-height - (and (not @command?) (seq @suggestions)) - c/suggestions-header-height - :else 0))))) (register-sub :command-icon-width @@ -242,21 +251,21 @@ (register-sub :input-margin (fn [] (let [kb-height (subscribe [:get :keyboard-height]) - command (subscribe [:get-chat-command]) focused (subscribe [:get :focused]) mode (subscribe [:kb-mode])] (reaction - (cond (or ios? - (and (not @focused) - (= :on-send (keyword (:suggestions-trigger @command))) - (pos? @kb-height))) - @kb-height - - (and @focused (= :pan @mode) (pos? @kb-height)) - 20 - + (cond ios? @kb-height + (and @focused (= :pan @mode) (pos? @kb-height)) 20 :else 0))))) +(register-sub :max-layout-height + (fn [db [_ status-bar]] + (let [layout-height (subscribe [:get :layout-height]) + input-margin (subscribe [:input-margin]) + status-bar-height (get-in platform-specific [:component-styles :status-bar status-bar :height])] + (reaction + (- @layout-height @input-margin status-bar-height))))) + (register-sub :all-messages-loaded? (fn [db] (let [chat-id (subscribe [:get-current-chat-id])] diff --git a/src/status_im/chat/views/new_message.cljs b/src/status_im/chat/views/new_message.cljs index 01308d0d98..02a8844fa4 100644 --- a/src/status_im/chat/views/new_message.cljs +++ b/src/status_im/chat/views/new_message.cljs @@ -1,20 +1,18 @@ (ns status-im.chat.views.new-message (:require-macros [status-im.utils.views :refer [defview]]) (:require - [re-frame.core :refer [subscribe]] - [status-im.components.react :refer [view]] + [re-frame.core :refer [dispatch subscribe]] + [status-im.components.react :refer [view + scroll-view]] [status-im.chat.views.message-input :refer [plain-message-input-view]] - [status-im.chat.views.staged-command :refer [simple-command-staged-view]] + [status-im.chat.views.staged-commands :refer [simple-command-staged-view]] + [status-im.chat.constants :refer [input-height]] [status-im.utils.platform :refer [platform-specific]] - [status-im.chat.styles.message :as st])) + [status-im.chat.styles.message :as st] + [taoensso.timbre :as log])) -(defn staged-command-view [stage-command] - [simple-command-staged-view stage-command]) - -(defn staged-commands-view [staged-commands] - [view {} - (for [command staged-commands] - ^{:key command} [staged-command-view command])]) +(defn get-height [event] + (.-height (.-layout (.-nativeEvent event)))) (defn get-options [{:keys [type placeholder]} command-type] (let [options (case (keyword type) @@ -29,19 +27,20 @@ options) (assoc-in options [:input-options :placeholder] "")))) -(defview show-input [] - [parameter [:get-command-parameter] +(defview chat-message-input-view [] + [margin [:input-margin] command? [:command?] - type [:command-type]] - [plain-message-input-view - (when command? (get-options parameter type))]) - -(defview chat-message-new [] - [staged-commands [:get-chat-staged-commands] - margin [:input-margin]] - (let [style (get-in platform-specific [:component-styles :chat :new-message])] - [view (merge (st/new-message-container margin) - style) - (when (seq staged-commands) - [staged-commands-view staged-commands]) - [show-input]])) + response-height [:response-height] + parameter [:get-command-parameter] + type [:command-type] + suggestions [:get-suggestions] + staged-commands [:get-chat-staged-commands]] + (let [on-top? (or (and (not (empty? suggestions)) + (not command?)) + (not= response-height input-height)) + style (when-not (seq staged-commands) + (get-in platform-specific [:component-styles :chat :new-message]))] + [view {:style (merge (st/new-message-container margin on-top?) style) + :on-layout #(dispatch [:set-message-input-view-height (get-height %)])} + [plain-message-input-view + (when command? (get-options parameter type))]])) diff --git a/src/status_im/chat/views/response.cljs b/src/status_im/chat/views/response.cljs index 8b66b338b9..b496391457 100644 --- a/src/status_im/chat/views/response.cljs +++ b/src/status_im/chat/views/response.cljs @@ -23,7 +23,8 @@ [status-im.utils.platform :refer [ios?]] [status-im.components.webview-bridge :refer [webview-bridge]] [status-im.i18n :refer [label]] - [status-im.utils.datetime :as dt])) + [status-im.utils.datetime :as dt] + [taoensso.timbre :as log])) (defn drag-icon [] [view st/drag-container @@ -52,7 +53,7 @@ (dt/format-date "HH:mm" added))])]) (defn request-info [response-height] - (let [layout-height (subscribe [:get :layout-height]) + (let [layout-height (subscribe [:max-layout-height :default]) pan-responder (resp/pan-responder response-height layout-height :fix-response-height) @@ -74,19 +75,22 @@ (defn container-animation-logic [{:keys [to-value val animate?]}] (when-let [to-value @to-value] - (when-not (= to-value (.-_value val)) - (if (or (nil? @animate?) @animate?) - (anim/start (anim/timing val {:toValue to-value - :duration 300})) - (anim/set-value val to-value))))) + (let [max-layout-height (subscribe [:max-layout-height :default]) + to-value (min to-value (max 0 @max-layout-height))] + (when-not (= to-value (.-_value val)) + (if (or (nil? @animate?) @animate?) + (anim/start (anim/timing val {:toValue to-value + :duration 300})) + (anim/set-value val to-value)))))) (defn container [response-height & children] (let [;; todo to-response-height, cur-response-height must be specific ;; for each chat to-response-height (subscribe [:response-height :default]) + input-margin (subscribe [:input-margin]) changed (subscribe [:animations :response-height-changed]) animate? (subscribe [:animate?]) - keyboard-height (subscribe [:get :keyboard-height]) + staged-commands (subscribe [:get-chat-staged-commands]) context {:to-value to-response-height :val response-height :animate? animate?} @@ -100,8 +104,9 @@ (fn [response-height & children] @to-response-height @changed (into [animated-view {:style (st/response-view - (if ios? @keyboard-height 0) - response-height)}] + response-height + @input-margin + @staged-commands)}] children))}))) (defn on-navigation-change diff --git a/src/status_im/chat/views/staged_command.cljs b/src/status_im/chat/views/staged_commands.cljs similarity index 50% rename from src/status_im/chat/views/staged_command.cljs rename to src/status_im/chat/views/staged_commands.cljs index c32c699116..674de6321d 100644 --- a/src/status_im/chat/views/staged_command.cljs +++ b/src/status_im/chat/views/staged_commands.cljs @@ -1,17 +1,23 @@ -(ns status-im.chat.views.staged-command +(ns status-im.chat.views.staged-commands + (:require-macros [status-im.utils.views :refer [defview]]) (:require [re-frame.core :refer [subscribe dispatch]] [status-im.components.react :refer [view image icon text - touchable-highlight]] - [status-im.resources :as res] + touchable-highlight + scroll-view]] [status-im.chat.styles.input :as st] - [status-im.chat.styles.command-pill :as pill-st])) + [status-im.chat.styles.command-pill :as pill-st] + [status-im.utils.platform :refer [platform-specific]] + [taoensso.timbre :as log])) (defn cancel-command-input [staged-command] (dispatch [:unstage-command staged-command])) +(defn get-height [event] + (.-height (.-layout (.-nativeEvent event)))) + (defn simple-command-staged-view [{:keys [command params] :as staged-command}] (let [{:keys [type name]} command] @@ -34,3 +40,21 @@ (if (= 1 (count params)) (first (vals params)) (str params))])]])) + +(defn staged-command-view [stage-command] + [simple-command-staged-view stage-command]) + +(defview staged-commands-view [staged-commands] + [message-input-height [:get-message-input-view-height] + input-margin [:input-margin]] + (let [style (when (seq staged-commands) + (get-in platform-specific [:component-styles :chat :new-message]))] + [view {:style (merge (st/staged-commands message-input-height input-margin) + style)} + [scroll-view {:bounces false + :ref #(dispatch [:set-staged-commands-scroll-view %]) + :on-layout #(dispatch [:set-staged-commands-scroll-height (get-height %)])} + [view {:on-layout #(dispatch [:staged-commands-scroll-to (get-height %)])} + (for [command staged-commands] + ^{:key command} [staged-command-view command]) + [view st/staged-commands-bottom]]]])) \ No newline at end of file diff --git a/src/status_im/chat/views/suggestions.cljs b/src/status_im/chat/views/suggestions.cljs index 8b7bbb5587..c4b1837012 100644 --- a/src/status_im/chat/views/suggestions.cljs +++ b/src/status_im/chat/views/suggestions.cljs @@ -18,7 +18,8 @@ [status-im.components.drag-drop :as drag] [status-im.utils.platform :refer [ios?]] [status-im.chat.suggestions-responder :as resp] - [status-im.chat.constants :as c])) + [status-im.chat.constants :as c] + [taoensso.timbre :as log])) (defn set-command-input [command] (dispatch [:set-chat-command command])) @@ -88,7 +89,7 @@ :renderRow render-row}]]]) (defn header [h] - (let [layout-height (subscribe [:get :layout-height]) + (let [layout-height (subscribe [:max-layout-height :default]) pan-responder (resp/pan-responder h layout-height :fix-commands-suggestions-height)] @@ -100,22 +101,25 @@ (defn container-animation-logic [{:keys [to-value val animate?]}] (when-let [to-value @to-value] - (when-not (= to-value (.-_value val)) - (if (or (nil? @animate?) @animate?) - (anim/start (anim/spring val {:toValue to-value})) - (anim/set-value val to-value))))) + (let [max-layout-height (subscribe [:max-layout-height :default]) + to-value (min to-value (max 0 @max-layout-height))] + (when-not (= to-value (.-_value val)) + (if (or (nil? @animate?) @animate?) + (anim/start (anim/spring val {:toValue to-value})) + (anim/set-value val to-value)))))) (defn container [h & elements] (let [;; todo to-response-height, cur-response-height must be specific ;; for each chat to-response-height (subscribe [:command-suggestions-height]) - keyboard-height (subscribe [:get :keyboard-height]) - changed (subscribe [:animations :commands-height-changed]) - animate? (subscribe [:animate?]) - context {:to-value to-response-height - :val h - :animate? animate?} - on-update #(container-animation-logic context)] + input-margin (subscribe [:input-margin]) + changed (subscribe [:animations :commands-height-changed]) + animate? (subscribe [:animate?]) + staged-commands (subscribe [:get-chat-staged-commands]) + context {:to-value to-response-height + :val h + :animate? animate?} + on-update #(container-animation-logic context)] (r/create-class {:component-did-mount on-update @@ -124,9 +128,9 @@ :reagent-render (fn [h & elements] @to-response-height @changed - (into [animated-view {:style (st/container (if ios? @keyboard-height 0) h)}] elements))}))) + (into [animated-view {:style (st/container h @input-margin @staged-commands)}] elements))}))) -(defn suggestion-container [] +(defview suggestion-container [any-staged-commands?] (let [h (anim/create-value c/input-height)] [container h [header h] diff --git a/src/status_im/translations/en.cljs b/src/status_im/translations/en.cljs index a6569cffed..145bc9cb5f 100644 --- a/src/status_im/translations/en.cljs +++ b/src/status_im/translations/en.cljs @@ -143,6 +143,7 @@ :command-text-location "Location: {{address}}" :command-text-browse "Browsing webpage: {{webpage}}" :command-text-send "Transaction: {{amount}} ETH" + :command-text-help "Help" ;new-group :group-chat-name "Chat name"