sanitize quo2 (#14859)

This commit is contained in:
flexsurfer 2023-01-23 14:41:55 +01:00 committed by GitHub
parent 098821d20b
commit d79d2e9d36
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
9 changed files with 124 additions and 110 deletions

View File

@ -1,6 +1,5 @@
(ns quo2.components.code.snippet (ns quo2.components.code.snippet
(:require ["react-native" :as react-native] (:require [cljs-bean.core :as bean]
[cljs-bean.core :as bean]
[clojure.string :as string] [clojure.string :as string]
[oops.core :as oops] [oops.core :as oops]
[quo2.components.buttons.button :as button] [quo2.components.buttons.button :as button]
@ -168,8 +167,8 @@
:on-copy-press #(when on-copy-press :on-copy-press #(when on-copy-press
(on-copy-press children))}) (on-copy-press children))})
;; Default props to adapt Highlighter for react-native. ;; Default props to adapt Highlighter for react-native.
:CodeTag react-native/View ;;:CodeTag react-native/View
:PreTag react-native/View ;;:PreTag react-native/View
:show-line-numbers false :show-line-numbers false
:style #js {} :style #js {}
:custom-style #js {:backgroundColor nil}} :custom-style #js {:backgroundColor nil}}

View File

@ -1,6 +1,5 @@
(ns quo2.components.community.token-gating (ns quo2.components.community.token-gating
(:require [quo.react-native :as rn] (:require [quo2.components.avatars.channel-avatar :as channel-avatar]
[quo2.components.avatars.channel-avatar :as channel-avatar]
[quo2.components.buttons.button :as button] [quo2.components.buttons.button :as button]
[quo2.components.icon :as icon] [quo2.components.icon :as icon]
[quo2.components.info.information-box :as information-box] [quo2.components.info.information-box :as information-box]
@ -8,7 +7,8 @@
[quo2.components.tags.token-tag :as token-tag] [quo2.components.tags.token-tag :as token-tag]
[quo2.foundations.colors :as colors] [quo2.foundations.colors :as colors]
[utils.i18n :as i18n] [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 ^:private token-tag-horizontal-spacing 7)
(def token-tag-vertical-spacing 5) (def token-tag-vertical-spacing 5)

View File

@ -3,8 +3,7 @@
[quo2.components.icon :as icons] [quo2.components.icon :as icons]
[quo2.components.markdown.text :as text] [quo2.components.markdown.text :as text]
[quo2.components.messages.author.style :as style] [quo2.components.messages.author.style :as style]
[react-native.core :as rn] [react-native.core :as rn]))
[status-im.utils.utils :as utils]))
(def middle-dot "·") (def middle-dot "·")
@ -35,7 +34,7 @@
profile-name])]))) profile-name])])))
(defn author (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> [:f>
(fn [] (fn []
(let [ens? (-> ens-name string/blank? not) (let [ens? (-> ens-name string/blank? not)
@ -85,7 +84,7 @@
{:monospace true {:monospace true
:size :paragraph-2 :size :paragraph-2
:style style/chat-key-text} :style style/chat-key-text}
(utils/get-shortened-address chat-key)]) short-chat-key])
(when-not ens? (when-not ens?
[text/text [text/text
{:monospace true {:monospace true

View File

@ -1,11 +1,12 @@
(ns quo2.components.tags.tags (ns quo2.components.tags.tags
(:require [reagent.core :as reagent] (:require [reagent.core :as reagent]
[quo.react-native :as rn]
[oops.core :refer [oget]] [oops.core :refer [oget]]
[status-im.ui.components.react :as react]
[status-im.utils.core :as utils]
[quo2.components.tags.tag :as tag] [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) (def default-tab-size 32)
@ -76,9 +77,9 @@
size default-tab-size} size default-tab-size}
:as props}] :as props}]
(let [maybe-mask-wrapper (if fade-end? (let [maybe-mask-wrapper (if fade-end?
[react/masked-view [masked-view/masked-view
{:mask-element (reagent/as-element {:mask-element (reagent/as-element
[react/linear-gradient [linear-gradient/linear-gradient
{:colors [:black :transparent] {:colors [:black :transparent]
:locations [(get @fading :fade-end-percentage) :locations [(get @fading :fade-end-percentage)
1] 1]
@ -92,64 +93,65 @@
(conj (conj
maybe-mask-wrapper maybe-mask-wrapper
[rn/flat-list [rn/flat-list
(merge (dissoc props (merge
:default-active (dissoc props
:fade-end-percentage :default-active
:fade-end? :fade-end-percentage
:on-change :fade-end?
:scroll-on-press? :on-change
:size) :scroll-on-press?
(when scroll-on-press? :size)
{:initial-scroll-index (utils/first-index #(= @active-tab-id (:id %)) data)}) (when scroll-on-press?
{:ref #(reset! flat-list-ref %) {:initial-scroll-index (utils.collection/first-index #(= @active-tab-id (:id %)) data)})
:extra-data (str @active-tab-id) {:ref #(reset! flat-list-ref %)
:horizontal true :extra-data (str @active-tab-id)
:scroll-event-throttle scroll-event-throttle :horizontal true
:shows-horizontal-scroll-indicator false :scroll-event-throttle scroll-event-throttle
:data data :shows-horizontal-scroll-indicator false
:key-fn (comp str :id) :data data
:on-scroll (fn [^js e] :key-fn (comp str :id)
(when fade-end? :on-scroll (fn [^js e]
(let [offset-x (oget e "nativeEvent.contentOffset.x") (when fade-end?
content-width (oget e "nativeEvent.contentSize.width") (let [offset-x (oget e "nativeEvent.contentOffset.x")
layout-width (oget e "nativeEvent.layoutMeasurement.width") content-width (oget e "nativeEvent.contentSize.width")
new-percentage (calculate-fade-end-percentage layout-width (oget e "nativeEvent.layoutMeasurement.width")
{:offset-x offset-x new-percentage (calculate-fade-end-percentage
:content-width content-width {:offset-x offset-x
:layout-width layout-width :content-width content-width
:max-fade-percentage fade-end-percentage})] :layout-width layout-width
;; Avoid unnecessary re-rendering. :max-fade-percentage fade-end-percentage})]
(when (not= new-percentage (get @fading :fade-end-percentage)) ;; Avoid unnecessary re-rendering.
(swap! fading assoc :fade-end-percentage new-percentage)))) (when (not= new-percentage (get @fading :fade-end-percentage))
(when on-scroll (swap! fading assoc :fade-end-percentage new-percentage))))
(on-scroll e))) (when on-scroll
:render-fn (fn [{:keys [id label resource]} index] (on-scroll e)))
[rn/view :render-fn (fn [{:keys [id label resource]} index]
{:style {:margin-right (if (= size default-tab-size) 12 8) [rn/view
:padding-right (when (= index (dec (count data))) {:style {:margin-right (if (= size default-tab-size) 12 8)
(get-in props [:style :padding-left]))}} :padding-right (when (= index (dec (count data)))
[tag/tag (get-in props [:style :padding-left]))}}
{:id id [tag/tag
:size size {:id id
:active (= id @active-tab-id) :size size
:resource resource :active (= id @active-tab-id)
:blurred? blurred? :resource resource
:icon-color icon-color :blurred? blurred?
:disabled? disabled? :icon-color icon-color
:label label :disabled? disabled?
:type type :label label
:labelled? labelled? :type type
:on-press (fn [id] :labelled? labelled?
(reset! active-tab-id id) :on-press (fn [id]
(when scroll-on-press? (reset! active-tab-id id)
(.scrollToIndex ^js @flat-list-ref (when scroll-on-press?
#js (.scrollToIndex ^js @flat-list-ref
{:animated true #js
:index index {:animated true
:viewPosition 0.5})) :index index
(when on-change :viewPosition 0.5}))
(on-change id)))} (when on-change
label]])})]) (on-change id)))}
label]])})])
[rn/view {:style {:flex-direction :row}} [rn/view {:style {:flex-direction :row}}
(for [{:keys [label id resource]} data] (for [{:keys [label id resource]} data]
^{:key id} ^{:key id}

View File

@ -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 %)))

View File

@ -117,3 +117,14 @@
{:ease-in-ease-out (-> ^js layout-animation .-Presets .-easeInEaseOut) {:ease-in-ease-out (-> ^js layout-animation .-Presets .-easeInEaseOut)
:linear (-> ^js layout-animation .-Presets .-linear) :linear (-> ^js layout-animation .-Presets .-linear)
:spring (-> ^js layout-animation .-Presets .-spring)}) :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")))

View File

@ -1,22 +1,20 @@
(ns status-im.ui2.screens.chat.composer.input (ns status-im.ui2.screens.chat.composer.input
(:require ["react-native" :as react-native] (:require [clojure.string :as string]
[clojure.string :as string]
[oops.core :as oops] [oops.core :as oops]
[quo.design-system.colors :as quo.colors]
[quo.react]
[quo.react-native :as rn]
[quo2.foundations.colors :as colors] [quo2.foundations.colors :as colors]
[re-frame.core :as re-frame] [re-frame.core :as re-frame]
[reagent.core :as reagent] [reagent.core :as reagent]
[status-im2.constants :as chat.constants] [status-im2.constants :as chat.constants]
[status-im.chat.models.mentions :as mentions] [status-im.chat.models.mentions :as mentions]
[utils.i18n :as i18n] [utils.i18n :as i18n]
[status-im.ui.components.react :as react]
[utils.re-frame :as rf] [utils.re-frame :as rf]
[status-im.utils.platform :as platform]
[status-im.utils.utils :as utils.utils]
[utils.transforms :as transforms] [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-texts (atom {}))
(defonce input-text-content-heights (atom {})) (defonce input-text-content-heights (atom {}))
@ -94,7 +92,7 @@
(when platform/ios? (when platform/ios?
(reset! (reset!
timeout-id timeout-id
(utils.utils/set-timeout (background-timer/set-timeout
#(rf/dispatch [::mentions/on-selection-change #(rf/dispatch [::mentions/on-selection-change
{:start start {:start start
:end end} :end end}
@ -128,7 +126,7 @@
;; happens during typing because it is not needed for mention ;; happens during typing because it is not needed for mention
;; suggestions calculation ;; suggestions calculation
(when (and platform/ios? @timeout-id) (when (and platform/ios? @timeout-id)
(utils.utils/clear-timeout @timeout-id)) (background-timer/clear-timeout @timeout-id))
(when platform/android? (when platform/android?
(reset! last-text-change (js/Date.now))) (reset! last-text-change (js/Date.now)))
@ -169,7 +167,7 @@
:min-height 34 :min-height 34
:margin 0 :margin 0
:flex-shrink 1 :flex-shrink 1
:color (:text-01 @quo.colors/theme) :color (colors/theme-colors colors/neutral-100 colors/white)
:margin-horizontal 20} :margin-horizontal 20}
(if platform/android? (if platform/android?
{:padding-vertical 8 {:padding-vertical 8
@ -195,7 +193,7 @@
:blur-on-submit false :blur-on-submit false
:auto-focus false :auto-focus false
:max-length chat.constants/max-text-size :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? :placeholder (if cooldown-enabled?
(i18n/label :cooldown/text-input-disabled) (i18n/label :cooldown/text-input-disabled)
(i18n/label :t/type-a-message)) (i18n/label :t/type-a-message))
@ -230,14 +228,6 @@
[rn/text-input props [rn/text-input props
children]))) 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) (declare first-level-menu-items second-level-menu-items)
(defn update-input-text (defn update-input-text
@ -269,24 +259,24 @@
;https://lightrun.com/answers/facebook-react-native-textinput-controlled-selection-broken-on-both-ios-and-android ;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 ;use native invoke instead! do not use setNativeProps! e.g. (.setNativeProps ^js text-input (clj->js
;{:selection {:start selection-start :end selection-end}})) ;{: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))) (oops/ocall manager :setSelection text-input-handle selection-start selection-end)))
(def first-level-menus (def first-level-menus
{:cut (fn [{:keys [content] :as params}] {:cut (fn [{:keys [content] :as params}]
(let [new-text (calculate-input-text params "")] (let [new-text (calculate-input-text params "")]
(react/copy-to-clipboard content) (clipboard/set-string content)
(update-input-text params new-text))) (update-input-text params new-text)))
:copy-to-clipboard (fn [{:keys [content]}] :copy-to-clipboard (fn [{:keys [content]}]
(react/copy-to-clipboard content)) (clipboard/set-string content))
:paste (fn [params] :paste (fn [params]
(let [callback (fn [paste-content] (let [callback (fn [paste-content]
(let [content (string/trim paste-content) (let [content (string/trim paste-content)
new-text (calculate-input-text params content)] new-text (calculate-input-text params content)]
(update-input-text params new-text)))] (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 :biu (fn [{:keys [first-level text-input-handle menu-items selection-start
selection-end]}] selection-end]}]
@ -340,7 +330,7 @@
menu-items (reagent/atom first-level-menu-items) menu-items (reagent/atom first-level-menu-items)
first-level (reagent/atom true) first-level (reagent/atom true)
selection-event (atom nil) selection-event (atom nil)
manager (selectable-text-input-manager)] manager (rn/selectable-text-input-manager)]
(reagent/create-class (reagent/create-class
{:component-did-mount {:component-did-mount
(fn [this] (fn [this]
@ -395,6 +385,6 @@
:style (dissoc style :margin-horizontal) :style (dissoc style :margin-horizontal)
:on-selection-change on-selection-change :on-selection-change on-selection-change
:on-selection on-selection})] :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 [rn/text-input props
children]]))}))) children]]))})))

View File

@ -16,7 +16,8 @@
[utils.re-frame :as rf] [utils.re-frame :as rf]
[status-im.ui2.screens.chat.messages.message :as old-message] [status-im.ui2.screens.chat.messages.message :as old-message]
[status-im2.common.not-implemented :as not-implemented] [status-im2.common.not-implemented :as not-implemented]
[utils.datetime :as datetime])) [utils.datetime :as datetime]
[status-im.utils.utils :as utils]))
(defn avatar (defn avatar
[{:keys [response-to last-in-group? pinned quoted-message from]}] [{: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])) (let [display-name (first (rf/sub [:contacts/contact-two-names-by-identity from]))
{:keys [ens-verified added?]} (rf/sub [:contacts/contact-by-address from])] {:keys [ens-verified added?]} (rf/sub [:contacts/contact-by-address from])]
[quo/author [quo/author
{:profile-name display-name {:profile-name display-name
:chat-key from :short-chat-key (utils/get-shortened-address from)
:time-str (datetime/timestamp->time timestamp) :time-str (datetime/timestamp->time timestamp)
:contact? added? :contact? added?
:verified? ens-verified}]))) :verified? ens-verified}])))
(defn system-message-content (defn system-message-content
[{:keys [content-type quoted-message] :as message-data}] [{:keys [content-type quoted-message] :as message-data}]

View File

@ -4,7 +4,8 @@
[quo2.foundations.colors :as colors] [quo2.foundations.colors :as colors]
[react-native.core :as rn] [react-native.core :as rn]
[reagent.core :as reagent] [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 (def descriptor
[{:label "Profile name" [{:label "Profile name"
@ -39,7 +40,8 @@
[] []
(let [state (reagent/atom {:profile-name "Alisher Yakupov" (let [state (reagent/atom {:profile-name "Alisher Yakupov"
:nickname "" :nickname ""
:chat-key "zQ3ssgRy5TtB47MMiMKMKaGyaawkCgMqqbrnAUYrZJ1sgt5N" :short-chat-key (utils/get-shortened-address
"zQ3ssgRy5TtB47MMiMKMKaGyaawkCgMqqbrnAUYrZJ1sgt5N")
:time-str "09:30" :time-str "09:30"
:ens-name "" :ens-name ""
:contact? false :contact? false