first attempt

Former-commit-id: 6cd5e29c8a
This commit is contained in:
Roman Volosovskyi 2016-06-25 18:44:37 +03:00
parent 4b33910c80
commit 4ed06ff622
10 changed files with 201 additions and 94 deletions

View File

@ -4,3 +4,4 @@
(def request-info-height 61) (def request-info-height 61)
(def response-height-normal 211) (def response-height-normal 211)
(def minimum-suggestion-height (+ input-height request-info-height)) (def minimum-suggestion-height (+ input-height request-info-height))
(def minimum-command-suggestions-height (+ input-height 22))

View File

@ -19,6 +19,7 @@
[status-im.utils.phone-number :refer [format-phone-number]] [status-im.utils.phone-number :refer [format-phone-number]]
[status-im.utils.datetime :as time] [status-im.utils.datetime :as time]
[status-im.components.jail :as j] [status-im.components.jail :as j]
[status-im.utils.types :refer [json->clj]]
[status-im.commands.utils :refer [generate-hiccup]])) [status-im.commands.utils :refer [generate-hiccup]]))
(register-handler :set-show-actions (register-handler :set-show-actions
@ -93,7 +94,7 @@
(register-handler :stage-command (register-handler :stage-command
(after invoke-command-preview!) (after invoke-command-preview!)
(fn [{:keys [current-chat-id] :as db} _] (fn [{:keys [current-chat-id] :as db} _]
(let [db (update-input-text db nil) (let [db (update-input-text db nil)
{:keys [command content]} {:keys [command content]}
(get-in db [:chats current-chat-id :command-input]) (get-in db [:chats current-chat-id :command-input])
command-info {:command command command-info {:command command
@ -115,9 +116,7 @@
(register-handler :set-response-chat-command (register-handler :set-response-chat-command
[(after invoke-suggestions-handler!) [(after invoke-suggestions-handler!)
(after #(dispatch [:command-edit-mode])) (after #(dispatch [:command-edit-mode]))]
;(after #(dispatch [:animate-show-response]))
]
(fn [db [_ to-msg-id command-key]] (fn [db [_ to-msg-id command-key]]
(commands/set-response-chat-command db to-msg-id command-key))) (commands/set-response-chat-command db to-msg-id command-key)))
@ -133,8 +132,17 @@
db)) db))
db)) db))
(defn check-suggestions
[{:keys [current-chat-id] :as db} [_ text]]
(assoc-in db
[:command-suggestions current-chat-id]
(suggestions/get-suggestions db text)))
(register-handler :set-chat-input-text (register-handler :set-chat-input-text
((enrich update-command) update-text)) [(enrich update-command)
(enrich check-suggestions)
(after #(dispatch [:animate-command-suggestions]))]
update-text)
(defn console? [s] (defn console? [s]
(= "console" s)) (= "console" s))
@ -437,9 +445,11 @@
((after save-chat!)) ((after save-chat!))
((after open-chat!)))) ((after open-chat!))))
(register-handler :switch-command-suggestions (register-handler :switch-command-suggestions!
(fn [db [_]] (u/side-effect!
(suggestions/switch-command-suggestions db))) (fn [db]
(let [text (if (suggestions/typing-command? db) "" "!")]
(dispatch [:set-chat-input-text text])))))
(defn remove-chat (defn remove-chat
[{:keys [current-chat-id] :as db} _] [{:keys [current-chat-id] :as db} _]

View File

@ -3,6 +3,7 @@
[re-frame.middleware :refer [path]] [re-frame.middleware :refer [path]]
[status-im.handlers.content-suggestions :refer [get-content-suggestions]] [status-im.handlers.content-suggestions :refer [get-content-suggestions]]
[status-im.chat.constants :refer [input-height request-info-height [status-im.chat.constants :refer [input-height request-info-height
minimum-command-suggestions-height
response-height-normal minimum-suggestion-height]] response-height-normal minimum-suggestion-height]]
[status-im.constants :refer [response-input-hiding-duration]])) [status-im.constants :refer [response-input-hiding-duration]]))
@ -19,45 +20,45 @@
(fn [db _] (fn [db _]
(assoc db (assoc db
:to-response-height input-height :to-response-height input-height
:messages-offset 0))) :messages-offset? false)))
(defn get-response-height (def response-height (+ input-height response-height-normal))
[{:keys [current-chat-id] :as db}]
(let [suggestions (get-in db [:suggestions current-chat-id])
suggestions-height (if suggestions middle-height 0)]
(+ input-height
(min response-height-normal (+ suggestions-height request-info-height)))))
(defn update-response-height [db] (defn update-response-height [db]
(assoc-in db [:animations :to-response-height] (get-response-height db))) (assoc-in db [:animations :to-response-height] response-height))
(register-handler :animate-show-response (register-handler :animate-command-suggestions
(fn [{:keys [current-chat-id] :as db} _]
(let [suggestions? (seq (get-in db [:command-suggestions current-chat-id]))
current (get-in db [:animations :command-suggestions-height])
height (if suggestions? middle-height 0.1)]
(-> db
(update :animations assoc
:messages-offset? suggestions?
:messages-offset-max 22
:command-suggestions-height height)
(update-in [:animations :commands-height-changed]
(if (and suggestions? (not= 0.1 current))
identity inc))))))
(animation-handler :animate-show-response
[(after #(dispatch [:command-edit-mode]))] [(after #(dispatch [:command-edit-mode]))]
(fn [db _] (fn [db]
(-> db (assoc db :messages-offset? true
(assoc-in [:animations :messages-offset] request-info-height) :messages-offset-max request-info-height
(update-response-height)))) :to-response-height response-height)))
(animation-handler :set-response-max-height (defn fix-height
(fn [db [_ height]] [height-key height-signal-key suggestions-key minimum]
(let [prev-height (:response-height-max db)]
(if (not= height prev-height)
(let [db (assoc db :response-height-max height)]
(if (= prev-height (:to-response-height db))
(assoc db :to-response-height height)
db))
db))))
(register-handler :fix-response-height
(fn [{:keys [current-chat-id] :as db} [_ vy current]] (fn [{:keys [current-chat-id] :as db} [_ vy current]]
(let [max-height (get-in db [:animations :response-height-max]) (let [max-height (get-in db [:layout-height])
moving-down? (pos? vy) moving-down? (pos? vy)
moving-up? (not moving-down?) moving-up? (not moving-down?)
under-middle-position? (<= current middle-height) under-middle-position? (<= current middle-height)
over-middle-position? (not under-middle-position?) over-middle-position? (not under-middle-position?)
suggestions (get-in db [:suggestions current-chat-id]) suggestions (get-in db [suggestions-key current-chat-id])
new-fixed (cond (not suggestions) new-fixed (cond (not suggestions)
minimum-suggestion-height minimum
(and under-middle-position? moving-up?) (and under-middle-position? moving-up?)
middle-height middle-height
@ -70,7 +71,20 @@
(and under-middle-position? (and under-middle-position?
moving-down?) moving-down?)
minimum-suggestion-height)] minimum)]
(println height-key new-fixed)
(-> db (-> db
(assoc-in [:animations :to-response-height] new-fixed) (assoc-in [:animations height-key] new-fixed)
(update-in [:animations :response-height-changed] inc))))) (update-in [:animations height-signal-key] inc)))))
(register-handler :fix-commands-suggestions-height
(fix-height :command-suggestions-height
:commands-height-changed
:command-suggestions
minimum-command-suggestions-height))
(register-handler :fix-response-height
(fix-height :to-response-height
:response-height-changed
:suggestions
minimum-suggestion-height))

View File

@ -18,7 +18,7 @@
[status-im.components.invertible-scroll-view :refer [invertible-scroll-view]] [status-im.components.invertible-scroll-view :refer [invertible-scroll-view]]
[status-im.components.toolbar :refer [toolbar]] [status-im.components.toolbar :refer [toolbar]]
[status-im.chat.views.message :refer [chat-message]] [status-im.chat.views.message :refer [chat-message]]
[status-im.chat.views.suggestions :refer [suggestions-view]] [status-im.chat.views.suggestions :refer [suggestion-container]]
[status-im.chat.views.response :refer [response-view]] [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-new]]
[status-im.i18n :refer [label label-pluralize]] [status-im.i18n :refer [label label-pluralize]]
@ -228,20 +228,19 @@
:keyboardShouldPersistTaps true :keyboardShouldPersistTaps true
:dataSource (to-datasource-inverted messages)}])) :dataSource (to-datasource-inverted messages)}]))
(defn messages-container-animation-logic [{:keys [to-value val]}] (defn messages-container-animation-logic
[{:keys [offset? val max]}]
(fn [_] (fn [_]
(let [to-value @to-value] (let [to-value (if @offset? @max 0)]
(anim/start (anim/spring val {:toValue to-value}) (anim/start (anim/spring val {:toValue to-value})))))
(fn [arg]
(when (.-finished arg)
(dispatch [:set-animation ::messages-offset-current to-value])))))))
(defn messages-container [messages] (defn messages-container [messages]
(let [to-messages-offset (subscribe [:animations :messages-offset]) (let [messages-offset? (subscribe [:animations :messages-offset?])
cur-messages-offset (subscribe [:animations ::messages-offset-current]) maximum-offset (subscribe [:animations :messages-offset-max])
messages-offset (anim/create-value (or @cur-messages-offset 0)) messages-offset (anim/create-value 0)
context {:to-value to-messages-offset context {:offset? messages-offset?
:val messages-offset} :val messages-offset
:max maximum-offset}
on-update (messages-container-animation-logic context)] on-update (messages-container-animation-logic context)]
(r/create-class (r/create-class
{:component-did-mount {:component-did-mount
@ -250,7 +249,7 @@
on-update on-update
:reagent-render :reagent-render
(fn [messages] (fn [messages]
@to-messages-offset @messages-offset?
[animated-view {:style (st/messages-container messages-offset)} [animated-view {:style (st/messages-container messages-offset)}
messages])}))) messages])})))
@ -259,16 +258,19 @@
show-actions-atom [:show-actions] show-actions-atom [:show-actions]
command [:get-chat-command] command [:get-chat-command]
command? [:command?] command? [:command?]
to-msg-id [:get-chat-command-to-msg-id]] suggestions [:get-suggestions]
[view {:style st/chat-view to-msg-id [:get-chat-command-to-msg-id]
layout-height [:get :layout-height]]
[view {:style st/chat-view
:onLayout (fn [event] :onLayout (fn [event]
(let [height (.. event -nativeEvent -layout -height)] (let [height (.. event -nativeEvent -layout -height)]
(dispatch [:set-response-max-height height])))} (when (not= height layout-height)
(dispatch [:set :layout-height height]))))}
[chat-toolbar] [chat-toolbar]
[messages-container [messages-container
[messages-view group-chat]] [messages-view group-chat]]
(when group-chat [typing-all]) (when group-chat [typing-all])
[response-view] [response-view]
(when-not command? [suggestions-view]) (when-not command? [suggestion-container])
[chat-message-new] [chat-message-new]
(when show-actions-atom [actions-view])]) (when show-actions-atom [actions-view])])

View File

@ -1,16 +1,16 @@
(ns status-im.chat.styles.suggestions (ns status-im.chat.styles.suggestions
(:require [status-im.components.styles :refer [font (:require [status-im.components.styles :refer [font
color-light-blue-transparent color-light-blue-transparent
color-white color-white
color-black color-black
color-blue color-blue
color-blue-transparent color-blue-transparent
selected-message-color selected-message-color
online-color online-color
separator-color separator-color
text1-color text1-color
text2-color text2-color
text3-color]])) text3-color]]))
(def suggestion-height 88) (def suggestion-height 88)
@ -59,11 +59,19 @@
:backgroundColor color-white :backgroundColor color-white
:borderRadius 5}) :borderRadius 5})
(def container (defn container [height]
{:backgroundColor color-white}) {:flexDirection :column
:position :absolute
:left 0
:right 0
:bottom 0
:height height
:backgroundColor color-white
:elevation 2})
(def drag-down-touchable (def drag-down-touchable
{:height 22 {:height 22
:background-color color-white
:alignItems :center :alignItems :center
:justifyContent :center}) :justifyContent :center})

View File

@ -43,11 +43,8 @@
(register-sub :get-suggestions (register-sub :get-suggestions
(fn [db _] (fn [db _]
(let [input-text (->> (:current-chat-id @db) (let [chat-id (subscribe [:get-current-chat-id])]
db/chat-input-text-path (reaction (get-in @db [:command-suggestions @chat-id])))))
(get-in @db)
(reaction))]
(reaction (get-suggestions @db @input-text)))))
(register-sub :get-commands (register-sub :get-commands
(fn [db _] (fn [db _]

View File

@ -21,19 +21,19 @@
command? [:command?]] command? [:command?]]
[plain-message-input-view [plain-message-input-view
(when command? (when command?
(case (:command command) (case (keyword (:name command))
:phone {:input-options {:keyboardType :phone-pad} :phone {:input-options {:keyboardType :phone-pad}
:validator valid-mobile-number?} :validator valid-mobile-number?}
:keypair {:input-options {:secureTextEntry true}} :keypair {:input-options {:secureTextEntry true}}
:confirmation-code {:input-options {:keyboardType :numeric}} :confirmation-code {:input-options {:keyboardType :numeric}}
:money {:input-options {:keyboardType :numeric}} :money {:input-options {:keyboardType :numeric}}
:request {:input-options {:keyboardType :numeric}} :request {:input-options {:keyboardType :numeric}}
;; todo maybe nil is finr for now :) ;; todo maybe nil is fine for now :)
nil #_(throw (js/Error. "Uknown command type"))))]) nil #_(throw (js/Error. "Uknown command type"))))])
(defview chat-message-new [] (defview chat-message-new []
[staged-commands [:get-chat-staged-commands]] [staged-commands [:get-chat-staged-commands]]
[view st/new-message-container [view st/new-message-container
(when (and staged-commands (pos? (count staged-commands))) (when (seq staged-commands)
[staged-commands-view staged-commands]) [staged-commands-view staged-commands])
[show-input]]) [show-input]])

View File

@ -52,7 +52,7 @@
on-update on-update
:reagent-render :reagent-render
(fn [] (fn []
[touchable-highlight {:on-press #(dispatch [:switch-command-suggestions]) [touchable-highlight {:on-press #(dispatch [:switch-command-suggestions!])
:disabled @command?} :disabled @command?}
[animated-view {:style (st/message-input-button-touchable [animated-view {:style (st/message-input-button-touchable
container-width)} container-width)}

View File

@ -6,9 +6,14 @@
icon icon
touchable-highlight touchable-highlight
list-view list-view
list-item]] list-item
animated-view]]
[status-im.utils.listview :refer [to-datasource]] [status-im.utils.listview :refer [to-datasource]]
[status-im.chat.styles.suggestions :as st])) [status-im.chat.styles.suggestions :as st]
[reagent.core :as r]
[status-im.components.animation :as anim]
[status-im.components.drag-drop :as drag]
[status-im.components.react :as react]))
(defn set-command-input [command] (defn set-command-input [command]
(dispatch [:set-chat-command command])) (dispatch [:set-chat-command command]))
@ -31,18 +36,89 @@
(list-item [suggestion-list-item row])) (list-item [suggestion-list-item row]))
(defview suggestions-view [] (defn suggestions-view []
[suggestions [:get-suggestions]] (let
(when (seq suggestions) [suggestions (subscribe [:get-suggestions])]
[view st/container (r/create-class
[touchable-highlight {:style st/drag-down-touchable {:reagent-render
:onPress (fn [] (fn []
;; TODO hide suggestions? [view (st/suggestions-container (count @suggestions))
)} [list-view {:dataSource (to-datasource @suggestions)
:enableEmptySections true
:keyboardShouldPersistTaps true
:renderRow render-row}]])})))
;; todo bad name. Ideas?
(defn enough-dy [gesture]
(> (Math/abs (.-dy gesture)) 10))
(defn on-move [response-height kb-height orientation]
(fn [_ gesture]
(when (enough-dy gesture)
(let [w (react/get-dimensions "window")
;; depending on orientation use height or width of screen
prop (if (= :portrait @orientation)
:height
:width)
;; subtract keyboard height to get "real height" of screen
;; then subtract gesture position to get suggestions height
;; todo maybe it is better to use margin-top instead height
;; it is not obvious
to-value (- (prop w) @kb-height (.-moveY gesture))]
(anim/start
(anim/spring response-height {:toValue to-value}))))))
(defn on-release [response-height]
(fn [_ gesture]
(when (enough-dy gesture)
(dispatch [:fix-commands-suggestions-height
(.-vy gesture)
;; todo access to "private" property
;; better to find another way...
(.-_value response-height)]))))
(defn pan-responder [response-height kb-height orientation]
(drag/create-pan-responder
{:on-move (on-move response-height kb-height orientation)
:on-release (on-release response-height)}))
(defn header [h]
(let [orientation (subscribe [:get :orientation])
kb-height (subscribe [:get :keyboard-height])
pan-responder (pan-responder h kb-height orientation)]
(fn [_]
[view [view
[icon :drag_down st/drag-down-icon]]] (merge (drag/pan-handlers pan-responder)
[view (st/suggestions-container (count suggestions)) {:style st/drag-down-touchable})
[list-view {:dataSource (to-datasource suggestions) [icon :drag_down st/drag-down-icon]])))
:enableEmptySections true
:keyboardShouldPersistTaps true (defn container-animation-logic [{:keys [to-value val]}]
:renderRow render-row}]]])) (fn [_]
(let [to-value @to-value]
(anim/start (anim/spring val {:toValue to-value
:tension 50
:friction 10})))))
(defn container [h & elements]
(let [;; todo to-response-height, cur-response-height must be specific
;; for each chat
to-response-height (subscribe [:animations :command-suggestions-height])
changed (subscribe [:animations :commands-height-changed])
context {:to-value to-response-height
:val h}
on-update (container-animation-logic context)]
(r/create-class
{:component-did-mount
on-update
:component-did-update
on-update
:reagent-render
(fn [h & elements]
@changed
(into [animated-view {:style (st/container h)}] elements))})))
(defn suggestion-container []
(let [h (anim/create-value 0)]
[container h
[header h]
[suggestions-view] ]))

View File

@ -38,7 +38,6 @@
:phone-number ""} :phone-number ""}
:disable-group-creation false :disable-group-creation false
:animations {:to-response-height 0.1 :animations {:to-response-height 0.1
:messages-offset 0
;; todo clear this ;; todo clear this
:tabs-bar-value (anim/create-value 0)}}) :tabs-bar-value (anim/create-value 0)}})