sanitize quo2 (#14859)
This commit is contained in:
parent
098821d20b
commit
d79d2e9d36
|
@ -1,6 +1,5 @@
|
|||
(ns quo2.components.code.snippet
|
||||
(:require ["react-native" :as react-native]
|
||||
[cljs-bean.core :as bean]
|
||||
(:require [cljs-bean.core :as bean]
|
||||
[clojure.string :as string]
|
||||
[oops.core :as oops]
|
||||
[quo2.components.buttons.button :as button]
|
||||
|
@ -168,8 +167,8 @@
|
|||
:on-copy-press #(when on-copy-press
|
||||
(on-copy-press children))})
|
||||
;; Default props to adapt Highlighter for react-native.
|
||||
:CodeTag react-native/View
|
||||
:PreTag react-native/View
|
||||
;;:CodeTag react-native/View
|
||||
;;:PreTag react-native/View
|
||||
:show-line-numbers false
|
||||
:style #js {}
|
||||
:custom-style #js {:backgroundColor nil}}
|
||||
|
|
|
@ -1,6 +1,5 @@
|
|||
(ns quo2.components.community.token-gating
|
||||
(:require [quo.react-native :as rn]
|
||||
[quo2.components.avatars.channel-avatar :as channel-avatar]
|
||||
(:require [quo2.components.avatars.channel-avatar :as channel-avatar]
|
||||
[quo2.components.buttons.button :as button]
|
||||
[quo2.components.icon :as icon]
|
||||
[quo2.components.info.information-box :as information-box]
|
||||
|
@ -8,7 +7,8 @@
|
|||
[quo2.components.tags.token-tag :as token-tag]
|
||||
[quo2.foundations.colors :as colors]
|
||||
[utils.i18n :as i18n]
|
||||
[react-native.fast-image :as fast-image]))
|
||||
[react-native.fast-image :as fast-image]
|
||||
[react-native.core :as rn]))
|
||||
|
||||
(def ^:private token-tag-horizontal-spacing 7)
|
||||
(def token-tag-vertical-spacing 5)
|
||||
|
|
|
@ -3,8 +3,7 @@
|
|||
[quo2.components.icon :as icons]
|
||||
[quo2.components.markdown.text :as text]
|
||||
[quo2.components.messages.author.style :as style]
|
||||
[react-native.core :as rn]
|
||||
[status-im.utils.utils :as utils]))
|
||||
[react-native.core :as rn]))
|
||||
|
||||
(def middle-dot "·")
|
||||
|
||||
|
@ -35,7 +34,7 @@
|
|||
profile-name])])))
|
||||
|
||||
(defn author
|
||||
[{:keys [profile-name nickname chat-key ens-name time-str contact? verified? untrustworthy?]}]
|
||||
[{:keys [profile-name nickname short-chat-key ens-name time-str contact? verified? untrustworthy?]}]
|
||||
[:f>
|
||||
(fn []
|
||||
(let [ens? (-> ens-name string/blank? not)
|
||||
|
@ -85,7 +84,7 @@
|
|||
{:monospace true
|
||||
:size :paragraph-2
|
||||
:style style/chat-key-text}
|
||||
(utils/get-shortened-address chat-key)])
|
||||
short-chat-key])
|
||||
(when-not ens?
|
||||
[text/text
|
||||
{:monospace true
|
||||
|
|
|
@ -1,11 +1,12 @@
|
|||
(ns quo2.components.tags.tags
|
||||
(:require [reagent.core :as reagent]
|
||||
[quo.react-native :as rn]
|
||||
[oops.core :refer [oget]]
|
||||
[status-im.ui.components.react :as react]
|
||||
[status-im.utils.core :as utils]
|
||||
[quo2.components.tags.tag :as tag]
|
||||
[utils.number :as number-utils]))
|
||||
[utils.number :as number-utils]
|
||||
[react-native.core :as rn]
|
||||
[react-native.masked-view :as masked-view]
|
||||
[react-native.linear-gradient :as linear-gradient]
|
||||
[utils.collection :as utils.collection]))
|
||||
|
||||
(def default-tab-size 32)
|
||||
|
||||
|
@ -76,9 +77,9 @@
|
|||
size default-tab-size}
|
||||
:as props}]
|
||||
(let [maybe-mask-wrapper (if fade-end?
|
||||
[react/masked-view
|
||||
[masked-view/masked-view
|
||||
{:mask-element (reagent/as-element
|
||||
[react/linear-gradient
|
||||
[linear-gradient/linear-gradient
|
||||
{:colors [:black :transparent]
|
||||
:locations [(get @fading :fade-end-percentage)
|
||||
1]
|
||||
|
@ -92,64 +93,65 @@
|
|||
(conj
|
||||
maybe-mask-wrapper
|
||||
[rn/flat-list
|
||||
(merge (dissoc props
|
||||
:default-active
|
||||
:fade-end-percentage
|
||||
:fade-end?
|
||||
:on-change
|
||||
:scroll-on-press?
|
||||
:size)
|
||||
(when scroll-on-press?
|
||||
{:initial-scroll-index (utils/first-index #(= @active-tab-id (:id %)) data)})
|
||||
{:ref #(reset! flat-list-ref %)
|
||||
:extra-data (str @active-tab-id)
|
||||
:horizontal true
|
||||
:scroll-event-throttle scroll-event-throttle
|
||||
:shows-horizontal-scroll-indicator false
|
||||
:data data
|
||||
:key-fn (comp str :id)
|
||||
:on-scroll (fn [^js e]
|
||||
(when fade-end?
|
||||
(let [offset-x (oget e "nativeEvent.contentOffset.x")
|
||||
content-width (oget e "nativeEvent.contentSize.width")
|
||||
layout-width (oget e "nativeEvent.layoutMeasurement.width")
|
||||
new-percentage (calculate-fade-end-percentage
|
||||
{:offset-x offset-x
|
||||
:content-width content-width
|
||||
:layout-width layout-width
|
||||
:max-fade-percentage fade-end-percentage})]
|
||||
;; Avoid unnecessary re-rendering.
|
||||
(when (not= new-percentage (get @fading :fade-end-percentage))
|
||||
(swap! fading assoc :fade-end-percentage new-percentage))))
|
||||
(when on-scroll
|
||||
(on-scroll e)))
|
||||
:render-fn (fn [{:keys [id label resource]} index]
|
||||
[rn/view
|
||||
{:style {:margin-right (if (= size default-tab-size) 12 8)
|
||||
:padding-right (when (= index (dec (count data)))
|
||||
(get-in props [:style :padding-left]))}}
|
||||
[tag/tag
|
||||
{:id id
|
||||
:size size
|
||||
:active (= id @active-tab-id)
|
||||
:resource resource
|
||||
:blurred? blurred?
|
||||
:icon-color icon-color
|
||||
:disabled? disabled?
|
||||
:label label
|
||||
:type type
|
||||
:labelled? labelled?
|
||||
:on-press (fn [id]
|
||||
(reset! active-tab-id id)
|
||||
(when scroll-on-press?
|
||||
(.scrollToIndex ^js @flat-list-ref
|
||||
#js
|
||||
{:animated true
|
||||
:index index
|
||||
:viewPosition 0.5}))
|
||||
(when on-change
|
||||
(on-change id)))}
|
||||
label]])})])
|
||||
(merge
|
||||
(dissoc props
|
||||
:default-active
|
||||
:fade-end-percentage
|
||||
:fade-end?
|
||||
:on-change
|
||||
:scroll-on-press?
|
||||
:size)
|
||||
(when scroll-on-press?
|
||||
{:initial-scroll-index (utils.collection/first-index #(= @active-tab-id (:id %)) data)})
|
||||
{:ref #(reset! flat-list-ref %)
|
||||
:extra-data (str @active-tab-id)
|
||||
:horizontal true
|
||||
:scroll-event-throttle scroll-event-throttle
|
||||
:shows-horizontal-scroll-indicator false
|
||||
:data data
|
||||
:key-fn (comp str :id)
|
||||
:on-scroll (fn [^js e]
|
||||
(when fade-end?
|
||||
(let [offset-x (oget e "nativeEvent.contentOffset.x")
|
||||
content-width (oget e "nativeEvent.contentSize.width")
|
||||
layout-width (oget e "nativeEvent.layoutMeasurement.width")
|
||||
new-percentage (calculate-fade-end-percentage
|
||||
{:offset-x offset-x
|
||||
:content-width content-width
|
||||
:layout-width layout-width
|
||||
:max-fade-percentage fade-end-percentage})]
|
||||
;; Avoid unnecessary re-rendering.
|
||||
(when (not= new-percentage (get @fading :fade-end-percentage))
|
||||
(swap! fading assoc :fade-end-percentage new-percentage))))
|
||||
(when on-scroll
|
||||
(on-scroll e)))
|
||||
:render-fn (fn [{:keys [id label resource]} index]
|
||||
[rn/view
|
||||
{:style {:margin-right (if (= size default-tab-size) 12 8)
|
||||
:padding-right (when (= index (dec (count data)))
|
||||
(get-in props [:style :padding-left]))}}
|
||||
[tag/tag
|
||||
{:id id
|
||||
:size size
|
||||
:active (= id @active-tab-id)
|
||||
:resource resource
|
||||
:blurred? blurred?
|
||||
:icon-color icon-color
|
||||
:disabled? disabled?
|
||||
:label label
|
||||
:type type
|
||||
:labelled? labelled?
|
||||
:on-press (fn [id]
|
||||
(reset! active-tab-id id)
|
||||
(when scroll-on-press?
|
||||
(.scrollToIndex ^js @flat-list-ref
|
||||
#js
|
||||
{:animated true
|
||||
:index index
|
||||
:viewPosition 0.5}))
|
||||
(when on-change
|
||||
(on-change id)))}
|
||||
label]])})])
|
||||
[rn/view {:style {:flex-direction :row}}
|
||||
(for [{:keys [label id resource]} data]
|
||||
^{:key id}
|
||||
|
|
|
@ -0,0 +1,10 @@
|
|||
(ns react-native.clipboard
|
||||
(:require ["@react-native-community/clipboard" :default Clipboard]))
|
||||
|
||||
(defn set-string
|
||||
[text]
|
||||
(.setString ^js Clipboard text))
|
||||
|
||||
(defn get-string
|
||||
[callback]
|
||||
(.then (.getString ^js Clipboard) #(callback %)))
|
|
@ -117,3 +117,14 @@
|
|||
{:ease-in-ease-out (-> ^js layout-animation .-Presets .-easeInEaseOut)
|
||||
:linear (-> ^js layout-animation .-Presets .-linear)
|
||||
:spring (-> ^js layout-animation .-Presets .-spring)})
|
||||
|
||||
(def find-node-handle (.-findNodeHandle ^js react-native))
|
||||
|
||||
(defn selectable-text-input-manager
|
||||
[]
|
||||
(when (exists? (.-NativeModules ^js react-native))
|
||||
(.-RNSelectableTextInputManager ^js (.-NativeModules ^js react-native))))
|
||||
|
||||
(defonce selectable-text-input
|
||||
(reagent/adapt-react-class
|
||||
(.requireNativeComponent ^js react-native "RNSelectableTextInput")))
|
||||
|
|
|
@ -1,22 +1,20 @@
|
|||
(ns status-im.ui2.screens.chat.composer.input
|
||||
(:require ["react-native" :as react-native]
|
||||
[clojure.string :as string]
|
||||
(:require [clojure.string :as string]
|
||||
[oops.core :as oops]
|
||||
[quo.design-system.colors :as quo.colors]
|
||||
[quo.react]
|
||||
[quo.react-native :as rn]
|
||||
[quo2.foundations.colors :as colors]
|
||||
[re-frame.core :as re-frame]
|
||||
[reagent.core :as reagent]
|
||||
[status-im2.constants :as chat.constants]
|
||||
[status-im.chat.models.mentions :as mentions]
|
||||
[utils.i18n :as i18n]
|
||||
[status-im.ui.components.react :as react]
|
||||
[utils.re-frame :as rf]
|
||||
[status-im.utils.platform :as platform]
|
||||
[status-im.utils.utils :as utils.utils]
|
||||
[utils.transforms :as transforms]
|
||||
[quo2.foundations.typography :as typography]))
|
||||
[quo2.foundations.typography :as typography]
|
||||
[react-native.background-timer :as background-timer]
|
||||
[react-native.platform :as platform]
|
||||
[react-native.core :as rn]
|
||||
[react-native.clipboard :as clipboard]
|
||||
[quo.react :as quo.react]))
|
||||
|
||||
(defonce input-texts (atom {}))
|
||||
(defonce input-text-content-heights (atom {}))
|
||||
|
@ -94,7 +92,7 @@
|
|||
(when platform/ios?
|
||||
(reset!
|
||||
timeout-id
|
||||
(utils.utils/set-timeout
|
||||
(background-timer/set-timeout
|
||||
#(rf/dispatch [::mentions/on-selection-change
|
||||
{:start start
|
||||
:end end}
|
||||
|
@ -128,7 +126,7 @@
|
|||
;; happens during typing because it is not needed for mention
|
||||
;; suggestions calculation
|
||||
(when (and platform/ios? @timeout-id)
|
||||
(utils.utils/clear-timeout @timeout-id))
|
||||
(background-timer/clear-timeout @timeout-id))
|
||||
(when platform/android?
|
||||
(reset! last-text-change (js/Date.now)))
|
||||
|
||||
|
@ -169,7 +167,7 @@
|
|||
:min-height 34
|
||||
:margin 0
|
||||
:flex-shrink 1
|
||||
:color (:text-01 @quo.colors/theme)
|
||||
:color (colors/theme-colors colors/neutral-100 colors/white)
|
||||
:margin-horizontal 20}
|
||||
(if platform/android?
|
||||
{:padding-vertical 8
|
||||
|
@ -195,7 +193,7 @@
|
|||
:blur-on-submit false
|
||||
:auto-focus false
|
||||
:max-length chat.constants/max-text-size
|
||||
:placeholder-text-color (:text-02 @quo.colors/theme)
|
||||
:placeholder-text-color (colors/theme-colors colors/neutral-40 colors/white-opa-30)
|
||||
:placeholder (if cooldown-enabled?
|
||||
(i18n/label :cooldown/text-input-disabled)
|
||||
(i18n/label :t/type-a-message))
|
||||
|
@ -230,14 +228,6 @@
|
|||
[rn/text-input props
|
||||
children])))
|
||||
|
||||
(defn selectable-text-input-manager
|
||||
[]
|
||||
(when (exists? (.-NativeModules react-native))
|
||||
(.-RNSelectableTextInputManager ^js (.-NativeModules react-native))))
|
||||
|
||||
(defonce rn-selectable-text-input
|
||||
(reagent/adapt-react-class (.requireNativeComponent react-native "RNSelectableTextInput")))
|
||||
|
||||
(declare first-level-menu-items second-level-menu-items)
|
||||
|
||||
(defn update-input-text
|
||||
|
@ -269,24 +259,24 @@
|
|||
;https://lightrun.com/answers/facebook-react-native-textinput-controlled-selection-broken-on-both-ios-and-android
|
||||
;use native invoke instead! do not use setNativeProps! e.g. (.setNativeProps ^js text-input (clj->js
|
||||
;{:selection {:start selection-start :end selection-end}}))
|
||||
(let [manager (selectable-text-input-manager)]
|
||||
(let [manager (rn/selectable-text-input-manager)]
|
||||
(oops/ocall manager :setSelection text-input-handle selection-start selection-end)))
|
||||
|
||||
(def first-level-menus
|
||||
{:cut (fn [{:keys [content] :as params}]
|
||||
(let [new-text (calculate-input-text params "")]
|
||||
(react/copy-to-clipboard content)
|
||||
(clipboard/set-string content)
|
||||
(update-input-text params new-text)))
|
||||
|
||||
:copy-to-clipboard (fn [{:keys [content]}]
|
||||
(react/copy-to-clipboard content))
|
||||
(clipboard/set-string content))
|
||||
|
||||
:paste (fn [params]
|
||||
(let [callback (fn [paste-content]
|
||||
(let [content (string/trim paste-content)
|
||||
new-text (calculate-input-text params content)]
|
||||
(update-input-text params new-text)))]
|
||||
(react/get-from-clipboard callback)))
|
||||
(clipboard/get-string callback)))
|
||||
|
||||
:biu (fn [{:keys [first-level text-input-handle menu-items selection-start
|
||||
selection-end]}]
|
||||
|
@ -340,7 +330,7 @@
|
|||
menu-items (reagent/atom first-level-menu-items)
|
||||
first-level (reagent/atom true)
|
||||
selection-event (atom nil)
|
||||
manager (selectable-text-input-manager)]
|
||||
manager (rn/selectable-text-input-manager)]
|
||||
(reagent/create-class
|
||||
{:component-did-mount
|
||||
(fn [this]
|
||||
|
@ -395,6 +385,6 @@
|
|||
:style (dissoc style :margin-horizontal)
|
||||
:on-selection-change on-selection-change
|
||||
:on-selection on-selection})]
|
||||
[rn-selectable-text-input {:menuItems @menu-items :style style}
|
||||
[rn/selectable-text-input {:menuItems @menu-items :style style}
|
||||
[rn/text-input props
|
||||
children]]))})))
|
||||
|
|
|
@ -16,7 +16,8 @@
|
|||
[utils.re-frame :as rf]
|
||||
[status-im.ui2.screens.chat.messages.message :as old-message]
|
||||
[status-im2.common.not-implemented :as not-implemented]
|
||||
[utils.datetime :as datetime]))
|
||||
[utils.datetime :as datetime]
|
||||
[status-im.utils.utils :as utils]))
|
||||
|
||||
(defn avatar
|
||||
[{:keys [response-to last-in-group? pinned quoted-message from]}]
|
||||
|
@ -41,11 +42,11 @@
|
|||
(let [display-name (first (rf/sub [:contacts/contact-two-names-by-identity from]))
|
||||
{:keys [ens-verified added?]} (rf/sub [:contacts/contact-by-address from])]
|
||||
[quo/author
|
||||
{:profile-name display-name
|
||||
:chat-key from
|
||||
:time-str (datetime/timestamp->time timestamp)
|
||||
:contact? added?
|
||||
:verified? ens-verified}])))
|
||||
{:profile-name display-name
|
||||
:short-chat-key (utils/get-shortened-address from)
|
||||
:time-str (datetime/timestamp->time timestamp)
|
||||
:contact? added?
|
||||
:verified? ens-verified}])))
|
||||
|
||||
(defn system-message-content
|
||||
[{:keys [content-type quoted-message] :as message-data}]
|
||||
|
|
|
@ -4,7 +4,8 @@
|
|||
[quo2.foundations.colors :as colors]
|
||||
[react-native.core :as rn]
|
||||
[reagent.core :as reagent]
|
||||
[status-im2.contexts.quo-preview.preview :as preview]))
|
||||
[status-im2.contexts.quo-preview.preview :as preview]
|
||||
[status-im.utils.utils :as utils]))
|
||||
|
||||
(def descriptor
|
||||
[{:label "Profile name"
|
||||
|
@ -39,7 +40,8 @@
|
|||
[]
|
||||
(let [state (reagent/atom {:profile-name "Alisher Yakupov"
|
||||
:nickname ""
|
||||
:chat-key "zQ3ssgRy5TtB47MMiMKMKaGyaawkCgMqqbrnAUYrZJ1sgt5N"
|
||||
:short-chat-key (utils/get-shortened-address
|
||||
"zQ3ssgRy5TtB47MMiMKMKaGyaawkCgMqqbrnAUYrZJ1sgt5N")
|
||||
:time-str "09:30"
|
||||
:ens-name ""
|
||||
:contact? false
|
||||
|
|
Loading…
Reference in New Issue