[#3014]: Updated chat input
Signed-off-by: Andrey Shovkoplyas <motor4ik@gmail.com>
This commit is contained in:
parent
058e6c5412
commit
2aa6c1992f
|
@ -38,7 +38,6 @@
|
|||
"web3",
|
||||
"eccjs",
|
||||
"chance",
|
||||
"react-native-emoji-picker",
|
||||
"react-native-autolink",
|
||||
"instabug-reactnative",
|
||||
"nfc-react-native",
|
||||
|
|
|
@ -53,7 +53,6 @@
|
|||
"react-native-config": "0.9.0",
|
||||
"react-native-crypto": "2.1.1",
|
||||
"react-native-dialogs": "0.0.20",
|
||||
"react-native-emoji-picker": "git+https://github.com/status-im/react-native-emoji-picker.git",
|
||||
"react-native-fcm": "10.0.3",
|
||||
"react-native-fs": "2.8.1",
|
||||
"react-native-http": "github:tradle/react-native-http#834492d",
|
||||
|
|
|
@ -6,7 +6,6 @@
|
|||
(def config (js/require "react-native-config"))
|
||||
(def dialogs (js/require "react-native-dialogs"))
|
||||
(def dismiss-keyboard (js/require "dismissKeyboard"))
|
||||
(def emoji-picker (js/require "react-native-emoji-picker"))
|
||||
(def fs (js/require "react-native-fs"))
|
||||
(def http-bridge (js/require "react-native-http-bridge"))
|
||||
;; i18n is now exported in default object of the module
|
||||
|
|
|
@ -1,3 +0,0 @@
|
|||
<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24">
|
||||
<path fill="" fill-rule="evenodd" d="M9,7 C9,6.44771525 9.4556644,6 9.99539757,6 L18.0046024,6 C18.5543453,6 19,6.44386482 19,7 C19,7.55228475 18.5443356,8 18.0046024,8 L9.99539757,8 C9.44565467,8 9,7.55613518 9,7 Z M9,12 C9,11.4477153 9.45303631,11 9.99703014,11 L16.0029699,11 C16.5536144,11 17,11.4438648 17,12 C17,12.5522847 16.5469637,13 16.0029699,13 L9.99703014,13 C9.4463856,13 9,12.5561352 9,12 Z M9,17 C9,16.4477153 9.4556644,16 9.99539757,16 L18.0046024,16 C18.5543453,16 19,16.4438648 19,17 C19,17.5522847 18.5443356,18 18.0046024,18 L9.99539757,18 C9.44565467,18 9,17.5561352 9,17 Z M6,8.29999971 C5.28202985,8.29999971 4.70000005,7.71796991 4.70000005,6.99999976 C4.70000005,6.28202961 5.28202985,5.69999981 6,5.69999981 C6.71797015,5.69999981 7.29999995,6.28202961 7.29999995,6.99999976 C7.29999995,7.71796991 6.71797015,8.29999971 6,8.29999971 Z M6,13.2999997 C5.28202985,13.2999997 4.70000005,12.7179699 4.70000005,11.9999998 C4.70000005,11.2820296 5.28202985,10.6999998 6,10.6999998 C6.71797015,10.6999998 7.29999995,11.2820296 7.29999995,11.9999998 C7.29999995,12.7179699 6.71797015,13.2999997 6,13.2999997 Z M6,18.2999997 C5.28202985,18.2999997 4.70000005,17.7179699 4.70000005,16.9999998 C4.70000005,16.2820296 5.28202985,15.6999998 6,15.6999998 C6.71797015,15.6999998 7.29999995,16.2820296 7.29999995,16.9999998 C7.29999995,17.7179699 6.71797015,18.2999997 6,18.2999997 Z"/>
|
||||
</svg>
|
Before Width: | Height: | Size: 1.5 KiB |
|
@ -0,0 +1,3 @@
|
|||
<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24">
|
||||
<path fill="#6E777E" fill-rule="nonzero" d="M7 5a2 2 0 0 0-2 2v10a2 2 0 0 0 2 2h10a2 2 0 0 0 2-2V7a2 2 0 0 0-2-2H7zm0-2h10a4 4 0 0 1 4 4v10a4 4 0 0 1-4 4H7a4 4 0 0 1-4-4V7a4 4 0 0 1 4-4zm6.618 5H14a.618.618 0 0 1 .553.894l-3.277 6.553a1 1 0 0 1-.894.553H10a.618.618 0 0 1-.553-.894l3.277-6.553A1 1 0 0 1 13.618 8z"/>
|
||||
</svg>
|
After Width: | Height: | Size: 412 B |
|
@ -0,0 +1,3 @@
|
|||
<svg xmlns="http://www.w3.org/2000/svg" width="22" height="22" viewBox="0 0 22 22">
|
||||
<path fill="#FFF" fill-rule="evenodd" d="M11.882 8.686l2.047 2.057a.87.87 0 1 0 1.227-1.233l-3.53-3.547a.865.865 0 0 0-.537-.251.866.866 0 0 0-.718.251L6.841 9.51a.88.88 0 0 0 0 1.234.864.864 0 0 0 1.228-.001l2.049-2.059v6.732a.88.88 0 0 0 .882.878c.49 0 .882-.393.882-.878v-6.73z"/>
|
||||
</svg>
|
After Width: | Height: | Size: 379 B |
|
@ -1,3 +0,0 @@
|
|||
<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24">
|
||||
<path fill="" fill-rule="evenodd" d="M11.9908333,2.83333333 C6.93083333,2.83333333 2.83333333,6.94 2.83333333,12 C2.83333333,17.06 6.93083333,21.1666667 11.9908333,21.1666667 C17.06,21.1666667 21.1666667,17.06 21.1666667,12 C21.1666667,6.94 17.06,2.83333333 11.9908333,2.83333333 L11.9908333,2.83333333 Z M12,19.3333333 C7.94833333,19.3333333 4.66666667,16.0516667 4.66666667,12 C4.66666667,7.94833333 7.94833333,4.66666667 12,4.66666667 C16.0516667,4.66666667 19.3333333,7.94833333 19.3333333,12 C19.3333333,16.0516667 16.0516667,19.3333333 12,19.3333333 L12,19.3333333 Z M15.2083333,11.0833333 C15.9691667,11.0833333 16.5833333,10.4691667 16.5833333,9.70833333 C16.5833333,8.9475 15.9691667,8.33333333 15.2083333,8.33333333 C14.4475,8.33333333 13.8333333,8.9475 13.8333333,9.70833333 C13.8333333,10.4691667 14.4475,11.0833333 15.2083333,11.0833333 L15.2083333,11.0833333 Z M8.79166667,11.0833333 C9.5525,11.0833333 10.1666667,10.4691667 10.1666667,9.70833333 C10.1666667,8.9475 9.5525,8.33333333 8.79166667,8.33333333 C8.03083333,8.33333333 7.41666667,8.9475 7.41666667,9.70833333 C7.41666667,10.4691667 8.03083333,11.0833333 8.79166667,11.0833333 L8.79166667,11.0833333 Z M15.5330465,14.6132288 C16.1687926,13.8879527 15.9015413,13.3000002 14.9440105,13.3000002 L9.05598946,13.3000002 C8.09492777,13.3000002 7.8208627,13.9096537 8.46695345,14.6132288 C8.46695345,14.6132288 10,16.8000002 12,16.8000002 C14,16.8000002 15.5330465,14.6132288 15.5330465,14.6132288 Z"/>
|
||||
</svg>
|
Before Width: | Height: | Size: 1.5 KiB |
|
@ -1,17 +1,11 @@
|
|||
function jsSuggestionsContainerStyle(suggestionsCount) {
|
||||
return {
|
||||
marginVertical: 1,
|
||||
marginHorizontal: 0,
|
||||
keyboardShouldPersistTaps: "always",
|
||||
//height: Math.min(150, (56 * suggestionsCount)),
|
||||
backgroundColor: "white",
|
||||
borderRadius: 5,
|
||||
keyboardShouldPersistTaps: "always"
|
||||
};
|
||||
}
|
||||
var jsSuggestionsContainerStyle = {
|
||||
keyboardShouldPersistTaps: "always",
|
||||
backgroundColor: "white",
|
||||
flexGrow: 1,
|
||||
bounces: false
|
||||
};
|
||||
|
||||
var jsSuggestionContainerStyle = {
|
||||
paddingLeft: 16,
|
||||
backgroundColor: "white"
|
||||
};
|
||||
|
||||
|
@ -22,22 +16,34 @@ var jsSubContainerStyle = {
|
|||
borderBottomColor: "#0000001f"
|
||||
};
|
||||
|
||||
function jsSuggestionSubContainerStyle(isLast) {
|
||||
var borderBottomWidth = (isLast ? 0 : 1);
|
||||
|
||||
return {
|
||||
paddingTop: 14,
|
||||
paddingBottom: 14,
|
||||
paddingRight: 14,
|
||||
marginLeft: 14,
|
||||
borderBottomWidth: borderBottomWidth,
|
||||
borderBottomColor: "#e8ebec"
|
||||
};
|
||||
}
|
||||
|
||||
var jsValueStyle = {
|
||||
fontSize: 14,
|
||||
fontSize: 15,
|
||||
fontFamily: "font",
|
||||
color: "#000000de"
|
||||
};
|
||||
|
||||
var jsBoldValueStyle = {
|
||||
fontSize: 14,
|
||||
fontSize: 15,
|
||||
fontFamily: "font",
|
||||
color: "#000000de",
|
||||
fontWeight: "bold"
|
||||
};
|
||||
|
||||
var jsDescriptionStyle = {
|
||||
marginTop: 1.5,
|
||||
paddingBottom: 9,
|
||||
marginTop: 2,
|
||||
fontSize: 14,
|
||||
fontFamily: "font",
|
||||
color: "#838c93de"
|
||||
|
@ -324,7 +330,7 @@ function jsSuggestions(params, context) {
|
|||
suggestion.title = createMarkupText(suggestion.title);
|
||||
}
|
||||
var suggestionMarkup = status.components.view(jsSuggestionContainerStyle,
|
||||
[status.components.view(jsSubContainerStyle,
|
||||
[status.components.view(jsSuggestionSubContainerStyle(i == suggestions.length - 1),
|
||||
[
|
||||
status.components.text({style: jsValueStyle},
|
||||
suggestion.title),
|
||||
|
@ -342,9 +348,7 @@ function jsSuggestions(params, context) {
|
|||
}
|
||||
|
||||
if (sugestionsMarkup.length > 0) {
|
||||
var view = status.components.scrollView(jsSuggestionsContainerStyle(sugestionsMarkup.length),
|
||||
sugestionsMarkup
|
||||
);
|
||||
var view = status.components.scrollView(jsSuggestionsContainerStyle, sugestionsMarkup);
|
||||
return {markup: view};
|
||||
} else {
|
||||
return {markup: null};
|
||||
|
@ -371,39 +375,41 @@ function jsHandler(params, context) {
|
|||
return result;
|
||||
}
|
||||
|
||||
function suggestionsContainerStyle(suggestionsCount) {
|
||||
return {
|
||||
marginVertical: 1,
|
||||
marginHorizontal: 0,
|
||||
keyboardShouldPersistTaps: "always",
|
||||
height: Math.min(150, (56 * suggestionsCount)),
|
||||
backgroundColor: "white",
|
||||
borderRadius: 5,
|
||||
flexGrow: 1
|
||||
};
|
||||
var suggestionsContainerStyle = {
|
||||
keyboardShouldPersistTaps: "always",
|
||||
backgroundColor: "white",
|
||||
flexGrow: 1,
|
||||
bounces: false
|
||||
}
|
||||
|
||||
var suggestionContainerStyle = {
|
||||
paddingLeft: 16,
|
||||
backgroundColor: "white"
|
||||
};
|
||||
|
||||
var suggestionSubContainerStyle = {
|
||||
height: 56,
|
||||
borderBottomWidth: 1,
|
||||
borderBottomColor: "#0000001f"
|
||||
};
|
||||
function suggestionSubContainerStyle(isTwoLineEntry, isLast) {
|
||||
var height = (isTwoLineEntry ? 64 : 48);
|
||||
var borderBottomWidth = (isLast ? 0 : 1);
|
||||
|
||||
return {
|
||||
paddingTop: 14,
|
||||
paddingBottom: 14,
|
||||
paddingRight: 14,
|
||||
marginLeft: 14,
|
||||
height: height,
|
||||
borderBottomWidth: borderBottomWidth,
|
||||
borderBottomColor: "#e8ebec"
|
||||
};
|
||||
}
|
||||
|
||||
var valueStyle = {
|
||||
marginTop: 9,
|
||||
fontSize: 14,
|
||||
fontSize: 15,
|
||||
fontFamily: "font",
|
||||
color: "#000000de"
|
||||
};
|
||||
|
||||
var descriptionStyle = {
|
||||
marginTop: 1.5,
|
||||
fontSize: 14,
|
||||
marginTop: 2,
|
||||
fontSize: 13,
|
||||
fontFamily: "font",
|
||||
color: "#838c93de"
|
||||
};
|
||||
|
@ -443,13 +449,15 @@ function getFaucets(networkId) {
|
|||
var faucets = getFaucets(status.ethereumNetworkId);
|
||||
|
||||
function faucetSuggestions(params) {
|
||||
var suggestions = faucets.map(function (entry) {
|
||||
var subContainerStyle = suggestionSubContainerStyle(true, false);
|
||||
|
||||
var suggestions = faucets.map(function (entry, index) {
|
||||
return status.components.touchable(
|
||||
{onPress: status.components.dispatch([status.events.SET_COMMAND_ARGUMENT, [0, entry.url, false]])},
|
||||
{onPress: status.components.dispatch([status.events.SET_COMMAND_ARGUMENT, [0, entry.url, true]])},
|
||||
status.components.view(
|
||||
suggestionContainerStyle,
|
||||
[status.components.view(
|
||||
suggestionSubContainerStyle,
|
||||
(index == faucets.length - 1 ? suggestionSubContainerStyle(true, true) : subContainerStyle),
|
||||
[
|
||||
status.components.text(
|
||||
{style: valueStyle},
|
||||
|
@ -466,11 +474,13 @@ function faucetSuggestions(params) {
|
|||
});
|
||||
|
||||
var view = status.components.scrollView(
|
||||
suggestionsContainerStyle(faucets.length),
|
||||
suggestionsContainerStyle,
|
||||
suggestions
|
||||
);
|
||||
|
||||
return {markup: view};
|
||||
var entryHeight = subContainerStyle.height + subContainerStyle.borderBottomWidth;
|
||||
|
||||
return {markup: view, height: entryHeight * faucets.length};
|
||||
}
|
||||
|
||||
var faucetCommandConfig ={
|
||||
|
@ -523,13 +533,16 @@ if (faucets.length > 0) {
|
|||
}
|
||||
|
||||
function debugSuggestions(params) {
|
||||
var suggestions = ["On", "Off"].map(function (entry) {
|
||||
var values = ["On", "Off"];
|
||||
var subContainerStyle = suggestionSubContainerStyle(false, false);
|
||||
|
||||
var suggestions = values.map(function (entry, index) {
|
||||
return status.components.touchable(
|
||||
{onPress: status.components.dispatch([status.events.SET_COMMAND_ARGUMENT, [0, entry, false]])},
|
||||
{onPress: status.components.dispatch([status.events.SET_COMMAND_ARGUMENT, [0, entry, true]])},
|
||||
status.components.view(
|
||||
suggestionContainerStyle,
|
||||
[status.components.view(
|
||||
suggestionSubContainerStyle,
|
||||
(index == values.length - 1 ? suggestionSubContainerStyle(false, true) : subContainerStyle),
|
||||
[
|
||||
status.components.text(
|
||||
{style: valueStyle},
|
||||
|
@ -542,11 +555,13 @@ function debugSuggestions(params) {
|
|||
});
|
||||
|
||||
var view = status.components.scrollView(
|
||||
suggestionsContainerStyle(faucets.length),
|
||||
suggestionsContainerStyle,
|
||||
suggestions
|
||||
);
|
||||
|
||||
return {markup: view};
|
||||
var entryHeight = subContainerStyle.height + subContainerStyle.borderBottomWidth;
|
||||
|
||||
return {markup: view, height: entryHeight * values.length};
|
||||
}
|
||||
|
||||
status.command({
|
||||
|
|
|
@ -132,7 +132,6 @@
|
|||
[re-frame/trim-v]
|
||||
(fn [db [details]]
|
||||
(model/set-chat-ui-props db {:show-bottom-info? true
|
||||
:show-emoji? false
|
||||
:bottom-info details})))
|
||||
|
||||
(def index-messages (partial into {} (map (juxt :message-id identity))))
|
||||
|
|
|
@ -186,7 +186,6 @@
|
|||
(bots-events/clear-bot-db owner-id)
|
||||
clear-seq-arguments
|
||||
(model/set-chat-ui-props {:show-suggestions? false
|
||||
:show-emoji? false
|
||||
:result-box nil
|
||||
:validation-messages nil
|
||||
:prev-command name})
|
||||
|
|
|
@ -97,9 +97,8 @@
|
|||
(defview chat []
|
||||
(letsubs [{:keys [group-chat input-text]} [:get-current-chat]
|
||||
show-bottom-info? [:get-current-chat-ui-prop :show-bottom-info?]
|
||||
show-emoji? [:get-current-chat-ui-prop :show-emoji?]
|
||||
layout-height [:get :layout-height]
|
||||
current-view [:get :view-id]]
|
||||
{:component-will-unmount #(re-frame/dispatch [:set-chat-ui-props {:show-emoji? false}])}
|
||||
[react/view {:style style/chat-view}
|
||||
[chat-toolbar]
|
||||
(when (= :chat current-view)
|
||||
|
|
|
@ -4,16 +4,6 @@
|
|||
(def color-root-border "rgba(192, 198, 202, 0.28)")
|
||||
(def header-draggable-icon "rgba(73, 84, 93, 0.23)")
|
||||
|
||||
(defn result-box-overlay [max-height opacity-anim-value]
|
||||
{:background-color common/color-black
|
||||
:position :absolute
|
||||
:opacity opacity-anim-value
|
||||
:height max-height
|
||||
:elevation 2
|
||||
:bottom 0
|
||||
:left 0
|
||||
:right 0})
|
||||
|
||||
(def overlap-container
|
||||
{:position :absolute
|
||||
:left 0
|
||||
|
@ -23,14 +13,14 @@
|
|||
|
||||
(defn expandable-container [anim-value bottom]
|
||||
{:background-color common/color-white
|
||||
:border-top-color color-root-border
|
||||
:border-top-width 1
|
||||
:elevation 2
|
||||
:height anim-value
|
||||
:left 0
|
||||
:right 0
|
||||
:bottom bottom
|
||||
:position :absolute})
|
||||
:position :absolute
|
||||
:border-top-color color-root-border
|
||||
:border-top-width 1
|
||||
:elevation 2})
|
||||
|
||||
(def header-container
|
||||
{:min-height 19
|
||||
|
|
|
@ -1,16 +0,0 @@
|
|||
(ns status-im.chat.styles.input.emoji
|
||||
(:require [status-im.ui.components.styles :as common]))
|
||||
|
||||
(def container-height 250)
|
||||
|
||||
(defn container [height]
|
||||
{:flex-direction :column
|
||||
:height (or height container-height)
|
||||
:background-color common/color-white})
|
||||
|
||||
(def emoji-container
|
||||
{:flex 1})
|
||||
|
||||
(def emoji-picker
|
||||
{:flex 1
|
||||
:background-color common/color-white})
|
|
@ -1,69 +1,52 @@
|
|||
(ns status-im.chat.styles.input.input
|
||||
(:require-macros [status-im.utils.styles :refer [defstyle defnstyle]])
|
||||
(:require [status-im.ui.components.styles :as common]
|
||||
[status-im.utils.platform :as platform]
|
||||
[taoensso.timbre :as log]))
|
||||
[status-im.ui.components.colors :as colors]
|
||||
[status-im.utils.platform :as platform]))
|
||||
|
||||
(def color-root-border "#e8eaeb")
|
||||
(def color-input "#edf1f3")
|
||||
(def color-input-helper-text "rgb(182, 189, 194)")
|
||||
(def color-input-helper-placeholder "rgb(182, 189, 194)")
|
||||
(def color-command "#70777d")
|
||||
(def color-send "rgb(98, 143, 227)")
|
||||
|
||||
(def min-input-height 38)
|
||||
(def min-input-height 36)
|
||||
(def padding-vertical 8)
|
||||
(def border-height 1)
|
||||
(def max-input-height (* 4 min-input-height))
|
||||
|
||||
(defnstyle root [margin-bottom]
|
||||
{:flex-direction :column
|
||||
:elevation 2
|
||||
:margin-bottom margin-bottom
|
||||
:border-top-width 1
|
||||
:border-top-color color-root-border})
|
||||
|
||||
(defn container [container-anim-margin bottom-anim-margin]
|
||||
{:background-color common/color-white
|
||||
:margin-bottom margin-bottom
|
||||
:flex-direction :column
|
||||
:padding-left container-anim-margin
|
||||
:padding-right container-anim-margin
|
||||
:padding-top 8
|
||||
:padding-bottom bottom-anim-margin})
|
||||
|
||||
(defstyle input-container-view
|
||||
{:ios {:z-index 1}})
|
||||
:border-top-width border-height
|
||||
:border-top-color colors/light-gray
|
||||
:elevation 2})
|
||||
|
||||
(def input-container
|
||||
{:flex-direction :row
|
||||
:align-items :flex-end})
|
||||
{:flex-direction :row
|
||||
:align-items :flex-end
|
||||
:padding-left 14
|
||||
:padding-right 14})
|
||||
|
||||
(defn input-root [content-height anim-margin]
|
||||
(def input-root
|
||||
{:padding-top padding-vertical
|
||||
:padding-bottom padding-vertical
|
||||
:flex 1})
|
||||
|
||||
(defn input-animated [content-height]
|
||||
{:align-items :flex-start
|
||||
:background-color color-input
|
||||
:flex-direction :row
|
||||
:flex-grow 1
|
||||
:height (min (max min-input-height content-height) max-input-height)
|
||||
:margin-top anim-margin
|
||||
:padding-left 10
|
||||
:padding-right 10
|
||||
:border-radius 8})
|
||||
|
||||
(defnstyle input-touch-handler-view [container-width]
|
||||
{:position :absolute
|
||||
:width container-width
|
||||
:height min-input-height})
|
||||
:height (min (max min-input-height content-height) max-input-height)})
|
||||
|
||||
(defnstyle input-view [content-height single-line-input?]
|
||||
{:flex 1
|
||||
:font-size 14
|
||||
:font-size 15
|
||||
:padding-top 9
|
||||
:padding-bottom 5
|
||||
:padding-right 12
|
||||
:height (if single-line-input?
|
||||
min-input-height
|
||||
(+ (min (max min-input-height content-height) max-input-height)))
|
||||
:android {:padding-top 3}})
|
||||
|
||||
(def invisible-input-text
|
||||
{:font-size 14
|
||||
{:font-size 15
|
||||
:position :absolute
|
||||
:left 0
|
||||
:background-color :transparent
|
||||
|
@ -72,7 +55,7 @@
|
|||
(defnstyle invisible-input-text-height [container-width]
|
||||
{:width container-width
|
||||
:flex 1
|
||||
:font-size 14
|
||||
:font-size 15
|
||||
:padding-top 5
|
||||
:padding-bottom 5
|
||||
:android {:padding-top 3}
|
||||
|
@ -81,45 +64,44 @@
|
|||
:background-color :transparent
|
||||
:color :transparent})
|
||||
|
||||
(defnstyle input-helper-view [left opacity]
|
||||
{:opacity opacity
|
||||
:position :absolute
|
||||
:height min-input-height
|
||||
:android {:left (+ 4 left)}
|
||||
:ios {:left left}})
|
||||
|
||||
(defnstyle input-helper-text [left]
|
||||
{:color color-input-helper-text
|
||||
:font-size 14
|
||||
:position :absolute
|
||||
{:color colors/gray
|
||||
:font-size 15
|
||||
:text-align-vertical :center
|
||||
:height min-input-height
|
||||
:align-items :center
|
||||
:android {:left (+ 15 left)
|
||||
:top -1}
|
||||
:ios {:line-height min-input-height
|
||||
:left (+ 10 left)}})
|
||||
:flex 1
|
||||
:android {:top -1}
|
||||
:ios {:line-height min-input-height}})
|
||||
|
||||
(defnstyle seq-input-text [left container-width]
|
||||
{:min-width (- container-width left)
|
||||
:font-size 14
|
||||
:font-size 15
|
||||
:position :absolute
|
||||
:text-align-vertical :center
|
||||
:height min-input-height
|
||||
:align-items :center
|
||||
:android {:left (+ 10 left)
|
||||
:top 0.5}
|
||||
:android {:left (+ 2 left)
|
||||
:height (+ 2 min-input-height)
|
||||
:top 0.5}
|
||||
:ios {:line-height min-input-height
|
||||
:left (+ 9 left)}})
|
||||
:height min-input-height
|
||||
:left left}})
|
||||
|
||||
(def input-emoji-icon
|
||||
{:margin-top 7
|
||||
:height 24
|
||||
:width 24})
|
||||
(def input-commands-icon
|
||||
{:margin-bottom 14
|
||||
:height 24
|
||||
:width 24})
|
||||
|
||||
(def input-clear-container
|
||||
{:width 24
|
||||
:height 24
|
||||
:margin-top 7
|
||||
:align-items :center})
|
||||
|
||||
(def input-clear-icon
|
||||
{:width 24
|
||||
:height 24
|
||||
:margin-top 0})
|
||||
{:width 24
|
||||
:height 24
|
||||
:margin-top 7
|
||||
:align-items :center})
|
||||
|
||||
(def commands-root
|
||||
{:flex-direction :row
|
||||
|
@ -133,30 +115,3 @@
|
|||
(def commands-list-icon
|
||||
{:height 24
|
||||
:width 24})
|
||||
|
||||
(def close-commands-list-icon
|
||||
{:height 24
|
||||
:width 24})
|
||||
|
||||
(def send-message-container
|
||||
{:background-color color-send
|
||||
:width 38
|
||||
:height 38
|
||||
:border-radius 19
|
||||
:padding 7
|
||||
:margin-left 8})
|
||||
|
||||
(def send-message-icon
|
||||
{:height 24
|
||||
:width 24})
|
||||
|
||||
(def commands
|
||||
{:flex-direction :row
|
||||
:margin-right 16})
|
||||
|
||||
(defn command [first?]
|
||||
{:color color-command
|
||||
:font-size 14
|
||||
:margin-left (if first? 10 16)
|
||||
:padding-top 8
|
||||
:padding-bottom 8})
|
||||
|
|
|
@ -1,27 +0,0 @@
|
|||
(ns status-im.chat.styles.input.input-actions
|
||||
(:require-macros [status-im.utils.styles :refer [defnstyle]])
|
||||
(:require [status-im.ui.components.styles :as common]))
|
||||
|
||||
(def actions-container
|
||||
{:flex-direction :row
|
||||
:margin-left 10})
|
||||
|
||||
(defn action-view [enabled?]
|
||||
{:width 38
|
||||
:height 38
|
||||
:opacity (if enabled? 1 0.5)
|
||||
:justify-content :center
|
||||
:align-items :center})
|
||||
|
||||
(def action-view-icon
|
||||
{:width 24
|
||||
:height 24})
|
||||
|
||||
(def action-view-icon-tinted
|
||||
{:width 24
|
||||
:height 24
|
||||
:tint-color "black"})
|
||||
|
||||
(def action-view-fullscreen-expand-icon
|
||||
{:width 16
|
||||
:height 16})
|
|
@ -0,0 +1,9 @@
|
|||
(ns status-im.chat.styles.input.parameter-box
|
||||
(:require [status-im.ui.components.styles :as common]
|
||||
[status-im.ui.components.colors :as colors]))
|
||||
|
||||
(def root
|
||||
{:background-color common/color-white
|
||||
:border-top-color colors/light-gray
|
||||
:border-top-width 1})
|
||||
|
|
@ -1,11 +1,10 @@
|
|||
(ns status-im.chat.styles.input.result-box
|
||||
(:require [status-im.ui.components.styles :as common]))
|
||||
|
||||
(def color-root-border "rgba(192, 198, 202, 0.5)")
|
||||
(:require [status-im.ui.components.styles :as common]
|
||||
[status-im.ui.components.colors :as colors]))
|
||||
|
||||
(defn root [height bottom]
|
||||
{:background-color common/color-white
|
||||
:border-top-color color-root-border
|
||||
:border-top-color colors/light-gray
|
||||
:border-top-width 1
|
||||
:flex-direction :column
|
||||
:height height
|
||||
|
|
|
@ -0,0 +1,16 @@
|
|||
(ns status-im.chat.styles.input.send-button
|
||||
(:require [status-im.ui.components.colors :as colors]))
|
||||
|
||||
(defn send-message-container [rotation]
|
||||
{:background-color colors/blue
|
||||
:width 30
|
||||
:height 30
|
||||
:border-radius 15
|
||||
:padding 4
|
||||
:margin-left 8
|
||||
:margin-bottom 11
|
||||
:transform [{:rotate rotation}]})
|
||||
|
||||
(def send-message-icon
|
||||
{:height 22
|
||||
:width 22})
|
|
@ -1,46 +1,32 @@
|
|||
(ns status-im.chat.styles.input.suggestions
|
||||
(:require-macros [status-im.utils.styles :refer [defnstyle]])
|
||||
(:require [status-im.ui.components.styles :as common]
|
||||
[status-im.ui.components.colors :as colors]
|
||||
[status-im.utils.platform :as platform]))
|
||||
|
||||
(def color-item-title-text "rgb(147, 155, 161)")
|
||||
(def color-item-suggestion-name "rgb(98, 143, 227)")
|
||||
(def color-item-border "#e8eaeb")
|
||||
(def item-height 52)
|
||||
(def border-height 1)
|
||||
|
||||
(defn item-title-container [top-padding?]
|
||||
{:margin-left 16
|
||||
:align-items :center
|
||||
:flex-direction :row
|
||||
:height 44})
|
||||
(def root
|
||||
{:background-color common/color-white
|
||||
:border-top-color colors/light-gray
|
||||
:border-top-width 1})
|
||||
|
||||
(def item-title-text
|
||||
{:font-size 14
|
||||
:color color-item-title-text})
|
||||
|
||||
(defnstyle item-suggestion-container [last?]
|
||||
{:flex-direction :row
|
||||
:align-items :center
|
||||
:height 56
|
||||
:margin-left 16
|
||||
:ios {:border-bottom-color color-item-border
|
||||
:border-bottom-width (if last? 0 1)}})
|
||||
(defn item-suggestion-container [last?]
|
||||
{:flex-direction :row
|
||||
:align-items :center
|
||||
:height item-height
|
||||
:margin-left 14
|
||||
:padding-right 14
|
||||
:border-bottom-color colors/light-gray
|
||||
:border-bottom-width (if last? 0 border-height)})
|
||||
|
||||
(def item-suggestion-name
|
||||
{:background-color color-item-suggestion-name
|
||||
:height 28
|
||||
:flex-direction :row
|
||||
:align-items :center
|
||||
:border-radius 4
|
||||
:padding-left 7
|
||||
:padding-right 7})
|
||||
|
||||
(def item-suggestion-name-text
|
||||
{:color common/color-white
|
||||
:font-size 14})
|
||||
{:color common/color-black
|
||||
:font-size 15})
|
||||
|
||||
(def item-suggestion-description
|
||||
{:flex 1
|
||||
:font-size 14
|
||||
:margin-left 16
|
||||
:margin-right 16
|
||||
:color color-item-title-text})
|
||||
{:flex 1
|
||||
:font-size 15
|
||||
:margin-left 10
|
||||
:color colors/gray})
|
||||
|
|
|
@ -1,14 +1,15 @@
|
|||
(ns status-im.chat.subs
|
||||
(:require [re-frame.core :refer [reg-sub subscribe]]
|
||||
(:require [clojure.string :as string]
|
||||
[re-frame.core :refer [reg-sub subscribe]]
|
||||
[status-im.constants :as constants]
|
||||
[status-im.chat.constants :as chat-constants]
|
||||
[status-im.chat.models.input :as input-model]
|
||||
[status-im.chat.models.commands :as commands-model]
|
||||
[status-im.chat.views.input.utils :as input-utils]
|
||||
[status-im.commands.utils :as commands-utils]
|
||||
[status-im.utils.datetime :as time]
|
||||
[status-im.utils.platform :as platform]
|
||||
[status-im.i18n :as i18n]
|
||||
[clojure.string :as string]))
|
||||
[status-im.i18n :as i18n]))
|
||||
|
||||
(reg-sub :get-chats :chats)
|
||||
|
||||
|
@ -169,7 +170,9 @@
|
|||
(defn- available-commands-responses [[commands-responses {:keys [input-text]}]]
|
||||
(->> commands-responses
|
||||
map->sorted-seq
|
||||
(filter #(string/includes? (commands-model/command-name %) (or input-text "")))))
|
||||
(filter (fn [item]
|
||||
(when (input-model/starts-as-command? input-text)
|
||||
(string/includes? (commands-model/command-name item) input-text))))))
|
||||
|
||||
(reg-sub
|
||||
:get-available-commands
|
||||
|
@ -198,6 +201,24 @@
|
|||
(fn [[chat commands responses]]
|
||||
(input-model/selected-chat-command chat commands responses)))
|
||||
|
||||
(reg-sub
|
||||
:chat-input-placeholder
|
||||
:<- [:chat :input-text]
|
||||
:<- [:selected-chat-command]
|
||||
(fn [[input-text command]]
|
||||
(when (and (string/ends-with? (or input-text "") chat-constants/spacing-char)
|
||||
(not (get-in command [:command :sequential-params])))
|
||||
(let [input (string/trim (or input-text ""))
|
||||
real-args (remove string/blank? (:args command))]
|
||||
(cond
|
||||
(and command (empty? real-args))
|
||||
(get-in command [:command :params 0 :placeholder])
|
||||
|
||||
(and command
|
||||
(= (count real-args) 1)
|
||||
(input-model/text-ends-with-space? input))
|
||||
(get-in command [:command :params 1 :placeholder]))))))
|
||||
|
||||
(reg-sub
|
||||
:current-chat-argument-position
|
||||
:<- [:selected-chat-command]
|
||||
|
@ -242,16 +263,22 @@
|
|||
input-model/command-completion)
|
||||
|
||||
(reg-sub
|
||||
:show-suggestions?
|
||||
:show-suggestions-view?
|
||||
:<- [:get-current-chat-ui-prop :show-suggestions?]
|
||||
:<- [:get-current-chat]
|
||||
:<- [:selected-chat-command]
|
||||
:<- [:get-available-commands-responses]
|
||||
(fn [[show-suggestions? {:keys [input-text]} selected-command commands-responses]]
|
||||
(and (or show-suggestions? (input-model/starts-as-command? (string/trim (or input-text ""))))
|
||||
(not (:command selected-command))
|
||||
(seq commands-responses))))
|
||||
|
||||
(reg-sub
|
||||
:show-suggestions?
|
||||
:<- [:show-suggestions-view?]
|
||||
:<- [:selected-chat-command]
|
||||
(fn [[show-suggestions-box? selected-command]]
|
||||
(and show-suggestions-box? (not (:command selected-command)))))
|
||||
|
||||
(reg-sub
|
||||
:is-request-answered?
|
||||
:<- [:get-current-chat]
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
(ns status-im.chat.views.api.choose-contact
|
||||
(:require-macros [status-im.utils.views :refer [defview]])
|
||||
(:require-macros [status-im.utils.views :refer [defview letsubs]])
|
||||
(:require [re-frame.core :as re-frame]
|
||||
[status-im.ui.components.contact.contact :refer [contact-view]]
|
||||
[status-im.ui.components.list.views :as list]
|
||||
|
@ -17,17 +17,17 @@
|
|||
(defview choose-contact-view [{title :title
|
||||
arg-index :index
|
||||
bot-db-key :bot-db-key}]
|
||||
[contacts [:people-in-current-chat]]
|
||||
[react/view {:flex 1}
|
||||
[react/text {:style {:font-size 14
|
||||
:color "rgb(147, 155, 161)"
|
||||
:padding-top 12
|
||||
:padding-left 16
|
||||
:padding-right 16
|
||||
:padding-bottom 12}}
|
||||
title]
|
||||
[list/flat-list {:data contacts
|
||||
:render-fn (render-contact arg-index bot-db-key)
|
||||
:enableEmptySections true
|
||||
:keyboardShouldPersistTaps :always
|
||||
:bounces false}]])
|
||||
(letsubs [contacts [:people-in-current-chat]]
|
||||
[react/view
|
||||
[react/text {:style {:font-size 14
|
||||
:color "rgb(147, 155, 161)"
|
||||
:padding-top 12
|
||||
:padding-left 16
|
||||
:padding-right 16
|
||||
:padding-bottom 12}}
|
||||
title]
|
||||
[list/flat-list {:data contacts
|
||||
:render-fn (render-contact arg-index bot-db-key)
|
||||
:enableEmptySections true
|
||||
:keyboardShouldPersistTaps :always
|
||||
:bounces false}]]))
|
||||
|
|
|
@ -1,92 +1,92 @@
|
|||
(ns status-im.chat.views.input.animations.expandable
|
||||
(:require-macros [status-im.utils.views :refer [defview letsubs]])
|
||||
(:require [reagent.core :as r]
|
||||
[reagent.impl.component :as rc]
|
||||
[re-frame.core :refer [dispatch subscribe]]
|
||||
[status-im.ui.components.animation :as anim]
|
||||
(:require [reagent.core :as reagent]
|
||||
[re-frame.core :as re-frame]
|
||||
[status-im.ui.components.animation :as animation]
|
||||
[status-im.ui.components.drag-drop :as drag]
|
||||
[status-im.ui.components.react :refer [view
|
||||
animated-view]]
|
||||
[status-im.chat.views.input.animations.responder :as resp]
|
||||
[status-im.ui.components.react :as react]
|
||||
[status-im.chat.views.input.animations.responder :as responder]
|
||||
[status-im.chat.views.input.utils :as input-utils]
|
||||
[status-im.chat.styles.animations :as style]
|
||||
[taoensso.timbre :as log]
|
||||
[status-im.utils.platform :as p]))
|
||||
[status-im.chat.styles.input.input :as input-style]))
|
||||
|
||||
(defn header [key container-height custom-header]
|
||||
(let [set-container-height (subscribe [:chat-animations key :height])
|
||||
max-container-height (subscribe [:get-max-container-area-height])
|
||||
pan-responder (resp/pan-responder container-height
|
||||
max-container-height
|
||||
:fix-expandable-height
|
||||
key)]
|
||||
(let [set-container-height (re-frame/subscribe [:chat-animations key :height])
|
||||
max-container-height (re-frame/subscribe [:get-max-container-area-height])
|
||||
pan-responder (responder/pan-responder container-height
|
||||
max-container-height
|
||||
:fix-expandable-height
|
||||
key)]
|
||||
(fn [_]
|
||||
[view (merge (drag/pan-handlers pan-responder)
|
||||
{:style style/header-container})
|
||||
[view style/header-icon]
|
||||
[react/view (merge (drag/pan-handlers pan-responder)
|
||||
{:style style/header-container})
|
||||
[react/view style/header-icon]
|
||||
(when (and custom-header
|
||||
(or (= @set-container-height :max)
|
||||
(> @set-container-height (:min-height style/header-container))))
|
||||
[custom-header])])))
|
||||
|
||||
(defn expandable-view-on-update [{:keys [anim-value to-changed-height max-height chat-input-margin height]}]
|
||||
(let [to-default-height (subscribe [:get-default-container-area-height])
|
||||
layout-height (subscribe [:get :layout-height])]
|
||||
(fn [_]
|
||||
(let [to-change-height (if (= @to-changed-height :max)
|
||||
(input-utils/max-container-area-height @chat-input-margin @layout-height)
|
||||
@to-changed-height)
|
||||
to-value (min (or @to-changed-height (or height @to-default-height))
|
||||
@max-height)]
|
||||
(dispatch [:set :expandable-view-height-to-value to-value])
|
||||
(anim/start
|
||||
(anim/spring anim-value {:toValue to-value
|
||||
:friction 10
|
||||
:tension 60}))))))
|
||||
(let [to-default-height (re-frame/subscribe [:get-default-container-area-height])
|
||||
layout-height (re-frame/subscribe [:get :layout-height])]
|
||||
(fn [component]
|
||||
;; we're going to change the height here
|
||||
|
||||
(defview overlay-view []
|
||||
(letsubs [max-height [:get-max-container-area-height]
|
||||
layout-height [:get :layout-height]
|
||||
view-height-to [:get :expandable-view-height-to-value]]
|
||||
(let [related-height (/ view-height-to max-height)]
|
||||
(when (> related-height 0.6)
|
||||
[animated-view {:style (style/result-box-overlay layout-height (- related-height (/ 0.4 related-height)))}]))))
|
||||
;; by default the height can be modified by dispatching :set-expandable-height,
|
||||
;; but there is also a way to make the height adjusted automatically — in this
|
||||
;; case you just need to set :dynamic-height? to true
|
||||
(let [{:keys [dynamic-height?] dynamic-height :height} (reagent/props component)
|
||||
to-changed-height (if dynamic-height?
|
||||
dynamic-height
|
||||
@to-changed-height)
|
||||
to-change-height (if (= to-changed-height :max)
|
||||
(input-utils/max-container-area-height @chat-input-margin @layout-height)
|
||||
to-changed-height)
|
||||
to-value (min (or to-change-height (or height @to-default-height))
|
||||
@max-height)]
|
||||
(re-frame/dispatch [:set :expandable-view-height-to-value to-value])
|
||||
(animation/start
|
||||
(animation/spring anim-value {:toValue to-value
|
||||
:friction 10
|
||||
:tension 60}))))))
|
||||
|
||||
(defn expandable-view [{:keys [key height hide-overlay?]} & _]
|
||||
(let [anim-value (anim/create-value 0)
|
||||
input-height (subscribe [:get-current-chat-ui-prop :input-height])
|
||||
max-height (subscribe [:get-max-container-area-height])
|
||||
fullscreen? (subscribe [:get-current-chat-ui-prop :fullscreen?])
|
||||
chat-input-margin (subscribe [:chat-input-margin])
|
||||
to-changed-height (subscribe [:chat-animations key :height])
|
||||
changes-counter (subscribe [:chat-animations key :changes-counter])
|
||||
on-update (expandable-view-on-update {:anim-value anim-value
|
||||
:to-changed-height to-changed-height
|
||||
:max-height max-height
|
||||
:chat-input-margin chat-input-margin
|
||||
:height height})]
|
||||
(r/create-class
|
||||
(let [anim-value (animation/create-value 0)
|
||||
input-height (re-frame/subscribe [:get-current-chat-ui-prop :input-height])
|
||||
max-height (re-frame/subscribe [:get-max-container-area-height])
|
||||
fullscreen? (re-frame/subscribe [:get-current-chat-ui-prop :fullscreen?])
|
||||
chat-input-margin (re-frame/subscribe [:chat-input-margin])
|
||||
to-changed-height (re-frame/subscribe [:chat-animations key :height])
|
||||
changes-counter (re-frame/subscribe [:chat-animations key :changes-counter])
|
||||
on-update (expandable-view-on-update {:anim-value anim-value
|
||||
:to-changed-height to-changed-height
|
||||
:max-height max-height
|
||||
:chat-input-margin chat-input-margin
|
||||
:height height})]
|
||||
(reagent/create-class
|
||||
{:component-did-mount
|
||||
on-update
|
||||
:component-did-update
|
||||
on-update
|
||||
:component-will-unmount
|
||||
(fn []
|
||||
(dispatch [:set-chat-ui-props {:fullscreen? false}])
|
||||
(re-frame/dispatch [:set-chat-ui-props {:fullscreen? false}])
|
||||
(if height
|
||||
(dispatch [:set-expandable-height key height])
|
||||
(dispatch [:choose-predefined-expandable-height key :default])))
|
||||
:display-name "expandable-view"
|
||||
(re-frame/dispatch [:set-expandable-height key height])
|
||||
(re-frame/dispatch [:choose-predefined-expandable-height key :default])))
|
||||
:display-name
|
||||
"expandable-view"
|
||||
:reagent-render
|
||||
(fn [{:keys [draggable? custom-header]} & elements]
|
||||
@to-changed-height @changes-counter @max-height
|
||||
(let [bottom (+ @input-height @chat-input-margin)
|
||||
height (if @fullscreen? @max-height anim-value)]
|
||||
[view style/overlap-container
|
||||
(when (and (not hide-overlay?)
|
||||
(not @fullscreen?))
|
||||
[overlay-view])
|
||||
(into [animated-view {:style (style/expandable-container height bottom)}
|
||||
(let [input-height (or @input-height (+ input-style/padding-vertical
|
||||
input-style/min-input-height
|
||||
input-style/padding-vertical
|
||||
input-style/border-height))
|
||||
bottom (+ input-height @chat-input-margin)
|
||||
height (if @fullscreen? @max-height anim-value)]
|
||||
[react/view style/overlap-container
|
||||
(into [react/animated-view {:style (style/expandable-container height bottom)}
|
||||
(when (and draggable?
|
||||
(not @fullscreen?))
|
||||
[header key anim-value custom-header])]
|
||||
|
|
|
@ -1,17 +0,0 @@
|
|||
(ns status-im.chat.views.input.emoji
|
||||
(:require-macros [status-im.utils.views :refer [defview]])
|
||||
(:require [re-frame.core :refer [subscribe dispatch]]
|
||||
[status-im.ui.components.react :refer [view
|
||||
text
|
||||
icon
|
||||
emoji-picker]]
|
||||
[status-im.chat.styles.input.emoji :as style]
|
||||
[status-im.i18n :refer [label]]))
|
||||
|
||||
(defview emoji-view []
|
||||
[keyboard-max-height [:get :keyboard-max-height]]
|
||||
[view {:style (style/container keyboard-max-height)}
|
||||
[view style/emoji-container
|
||||
[emoji-picker {:style style/emoji-picker
|
||||
:hideClearButton true
|
||||
:onEmojiSelected #(dispatch [:add-to-chat-input-text %])}]]])
|
|
@ -1,138 +1,104 @@
|
|||
(ns status-im.chat.views.input.input
|
||||
(:require-macros [status-im.utils.views :refer [defview letsubs]])
|
||||
(:require [clojure.string :as str]
|
||||
[reagent.core :as r]
|
||||
[re-frame.core :refer [subscribe dispatch]]
|
||||
[taoensso.timbre :as log]
|
||||
[status-im.chat.constants :as const]
|
||||
[status-im.chat.models.input :as input-model]
|
||||
[status-im.chat.models.commands :as commands-model]
|
||||
[status-im.chat.styles.input.input :as style]
|
||||
[status-im.chat.views.input.emoji :as emoji]
|
||||
(:require [clojure.string :as string]
|
||||
[reagent.core :as reagent]
|
||||
[re-frame.core :as re-frame]
|
||||
[status-im.chat.constants :as constants]
|
||||
[status-im.chat.styles.input.input :as style]
|
||||
[status-im.chat.views.input.parameter-box :as parameter-box]
|
||||
[status-im.chat.views.input.input-actions :as input-actions]
|
||||
[status-im.chat.views.input.result-box :as result-box]
|
||||
[status-im.chat.views.input.send-button :as send-button]
|
||||
[status-im.chat.views.input.suggestions :as suggestions]
|
||||
[status-im.chat.views.input.validation-messages :as validation-messages]
|
||||
[status-im.ui.components.animation :as anim]
|
||||
[status-im.ui.components.animation :as animation]
|
||||
[status-im.ui.components.colors :as colors]
|
||||
[status-im.ui.components.react :as react]
|
||||
[status-im.ui.components.icons.vector-icons :as vi]
|
||||
[status-im.i18n :as i18n]
|
||||
[status-im.utils.platform :as platform]
|
||||
[status-im.utils.utils :as utils]))
|
||||
|
||||
(defn command-view [first? command]
|
||||
[react/touchable-highlight {:on-press #(dispatch [:select-chat-input-command command nil])}
|
||||
[react/view
|
||||
[react/text {:style (style/command first?)
|
||||
:font :roboto-mono}
|
||||
(commands-model/command-name command)]]])
|
||||
(defview basic-text-input [{:keys [set-layout-height-fn set-container-width-fn height single-line-input?]}]
|
||||
(letsubs [input-text [:chat :input-text]
|
||||
command [:selected-chat-command]
|
||||
input-focused? [:get-current-chat-ui-prop :input-focused?]
|
||||
input-ref (atom nil)]
|
||||
[react/text-input
|
||||
{:ref #(when %
|
||||
(re-frame/dispatch [:set-chat-ui-props {:input-ref %}])
|
||||
(reset! input-ref %))
|
||||
:accessibility-label :chat-message-input
|
||||
:multiline (not single-line-input?)
|
||||
:default-value (or input-text "")
|
||||
:editable true
|
||||
:blur-on-submit false
|
||||
:on-focus #(re-frame/dispatch [:set-chat-ui-props {:input-focused? true}])
|
||||
:on-blur #(re-frame/dispatch [:set-chat-ui-props {:input-focused? false}])
|
||||
:on-submit-editing (fn [e]
|
||||
(if single-line-input?
|
||||
(re-frame/dispatch [:send-current-message])
|
||||
(.setNativeProps @input-ref (clj->js {:text (str input-text "\n")}))))
|
||||
:on-layout (fn [e]
|
||||
(set-container-width-fn (.-width (.-layout (.-nativeEvent e)))))
|
||||
:on-change (fn [e]
|
||||
(let [native-event (.-nativeEvent e)
|
||||
text (.-text native-event)
|
||||
content-size (.. native-event -contentSize)]
|
||||
(when (and (not single-line-input?)
|
||||
content-size)
|
||||
(set-layout-height-fn (.-height content-size)))
|
||||
(when (not= text input-text)
|
||||
(re-frame/dispatch [:set-chat-input-text text])
|
||||
(when command
|
||||
(re-frame/dispatch [:load-chat-parameter-box (:command command)]))
|
||||
(re-frame/dispatch [:update-input-data]))))
|
||||
:on-content-size-change (when (and (not input-focused?)
|
||||
(not single-line-input?))
|
||||
#(let [h (-> (.-nativeEvent %)
|
||||
(.-contentSize)
|
||||
(.-height))]
|
||||
(set-layout-height-fn h)))
|
||||
:on-selection-change #(let [s (-> (.-nativeEvent %)
|
||||
(.-selection))
|
||||
end (.-end s)]
|
||||
(re-frame/dispatch [:update-text-selection end]))
|
||||
:style (style/input-view height single-line-input?)
|
||||
:placeholder-text-color colors/gray
|
||||
:auto-capitalize :sentences}]))
|
||||
|
||||
(defview commands-view []
|
||||
[all-commands-responses [:get-available-commands-responses]
|
||||
show-suggestions? [:show-suggestions?]]
|
||||
[react/view style/commands-root
|
||||
[react/view style/command-list-icon-container
|
||||
[react/touchable-highlight {:on-press #(dispatch [:show-suggestions])}
|
||||
[react/view style/commands-list-icon
|
||||
(if show-suggestions?
|
||||
[vi/icon :icons/close]
|
||||
[vi/icon :icons/commands-list])]]]
|
||||
[react/scroll-view {:horizontal true
|
||||
:showsHorizontalScrollIndicator false
|
||||
:keyboardShouldPersistTaps :always}
|
||||
[react/view style/commands
|
||||
(for [[index command] (map-indexed vector all-commands-responses)]
|
||||
^{:key (str "command-" index)}
|
||||
[command-view (= index 0) command])]]])
|
||||
|
||||
(defn- basic-text-input [_]
|
||||
(let [input-text (subscribe [:chat :input-text])
|
||||
command (subscribe [:selected-chat-command])
|
||||
input-focused? (subscribe [:get-current-chat-ui-prop :input-focused?])
|
||||
input-ref (atom nil)]
|
||||
(fn [{:keys [set-layout-height-fn set-container-width-fn height single-line-input?]}]
|
||||
[react/text-input
|
||||
{:ref #(when %
|
||||
(dispatch [:set-chat-ui-props {:input-ref %}])
|
||||
(reset! input-ref %))
|
||||
:accessibility-label :chat-message-input
|
||||
:multiline (not single-line-input?)
|
||||
:default-value (or @input-text "")
|
||||
:editable true
|
||||
:blur-on-submit false
|
||||
:on-focus #(dispatch [:set-chat-ui-props {:input-focused? true
|
||||
:show-emoji? false}])
|
||||
:on-blur #(dispatch [:set-chat-ui-props {:input-focused? false}])
|
||||
:on-submit-editing (fn [e]
|
||||
(if single-line-input?
|
||||
(dispatch [:send-current-message])
|
||||
(.setNativeProps @input-ref (clj->js {:text (str @input-text "\n")}))))
|
||||
:on-layout (fn [e]
|
||||
(set-container-width-fn (.-width (.-layout (.-nativeEvent e)))))
|
||||
:on-change (fn [e]
|
||||
(let [native-event (.-nativeEvent e)
|
||||
text (.-text native-event)
|
||||
content-size (.. native-event -contentSize)]
|
||||
(when (and (not single-line-input?)
|
||||
content-size)
|
||||
(set-layout-height-fn (.-height content-size)))
|
||||
(when (not= text @input-text)
|
||||
(dispatch [:set-chat-input-text text])
|
||||
(when @command
|
||||
(dispatch [:load-chat-parameter-box (:command @command)]))
|
||||
(dispatch [:update-input-data]))))
|
||||
:on-content-size-change (when (and (not @input-focused?)
|
||||
(not single-line-input?))
|
||||
#(let [h (-> (.-nativeEvent %)
|
||||
(.-contentSize)
|
||||
(.-height))]
|
||||
(set-layout-height-fn h)))
|
||||
:on-selection-change #(let [s (-> (.-nativeEvent %)
|
||||
(.-selection))
|
||||
end (.-end s)]
|
||||
(dispatch [:update-text-selection end]))
|
||||
:style (style/input-view height single-line-input?)
|
||||
:placeholder-text-color style/color-input-helper-placeholder
|
||||
:auto-capitalize :sentences}])))
|
||||
|
||||
(defn- invisible-input [{:keys [set-layout-width-fn value]}]
|
||||
(let [input-text (subscribe [:chat :input-text])]
|
||||
(defview invisible-input [{:keys [set-layout-width-fn value]}]
|
||||
(letsubs [input-text [:chat :input-text]]
|
||||
[react/text {:style style/invisible-input-text
|
||||
:on-layout #(let [w (-> (.-nativeEvent %)
|
||||
(.-layout)
|
||||
(.-width))]
|
||||
(set-layout-width-fn w))}
|
||||
(or @input-text "")]))
|
||||
(or input-text "")]))
|
||||
|
||||
(defn- invisible-input-height [{:keys [set-layout-height-fn container-width]}]
|
||||
(let [input-text (subscribe [:chat :input-text])]
|
||||
(defview invisible-input-height [{:keys [set-layout-height-fn container-width]}]
|
||||
(letsubs [input-text [:chat :input-text]]
|
||||
[react/text {:style (style/invisible-input-text-height container-width)
|
||||
:on-layout #(let [h (-> (.-nativeEvent %)
|
||||
(.-layout)
|
||||
(.-height))]
|
||||
(set-layout-height-fn h))}
|
||||
(or @input-text "")]))
|
||||
(or input-text "")]))
|
||||
|
||||
(defn- input-helper [_]
|
||||
(let [input-text (subscribe [:chat :input-text])]
|
||||
(fn [{:keys [command width]}]
|
||||
(when-not (get-in command [:command :sequential-params])
|
||||
(let [input (str/trim (or @input-text ""))
|
||||
real-args (remove str/blank? (:args command))]
|
||||
(when-let [placeholder (cond
|
||||
(= const/command-char input)
|
||||
(i18n/label :t/type-a-command)
|
||||
(defn- input-helper-view-on-update [{:keys [opacity-value placeholder]}]
|
||||
(fn [_]
|
||||
(let [to-value (if @placeholder 1 0)]
|
||||
(animation/start
|
||||
(animation/timing opacity-value {:toValue to-value
|
||||
:duration 300})))))
|
||||
|
||||
(and command (empty? real-args))
|
||||
(get-in command [:command :params 0 :placeholder])
|
||||
(defview input-helper [{:keys [width]}]
|
||||
(letsubs [placeholder [:chat-input-placeholder]
|
||||
opacity-value (animation/create-value 0)
|
||||
on-update (input-helper-view-on-update {:opacity-value opacity-value
|
||||
:placeholder placeholder})]
|
||||
{:component-did-update on-update}
|
||||
[react/animated-view {:style (style/input-helper-view width opacity-value)}
|
||||
[react/text {:style (style/input-helper-text width)}
|
||||
placeholder]]))
|
||||
|
||||
(and command
|
||||
(= (count real-args) 1)
|
||||
(input-model/text-ends-with-space? input))
|
||||
(get-in command [:command :params 1 :placeholder]))]
|
||||
[react/text {:style (style/input-helper-text width)}
|
||||
placeholder]))))))
|
||||
|
||||
(defn get-options [type]
|
||||
(case (keyword type)
|
||||
|
@ -141,149 +107,80 @@
|
|||
:number {:keyboard-type "numeric"}
|
||||
nil))
|
||||
|
||||
(defn- seq-input [_]
|
||||
(let [command (subscribe [:selected-chat-command])
|
||||
arg-pos (subscribe [:current-chat-argument-position])
|
||||
seq-arg-input-text (subscribe [:chat :seq-argument-input-text])]
|
||||
(fn [{:keys [command-width container-width]}]
|
||||
(when (get-in @command [:command :sequential-params])
|
||||
(let [{:keys [placeholder hidden type]} (get-in @command [:command :params @arg-pos])]
|
||||
[react/text-input (merge {:ref #(dispatch [:set-chat-ui-props {:seq-input-ref %}])
|
||||
:style (style/seq-input-text command-width container-width)
|
||||
:default-value (or @seq-arg-input-text "")
|
||||
:on-change-text #(do (dispatch [:set-chat-seq-arg-input-text %])
|
||||
(dispatch [:load-chat-parameter-box (:command @command)])
|
||||
(dispatch [:set-chat-ui-props {:validation-messages nil}]))
|
||||
:placeholder placeholder
|
||||
:accessibility-label :chat-request-input
|
||||
:blur-on-submit false
|
||||
:editable true
|
||||
:on-focus #(dispatch [:set-chat-ui-props {:show-emoji? false}])
|
||||
:on-submit-editing (fn []
|
||||
(when-not (or (str/blank? @seq-arg-input-text)
|
||||
(get-in @command [:command :hide-send-button]))
|
||||
(dispatch [:send-seq-argument]))
|
||||
(utils/set-timeout
|
||||
#(dispatch [:chat-input-focus :seq-input-ref])
|
||||
100))}
|
||||
(get-options type))])))))
|
||||
(defview seq-input [{:keys [command-width container-width]}]
|
||||
(letsubs [command [:selected-chat-command]
|
||||
arg-pos [:current-chat-argument-position]
|
||||
seq-arg-input-text [:chat :seq-argument-input-text]]
|
||||
(when (get-in command [:command :sequential-params])
|
||||
(let [{:keys [placeholder hidden type]} (get-in command [:command :params arg-pos])]
|
||||
[react/text-input (merge {:ref #(re-frame/dispatch [:set-chat-ui-props {:seq-input-ref %}])
|
||||
:style (style/seq-input-text command-width container-width)
|
||||
:default-value (or seq-arg-input-text "")
|
||||
:on-change-text #(do (re-frame/dispatch [:set-chat-seq-arg-input-text %])
|
||||
(re-frame/dispatch [:load-chat-parameter-box (:command command)])
|
||||
(re-frame/dispatch [:set-chat-ui-props {:validation-messages nil}]))
|
||||
:placeholder placeholder
|
||||
:accessibility-label :chat-request-input
|
||||
:blur-on-submit false
|
||||
:editable true
|
||||
:on-submit-editing (fn []
|
||||
(when-not (or (string/blank? seq-arg-input-text)
|
||||
(get-in @command [:command :hide-send-button]))
|
||||
(re-frame/dispatch [:send-seq-argument]))
|
||||
(utils/set-timeout
|
||||
#(re-frame/dispatch [:chat-input-focus :seq-input-ref])
|
||||
100))}
|
||||
(get-options type))]))))
|
||||
|
||||
(defn input-view [_]
|
||||
(let [component (r/current-component)
|
||||
set-layout-width-fn #(r/set-state component {:width %})
|
||||
set-layout-height-fn #(r/set-state component {:height %})
|
||||
set-container-width-fn #(r/set-state component {:container-width %})
|
||||
command (subscribe [:selected-chat-command])]
|
||||
(r/create-class
|
||||
{:display-name "input-view"
|
||||
:reagent-render
|
||||
(fn [{:keys [anim-margin single-line-input?]}]
|
||||
(let [{:keys [width height container-width]} (r/state component)
|
||||
command @command]
|
||||
[react/animated-view {:style (style/input-root height anim-margin)}
|
||||
[invisible-input {:set-layout-width-fn set-layout-width-fn}]
|
||||
[invisible-input-height {:set-layout-height-fn set-layout-height-fn
|
||||
:container-width container-width}]
|
||||
[basic-text-input {:set-layout-height-fn set-layout-height-fn
|
||||
:set-container-width-fn set-container-width-fn
|
||||
:height height
|
||||
:single-line-input? single-line-input?}]
|
||||
[input-helper {:command command
|
||||
:width width}]
|
||||
[seq-input {:command-width width
|
||||
:container-width container-width}]
|
||||
(if-not command
|
||||
[react/touchable-highlight
|
||||
{:on-press #(do (dispatch [:toggle-chat-ui-props :show-emoji?])
|
||||
(react/dismiss-keyboard!))}
|
||||
[react/view
|
||||
[vi/icon :icons/smile {:container-style style/input-emoji-icon}]]]
|
||||
(when-not single-line-input?
|
||||
[react/touchable-highlight
|
||||
{:on-press #(do (dispatch [:set-chat-input-text nil])
|
||||
(dispatch [:set-chat-input-metadata nil])
|
||||
(dispatch [:set-chat-ui-props {:result-box nil
|
||||
:validation-messages nil}])
|
||||
(dispatch [:clear-seq-arguments]))}
|
||||
[react/view style/input-clear-container
|
||||
[vi/icon :icons/close]]]))]))})))
|
||||
(defview input-view [{:keys [single-line-input?]}]
|
||||
(letsubs [command [:selected-chat-command]]
|
||||
(let [component (reagent/current-component)
|
||||
set-layout-width-fn #(reagent/set-state component {:width %})
|
||||
set-layout-height-fn #(reagent/set-state component {:height %})
|
||||
set-container-width-fn #(reagent/set-state component {:container-width %})
|
||||
{:keys [width height container-width]} (reagent/state component)]
|
||||
[react/view {:style style/input-root}
|
||||
[react/animated-view {:style (style/input-animated height)}
|
||||
[invisible-input {:set-layout-width-fn set-layout-width-fn}]
|
||||
[invisible-input-height {:set-layout-height-fn set-layout-height-fn
|
||||
:container-width container-width}]
|
||||
[basic-text-input {:set-layout-height-fn set-layout-height-fn
|
||||
:set-container-width-fn set-container-width-fn
|
||||
:height height
|
||||
:single-line-input? single-line-input?}]
|
||||
[input-helper {:width width}]
|
||||
[seq-input {:command-width width
|
||||
:container-width container-width}]]])))
|
||||
|
||||
(defview input-container [{:keys [anim-margin]}]
|
||||
(letsubs [command-completion [:command-completion]
|
||||
selected-command [:selected-chat-command]
|
||||
input-text [:chat :input-text]
|
||||
seq-arg-input-text [:chat :seq-argument-input-text]
|
||||
result-box [:get-current-chat-ui-prop :result-box]]
|
||||
(let [single-line-input? (:singleLineInput result-box)
|
||||
{:keys [hide-send-button sequential-params]} (:command selected-command)]
|
||||
[react/view style/input-container
|
||||
[input-view {:anim-margin anim-margin
|
||||
:single-line-input? single-line-input?}]
|
||||
(if (:actions result-box)
|
||||
[input-actions/input-actions-view]
|
||||
(when (and (not (str/blank? input-text))
|
||||
(or (not selected-command)
|
||||
(some #{:complete :less-than-needed} [command-completion]))
|
||||
(not hide-send-button))
|
||||
[react/touchable-highlight {:on-press #(if sequential-params
|
||||
(do
|
||||
(when-not (str/blank? seq-arg-input-text)
|
||||
(dispatch [:send-seq-argument]))
|
||||
(utils/set-timeout
|
||||
(fn [] (dispatch [:chat-input-focus :seq-input-ref]))
|
||||
100))
|
||||
(dispatch [:send-current-message]))}
|
||||
[react/view {:style style/send-message-container
|
||||
:accessibility-label :send-message-button}
|
||||
[react/icon :arrow_top style/send-message-icon]]]))])))
|
||||
(defn commands-button []
|
||||
[react/touchable-highlight
|
||||
{:on-press #(do (re-frame/dispatch [:set-chat-input-text constants/command-char])
|
||||
(react/dismiss-keyboard!))}
|
||||
[react/view
|
||||
[vi/icon :icons/input-commands {:container-style style/input-commands-icon
|
||||
:color :dark}]]])
|
||||
|
||||
(defview input-container []
|
||||
(letsubs [margin [:chat-input-margin]
|
||||
input-text [:chat :input-text]
|
||||
result-box [:get-current-chat-ui-prop :result-box]]
|
||||
(let [single-line-input? (:singleLineInput result-box)]
|
||||
[react/view {:style (style/root margin)
|
||||
:on-layout #(let [h (-> (.-nativeEvent %)
|
||||
(.-layout)
|
||||
(.-height))]
|
||||
(when (> h 0)
|
||||
(re-frame/dispatch [:set-chat-ui-props {:input-height h}])))}
|
||||
[react/view {:style style/input-container}
|
||||
[input-view {:single-line-input? single-line-input?}]
|
||||
(when (string/blank? input-text)
|
||||
[commands-button])
|
||||
[send-button/send-button-view]]])))
|
||||
|
||||
(defn container []
|
||||
(let [margin (subscribe [:chat-input-margin])
|
||||
show-emoji? (subscribe [:get-current-chat-ui-prop :show-emoji?])
|
||||
input-text (subscribe [:chat :input-text])
|
||||
anim-margin (anim/create-value 10)
|
||||
container-anim-margin (anim/create-value 16)
|
||||
bottom-anim-margin (anim/create-value 14)]
|
||||
(r/create-class
|
||||
{:display-name "input-container"
|
||||
:component-did-mount
|
||||
(fn []
|
||||
(when-not (str/blank? @input-text)
|
||||
(.setValue anim-margin 0)
|
||||
(.setValue container-anim-margin 8)
|
||||
(.setValue bottom-anim-margin 8)))
|
||||
:component-did-update
|
||||
(fn [component]
|
||||
(let [{:keys [text-empty?]} (reagent.core/props component)]
|
||||
(let [to-anim-value (if text-empty? 10 0)
|
||||
to-container-anim-value (if text-empty? 16 8)
|
||||
to-bottom-anim-value (if text-empty? 14 8)]
|
||||
(anim/start
|
||||
(anim/timing anim-margin {:toValue to-anim-value
|
||||
:duration 100}))
|
||||
(anim/start
|
||||
(anim/timing container-anim-margin {:toValue to-container-anim-value
|
||||
:duration 100}))
|
||||
(anim/start
|
||||
(anim/timing bottom-anim-margin {:toValue to-bottom-anim-value
|
||||
:duration 100})))))
|
||||
|
||||
:reagent-render
|
||||
(fn []
|
||||
[react/view style/input-container-view
|
||||
[parameter-box/parameter-box-view]
|
||||
[result-box/result-box-view]
|
||||
[suggestions/suggestions-view]
|
||||
[validation-messages/validation-messages-view]
|
||||
[react/view {:style (style/root @margin)
|
||||
:on-layout #(let [h (-> (.-nativeEvent %)
|
||||
(.-layout)
|
||||
(.-height))]
|
||||
(when (> h 0)
|
||||
(dispatch [:set-chat-ui-props {:input-height h}])))}
|
||||
[react/animated-view {:style (style/container container-anim-margin bottom-anim-margin)}
|
||||
(when (str/blank? @input-text)
|
||||
[commands-view])
|
||||
[input-container {:anim-margin anim-margin}]]
|
||||
(when @show-emoji?
|
||||
[emoji/emoji-view])]])})))
|
||||
[react/view
|
||||
[parameter-box/parameter-box-view]
|
||||
[result-box/result-box-view]
|
||||
[suggestions/suggestions-view]
|
||||
[validation-messages/validation-messages-view]
|
||||
[input-container]])
|
||||
|
|
|
@ -1,25 +0,0 @@
|
|||
(ns status-im.chat.views.input.input-actions
|
||||
(:require [re-frame.core :as re-frame]
|
||||
[taoensso.timbre :as log]
|
||||
[status-im.ui.components.react :as react]
|
||||
[status-im.chat.styles.input.input-actions :as style]))
|
||||
|
||||
(defmulti action-view (fn [{:keys [type]}] (keyword type)))
|
||||
|
||||
(defmethod action-view :default
|
||||
[{:keys [image executeJs]}]
|
||||
[react/touchable-highlight
|
||||
{:on-press #(re-frame/dispatch [:chat-webview-bridge/send-to-bridge
|
||||
{:event "actions-execute-js"
|
||||
:js executeJs}])}
|
||||
[react/view (style/action-view true)
|
||||
[react/icon (str "action_" image) style/action-view-icon]]])
|
||||
|
||||
(defn input-actions-view []
|
||||
(let [result-box (re-frame/subscribe [:get-current-chat-ui-prop :result-box])]
|
||||
(fn []
|
||||
(let [{:keys [actions]} @result-box]
|
||||
[react/view style/actions-container
|
||||
(for [{:keys [type] :as action} actions]
|
||||
^{:key type}
|
||||
[action-view action])]))))
|
|
@ -1,23 +1,32 @@
|
|||
(ns status-im.chat.views.input.parameter-box
|
||||
(:require-macros [status-im.utils.views :refer [defview]])
|
||||
(:require-macros [status-im.utils.views :refer [defview letsubs]])
|
||||
(:require [re-frame.core :refer [subscribe dispatch]]
|
||||
[status-im.chat.views.input.animations.expandable :refer [expandable-view]]
|
||||
[status-im.chat.views.input.animations.expandable :as expandable]
|
||||
[status-im.chat.views.input.box-header :as box-header]
|
||||
[status-im.chat.styles.input.parameter-box :as style]
|
||||
[status-im.commands.utils :as command-utils]
|
||||
[status-im.ui.components.react :as react]
|
||||
[taoensso.timbre :as log]))
|
||||
|
||||
(defview parameter-box-container []
|
||||
[{:keys [markup]} [:chat-parameter-box]
|
||||
bot-id-bot-db [:current-bot-db]]
|
||||
(when markup
|
||||
(command-utils/generate-hiccup markup (first bot-id-bot-db) (second bot-id-bot-db))))
|
||||
[react/view style/root
|
||||
(command-utils/generate-hiccup markup (first bot-id-bot-db) (second bot-id-bot-db))]))
|
||||
|
||||
(defview parameter-box-view []
|
||||
[show-parameter-box? [:show-parameter-box?]
|
||||
{:keys [title]} [:chat-parameter-box]]
|
||||
(when show-parameter-box?
|
||||
[expandable-view {:key :parameter-box
|
||||
:draggable? true
|
||||
:custom-header (when title
|
||||
(box-header/get-header :parameter-box))}
|
||||
[parameter-box-container]]))
|
||||
(letsubs [show-parameter-box? [:show-parameter-box?]
|
||||
parameter-box [:chat-parameter-box]]
|
||||
(let [{:keys [title height]} parameter-box
|
||||
draggable? (not height)]
|
||||
(when show-parameter-box?
|
||||
[expandable/expandable-view
|
||||
{:key :parameter-box
|
||||
:draggable? draggable?
|
||||
:custom-header (when title
|
||||
(box-header/get-header :parameter-box))
|
||||
:height (when-not draggable?
|
||||
(+ height (:border-top-width style/root)))
|
||||
:dynamic-height? (not draggable?)}
|
||||
[parameter-box-container]]))))
|
||||
|
|
|
@ -0,0 +1,47 @@
|
|||
(ns status-im.chat.views.input.send-button
|
||||
(:require-macros [status-im.utils.views :refer [defview letsubs]])
|
||||
(:require [clojure.string :as string]
|
||||
[reagent.core :as reagent]
|
||||
[re-frame.core :as re-frame]
|
||||
[status-im.chat.styles.input.send-button :as style]
|
||||
[status-im.ui.components.animation :as animation]
|
||||
[status-im.ui.components.react :as react]
|
||||
[status-im.ui.components.icons.vector-icons :as vi]
|
||||
[status-im.utils.utils :as utils]))
|
||||
|
||||
(defn send-button-view-on-update [{:keys [spin-value opacity-value command-completion]}]
|
||||
(fn [_]
|
||||
(let [to-spin-value (if (some #{:complete :no-command} [@command-completion]) 1 0)]
|
||||
(animation/start
|
||||
(animation/timing spin-value {:toValue to-spin-value
|
||||
:duration 300})))))
|
||||
|
||||
(defview send-button-view []
|
||||
(letsubs [command-completion [:command-completion]
|
||||
selected-command [:selected-chat-command]
|
||||
input-text [:chat :input-text]
|
||||
seq-arg-input-text [:chat :seq-argument-input-text]
|
||||
spin-value (animation/create-value 1)
|
||||
on-update (send-button-view-on-update {:spin-value spin-value
|
||||
:command-completion command-completion})]
|
||||
{:component-did-update on-update}
|
||||
(let [{:keys [hide-send-button sequential-params]} (:command selected-command)]
|
||||
(when (and (not (string/blank? input-text))
|
||||
(or (not selected-command)
|
||||
(some #{:complete :less-than-needed} [command-completion]))
|
||||
(not hide-send-button))
|
||||
[react/touchable-highlight {:on-press #(if sequential-params
|
||||
(do
|
||||
(when-not (string/blank? seq-arg-input-text)
|
||||
(re-frame/dispatch [:send-seq-argument]))
|
||||
(utils/set-timeout
|
||||
(fn [] (re-frame/dispatch [:chat-input-focus :seq-input-ref]))
|
||||
100))
|
||||
(re-frame/dispatch [:send-current-message]))}
|
||||
(let [spin (.interpolate spin-value (clj->js {:inputRange [0 1]
|
||||
:outputRange ["0deg" "90deg"]}))]
|
||||
[react/animated-view
|
||||
{:style (style/send-message-container spin)
|
||||
:accessibility-label :send-message-button}
|
||||
[vi/icon :icons/input-send {:container-style style/send-message-icon
|
||||
:color :white}]])]))))
|
|
@ -1,18 +1,18 @@
|
|||
(ns status-im.chat.views.input.suggestions
|
||||
(:require-macros [status-im.utils.views :refer [defview]])
|
||||
(:require-macros [status-im.utils.views :refer [defview letsubs]])
|
||||
(:require [re-frame.core :as re-frame]
|
||||
[status-im.ui.components.react :as react]
|
||||
[status-im.chat.styles.input.suggestions :as style]
|
||||
[status-im.chat.views.input.animations.expandable :as expandable]
|
||||
[status-im.chat.models.commands :as commands-model]
|
||||
[status-im.i18n :as i18n]))
|
||||
[status-im.chat.models.commands :as commands-model]
|
||||
[status-im.i18n :as i18n]
|
||||
[taoensso.timbre :as log]))
|
||||
|
||||
(defn suggestion-item [{:keys [on-press name description last?]}]
|
||||
[react/touchable-highlight {:on-press on-press}
|
||||
[react/view (style/item-suggestion-container last?)
|
||||
[react/view {:style style/item-suggestion-name}
|
||||
[react/text {:style style/item-suggestion-name-text
|
||||
:font :roboto-mono} name]]
|
||||
[react/text {:style style/item-suggestion-name}
|
||||
name]
|
||||
[react/text {:style style/item-suggestion-description
|
||||
:number-of-lines 2}
|
||||
description]]])
|
||||
|
@ -34,30 +34,25 @@
|
|||
:description description
|
||||
:last? last?}])
|
||||
|
||||
(defn item-title [top-padding? title]
|
||||
[react/view (style/item-title-container top-padding?)
|
||||
[react/text {:style style/item-title-text}
|
||||
title]])
|
||||
|
||||
(defview suggestions-view []
|
||||
[show-suggestions? [:show-suggestions?]
|
||||
responses [:get-available-responses]
|
||||
commands [:get-available-commands]]
|
||||
(when show-suggestions?
|
||||
[expandable/expandable-view {:key :suggestions
|
||||
:draggable? false
|
||||
:height 212}
|
||||
[react/view {:flex 1}
|
||||
[react/scroll-view {:keyboardShouldPersistTaps :always}
|
||||
(when (seq responses)
|
||||
[react/view
|
||||
[item-title false (i18n/label :t/suggestions-requests)]
|
||||
(for [[i response] (map-indexed vector responses)]
|
||||
^{:key i}
|
||||
[response-item response (= i (dec (count responses)))])])
|
||||
(when (seq commands)
|
||||
[react/view
|
||||
[item-title (seq responses) (i18n/label :t/suggestions-commands)]
|
||||
(for [[i command] (map-indexed vector commands)]
|
||||
^{:key i}
|
||||
[command-item command (= i (dec (count commands)))])])]]]))
|
||||
(letsubs [show-suggestions-view? [:show-suggestions-view?]
|
||||
responses [:get-available-responses]
|
||||
commands [:get-available-commands]]
|
||||
(let [number-of-entries (+ (count responses) (count commands))]
|
||||
[expandable/expandable-view {:key :suggestions
|
||||
:draggable? false
|
||||
:height (* number-of-entries
|
||||
(+ style/item-height
|
||||
style/border-height))
|
||||
:dynamic-height? true}
|
||||
[react/view
|
||||
[react/scroll-view {:keyboard-should-persist-taps :always
|
||||
:bounces false}
|
||||
(when (seq responses)
|
||||
(for [[i response] (map-indexed vector responses)]
|
||||
^{:key i}
|
||||
[response-item response (= i (dec (count responses)))]))
|
||||
(when (seq commands)
|
||||
(for [[i command] (map-indexed vector commands)]
|
||||
^{:key i}
|
||||
[command-item command (= i (dec (count commands)))]))]]])))
|
||||
|
|
|
@ -305,8 +305,6 @@
|
|||
(fn [{:keys [outgoing group-chat content-type content] :as message}]
|
||||
[message-container message
|
||||
[react/touchable-highlight {:on-press #(when platform/ios?
|
||||
(re-frame/dispatch [:set-chat-ui-props
|
||||
{:show-emoji? false}])
|
||||
(react/dismiss-keyboard!))
|
||||
:on-long-press #(when (= content-type constants/text-content-type)
|
||||
(list-selection/share content (i18n/label :t/message)))}
|
||||
|
|
|
@ -206,7 +206,7 @@
|
|||
:transactions-filter-type :next :recent
|
||||
:open-on-etherscan :share :status :from
|
||||
:wrong-password :search-chats :transactions-sign-later :in-contacts
|
||||
:transactions-sign :sharing-share :type-a-message :type-a-command
|
||||
:transactions-sign :sharing-share :type-a-message
|
||||
:usd-currency :existing-networks :node-unavailable :url :shake-your-phone
|
||||
:add-network :unknown-status-go-error :contacts-group-new-chat :and-you
|
||||
:wallets :clear-history :wallet-choose-from-contacts
|
||||
|
|
|
@ -11,5 +11,5 @@
|
|||
(def gray-lighter "#eef2f5") ;; Used as a background or shadow
|
||||
(def blue "#4360df") ;; Used as main wallet color
|
||||
(def red "#ff2d55") ;; Used to highlight errors or "dangerous" actions
|
||||
(def light-gray "#eef2f5") ;; Used as a background or shadow
|
||||
(def light-gray "#e8ebec") ;; Used as a background or shadow
|
||||
(def text-light-gray "#212121") ;; Used for labels (home items)
|
||||
|
|
|
@ -62,8 +62,8 @@
|
|||
:icons/public (slurp/slurp-svg "./resources/icons/public.svg")
|
||||
:icons/public-chat (slurp/slurp-svg "./resources/icons/public_chat.svg")
|
||||
:icons/qr (slurp/slurp-svg "./resources/icons/QR.svg")
|
||||
:icons/smile (slurp/slurp-svg "./resources/icons/smile.svg")
|
||||
:icons/commands-list (slurp/slurp-svg "./resources/icons/commands_list.svg")
|
||||
:icons/input-commands (slurp/slurp-svg "./resources/icons/input_commands.svg")
|
||||
:icons/input-send (slurp/slurp-svg "./resources/icons/input_send.svg")
|
||||
:icons/back (slurp/slurp-svg "./resources/icons/back.svg")
|
||||
:icons/forward (slurp/slurp-svg "./resources/icons/forward.svg")
|
||||
:icons/dropdown-up (slurp/slurp-svg "./resources/icons/dropdown_up.svg")
|
||||
|
|
|
@ -161,14 +161,6 @@
|
|||
(.then clipboard-contents #(clbk %))))
|
||||
|
||||
|
||||
;; Emoji
|
||||
|
||||
(def emoji-picker-class js-dependencies/emoji-picker)
|
||||
|
||||
(def emoji-picker
|
||||
(let [emoji-picker (.-default emoji-picker-class)]
|
||||
(reagent/adapt-react-class emoji-picker)))
|
||||
|
||||
;; Autolink
|
||||
|
||||
(def autolink-class (reagent/adapt-react-class (.-default js-dependencies/autolink)))
|
||||
|
|
Loading…
Reference in New Issue